@1agh/maude 0.42.0 → 0.44.0
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/apps/studio/.ai/cache/_stats.json +7 -0
- package/apps/studio/acp/bootstrap-brief.ts +12 -2
- package/apps/studio/acp/bridge.ts +44 -10
- package/apps/studio/acp/env.ts +23 -0
- package/apps/studio/acp/login-state.ts +263 -0
- package/apps/studio/acp/plugin-bootstrap.ts +31 -25
- package/apps/studio/acp/probe.ts +152 -1
- package/apps/studio/annotations-layer.tsx +1451 -324
- package/apps/studio/annotations-model.ts +58 -0
- package/apps/studio/api.ts +568 -24
- package/apps/studio/bin/_audio-search.mjs +140 -0
- package/apps/studio/bin/_import-asset-pdf-worker.mjs +34 -0
- package/apps/studio/bin/_import-asset.mjs +815 -0
- package/apps/studio/bin/_import-brand.mjs +635 -0
- package/apps/studio/bin/_import-tokens-alias-resolver.mjs +95 -0
- package/apps/studio/bin/_import-tokens.mjs +1201 -0
- package/apps/studio/bin/_ingest-footage.mjs +386 -0
- package/apps/studio/bin/_probe-footage-playwright.mjs +269 -0
- package/apps/studio/bin/_transcribe.mjs +419 -0
- package/apps/studio/bin/_transcribe.test.mjs +80 -0
- package/apps/studio/bin/_video-playwright.mjs +141 -71
- package/apps/studio/bin/audio-search.sh +28 -0
- package/apps/studio/bin/generate.sh +154 -0
- package/apps/studio/bin/import-asset.sh +34 -0
- package/apps/studio/bin/import-brand.sh +29 -0
- package/apps/studio/bin/import-tokens.sh +33 -0
- package/apps/studio/bin/ingest-footage.sh +27 -0
- package/apps/studio/bin/photo-adjust.sh +163 -0
- package/apps/studio/bin/photo-bg-remove.sh +258 -0
- package/apps/studio/bin/probe-footage.sh +28 -0
- package/apps/studio/bin/read-annotations.mjs +125 -2
- package/apps/studio/bin/transcribe.sh +39 -0
- package/apps/studio/canvas-edit.ts +656 -12
- package/apps/studio/canvas-lib.tsx +637 -10
- package/apps/studio/canvas-pipeline.ts +65 -7
- package/apps/studio/canvas-shell.tsx +156 -16
- package/apps/studio/client/app.jsx +2385 -699
- package/apps/studio/client/export-center.jsx +35 -1
- package/apps/studio/client/generate-dialog.jsx +352 -0
- package/apps/studio/client/github.js +18 -0
- package/apps/studio/client/inspector-controls.jsx +781 -0
- package/apps/studio/client/panels/BrandUploadPanel.jsx +233 -0
- package/apps/studio/client/panels/ChatPanel.jsx +15 -33
- package/apps/studio/client/panels/GitPanel.jsx +8 -0
- package/apps/studio/client/panels/IntroVideoDialog.jsx +44 -0
- package/apps/studio/client/panels/OnboardingWizard.jsx +12 -0
- package/apps/studio/client/panels/ReadinessList.jsx +227 -7
- package/apps/studio/client/panels/RepoBranchSwitcher.jsx +133 -21
- package/apps/studio/client/panels/SettingsPanel.jsx +828 -0
- package/apps/studio/client/panels/SetupChecklist.jsx +223 -0
- package/apps/studio/client/panels/StickerPicker.jsx +160 -0
- package/apps/studio/client/panels/TimelinePanel.jsx +15 -2
- package/apps/studio/client/photo-knobs.jsx +432 -0
- package/apps/studio/client/styles/3-shell-maude.css +376 -28
- package/apps/studio/client/styles/4-components.css +223 -0
- package/apps/studio/client/styles/6-acp-chat.css +86 -0
- package/apps/studio/client/tour/quick-setup-tour.js +39 -0
- package/apps/studio/commands/annotation-strokes-command.ts +13 -3
- package/apps/studio/commands/edit-source-command.ts +31 -4
- package/apps/studio/config.schema.json +70 -0
- package/apps/studio/context-menu.tsx +42 -8
- package/apps/studio/context.ts +16 -0
- package/apps/studio/design-setup-readiness.ts +115 -0
- package/apps/studio/dist/client.bundle.js +5572 -21
- package/apps/studio/dist/comment-mount.js +2 -2
- package/apps/studio/dist/runtime/.min-sizes.json +1 -0
- package/apps/studio/dist/runtime/@imgly_background-removal.js +5543 -0
- package/apps/studio/dist/runtime/pixi-js.js +519 -519
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/dom-selection.ts +25 -0
- package/apps/studio/draw/palette.ts +34 -0
- package/apps/studio/exporters/jobs.ts +47 -5
- package/apps/studio/exporters/video.ts +24 -4
- package/apps/studio/footage/schema.test.ts +287 -0
- package/apps/studio/footage/schema.ts +662 -0
- package/apps/studio/footage-store.ts +235 -0
- package/apps/studio/fs-watch.ts +10 -0
- package/apps/studio/generation/adapters/elevenlabs.ts +370 -0
- package/apps/studio/generation/adapters/gemini.ts +542 -0
- package/apps/studio/generation/adapters/groq.test.ts +80 -0
- package/apps/studio/generation/adapters/groq.ts +247 -0
- package/apps/studio/generation/audio-library.test.ts +95 -0
- package/apps/studio/generation/audio-library.ts +156 -0
- package/apps/studio/generation/captions.test.ts +78 -0
- package/apps/studio/generation/captions.ts +132 -0
- package/apps/studio/generation/download.ts +76 -0
- package/apps/studio/generation/elevenlabs.test.ts +223 -0
- package/apps/studio/generation/gemini.test.ts +350 -0
- package/apps/studio/generation/jobs.test.ts +128 -0
- package/apps/studio/generation/jobs.ts +243 -0
- package/apps/studio/generation/keys.test.ts +75 -0
- package/apps/studio/generation/keys.ts +162 -0
- package/apps/studio/generation/prefs.test.ts +95 -0
- package/apps/studio/generation/prefs.ts +82 -0
- package/apps/studio/generation/registry.ts +88 -0
- package/apps/studio/generation/types.test.ts +123 -0
- package/apps/studio/generation/types.ts +266 -0
- package/apps/studio/generation/whisper-models.test.ts +152 -0
- package/apps/studio/generation/whisper-models.ts +257 -0
- package/apps/studio/generation/whisper-spike-results.md +61 -0
- package/apps/studio/git/endpoints.ts +68 -7
- package/apps/studio/git/service.ts +199 -21
- package/apps/studio/github/service.ts +67 -0
- package/apps/studio/handoff.ts +3 -2
- package/apps/studio/http.ts +1039 -22
- package/apps/studio/input-router.tsx +10 -0
- package/apps/studio/inspect.ts +53 -1
- package/apps/studio/media/intro.mp4 +0 -0
- package/apps/studio/media-commit-chain.ts +119 -0
- package/apps/studio/paths.ts +20 -0
- package/apps/studio/photo/filters.ts +285 -0
- package/apps/studio/photo/pipeline.ts +607 -0
- package/apps/studio/photo/schema.ts +367 -0
- package/apps/studio/photo-store.ts +154 -0
- package/apps/studio/readiness.ts +108 -20
- package/apps/studio/runtime-bundle.ts +29 -6
- package/apps/studio/scaffold-design.ts +1145 -0
- package/apps/studio/server.ts +18 -2
- package/apps/studio/stickers/figjam-doodle/manifest.json +104 -0
- package/apps/studio/stickers/figjam-doodle/slice1.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice10.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice11.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice12.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice13.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice14.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice15.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice16.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice17.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice18.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice19.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice2.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice20.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice21.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice22.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice23.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice24.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice3.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice4.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice5.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice6.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice7.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice8.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice9.png +0 -0
- package/apps/studio/stickers/life-style/best.png +0 -0
- package/apps/studio/stickers/life-style/come-on.png +0 -0
- package/apps/studio/stickers/life-style/cut.png +0 -0
- package/apps/studio/stickers/life-style/detox.png +0 -0
- package/apps/studio/stickers/life-style/just.png +0 -0
- package/apps/studio/stickers/life-style/manifest.json +68 -0
- package/apps/studio/stickers/life-style/mirror.png +0 -0
- package/apps/studio/stickers/life-style/nice.png +0 -0
- package/apps/studio/stickers/life-style/objects.png +0 -0
- package/apps/studio/stickers/life-style/ok.png +0 -0
- package/apps/studio/stickers/life-style/queen.png +0 -0
- package/apps/studio/stickers/life-style/star.png +0 -0
- package/apps/studio/stickers/life-style/sun.png +0 -0
- package/apps/studio/stickers/life-style/water.png +0 -0
- package/apps/studio/stickers/life-style/yeah.png +0 -0
- package/apps/studio/stickers/life-style/you-can.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/check-the-deets.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/cut-it.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/dope.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/fresh.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/hot.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/idea.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/keep-exploring.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/killed-it.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/love-it.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/manifest.json +88 -0
- package/apps/studio/stickers/opposing-thoughts/not-sure.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/ok.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/pure-gold.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/save-for-later.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/steal-this.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/take-a-peek.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/this-or-that.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/thoughts.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/vibes.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/winner.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/wip.png +0 -0
- package/apps/studio/stickers/project-status/group-100.png +0 -0
- package/apps/studio/stickers/project-status/group-101.png +0 -0
- package/apps/studio/stickers/project-status/group-102.png +0 -0
- package/apps/studio/stickers/project-status/group-103.png +0 -0
- package/apps/studio/stickers/project-status/group-104.png +0 -0
- package/apps/studio/stickers/project-status/group-105.png +0 -0
- package/apps/studio/stickers/project-status/group-106.png +0 -0
- package/apps/studio/stickers/project-status/group-107.png +0 -0
- package/apps/studio/stickers/project-status/group-108.png +0 -0
- package/apps/studio/stickers/project-status/group-109.png +0 -0
- package/apps/studio/stickers/project-status/group-110.png +0 -0
- package/apps/studio/stickers/project-status/group-111.png +0 -0
- package/apps/studio/stickers/project-status/group-112.png +0 -0
- package/apps/studio/stickers/project-status/group-113.png +0 -0
- package/apps/studio/stickers/project-status/group-114.png +0 -0
- package/apps/studio/stickers/project-status/group-115.png +0 -0
- package/apps/studio/stickers/project-status/group-117.png +0 -0
- package/apps/studio/stickers/project-status/group-118.png +0 -0
- package/apps/studio/stickers/project-status/group-119.png +0 -0
- package/apps/studio/stickers/project-status/group-120.png +0 -0
- package/apps/studio/stickers/project-status/group-121.png +0 -0
- package/apps/studio/stickers/project-status/group-122.png +0 -0
- package/apps/studio/stickers/project-status/group-41.png +0 -0
- package/apps/studio/stickers/project-status/group-42.png +0 -0
- package/apps/studio/stickers/project-status/group-43.png +0 -0
- package/apps/studio/stickers/project-status/group-44.png +0 -0
- package/apps/studio/stickers/project-status/group-45.png +0 -0
- package/apps/studio/stickers/project-status/group-46.png +0 -0
- package/apps/studio/stickers/project-status/group-47.png +0 -0
- package/apps/studio/stickers/project-status/group-48.png +0 -0
- package/apps/studio/stickers/project-status/group-49.png +0 -0
- package/apps/studio/stickers/project-status/group-50.png +0 -0
- package/apps/studio/stickers/project-status/group-51.png +0 -0
- package/apps/studio/stickers/project-status/group-52.png +0 -0
- package/apps/studio/stickers/project-status/group-53.png +0 -0
- package/apps/studio/stickers/project-status/group-54.png +0 -0
- package/apps/studio/stickers/project-status/group-55.png +0 -0
- package/apps/studio/stickers/project-status/group-56.png +0 -0
- package/apps/studio/stickers/project-status/group-57.png +0 -0
- package/apps/studio/stickers/project-status/group-58.png +0 -0
- package/apps/studio/stickers/project-status/group-59.png +0 -0
- package/apps/studio/stickers/project-status/group-60.png +0 -0
- package/apps/studio/stickers/project-status/group-61.png +0 -0
- package/apps/studio/stickers/project-status/group-62.png +0 -0
- package/apps/studio/stickers/project-status/group-63.png +0 -0
- package/apps/studio/stickers/project-status/group-64.png +0 -0
- package/apps/studio/stickers/project-status/group-65.png +0 -0
- package/apps/studio/stickers/project-status/group-66.png +0 -0
- package/apps/studio/stickers/project-status/group-67.png +0 -0
- package/apps/studio/stickers/project-status/group-68.png +0 -0
- package/apps/studio/stickers/project-status/group-69.png +0 -0
- package/apps/studio/stickers/project-status/group-70.png +0 -0
- package/apps/studio/stickers/project-status/group-71.png +0 -0
- package/apps/studio/stickers/project-status/group-72.png +0 -0
- package/apps/studio/stickers/project-status/group-73.png +0 -0
- package/apps/studio/stickers/project-status/group-74.png +0 -0
- package/apps/studio/stickers/project-status/group-75.png +0 -0
- package/apps/studio/stickers/project-status/group-76.png +0 -0
- package/apps/studio/stickers/project-status/group-77.png +0 -0
- package/apps/studio/stickers/project-status/group-78.png +0 -0
- package/apps/studio/stickers/project-status/group-79.png +0 -0
- package/apps/studio/stickers/project-status/group-80.png +0 -0
- package/apps/studio/stickers/project-status/group-81.png +0 -0
- package/apps/studio/stickers/project-status/group-82.png +0 -0
- package/apps/studio/stickers/project-status/group-83.png +0 -0
- package/apps/studio/stickers/project-status/group-84.png +0 -0
- package/apps/studio/stickers/project-status/group-85.png +0 -0
- package/apps/studio/stickers/project-status/group-86.png +0 -0
- package/apps/studio/stickers/project-status/group-87.png +0 -0
- package/apps/studio/stickers/project-status/group-88.png +0 -0
- package/apps/studio/stickers/project-status/group-89.png +0 -0
- package/apps/studio/stickers/project-status/group-90.png +0 -0
- package/apps/studio/stickers/project-status/group-91.png +0 -0
- package/apps/studio/stickers/project-status/group-92.png +0 -0
- package/apps/studio/stickers/project-status/group-93.png +0 -0
- package/apps/studio/stickers/project-status/group-94.png +0 -0
- package/apps/studio/stickers/project-status/group-96.png +0 -0
- package/apps/studio/stickers/project-status/group-97.png +0 -0
- package/apps/studio/stickers/project-status/group-98.png +0 -0
- package/apps/studio/stickers/project-status/group-99.png +0 -0
- package/apps/studio/stickers/project-status/manifest.json +328 -0
- package/apps/studio/test/_helpers.ts +15 -2
- package/apps/studio/test/acp-bootstrap-brief.test.ts +11 -0
- package/apps/studio/test/acp-bridge.test.ts +34 -1
- package/apps/studio/test/acp-commands.test.ts +2 -1
- package/apps/studio/test/acp-env.test.ts +30 -0
- package/apps/studio/test/acp-plugin-bootstrap.test.ts +23 -57
- package/apps/studio/test/acp-session-plugins.test.ts +72 -1
- package/apps/studio/test/annotation-strokes-command.test.ts +17 -0
- package/apps/studio/test/annotations-layer.test.ts +174 -0
- package/apps/studio/test/asset-api.test.ts +3 -3
- package/apps/studio/test/canvas-edit.test.ts +17 -6
- package/apps/studio/test/canvas-origin-gate.test.ts +50 -0
- package/apps/studio/test/csp-canvas-shell.test.ts +11 -0
- package/apps/studio/test/csrf-write-guard.test.ts +23 -1
- package/apps/studio/test/design-setup-readiness.test.ts +155 -0
- package/apps/studio/test/dynamic-text-edit.test.ts +162 -0
- package/apps/studio/test/edit-source-command.test.ts +23 -0
- package/apps/studio/test/element-structural-edit.test.ts +154 -0
- package/apps/studio/test/fixtures/fake-claude-auth.mjs +13 -0
- package/apps/studio/test/footage-store.test.ts +100 -0
- package/apps/studio/test/generate-route.test.ts +106 -0
- package/apps/studio/test/git-branches.test.ts +97 -0
- package/apps/studio/test/github-api.test.ts +56 -1
- package/apps/studio/test/import-asset-browser.test.ts +64 -0
- package/apps/studio/test/import-asset-route.test.ts +71 -0
- package/apps/studio/test/import-asset.test.ts +399 -0
- package/apps/studio/test/import-brand-browser.test.ts +88 -0
- package/apps/studio/test/import-brand-route.test.ts +120 -0
- package/apps/studio/test/import-brand.test.ts +206 -0
- package/apps/studio/test/import-tokens.test.ts +722 -0
- package/apps/studio/test/input-router.test.ts +33 -0
- package/apps/studio/test/inspect-script-syntax.test.ts +53 -0
- package/apps/studio/test/media-commit-chain.test.ts +210 -0
- package/apps/studio/test/photo-bg-remove-validation.test.ts +71 -0
- package/apps/studio/test/photo-canvas-bundle.test.ts +61 -0
- package/apps/studio/test/photo-edit-api.test.ts +201 -0
- package/apps/studio/test/photo-filters.test.ts +149 -0
- package/apps/studio/test/photo-pipeline.test.ts +106 -0
- package/apps/studio/test/photo-taxonomy.test.ts +96 -0
- package/apps/studio/test/read-annotations.test.ts +164 -0
- package/apps/studio/test/readiness.test.ts +13 -11
- package/apps/studio/test/scaffold-design.test.ts +122 -0
- package/apps/studio/test/shell-importmap.test.ts +49 -0
- package/apps/studio/test/text-editability-stamp.test.ts +131 -0
- package/apps/studio/test/timeline-parse.test.ts +57 -0
- package/apps/studio/test/tool-palette-insert-anchor.test.ts +5 -3
- package/apps/studio/test/tour-overlay.test.tsx +16 -0
- package/apps/studio/test/undo-stack.test.ts +33 -0
- package/apps/studio/test/video-asset.test.ts +5 -5
- package/apps/studio/test/video-render-bridge.test.ts +23 -1
- package/apps/studio/text-caret.ts +239 -0
- package/apps/studio/tool-palette.tsx +49 -21
- package/apps/studio/ui-prefs.ts +130 -0
- package/apps/studio/undo-stack.ts +94 -2
- package/apps/studio/use-annotation-resize.tsx +4 -4
- package/apps/studio/use-canvas-media-drop.tsx +40 -1
- package/apps/studio/use-chrome-visibility.tsx +8 -2
- package/apps/studio/use-selection-set.tsx +21 -0
- package/apps/studio/video-comp.tsx +48 -7
- package/apps/studio/whats-new.json +149 -0
- package/apps/studio/ws.ts +5 -0
- package/cli/bin/maude.mjs +6 -6
- package/cli/commands/design.mjs +67 -3
- package/cli/lib/gitignore-block.mjs +2 -0
- package/cli/lib/pkg-root.mjs +107 -0
- package/cli/lib/pkg-root.test.mjs +79 -0
- package/cli/lib/reconstruct-toolset.test.mjs +194 -0
- package/cli/lib/update-check.mjs +8 -0
- package/package.json +13 -11
- package/plugins/design/dependencies.json +18 -0
- package/plugins/design/templates/_shell.html +1 -0
|
@@ -859,6 +859,12 @@
|
|
|
859
859
|
}
|
|
860
860
|
.help-modal-body::-webkit-scrollbar { width: 6px; }
|
|
861
861
|
.help-modal-body::-webkit-scrollbar-thumb { background: var(--u-border); }
|
|
862
|
+
|
|
863
|
+
/* Watch-the-intro player (DDR-166 Phase 1 / T2) — wider modal, no padding
|
|
864
|
+
around the video so it fills edge-to-edge. */
|
|
865
|
+
.help-modal--wide { width: min(960px, 100%); }
|
|
866
|
+
.intro-video-body { padding: 0; overflow: hidden; }
|
|
867
|
+
.intro-video-el { display: block; width: 100%; aspect-ratio: 16 / 9; background: #000; }
|
|
862
868
|
.help-modal-body details {
|
|
863
869
|
margin: 0 0 var(--u-s-2);
|
|
864
870
|
border-bottom: 1px solid var(--u-border-subtle);
|
|
@@ -1652,3 +1658,220 @@
|
|
|
1652
1658
|
background: var(--u-accent);
|
|
1653
1659
|
color: var(--u-accent-fg);
|
|
1654
1660
|
}
|
|
1661
|
+
|
|
1662
|
+
/* ── Settings — AI generation (feature-ai-media-generation, DDR-16x) ─────── */
|
|
1663
|
+
.st-settings-intro {
|
|
1664
|
+
font-size: var(--type-xs, 12px);
|
|
1665
|
+
color: var(--fg-3);
|
|
1666
|
+
line-height: 1.5;
|
|
1667
|
+
margin: 6px 0 12px;
|
|
1668
|
+
}
|
|
1669
|
+
.st-settings-intro code {
|
|
1670
|
+
font-family: var(--font-mono);
|
|
1671
|
+
font-size: 0.92em;
|
|
1672
|
+
color: var(--fg-2);
|
|
1673
|
+
}
|
|
1674
|
+
.st-provider-card {
|
|
1675
|
+
border: 1px solid var(--border-default);
|
|
1676
|
+
border-radius: var(--radius-sm);
|
|
1677
|
+
background: var(--bg-2);
|
|
1678
|
+
padding: 12px;
|
|
1679
|
+
margin-bottom: 10px;
|
|
1680
|
+
}
|
|
1681
|
+
.st-provider-hd {
|
|
1682
|
+
display: flex;
|
|
1683
|
+
align-items: center;
|
|
1684
|
+
gap: 8px;
|
|
1685
|
+
}
|
|
1686
|
+
.st-provider-name {
|
|
1687
|
+
font-family: var(--font-mono);
|
|
1688
|
+
font-size: var(--type-sm, 13px);
|
|
1689
|
+
color: var(--fg-1);
|
|
1690
|
+
font-weight: 600;
|
|
1691
|
+
}
|
|
1692
|
+
.st-provider-card .st-pill {
|
|
1693
|
+
display: inline-flex;
|
|
1694
|
+
align-items: center;
|
|
1695
|
+
gap: 3px;
|
|
1696
|
+
font-size: 10px;
|
|
1697
|
+
text-transform: uppercase;
|
|
1698
|
+
letter-spacing: 0.03em;
|
|
1699
|
+
color: var(--fg-3);
|
|
1700
|
+
border: 1px solid var(--border-default);
|
|
1701
|
+
border-radius: var(--radius-pill, 999px);
|
|
1702
|
+
padding: 1px 7px;
|
|
1703
|
+
}
|
|
1704
|
+
.st-provider-card .st-pill.is-local {
|
|
1705
|
+
color: var(--accent);
|
|
1706
|
+
border-color: var(--accent-muted, var(--accent));
|
|
1707
|
+
}
|
|
1708
|
+
.st-provider-configured {
|
|
1709
|
+
display: inline-flex;
|
|
1710
|
+
align-items: center;
|
|
1711
|
+
gap: 3px;
|
|
1712
|
+
margin-left: auto;
|
|
1713
|
+
font-size: 11px;
|
|
1714
|
+
color: var(--accent);
|
|
1715
|
+
}
|
|
1716
|
+
.st-provider-modalities {
|
|
1717
|
+
font-family: var(--font-mono);
|
|
1718
|
+
font-size: 11px;
|
|
1719
|
+
color: var(--fg-3);
|
|
1720
|
+
margin-top: 4px;
|
|
1721
|
+
}
|
|
1722
|
+
.st-provider-notes {
|
|
1723
|
+
font-size: 11px;
|
|
1724
|
+
color: var(--fg-3);
|
|
1725
|
+
line-height: 1.5;
|
|
1726
|
+
margin-top: 6px;
|
|
1727
|
+
}
|
|
1728
|
+
.st-provider-keylink {
|
|
1729
|
+
display: inline-flex;
|
|
1730
|
+
align-items: center;
|
|
1731
|
+
gap: 4px;
|
|
1732
|
+
font-size: 11px;
|
|
1733
|
+
color: var(--accent);
|
|
1734
|
+
text-decoration: none;
|
|
1735
|
+
margin-top: 6px;
|
|
1736
|
+
}
|
|
1737
|
+
.st-provider-keylink:hover {
|
|
1738
|
+
text-decoration: underline;
|
|
1739
|
+
}
|
|
1740
|
+
.st-provider-keyrow {
|
|
1741
|
+
display: flex;
|
|
1742
|
+
align-items: center;
|
|
1743
|
+
gap: 6px;
|
|
1744
|
+
margin-top: 10px;
|
|
1745
|
+
}
|
|
1746
|
+
.st-provider-keyinput {
|
|
1747
|
+
flex: 1;
|
|
1748
|
+
min-width: 0;
|
|
1749
|
+
}
|
|
1750
|
+
.st-provider-status {
|
|
1751
|
+
font-size: 11px;
|
|
1752
|
+
margin-top: 6px;
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
/* ── Transcription-engine selector (Task 2.6) ───────────────────────────── */
|
|
1756
|
+
.st-engine-radios {
|
|
1757
|
+
display: flex;
|
|
1758
|
+
flex-direction: column;
|
|
1759
|
+
gap: 6px;
|
|
1760
|
+
margin-top: 10px;
|
|
1761
|
+
}
|
|
1762
|
+
.st-engine-radio {
|
|
1763
|
+
display: flex;
|
|
1764
|
+
align-items: flex-start;
|
|
1765
|
+
gap: 9px;
|
|
1766
|
+
padding: 9px 11px;
|
|
1767
|
+
border: 1px solid var(--border-default);
|
|
1768
|
+
border-radius: var(--radius-sm);
|
|
1769
|
+
background: var(--bg-1);
|
|
1770
|
+
cursor: pointer;
|
|
1771
|
+
}
|
|
1772
|
+
.st-engine-radio.is-selected {
|
|
1773
|
+
border-color: var(--accent);
|
|
1774
|
+
background: var(--bg-2);
|
|
1775
|
+
}
|
|
1776
|
+
.st-engine-radio input {
|
|
1777
|
+
margin-top: 2px;
|
|
1778
|
+
accent-color: var(--accent);
|
|
1779
|
+
}
|
|
1780
|
+
.st-engine-radio-body {
|
|
1781
|
+
display: flex;
|
|
1782
|
+
flex-direction: column;
|
|
1783
|
+
gap: 2px;
|
|
1784
|
+
}
|
|
1785
|
+
.st-engine-radio-label {
|
|
1786
|
+
font-size: var(--type-sm, 13px);
|
|
1787
|
+
color: var(--fg-1);
|
|
1788
|
+
font-weight: 600;
|
|
1789
|
+
}
|
|
1790
|
+
.st-engine-radio-note {
|
|
1791
|
+
font-size: 11px;
|
|
1792
|
+
color: var(--fg-3);
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
/* ── Local whisper model download (Task 2.7) ────────────────────────────── */
|
|
1796
|
+
.st-model-list {
|
|
1797
|
+
display: flex;
|
|
1798
|
+
flex-direction: column;
|
|
1799
|
+
gap: 8px;
|
|
1800
|
+
margin-top: 10px;
|
|
1801
|
+
}
|
|
1802
|
+
.st-model-row {
|
|
1803
|
+
display: flex;
|
|
1804
|
+
align-items: flex-start;
|
|
1805
|
+
justify-content: space-between;
|
|
1806
|
+
gap: 10px;
|
|
1807
|
+
padding: 9px 11px;
|
|
1808
|
+
border: 1px solid var(--border-default);
|
|
1809
|
+
border-radius: var(--radius-sm);
|
|
1810
|
+
background: var(--bg-1);
|
|
1811
|
+
}
|
|
1812
|
+
.st-model-info {
|
|
1813
|
+
display: flex;
|
|
1814
|
+
flex-direction: column;
|
|
1815
|
+
gap: 3px;
|
|
1816
|
+
min-width: 0;
|
|
1817
|
+
}
|
|
1818
|
+
.st-model-label {
|
|
1819
|
+
display: flex;
|
|
1820
|
+
align-items: center;
|
|
1821
|
+
gap: 7px;
|
|
1822
|
+
flex-wrap: wrap;
|
|
1823
|
+
font-size: var(--type-sm, 13px);
|
|
1824
|
+
color: var(--fg-1);
|
|
1825
|
+
font-weight: 600;
|
|
1826
|
+
}
|
|
1827
|
+
.st-model-size {
|
|
1828
|
+
font-size: 11px;
|
|
1829
|
+
color: var(--fg-3);
|
|
1830
|
+
font-weight: 400;
|
|
1831
|
+
}
|
|
1832
|
+
.st-model-progress {
|
|
1833
|
+
font-size: 11px;
|
|
1834
|
+
color: var(--accent);
|
|
1835
|
+
font-variant-numeric: tabular-nums;
|
|
1836
|
+
}
|
|
1837
|
+
.st-model-actions {
|
|
1838
|
+
display: flex;
|
|
1839
|
+
align-items: center;
|
|
1840
|
+
gap: 8px;
|
|
1841
|
+
flex-shrink: 0;
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
/* ── Generate dialog (feature-ai-media-generation, DDR-16x) ─────────────── */
|
|
1845
|
+
.st-gen-prompt {
|
|
1846
|
+
width: 100%;
|
|
1847
|
+
resize: vertical;
|
|
1848
|
+
min-height: 60px;
|
|
1849
|
+
font-family: var(--font-sans, system-ui, sans-serif);
|
|
1850
|
+
margin-bottom: 10px;
|
|
1851
|
+
}
|
|
1852
|
+
.st-gen-go {
|
|
1853
|
+
color: var(--accent);
|
|
1854
|
+
border-color: var(--accent-muted, var(--accent));
|
|
1855
|
+
}
|
|
1856
|
+
.st-gen-result {
|
|
1857
|
+
display: flex;
|
|
1858
|
+
gap: 10px;
|
|
1859
|
+
align-items: flex-start;
|
|
1860
|
+
margin-top: 12px;
|
|
1861
|
+
padding: 10px;
|
|
1862
|
+
border: 1px solid var(--border-default);
|
|
1863
|
+
border-radius: var(--radius-sm);
|
|
1864
|
+
background: var(--bg-2);
|
|
1865
|
+
}
|
|
1866
|
+
.st-gen-thumb {
|
|
1867
|
+
width: 96px;
|
|
1868
|
+
height: 96px;
|
|
1869
|
+
object-fit: cover;
|
|
1870
|
+
border-radius: var(--radius-sm);
|
|
1871
|
+
background: var(--bg-3);
|
|
1872
|
+
}
|
|
1873
|
+
.st-gen-result-actions {
|
|
1874
|
+
display: flex;
|
|
1875
|
+
flex-direction: column;
|
|
1876
|
+
gap: 6px;
|
|
1877
|
+
}
|
|
@@ -1181,7 +1181,93 @@
|
|
|
1181
1181
|
}
|
|
1182
1182
|
.rdy-copy:hover { color: var(--fg-0); background: var(--bg-3); }
|
|
1183
1183
|
.rdy-foot { display: flex; justify-content: flex-end; }
|
|
1184
|
+
/* DDR-166 T0c/T0d — verbatim install command + Sign-in action rows. */
|
|
1185
|
+
.rdy-cmd {
|
|
1186
|
+
margin-top: var(--space-2); display: flex; gap: var(--space-2);
|
|
1187
|
+
align-items: center; flex-wrap: wrap;
|
|
1188
|
+
}
|
|
1189
|
+
.rdy-cmd-tx {
|
|
1190
|
+
font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-0);
|
|
1191
|
+
background: var(--bg-3); padding: var(--space-1) var(--space-2);
|
|
1192
|
+
border-radius: var(--radius-xs); overflow-wrap: anywhere; flex: 1 1 auto;
|
|
1193
|
+
}
|
|
1194
|
+
.rdy-fix-tx--err { color: var(--status-error); }
|
|
1195
|
+
.rdy-fallback-label { display: block; margin-top: var(--space-2); color: var(--fg-3); }
|
|
1196
|
+
/* DDR-166 Decision 3 — the resolved-binary disclosure shown before Sign-in. */
|
|
1197
|
+
.rdy-resolved-path { display: block; margin-top: var(--space-2); color: var(--fg-3); word-break: break-all; }
|
|
1198
|
+
.rdy-resolved-path code { font-family: var(--font-mono); color: var(--fg-1); }
|
|
1199
|
+
.rdy-signin {
|
|
1200
|
+
flex-shrink: 0; cursor: pointer;
|
|
1201
|
+
font-size: var(--type-xs); font-weight: 600; color: var(--bg-0);
|
|
1202
|
+
background: var(--accent); border: 1px solid var(--accent);
|
|
1203
|
+
border-radius: var(--radius-xs); padding: 3px 10px;
|
|
1204
|
+
}
|
|
1205
|
+
.rdy-signin:hover { filter: brightness(1.08); }
|
|
1184
1206
|
/* Help ▸ Check AI editing readiness… modal (reuses .help-modal chrome). */
|
|
1185
1207
|
.rdy-modal { max-width: 520px; }
|
|
1186
1208
|
.rdy-modal-note { margin: 0 0 var(--space-3); color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-md); }
|
|
1209
|
+
/* DDR-166 Decision 5 — auto-setup opt-out, mirrors .ob-crash-optin. */
|
|
1210
|
+
.rdy-autosetup-toggle { display: flex; align-items: flex-start; gap: var(--space-2); margin-top: var(--space-3); color: var(--fg-2); font-size: var(--type-xs); line-height: var(--lh-md); cursor: pointer; text-align: left; }
|
|
1211
|
+
.rdy-autosetup-toggle input { margin-top: 2px; flex: 0 0 auto; accent-color: var(--accent); cursor: pointer; }
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
/* DDR-166 plan, Phase 2 (T7/T8) — design-setup checklist (SetupChecklist.jsx).
|
|
1215
|
+
Mirrors .rdy-* above (same present/missing two-state shape, no remediation
|
|
1216
|
+
copy — this probe never offers an automated fix, just progress). */
|
|
1217
|
+
@layer components {
|
|
1218
|
+
.setup-cl { display: flex; flex-direction: column; gap: var(--space-3); }
|
|
1219
|
+
.setup-cl-list {
|
|
1220
|
+
list-style: none; margin: 0; padding: 0;
|
|
1221
|
+
display: flex; flex-direction: column; gap: var(--space-2);
|
|
1222
|
+
}
|
|
1223
|
+
.setup-cl-row {
|
|
1224
|
+
display: flex; gap: var(--space-2); align-items: flex-start;
|
|
1225
|
+
padding: var(--space-2) var(--space-3);
|
|
1226
|
+
border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
|
|
1227
|
+
background: var(--bg-2); text-align: left;
|
|
1228
|
+
}
|
|
1229
|
+
.setup-cl-ic { flex-shrink: 0; margin-top: 1px; }
|
|
1230
|
+
.setup-cl-row--present .setup-cl-ic { color: var(--status-success); }
|
|
1231
|
+
.setup-cl-row--missing .setup-cl-ic { color: var(--fg-3); }
|
|
1232
|
+
.setup-cl-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
1233
|
+
.setup-cl-label { font-size: var(--type-sm); font-weight: 600; color: var(--fg-0); }
|
|
1234
|
+
.setup-cl-detail { font-size: var(--type-xs); color: var(--fg-2); line-height: var(--lh-xs); }
|
|
1235
|
+
.setup-cl-foot { display: flex; justify-content: flex-end; gap: var(--space-2); flex-wrap: wrap; }
|
|
1236
|
+
.setup-cl-brand { text-decoration: none; }
|
|
1237
|
+
.setup-cl-modal { max-width: 520px; }
|
|
1238
|
+
.setup-cl-note { margin: 0 0 var(--space-3); color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-md); }
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
/* T12 (DDR-173) — the in-app Brand-upload panel (BrandUploadPanel.jsx).
|
|
1242
|
+
Reuses .help-modal-* chrome; new rules cover the pick/result content only. */
|
|
1243
|
+
@layer components {
|
|
1244
|
+
.brand-up-modal { max-width: 480px; }
|
|
1245
|
+
.brand-up-note { margin: 0 0 var(--space-4); color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-md); }
|
|
1246
|
+
.brand-up-pick { display: flex; justify-content: center; padding: var(--space-5) 0; }
|
|
1247
|
+
.brand-up-error { margin: var(--space-2) 0 0; color: var(--status-error); font-size: var(--type-sm); }
|
|
1248
|
+
.brand-up-empty { margin: 0; color: var(--fg-3); font-size: var(--type-xs); line-height: var(--lh-sm); }
|
|
1249
|
+
.brand-up-preview {
|
|
1250
|
+
display: block; max-width: 100%; max-height: 120px; margin: 0 auto var(--space-4);
|
|
1251
|
+
border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--bg-3);
|
|
1252
|
+
padding: var(--space-3);
|
|
1253
|
+
}
|
|
1254
|
+
.brand-up-sechd {
|
|
1255
|
+
margin: var(--space-4) 0 var(--space-2); font-size: var(--type-xs); font-weight: 600;
|
|
1256
|
+
text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-2);
|
|
1257
|
+
}
|
|
1258
|
+
.brand-up-swatches { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
|
|
1259
|
+
.brand-up-swatch { display: flex; align-items: center; gap: var(--space-2); }
|
|
1260
|
+
.brand-up-swatch-chip {
|
|
1261
|
+
display: inline-block; width: 20px; height: 20px; border-radius: var(--radius-xs);
|
|
1262
|
+
border: 1px solid var(--border-default);
|
|
1263
|
+
}
|
|
1264
|
+
.brand-up-swatch-value { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); }
|
|
1265
|
+
.brand-up-fonts { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
|
|
1266
|
+
.brand-up-font-chip {
|
|
1267
|
+
padding: 2px var(--space-2); border-radius: var(--radius-pill); border: 1px solid var(--border-default);
|
|
1268
|
+
background: var(--bg-2); font-size: var(--type-xs); color: var(--fg-1);
|
|
1269
|
+
}
|
|
1270
|
+
.brand-up-nextstep { margin: var(--space-4) 0 0; font-size: var(--type-sm); color: var(--fg-1); line-height: var(--lh-md); }
|
|
1271
|
+
.brand-up-nextstep code { font-family: var(--font-mono); background: var(--bg-3); padding: 1px 4px; border-radius: var(--radius-xs); }
|
|
1272
|
+
.brand-up-actions { display: flex; gap: var(--space-2); margin-top: var(--space-3); }
|
|
1187
1273
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// quick-setup-tour.js — DDR-166 plan, Phase 2 (T7). The "empty → design system
|
|
2
|
+
// → first canvas → first AI edit" journey, on the existing tour engine
|
|
3
|
+
// (overlay.jsx), never a fork — same convention as usage-tour.js/collab-tour.js.
|
|
4
|
+
//
|
|
5
|
+
// Native, no-terminal posture (DDR-126/128): this deck can't execute
|
|
6
|
+
// `/design:setup-ds` for the user (the canvas iframe is cross-origin — DDR-054 —
|
|
7
|
+
// and the shell has no terminal). It coach-marks the Assistant panel instead:
|
|
8
|
+
// point at it, tell the user what to type, let THEM send it. The terminal
|
|
9
|
+
// `/design:*` path stays the power-user route.
|
|
10
|
+
|
|
11
|
+
export const QUICK_SETUP_TOUR = [
|
|
12
|
+
{
|
|
13
|
+
// Centered, no target — the overview step.
|
|
14
|
+
title: "Let's get you set up",
|
|
15
|
+
body: 'Three short steps: a design system for your brand, a first canvas, then your first AI edit. Everything after this happens right here — no terminal.',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
target: "[data-tour='sidebar']",
|
|
19
|
+
title: 'Your canvases will live here',
|
|
20
|
+
body: "Empty for now. Once you have a design system, this fills up with real screens — click any one to open it.",
|
|
21
|
+
placement: 'right',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
target: "[data-testid='assistant-toggle']",
|
|
25
|
+
title: 'Ask the Assistant to build your design system',
|
|
26
|
+
body: 'Open the Assistant and describe your brand — colors, type, the vibe you want. It sets up a real design system for you. Already have one? Say so and it can bring it in.',
|
|
27
|
+
placement: 'left',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
target: "[data-tour='viewport']",
|
|
31
|
+
title: 'Your first canvas appears here',
|
|
32
|
+
body: "Once the design system is ready, ask for a first screen and watch it land right in this space, ready to edit.",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
// Centered — the close-out step.
|
|
36
|
+
title: "You're ready",
|
|
37
|
+
body: 'Hold ⌘ and click anything on a canvas to point at it, describe the change in the Assistant, and watch it update live. Restart this tour any time from Help ▸ Quick setup.',
|
|
38
|
+
},
|
|
39
|
+
];
|
|
@@ -27,8 +27,18 @@ import { registerCommand } from '../undo-stack.ts';
|
|
|
27
27
|
* Push-once callable that submits a full `Stroke[]` to the server (or its
|
|
28
28
|
* test stub) AND updates the iframe's local strokes state. The
|
|
29
29
|
* annotations-layer `putStrokes` is the production binding.
|
|
30
|
+
*
|
|
31
|
+
* `before` is the baseline THIS command's `next` was computed from — passed
|
|
32
|
+
* through so the consumer can distinguish "an id `prev` still has that
|
|
33
|
+
* `before` already lacked too" (a genuinely concurrent addition, fold it in)
|
|
34
|
+
* from "an id `before` had that `next` deliberately dropped" (this command's
|
|
35
|
+
* own delete — must stay dropped even if React's rendered state hasn't
|
|
36
|
+
* caught up yet). See `reconcileCommit` in annotations-layer.tsx.
|
|
30
37
|
*/
|
|
31
|
-
export type StrokesPutFn = (
|
|
38
|
+
export type StrokesPutFn = (
|
|
39
|
+
next: readonly Stroke[],
|
|
40
|
+
before: readonly Stroke[]
|
|
41
|
+
) => void | Promise<void>;
|
|
32
42
|
|
|
33
43
|
export interface AnnotationStrokesPayload {
|
|
34
44
|
before: readonly Stroke[];
|
|
@@ -58,10 +68,10 @@ export function createAnnotationStrokesCommand(init: AnnotationStrokesCommandIni
|
|
|
58
68
|
kind,
|
|
59
69
|
label,
|
|
60
70
|
async do() {
|
|
61
|
-
await putFn(after.map(cloneStroke));
|
|
71
|
+
await putFn(after.map(cloneStroke), before.map(cloneStroke));
|
|
62
72
|
},
|
|
63
73
|
async undo() {
|
|
64
|
-
await putFn(before.map(cloneStroke));
|
|
74
|
+
await putFn(before.map(cloneStroke), after.map(cloneStroke));
|
|
65
75
|
},
|
|
66
76
|
};
|
|
67
77
|
}
|
|
@@ -46,6 +46,14 @@ export interface EditSourcePayload {
|
|
|
46
46
|
before: string | null;
|
|
47
47
|
/** Value after the edit. `null` = the edit removed the prop/attr (the reset path). */
|
|
48
48
|
after: string | null;
|
|
49
|
+
/**
|
|
50
|
+
* `op:'text'` only — which rendered instance this edit targeted (index among
|
|
51
|
+
* same-cd-id DOM nodes). Needed to re-apply a `{variable}` text edit through
|
|
52
|
+
* undo/redo: the engine traces the string back to the right `.map()` item or
|
|
53
|
+
* component-prop usage, and that resolution needs the occurrence. Undefined
|
|
54
|
+
* for literal text (the engine ignores it there) and for css/attr.
|
|
55
|
+
*/
|
|
56
|
+
occurrence?: number;
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
/**
|
|
@@ -60,6 +68,14 @@ export type EditSourceApplyFn = (apply: {
|
|
|
60
68
|
id: string;
|
|
61
69
|
key: string;
|
|
62
70
|
value: string | null;
|
|
71
|
+
/**
|
|
72
|
+
* `op:'text'` re-application only — the value CURRENTLY on disk (the side we
|
|
73
|
+
* replace FROM: `before` on redo, `after` on undo), so a `{variable}` edit
|
|
74
|
+
* can be traced to the right source string. Plus the occurrence. Ignored by
|
|
75
|
+
* css/attr and by literal-text edits.
|
|
76
|
+
*/
|
|
77
|
+
from?: string | null;
|
|
78
|
+
occurrence?: number;
|
|
63
79
|
}) => void | Promise<void>;
|
|
64
80
|
|
|
65
81
|
export const EDIT_SOURCE_KIND = 'edit-source';
|
|
@@ -72,16 +88,27 @@ export interface EditSourceCommandInit {
|
|
|
72
88
|
|
|
73
89
|
export function createEditSourceCommand(init: EditSourceCommandInit): EditCommand {
|
|
74
90
|
const { payload, applyFn } = init;
|
|
75
|
-
|
|
76
|
-
|
|
91
|
+
// `from` = the value on disk BEFORE this re-application (what a `{variable}`
|
|
92
|
+
// text resolver matches against). do() writes `after` over `before`; undo()
|
|
93
|
+
// writes `before` over `after`.
|
|
94
|
+
const apply = (value: string | null, from: string | null) =>
|
|
95
|
+
applyFn({
|
|
96
|
+
op: payload.op,
|
|
97
|
+
canvas: payload.canvas,
|
|
98
|
+
id: payload.id,
|
|
99
|
+
key: payload.key,
|
|
100
|
+
value,
|
|
101
|
+
from,
|
|
102
|
+
occurrence: payload.occurrence,
|
|
103
|
+
});
|
|
77
104
|
return {
|
|
78
105
|
kind: EDIT_SOURCE_KIND,
|
|
79
106
|
label: init.label ?? defaultLabel(payload),
|
|
80
107
|
async do() {
|
|
81
|
-
await apply(payload.after);
|
|
108
|
+
await apply(payload.after, payload.before);
|
|
82
109
|
},
|
|
83
110
|
async undo() {
|
|
84
|
-
await apply(payload.before);
|
|
111
|
+
await apply(payload.before, payload.after);
|
|
85
112
|
},
|
|
86
113
|
};
|
|
87
114
|
}
|
|
@@ -231,6 +231,76 @@
|
|
|
231
231
|
}
|
|
232
232
|
},
|
|
233
233
|
"additionalProperties": false
|
|
234
|
+
},
|
|
235
|
+
"generation": {
|
|
236
|
+
"type": "object",
|
|
237
|
+
"description": "BYOK AI-media generation preferences (feature-ai-media-generation, DDR-16x). NON-SECRET ONLY — provider API keys are NEVER in this committed config; they live in the OS keychain (native) or ~/.config/maude/keys.json mode 0600 (browser). This block only carries routing/UI preferences. Hot-reloadable — Settings saves take effect without a server restart.",
|
|
238
|
+
"properties": {
|
|
239
|
+
"defaultImageProvider": {
|
|
240
|
+
"type": "string",
|
|
241
|
+
"description": "Provider id used when an image-generation request leaves the provider unspecified (e.g. 'gemini'). Must be a registered provider that supports the image modality.",
|
|
242
|
+
"default": "gemini"
|
|
243
|
+
},
|
|
244
|
+
"defaultAudioProvider": {
|
|
245
|
+
"type": "string",
|
|
246
|
+
"description": "Provider id used when an audio-generation request (music / sfx / voiceover) leaves the provider unspecified. Must be a registered provider that supports the audio modality (v1: 'elevenlabs').",
|
|
247
|
+
"default": "elevenlabs"
|
|
248
|
+
},
|
|
249
|
+
"defaultModels": {
|
|
250
|
+
"type": "object",
|
|
251
|
+
"description": "Per-provider default model id (e.g. { \"gemini\": \"gemini-2.5-flash-image\" }). Used when a request leaves the model unspecified.",
|
|
252
|
+
"additionalProperties": { "type": "string" },
|
|
253
|
+
"default": {}
|
|
254
|
+
},
|
|
255
|
+
"preferLocalWhenAvailable": {
|
|
256
|
+
"type": "boolean",
|
|
257
|
+
"description": "When a local runtime (Ollama / ComfyUI / Draw Things, post-v1) is detected on loopback, prefer it over a cloud provider for the same modality (free, offline, private). Inert until local engines ship (Phase 5).",
|
|
258
|
+
"default": false
|
|
259
|
+
},
|
|
260
|
+
"transcription": {
|
|
261
|
+
"type": "object",
|
|
262
|
+
"description": "Speech-to-text / subtitle engine preference (Task 2.6, DDR-164). The engine is an EXPLICIT user choice, never an automatic fallback: a chosen-but-unavailable engine errors clearly and Maude never silently switches to another. `maude design transcribe --provider` overrides this per-call.",
|
|
263
|
+
"properties": {
|
|
264
|
+
"provider": {
|
|
265
|
+
"type": "string",
|
|
266
|
+
"enum": ["whisper", "elevenlabs", "groq"],
|
|
267
|
+
"description": "Which engine transcribes when no --provider flag is given. `whisper` = local whisper.cpp (free, offline, no key); `elevenlabs` = ElevenLabs Scribe (cloud, key); `groq` = Groq Whisper (cloud, key). Absent ⇒ whisper.",
|
|
268
|
+
"default": "whisper"
|
|
269
|
+
},
|
|
270
|
+
"model": {
|
|
271
|
+
"type": "string",
|
|
272
|
+
"description": "Optional engine-specific model id override (e.g. a Groq 'whisper-large-v3-turbo', an ElevenLabs 'scribe_v1', or a local ggml model name). Absent ⇒ the engine's own default."
|
|
273
|
+
},
|
|
274
|
+
"whisperModel": {
|
|
275
|
+
"type": "string",
|
|
276
|
+
"enum": ["tiny", "base", "base.en", "small", "large-v3-turbo"],
|
|
277
|
+
"description": "Preferred managed local whisper.cpp model id (Task 2.7). Downloaded via Settings → Subtitles → 'Download model' into a per-machine cache; `maude design transcribe --provider whisper` auto-resolves it (no --model). Absent ⇒ any downloaded multilingual model. 'base' is the recommended default; '.en' variants are English-only."
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
"additionalProperties": false
|
|
281
|
+
},
|
|
282
|
+
"providers": {
|
|
283
|
+
"type": "object",
|
|
284
|
+
"description": "Per-provider non-secret toggles keyed by provider id. `enabled: false` hides a provider from the generate UI even if a key is present. `localEndpoint` overrides the default host:port for a local runtime.",
|
|
285
|
+
"additionalProperties": {
|
|
286
|
+
"type": "object",
|
|
287
|
+
"properties": {
|
|
288
|
+
"enabled": {
|
|
289
|
+
"type": "boolean",
|
|
290
|
+
"description": "Whether this provider is offered in the generate UI. Default true.",
|
|
291
|
+
"default": true
|
|
292
|
+
},
|
|
293
|
+
"localEndpoint": {
|
|
294
|
+
"type": "string",
|
|
295
|
+
"description": "Override host:port for a local runtime provider (e.g. '127.0.0.1:11434' for Ollama). Ignored for cloud providers."
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
"additionalProperties": false
|
|
299
|
+
},
|
|
300
|
+
"default": {}
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
"additionalProperties": false
|
|
234
304
|
}
|
|
235
305
|
}
|
|
236
306
|
}
|
|
@@ -54,7 +54,12 @@ export interface MenuItem {
|
|
|
54
54
|
/** Right-aligned shortcut hint (e.g. `⌘C`, `⌫`). */
|
|
55
55
|
shortcut?: string;
|
|
56
56
|
destructive?: boolean;
|
|
57
|
-
|
|
57
|
+
/**
|
|
58
|
+
* A FUNCTION form is resolved per-click against `target` — same rationale as
|
|
59
|
+
* the function-form `submenu` below (e.g. "Open Timeline" only enabled when
|
|
60
|
+
* THIS right-clicked artboard actually contains a video sequence).
|
|
61
|
+
*/
|
|
62
|
+
disabled?: boolean | ((target: ContextTarget) => boolean);
|
|
58
63
|
/**
|
|
59
64
|
* Optional nested flyout (e.g. `Theme ▸ DS default / Light / Dark / Follow
|
|
60
65
|
* chrome`). When present the row opens a submenu on hover / ArrowRight /
|
|
@@ -70,6 +75,13 @@ export interface MenuItem {
|
|
|
70
75
|
submenu?: MenuItem[] | ((target: ContextTarget) => MenuItem[]);
|
|
71
76
|
/** Hover/title hint shown when the item is `disabled` (a11y affordance). */
|
|
72
77
|
disabledHint?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Fully REMOVE the item for a target (vs. `disabled`, which greys it in place).
|
|
80
|
+
* Resolved per-click. Use when an entry is meaningless — not merely
|
|
81
|
+
* unavailable — for the right-clicked element (e.g. "Edit Photo…" only makes
|
|
82
|
+
* sense on an `<img>`, so it shouldn't appear at all on a `<div>`).
|
|
83
|
+
*/
|
|
84
|
+
hidden?: boolean | ((target: ContextTarget) => boolean);
|
|
73
85
|
onSelect: (target: ContextTarget) => void;
|
|
74
86
|
}
|
|
75
87
|
|
|
@@ -204,10 +216,19 @@ const MENU_CSS = `
|
|
|
204
216
|
font: inherit;
|
|
205
217
|
color: inherit;
|
|
206
218
|
}
|
|
207
|
-
.dc-context-menu .dc-menu-item:hover
|
|
219
|
+
.dc-context-menu .dc-menu-item:hover {
|
|
220
|
+
background: color-mix(in oklab, var(--maude-chrome-fg-0, #1c1917) 8%, transparent);
|
|
221
|
+
}
|
|
208
222
|
.dc-context-menu .dc-menu-item:focus-visible {
|
|
223
|
+
/* fix-photo-editor-followup-debt Task 16 — was outline: none (an
|
|
224
|
+
~1.05:1-contrast, effectively invisible focus ring). Reuses
|
|
225
|
+
--maude-hud-accent (canvas-lib.tsx's own established focus-visible
|
|
226
|
+
token for this chrome family — artboard labels, zoom toolbar) rather
|
|
227
|
+
than inventing a new one; -2px inset offset matches that same
|
|
228
|
+
convention for a control inside a bordered container. */
|
|
209
229
|
background: color-mix(in oklab, var(--maude-chrome-fg-0, #1c1917) 8%, transparent);
|
|
210
|
-
outline:
|
|
230
|
+
outline: 2px solid var(--maude-hud-accent, #d63b1f);
|
|
231
|
+
outline-offset: -2px;
|
|
211
232
|
}
|
|
212
233
|
.dc-context-menu .dc-menu-item[disabled] {
|
|
213
234
|
opacity: 0.45;
|
|
@@ -371,9 +392,19 @@ export function ContextMenuView({
|
|
|
371
392
|
};
|
|
372
393
|
}, [target.clientX, target.clientY, onClose, pos.x, pos.y]);
|
|
373
394
|
|
|
395
|
+
// Resolve per-target `hidden` and drop now-empty sections (so a section that
|
|
396
|
+
// held only a hidden item doesn't leave a dangling separator).
|
|
397
|
+
const visibleSections = sections
|
|
398
|
+
.map((section) =>
|
|
399
|
+
section.filter((item) => {
|
|
400
|
+
const h = typeof item.hidden === 'function' ? item.hidden(target) : item.hidden;
|
|
401
|
+
return !h;
|
|
402
|
+
})
|
|
403
|
+
)
|
|
404
|
+
.filter((section) => section.length > 0);
|
|
374
405
|
return (
|
|
375
406
|
<div ref={ref} className="dc-context-menu" role="menu" style={{ left: pos.x, top: pos.y }}>
|
|
376
|
-
{
|
|
407
|
+
{visibleSections.map((section, si) => {
|
|
377
408
|
const sectionKey = section.map((i) => i.id).join('|') || `s${si}`;
|
|
378
409
|
return (
|
|
379
410
|
<div key={sectionKey} role="group">
|
|
@@ -411,17 +442,20 @@ function MenuItemRow({
|
|
|
411
442
|
// Resolve a function-form submenu against THIS click's target (e.g.
|
|
412
443
|
// "Select layer" computing candidates from `target.clientX/clientY`).
|
|
413
444
|
const submenuItems = typeof item.submenu === 'function' ? item.submenu(target) : item.submenu;
|
|
445
|
+
// Same per-click resolution for a function-form `disabled` (e.g. "Open
|
|
446
|
+
// Timeline" only enabled on an artboard that actually contains video).
|
|
447
|
+
const disabled = typeof item.disabled === 'function' ? item.disabled(target) : item.disabled;
|
|
414
448
|
|
|
415
449
|
if (!submenuItems || submenuItems.length === 0) {
|
|
416
450
|
return (
|
|
417
451
|
<button
|
|
418
452
|
type="button"
|
|
419
453
|
role="menuitem"
|
|
420
|
-
disabled={
|
|
421
|
-
title={
|
|
454
|
+
disabled={disabled}
|
|
455
|
+
title={disabled ? item.disabledHint : undefined}
|
|
422
456
|
className={`dc-menu-item${item.destructive ? ' is-destructive' : ''}`}
|
|
423
457
|
onClick={() => {
|
|
424
|
-
if (
|
|
458
|
+
if (disabled) return;
|
|
425
459
|
item.onSelect(target);
|
|
426
460
|
onClose();
|
|
427
461
|
}}
|
|
@@ -464,7 +498,7 @@ function MenuItemRow({
|
|
|
464
498
|
role="menuitem"
|
|
465
499
|
aria-haspopup="menu"
|
|
466
500
|
aria-expanded={subOpen}
|
|
467
|
-
disabled={
|
|
501
|
+
disabled={disabled}
|
|
468
502
|
className="dc-menu-item"
|
|
469
503
|
onClick={() => (subOpen ? setSubOpen(false) : open())}
|
|
470
504
|
onKeyDown={(e) => {
|
package/apps/studio/context.ts
CHANGED
|
@@ -55,9 +55,25 @@ export interface DevServerConfig {
|
|
|
55
55
|
newCanvasDir: string;
|
|
56
56
|
newComponentDir: string;
|
|
57
57
|
linkedHub?: LinkedHub;
|
|
58
|
+
/**
|
|
59
|
+
* feature-ai-media-generation (DDR-16x) — BYOK generation preferences.
|
|
60
|
+
* NON-SECRET ONLY: provider keys live in the OS keychain / ~/.config/maude/
|
|
61
|
+
* keys.json (0600), NEVER here. Hot-reloadable via the full in-place cfg swap
|
|
62
|
+
* in reloadConfig (only designRoot + linkedHub are boot-pinned). See
|
|
63
|
+
* config.schema.json for the field contract.
|
|
64
|
+
*/
|
|
65
|
+
generation?: GenerationConfig;
|
|
58
66
|
_source: ConfigSource;
|
|
59
67
|
}
|
|
60
68
|
|
|
69
|
+
/** Non-secret AI-media generation preferences (DDR-16x). Keys are NOT here. */
|
|
70
|
+
export interface GenerationConfig {
|
|
71
|
+
defaultImageProvider?: string;
|
|
72
|
+
defaultModels?: Record<string, string>;
|
|
73
|
+
preferLocalWhenAvailable?: boolean;
|
|
74
|
+
providers?: Record<string, { enabled?: boolean; localEndpoint?: string }>;
|
|
75
|
+
}
|
|
76
|
+
|
|
61
77
|
const DEFAULT_CONFIG: Omit<DevServerConfig, '_source'> = {
|
|
62
78
|
name: 'Design',
|
|
63
79
|
projectLabel: null,
|