@dailies-studio/shot-editor 0.1.0 → 0.2.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/dist/.vite/manifest.json +382 -0
- package/dist/assets/AgentPanel-CQejLbiX.js +2 -0
- package/dist/assets/AgentPanel-DJEphah0.css +1 -0
- package/dist/assets/AgentQuestionDialog-BqkD0kXF.js +1 -0
- package/dist/assets/CodeStudio-Dv4ihHpz.js +23 -0
- package/dist/assets/CommentsPanel-B4yhhT1T.js +1 -0
- package/dist/assets/ComponentLibraryRail-Ch_dsAru.js +1 -0
- package/dist/assets/ComponentStage-BRhRotyH.js +1 -0
- package/dist/assets/CurvePane-BjFVabKX.css +1 -0
- package/dist/assets/CurvePane-R22WzllJ.js +1 -0
- package/dist/assets/ExportDialog-CWLQWTmG.js +2 -0
- package/dist/assets/FontPicker-DWKaYL7F.js +1 -0
- package/dist/assets/FontPicker-v0IOIArM.css +1 -0
- package/dist/assets/GenerateDrawer-Bh3SqDKt.js +2 -0
- package/dist/assets/InsertDrawer-Ce1fod1L.js +1 -0
- package/dist/assets/LibraryBrowser-D9sEGz5w.js +2 -0
- package/dist/assets/MakeItYoursSection-CMO4319_.js +2 -0
- package/dist/assets/MaterialGraphCanvas-BFzl4wWR.js +23 -0
- package/dist/assets/MaterialGraphCanvas-BIUD59ik.css +1 -0
- package/dist/assets/MaterialWorkspace-CqTWqaRA.js +14 -0
- package/dist/assets/PreferencesDialog-CBf9_OoD.js +1 -0
- package/dist/assets/PresetsSection-CUEaoCVU.js +1 -0
- package/dist/assets/SoundHistory-BeS8EW1h.js +1 -0
- package/dist/assets/SoundMode-BmcZru3i.js +3 -0
- package/dist/assets/StockSounds-DdAUGRYK.js +1 -0
- package/dist/assets/TemplateFieldSection-CaeXpLFo.js +1 -0
- package/dist/assets/VersionHistoryPanel-CxG6XhNP.js +1 -0
- package/dist/assets/board-B88EPuLO.css +1 -0
- package/dist/assets/board-CL-he7SL.js +3 -0
- package/dist/assets/components-0oOSPN0l.js +1 -0
- package/dist/assets/googleFontRanges-gp32wJMo.js +1 -0
- package/dist/assets/googleFonts-BNon6M7X.js +1 -0
- package/dist/assets/iconsAndAliases-DL7gXP5j.js +1863 -0
- package/dist/assets/index-4F5NQmI8.css +1 -0
- package/dist/assets/index-BGHQGV5z.js +117 -0
- package/dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/assets/libraryModel-CpIwfFha.js +1 -0
- package/dist/assets/lucide-6iK64tTB.js +9319 -0
- package/dist/assets/motionStamp-CH-Hew4E.js +1 -0
- package/dist/assets/takeMeasure-Tdg0TxEi.js +1 -0
- package/dist/assets/webmcp-BsB9gxWC.js +2 -0
- package/dist/index.html +34 -3
- package/package.json +12 -9
- package/src/addFamilies.ts +66 -0
- package/src/api.ts +1631 -55
- package/src/app/App.tsx +977 -198
- package/src/app/lazyPanel.tsx +137 -0
- package/src/app/lazySurfaces.tsx +203 -0
- package/src/audio/index.tsx +41 -10
- package/src/audio/meter.ts +485 -0
- package/src/audio/meterMath.ts +273 -0
- package/src/audio/meterStore.ts +155 -0
- package/src/audio/offlineMix.ts +289 -0
- package/src/audio/preview.ts +928 -118
- package/src/bridge.ts +15 -5
- package/src/bridgeTypes.ts +1611 -36
- package/src/channels.ts +17 -32
- package/src/fonts/googleFonts.ts +4 -0
- package/src/hostApi.ts +174 -0
- package/src/icons.tsx +770 -0
- package/src/layerWords.ts +61 -0
- package/src/main.tsx +56 -4
- package/src/panels/ResizeHandle.tsx +33 -43
- package/src/panels/agent/AgentDots.tsx +36 -0
- package/src/panels/agent/AgentPanel.tsx +119 -43
- package/src/panels/agent/AgentQuestionDialog.tsx +202 -0
- package/src/panels/agent/agent.css +113 -97
- package/src/panels/agent/agentGate.ts +35 -0
- package/src/panels/code/CodeDefaultsPanel.tsx +345 -0
- package/src/panels/code/CodeStudio.tsx +373 -0
- package/src/panels/code/FileTree.tsx +265 -0
- package/src/panels/code/codeBufferGuard.ts +52 -0
- package/src/panels/code/codeParts.tsx +321 -0
- package/src/panels/comments/CommentComposer.tsx +239 -0
- package/src/panels/comments/CommentThread.tsx +346 -0
- package/src/panels/comments/CommentsPanel.tsx +336 -0
- package/src/panels/comments/InboxButton.tsx +131 -0
- package/src/panels/comments/MentionMenu.tsx +98 -0
- package/src/panels/comments/parts.tsx +171 -0
- package/src/panels/export/ExportDialog.tsx +919 -96
- package/src/panels/export/ExportScrim.tsx +57 -0
- package/src/panels/files/AssetsTab.tsx +656 -0
- package/src/panels/files/FilePanel.tsx +1466 -216
- package/src/panels/files/LayerMarks.tsx +40 -0
- package/src/panels/files/LeftColumn.tsx +37 -0
- package/src/panels/files/McpSection.tsx +690 -47
- package/src/panels/files/MissingAssetsNotice.tsx +60 -0
- package/src/panels/files/assetDrag.ts +79 -0
- package/src/panels/files/resourceParts.tsx +255 -0
- package/src/panels/fonts/FontPicker.tsx +762 -0
- package/src/panels/fonts/faceCache.ts +207 -0
- package/src/panels/fonts/fontPicker.css +271 -0
- package/src/panels/fonts/pickerModel.ts +265 -0
- package/src/panels/fonts/pickerRequest.ts +46 -0
- package/src/panels/header/AccountAvatar.tsx +76 -0
- package/src/panels/header/AgentChip.tsx +77 -0
- package/src/panels/header/AppMenu.tsx +213 -0
- package/src/panels/header/Header.tsx +564 -84
- package/src/panels/header/HistoryControls.tsx +31 -5
- package/src/panels/header/PresenceStack.tsx +329 -0
- package/src/panels/header/ProjectTitle.tsx +232 -0
- package/src/panels/header/ShareButton.tsx +59 -0
- package/src/panels/header/StatusBadges.tsx +358 -27
- package/src/panels/header/SyncDeletedDialog.tsx +88 -0
- package/src/panels/header/ZoomControls.tsx +46 -15
- package/src/panels/header/agentHandoff.ts +52 -0
- package/src/panels/header/leave.ts +26 -0
- package/src/panels/help/HelpSection.tsx +189 -163
- package/src/panels/insert/InsertDrawer.tsx +723 -0
- package/src/panels/insert/iconSet.ts +109 -0
- package/src/panels/inspector/ExposeDot.tsx +117 -0
- package/src/panels/inspector/FramingRows.tsx +314 -44
- package/src/panels/inspector/InspectorFooter.tsx +91 -0
- package/src/panels/inspector/InspectorHead.tsx +425 -0
- package/src/panels/inspector/InspectorPanel.tsx +408 -124
- package/src/panels/inspector/KeyframeDot.tsx +373 -0
- package/src/panels/inspector/KeyframeSection.tsx +257 -0
- package/src/panels/inspector/MarkerSection.tsx +55 -11
- package/src/panels/inspector/ParamRow.tsx +84 -53
- package/src/panels/inspector/RightColumn.tsx +152 -0
- package/src/panels/inspector/TimeSection.tsx +866 -0
- package/src/panels/inspector/animate/EaseControl.tsx +244 -0
- package/src/panels/inspector/animate/PresetsSection.tsx +135 -0
- package/src/panels/inspector/animate/ShotSection.tsx +562 -48
- package/src/panels/inspector/design/AlignRow.tsx +95 -31
- package/src/panels/inspector/design/AppearanceSection.tsx +118 -9
- package/src/panels/inspector/design/ClonerSection.tsx +323 -62
- package/src/panels/inspector/design/ComponentSection.tsx +50 -43
- package/src/panels/inspector/design/CornerSection.tsx +45 -14
- package/src/panels/inspector/design/DefinitionProps.tsx +315 -0
- package/src/panels/inspector/design/DefinitionSection.tsx +136 -0
- package/src/panels/inspector/design/DeviceSection.tsx +210 -0
- package/src/panels/inspector/design/FillSection.tsx +83 -51
- package/src/panels/inspector/design/FontField.tsx +196 -0
- package/src/panels/inspector/design/HtmlSection.tsx +23 -12
- package/src/panels/inspector/design/InstanceSection.tsx +373 -154
- package/src/panels/inspector/design/MaskSection.tsx +84 -0
- package/src/panels/inspector/design/MaterialSection.tsx +177 -0
- package/src/panels/inspector/design/MediaSection.tsx +273 -120
- package/src/panels/inspector/design/MeshSection.tsx +910 -82
- package/src/panels/inspector/design/PaintRows.tsx +550 -0
- package/src/panels/inspector/design/PlateStyleSection.tsx +177 -0
- package/src/panels/inspector/design/ShadowSection.tsx +221 -48
- package/src/panels/inspector/design/SplineFollowSection.tsx +235 -0
- package/src/panels/inspector/design/StrokeSection.tsx +228 -43
- package/src/panels/inspector/design/TemplateFieldSection.tsx +57 -0
- package/src/panels/inspector/design/TransformSection.tsx +244 -50
- package/src/panels/inspector/design/TypographySection.tsx +679 -110
- package/src/panels/inspector/layout.ts +295 -0
- package/src/panels/inspector/propValue.ts +199 -0
- package/src/panels/inspector/scene/CameraSection.tsx +232 -22
- package/src/panels/inspector/scene/EffectsSection.tsx +722 -71
- package/src/panels/inspector/scene/MakeItYoursSection.tsx +180 -0
- package/src/panels/inspector/scene/SceneDocSection.tsx +191 -0
- package/src/panels/inspector/scene/SceneSection.tsx +219 -44
- package/src/panels/inspector/scene/TransitionSection.tsx +523 -72
- package/src/panels/inspector/storyboard/StoryboardReferenceSection.tsx +593 -0
- package/src/panels/inspector/storyboard/VideoStill.tsx +120 -0
- package/src/panels/inspector/timeModel.ts +190 -0
- package/src/panels/inspector/useDocWrite.ts +438 -146
- package/src/panels/library/LibraryBrowser.tsx +435 -0
- package/src/panels/library/LibraryGrid.tsx +190 -0
- package/src/panels/library/LibraryPreviewPanel.tsx +349 -0
- package/src/panels/library/LibraryRail.tsx +84 -0
- package/src/panels/library/LibrarySoundPanel.tsx +293 -0
- package/src/panels/library/SoundHistory.tsx +245 -0
- package/src/panels/library/StockSounds.tsx +390 -0
- package/src/panels/library/libraryModel.ts +147 -0
- package/src/panels/library/stockSearch.ts +77 -0
- package/src/panels/maskMarks.tsx +117 -0
- package/src/panels/material/MaterialCommentNode.tsx +54 -0
- package/src/panels/material/MaterialGraphCanvas.tsx +861 -0
- package/src/panels/material/MaterialGraphMenu.tsx +45 -0
- package/src/panels/material/MaterialGroupNode.tsx +56 -0
- package/src/panels/material/MaterialLibrary.tsx +253 -0
- package/src/panels/material/MaterialNode.tsx +453 -0
- package/src/panels/material/MaterialNodePalette.tsx +349 -0
- package/src/panels/material/MaterialParameterControls.tsx +525 -0
- package/src/panels/material/MaterialRerouteNode.tsx +42 -0
- package/src/panels/material/MaterialWorkspace.tsx +501 -0
- package/src/panels/material/NodePreview.tsx +70 -0
- package/src/panels/material/flowModel.ts +441 -0
- package/src/panels/material/parameterValues.ts +231 -0
- package/src/panels/material/previewScheduler.ts +235 -0
- package/src/panels/material/reactFlow.css +6 -0
- package/src/panels/material/socketGlyph.ts +85 -0
- package/src/panels/material/viewportMemory.ts +58 -0
- package/src/panels/preferences/PreferencesDialog.tsx +215 -0
- package/src/panels/share/ShareComponentDialog.tsx +247 -0
- package/src/panels/stage/StageMenu.tsx +35 -5
- package/src/panels/stage/StagePanel.tsx +338 -23
- package/src/panels/stage/cellSlots.tsx +70 -0
- package/src/panels/storyboard/BoardCanvas.tsx +739 -0
- package/src/panels/storyboard/BoardCursors.tsx +158 -0
- package/src/panels/storyboard/BoardDropDialog.tsx +161 -0
- package/src/panels/storyboard/BoardPlan.tsx +42 -0
- package/src/panels/storyboard/ComponentSheet.tsx +187 -0
- package/src/panels/storyboard/ComponentStage.tsx +235 -0
- package/src/panels/storyboard/MiniSketch.tsx +173 -0
- package/src/panels/storyboard/PartPicker.tsx +64 -0
- package/src/panels/storyboard/PlanPanel.tsx +617 -0
- package/src/panels/storyboard/ReferencePreview.tsx +217 -0
- package/src/panels/storyboard/ShotBrief.tsx +360 -0
- package/src/panels/storyboard/ShotCard.tsx +251 -0
- package/src/panels/storyboard/StagePreview.tsx +348 -0
- package/src/panels/storyboard/StillThumbs.tsx +162 -0
- package/src/panels/storyboard/StoryboardView.tsx +79 -0
- package/src/panels/storyboard/board.css +1065 -0
- package/src/panels/storyboard/board.ts +12 -0
- package/src/panels/storyboard/boardClipboard.ts +111 -0
- package/src/panels/storyboard/boardOrder.ts +68 -0
- package/src/panels/storyboard/boardRows.tsx +425 -0
- package/src/panels/storyboard/liveCap.ts +90 -0
- package/src/panels/storyboard/plan.css +295 -0
- package/src/panels/storyboard/posterCache.ts +133 -0
- package/src/panels/storyboard/shotboard/ComponentPicker.tsx +373 -0
- package/src/panels/storyboard/shotboard/ImagePicker.tsx +145 -0
- package/src/panels/storyboard/shotboard/ShotBoard.tsx +292 -0
- package/src/panels/storyboard/shotboard/SketchCanvas.tsx +443 -0
- package/src/panels/storyboard/shotboard/SketchInspector.tsx +471 -0
- package/src/panels/storyboard/shotboard/SketchItem.tsx +240 -0
- package/src/panels/storyboard/shotboard/SketchLayers.tsx +130 -0
- package/src/panels/storyboard/shotboard/SketchPlay.tsx +108 -0
- package/src/panels/storyboard/shotboard/SketchStrip.tsx +178 -0
- package/src/panels/storyboard/shotboard/SketchToolFooter.tsx +99 -0
- package/src/panels/storyboard/shotboard/sketch.css +1392 -0
- package/src/panels/storyboard/shotboard/sketchModel.ts +219 -0
- package/src/panels/storyboard/storyboardDrop.ts +164 -0
- package/src/panels/studio/ComponentLibraryRail.tsx +346 -0
- package/src/panels/studio/ComponentSidePanel.tsx +355 -0
- package/src/panels/studio/ComponentStudio.tsx +243 -0
- package/src/panels/studio/ComponentsHome.tsx +318 -0
- package/src/panels/studio/ComponentsPreview.tsx +179 -0
- package/src/panels/studio/EveryUse.tsx +244 -0
- package/src/panels/studio/ThisUsePanel.tsx +679 -0
- package/src/panels/studio/componentParts.tsx +341 -0
- package/src/panels/studio/components.ts +6 -0
- package/src/panels/studio/newCodeComponent.ts +66 -0
- package/src/panels/timeline/AudioFxButton.tsx +290 -0
- package/src/panels/timeline/AudioLane.tsx +674 -85
- package/src/panels/timeline/BlockRow.tsx +154 -85
- package/src/panels/timeline/ChannelRow.tsx +378 -129
- package/src/panels/timeline/CurvePane.tsx +508 -0
- package/src/panels/timeline/Filmstrip.tsx +361 -0
- package/src/panels/timeline/GenerateDrawer.tsx +407 -0
- package/src/panels/timeline/KeyStretch.tsx +115 -0
- package/src/panels/timeline/LifespanRow.tsx +730 -47
- package/src/panels/timeline/MarkerLane.tsx +46 -8
- package/src/panels/timeline/PlayButton.tsx +91 -0
- package/src/panels/timeline/PropertyPicker.tsx +254 -0
- package/src/panels/timeline/ShotRow.tsx +400 -0
- package/src/panels/timeline/SoundMode.tsx +1406 -0
- package/src/panels/timeline/TimelineDock.tsx +2338 -272
- package/src/panels/timeline/TransportVolume.tsx +163 -0
- package/src/panels/timeline/beatRuler.ts +74 -0
- package/src/panels/timeline/curveModel.ts +500 -0
- package/src/panels/timeline/duckUnderVoice.ts +68 -0
- package/src/panels/timeline/keyframeMenu.ts +138 -0
- package/src/panels/timeline/labelWidth.ts +49 -0
- package/src/panels/timeline/marquee.ts +155 -0
- package/src/panels/timeline/model.ts +1860 -199
- package/src/panels/timeline/snap.ts +125 -43
- package/src/panels/timeline/staggerPreview.tsx +92 -0
- package/src/panels/timeline/takeMeasure.ts +72 -0
- package/src/panels/timeline/useLive.ts +48 -0
- package/src/panels/timeline/viewport.ts +234 -0
- package/src/panels/toolbar/BackChip.tsx +116 -0
- package/src/panels/toolbar/CameraViewBar.tsx +118 -49
- package/src/panels/toolbar/CanvasBar.tsx +117 -0
- package/src/panels/toolbar/InsertButton.tsx +38 -0
- package/src/panels/toolbar/IsolationTrail.tsx +156 -0
- package/src/panels/toolbar/PanelToggles.tsx +86 -0
- package/src/panels/toolbar/ShadingBar.tsx +119 -26
- package/src/panels/toolbar/ToolDockBar.tsx +329 -80
- package/src/panels/toolbar/ToolFooter.tsx +102 -0
- package/src/panels/toolbar/ViewModeBar.tsx +247 -38
- package/src/panels/toolbar/WorkPlaneBar.tsx +94 -0
- package/src/panels/toolbar/useAddRows.tsx +326 -0
- package/src/panels/toolbar/useDismiss.ts +122 -0
- package/src/panels/versions/VersionHistoryPanel.tsx +274 -0
- package/src/panels/versions/versionModel.ts +103 -0
- package/src/panels/virtualWindow.ts +271 -0
- package/src/shotTokens.css +151 -60
- package/src/stage/FrustumGizmo.tsx +504 -84
- package/src/stage/GridPlane.tsx +225 -16
- package/src/stage/NodePreviews.tsx +628 -0
- package/src/stage/PerfHud.tsx +437 -47
- package/src/stage/SplitRenderer.tsx +816 -169
- package/src/stage/StageApp.tsx +4274 -486
- package/src/stage/StageRootBoundary.tsx +114 -0
- package/src/stage/StageTools.tsx +651 -151
- package/src/stage/TransformGizmo.tsx +696 -0
- package/src/stage/adaptivePresentation.ts +145 -0
- package/src/stage/bridgeClient.ts +2522 -41
- package/src/stage/exportWorker.ts +9 -0
- package/src/stage/feed.ts +305 -14
- package/src/stage/fontPreview.ts +176 -0
- package/src/stage/frustumGeometry.ts +319 -1
- package/src/stage/furnitureTokens.ts +33 -0
- package/src/stage/gizmoMath.ts +508 -16
- package/src/stage/gpuTimer.ts +276 -0
- package/src/stage/instanceModules.ts +194 -33
- package/src/stage/interactions/move.ts +24 -5
- package/src/stage/isolation.ts +291 -33
- package/src/stage/jsSelfProfiler.ts +325 -0
- package/src/stage/main.tsx +116 -16
- package/src/stage/modalState.ts +222 -23
- package/src/stage/moduleEpoch.ts +60 -0
- package/src/stage/motionPathStage.ts +279 -0
- package/src/stage/motionPreview.ts +74 -0
- package/src/stage/overlays/Overlays.tsx +1112 -159
- package/src/stage/overlays/Rulers.tsx +495 -0
- package/src/stage/panes.ts +159 -10
- package/src/stage/project.ts +68 -3
- package/src/stage/renderScaleController.ts +730 -0
- package/src/stage/rulers.ts +129 -0
- package/src/stage/sceneExtent.ts +75 -0
- package/src/stage/shading.ts +20 -0
- package/src/stage/splineStage.ts +632 -0
- package/src/stage/stagePerformanceTelemetry.ts +717 -0
- package/src/stage/stageTheme.ts +36 -0
- package/src/stage/stageWarmup.ts +11 -0
- package/src/stage/textAutoSize.ts +124 -0
- package/src/stage/tier1Export.ts +641 -0
- package/src/stage/tokenColor.ts +14 -9
- package/src/stage/view.ts +56 -9
- package/src/stage/workingView.ts +277 -33
- package/src/state/accountPrefs.ts +261 -0
- package/src/state/agentActions.ts +173 -15
- package/src/state/agentActivity.ts +198 -0
- package/src/state/agentQuestion.ts +239 -0
- package/src/state/bootOpen.ts +42 -0
- package/src/state/cameraVerbs.ts +139 -0
- package/src/state/clientId.ts +6 -1
- package/src/state/comments.ts +1099 -0
- package/src/state/context.tsx +19 -1
- package/src/state/editorPrefs.ts +220 -0
- package/src/state/errorReports.ts +121 -0
- package/src/state/fieldWrite.ts +161 -0
- package/src/state/fontRecents.ts +70 -0
- package/src/state/fonts.ts +656 -0
- package/src/state/graphClipboard.ts +414 -0
- package/src/state/imageThumbs.ts +216 -0
- package/src/state/insert.ts +444 -67
- package/src/state/isolationTrail.ts +92 -0
- package/src/state/keyMoves.ts +134 -0
- package/src/state/keyframeClipboard.ts +177 -0
- package/src/state/keymap.ts +1153 -117
- package/src/state/layoutPrefs.ts +272 -0
- package/src/state/layouts.ts +205 -0
- package/src/state/measureMedia.ts +167 -0
- package/src/state/menu.ts +2341 -28
- package/src/state/motionStamp.ts +7 -0
- package/src/state/panelSize.ts +375 -5
- package/src/state/pendingChanges.ts +119 -0
- package/src/state/playHold.ts +78 -0
- package/src/state/playbackPreparation.ts +562 -0
- package/src/state/posterCapture.ts +242 -0
- package/src/state/presence.ts +254 -0
- package/src/state/projectComponents.ts +160 -0
- package/src/state/renderEvents.ts +298 -18
- package/src/state/runtimeErrors.ts +46 -0
- package/src/state/selection.ts +12 -0
- package/src/state/shortcuts.ts +1606 -0
- package/src/state/sketchGuide.ts +51 -0
- package/src/state/splineRefs.ts +87 -0
- package/src/state/stageHealth.ts +259 -0
- package/src/state/stageWatchdog.ts +47 -0
- package/src/state/stillStage.ts +330 -0
- package/src/state/stillThumbs.ts +474 -0
- package/src/state/store.ts +23591 -2982
- package/src/state/storyboardModel.ts +528 -0
- package/src/state/sync.ts +1257 -0
- package/src/state/syncCache.ts +159 -0
- package/src/state/triangles.ts +13 -0
- package/src/state/types.ts +1698 -55
- package/src/state/unsavedGuard.ts +49 -0
- package/src/state/viewMode.ts +200 -0
- package/src/state/webmcp.ts +1128 -0
- package/src/state/workspace.ts +1147 -0
- package/src/styles/assets-tab.css +304 -0
- package/src/styles/canvas.css +545 -0
- package/src/styles/comments.css +1435 -0
- package/src/styles/controls.css +162 -0
- package/src/styles/dialogs.css +390 -0
- package/src/styles/insert-drawer.css +586 -0
- package/src/styles/inspector-board.css +207 -0
- package/src/styles/inspector-object.css +486 -0
- package/src/styles/inspector-shot.css +252 -0
- package/src/styles/inspector.css +360 -0
- package/src/styles/left-column.css +1628 -0
- package/src/styles/library-preview.css +575 -0
- package/src/styles/library.css +512 -0
- package/src/styles/modes/code.css +569 -0
- package/src/styles/modes/component.css +1561 -0
- package/src/styles/modes/material.css +1201 -0
- package/src/styles/modes/storyboard.css +518 -0
- package/src/styles/share-component.css +49 -0
- package/src/styles/shell.css +653 -0
- package/src/styles/shot-brief.css +360 -0
- package/src/styles/states.css +76 -0
- package/src/styles/sync.css +380 -0
- package/src/styles/timeline-graph.css +384 -0
- package/src/styles/timeline-meters.css +89 -0
- package/src/styles/timeline-rows.css +1959 -0
- package/src/styles/timeline-sound.css +1003 -0
- package/src/styles/timeline.css +754 -0
- package/src/styles/tool-footer.css +525 -0
- package/src/styles/topbar.css +886 -0
- package/src/styles/versions.css +262 -0
- package/src/styles.css +72 -2921
- package/src/tools.ts +108 -23
- package/dist/assets/index-B7notge7.css +0 -1
- package/dist/assets/index-BBE6Ta9L.js +0 -52
- package/src/panels/files/icons.tsx +0 -118
- package/src/panels/header/DocSwitcher.tsx +0 -85
- package/src/panels/header/TransportBar.tsx +0 -86
- package/src/panels/inspector/animate/BlockTiming.tsx +0 -341
- package/src/panels/inspector/animate/DuringBlocks.tsx +0 -85
- package/src/panels/inspector/animate/InOutPresets.tsx +0 -57
- package/src/panels/inspector/animate/ResolvedChannels.tsx +0 -150
- package/src/panels/inspector/animate/useBlocks.ts +0 -43
- package/src/panels/material/MaterialPicker.tsx +0 -172
- package/src/panels/timeline/SceneStrip.tsx +0 -145
- package/src/panels/toolbar/AddMenu.tsx +0 -230
- package/src/stage/MoveGizmo.tsx +0 -411
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// The human word for a layer: what the inspector's head, the isolation
|
|
2
|
+
// refusal and anything else that names a layer by its kind all say.
|
|
3
|
+
//
|
|
4
|
+
// Plain data, no React, so the state modules can read it as well as panels.
|
|
5
|
+
import { meshPrimitiveOf } from "@dailies-studio/shot/doc";
|
|
6
|
+
import type { Layer3D, Layer3DKind, MeshPrimitiveKind } from "@dailies-studio/shot/doc";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The human word for a layer kind.
|
|
10
|
+
*
|
|
11
|
+
* A TYPED RECORD over the schema's own union, in the spirit of `KIND_ICONS`: a
|
|
12
|
+
* sixteenth layer kind is a compile error here rather than a head that quietly
|
|
13
|
+
* says nothing for the one kind nobody remembered. The words are what the Add
|
|
14
|
+
* menu and the outliner call these things, not the wire spelling ("rect" is a
|
|
15
|
+
* Rectangle to an author and only ever a `rect` to the document).
|
|
16
|
+
*/
|
|
17
|
+
const KIND_WORDS: Record<Layer3DKind, string> = {
|
|
18
|
+
text: "Text",
|
|
19
|
+
image: "Image",
|
|
20
|
+
video: "Video",
|
|
21
|
+
rect: "Rectangle",
|
|
22
|
+
ellipse: "Ellipse",
|
|
23
|
+
line: "Line",
|
|
24
|
+
arrow: "Arrow",
|
|
25
|
+
path: "Path",
|
|
26
|
+
html: "HTML",
|
|
27
|
+
group: "Group",
|
|
28
|
+
device: "Device",
|
|
29
|
+
mesh: "Mesh",
|
|
30
|
+
cloner: "Cloner",
|
|
31
|
+
instance: "Component",
|
|
32
|
+
component: "Component",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The word for a parametric mesh, mirroring `PRIMITIVE_ICONS` one for one.
|
|
37
|
+
*
|
|
38
|
+
* Without it a spline drew the curve glyph beside the word "Mesh", which is
|
|
39
|
+
* the head disagreeing with its own icon: `iconFor` already answers by what
|
|
40
|
+
* the layer IS to an author, and the word has to answer the same way or the
|
|
41
|
+
* pair reads as a bug.
|
|
42
|
+
*/
|
|
43
|
+
const MESH_WORDS: Record<MeshPrimitiveKind, string> = {
|
|
44
|
+
box: "Box",
|
|
45
|
+
sphere: "Sphere",
|
|
46
|
+
cylinder: "Cylinder",
|
|
47
|
+
cone: "Cone",
|
|
48
|
+
capsule: "Capsule",
|
|
49
|
+
torus: "Torus",
|
|
50
|
+
pyramid: "Pyramid",
|
|
51
|
+
plane: "Plane",
|
|
52
|
+
spline: "Spline",
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function wordFor(layer: Layer3D): string {
|
|
56
|
+
if (layer.kind === "mesh") {
|
|
57
|
+
const primitive = meshPrimitiveOf(layer.mesh);
|
|
58
|
+
if (primitive !== null) return MESH_WORDS[primitive.kind];
|
|
59
|
+
}
|
|
60
|
+
return KIND_WORDS[layer.kind];
|
|
61
|
+
}
|
package/src/main.tsx
CHANGED
|
@@ -1,15 +1,67 @@
|
|
|
1
|
+
// FIRST, and not for tidiness: the index opens with the cascade-layer order,
|
|
2
|
+
// and CSS a component imports itself (App's subtree) would otherwise be
|
|
3
|
+
// emitted ahead of it and fix its layer's rank by arriving first.
|
|
4
|
+
import "./styles.css";
|
|
1
5
|
import { StrictMode } from "react";
|
|
6
|
+
import { PanelBoundary, StudioMotionProvider } from "@dailies-studio/ui";
|
|
7
|
+
import { StudioThemeProvider } from "@dailies-studio/ui/theme";
|
|
2
8
|
import { createRoot } from "react-dom/client";
|
|
3
9
|
import { createShotEditorStore } from "./state/store.js";
|
|
10
|
+
import { startBootOpen } from "./state/bootOpen.js";
|
|
11
|
+
import { persistLayoutPrefs, readLayoutPrefs } from "./state/layoutPrefs.js";
|
|
12
|
+
import { persistEditorPrefs } from "./state/editorPrefs.js";
|
|
4
13
|
import { StoreProvider } from "./state/context.js";
|
|
5
14
|
import { App } from "./app/App.js";
|
|
6
|
-
import "./styles.css";
|
|
7
15
|
|
|
8
16
|
const store = createShotEditorStore();
|
|
17
|
+
// The layout is settled BEFORE the first commit, not in a mount effect, so the
|
|
18
|
+
// panels are never painted at the defaults and then snapped to the author's
|
|
19
|
+
// sizes. `window` is unconditional here — this module ends by reaching into
|
|
20
|
+
// `document` for the root element — so there is nothing to guard.
|
|
21
|
+
//
|
|
22
|
+
// Read then subscribe, in that order: the seed inside `persistLayoutPrefs` has
|
|
23
|
+
// to be the layout `bootLayout` just applied, or the boot's own application of
|
|
24
|
+
// the record is indistinguishable from a drag — and a size this window CLAMPED
|
|
25
|
+
// is then written back at the clamped value, so the number the author chose is
|
|
26
|
+
// gone on the wider window that could have honoured it. What keeps the
|
|
27
|
+
// window-fitted sizes out of the record is `authorLayout`, not this order.
|
|
28
|
+
// layoutPrefs.ts owns both rules and states them whole.
|
|
29
|
+
store.bootLayout(window.innerWidth, window.innerHeight, readLayoutPrefs());
|
|
30
|
+
persistLayoutPrefs(store);
|
|
31
|
+
// The store read the editor preferences at birth, so this subscribes with that
|
|
32
|
+
// as its seed and writes only when a toggle changes one.
|
|
33
|
+
persistEditorPrefs(store);
|
|
34
|
+
// The document fetch starts HERE, at module evaluation — before createRoot and
|
|
35
|
+
// the first commit — so the round trip overlaps the mount instead of following
|
|
36
|
+
// it. `useOpenFromUrl` adopts the promise for its deep-link continuations.
|
|
37
|
+
// Module-scope start also means StrictMode's double effect adopts one fetch
|
|
38
|
+
// instead of relying on the generation fence to absorb a second.
|
|
39
|
+
startBootOpen(store);
|
|
40
|
+
// The browser agent's tool surface, offered here for the same reason the two
|
|
41
|
+
// calls above are: the store exists before React does, so no component owns the
|
|
42
|
+
// registration and there is no mount order to get wrong. A browser without
|
|
43
|
+
// `document.modelContext` gets nothing and pays nothing: the tool table is a
|
|
44
|
+
// chunk of its own, fetched only where the API exists.
|
|
45
|
+
if (document.modelContext !== undefined) void import("./state/webmcp.js").then((m) => m.startModelContext(store));
|
|
9
46
|
createRoot(document.getElementById("root")!).render(
|
|
10
47
|
<StrictMode>
|
|
11
|
-
<
|
|
12
|
-
<
|
|
13
|
-
|
|
48
|
+
<StudioThemeProvider>
|
|
49
|
+
<StudioMotionProvider enabled>
|
|
50
|
+
<StoreProvider store={store}>
|
|
51
|
+
{/* THE LAST RESORT, and the only boundary allowed above the stage.
|
|
52
|
+
Everything a panel or a mode can throw is caught
|
|
53
|
+
nearer the throw; what reaches here is a throw in the shell
|
|
54
|
+
itself, and React's answer to that is to unmount the whole root
|
|
55
|
+
and leave a WHITE PAGE with the error only in the console. This
|
|
56
|
+
cannot save the stage — a catch unmounts it either way — but it
|
|
57
|
+
turns a blank window into a named error the author can report,
|
|
58
|
+
and a retry that costs no more than the reload they would
|
|
59
|
+
otherwise do by hand. */}
|
|
60
|
+
<PanelBoundary label="Dailies">
|
|
61
|
+
<App />
|
|
62
|
+
</PanelBoundary>
|
|
63
|
+
</StoreProvider>
|
|
64
|
+
</StudioMotionProvider>
|
|
65
|
+
</StudioThemeProvider>
|
|
14
66
|
</StrictMode>,
|
|
15
67
|
);
|
|
@@ -17,15 +17,24 @@
|
|
|
17
17
|
// size exactly once per gesture — at the press — so it asks for it then, and
|
|
18
18
|
// the hosts subscribe to nothing on its behalf.
|
|
19
19
|
//
|
|
20
|
-
// ── WRITES ARE COALESCED TO THE FRAME
|
|
20
|
+
// ── WRITES ARE COALESCED TO THE FRAME, BY startDrag ──────────────────────
|
|
21
21
|
//
|
|
22
22
|
// A pointer reports far above display rate; each `onChange` is a store write
|
|
23
|
-
// and a full listener sweep.
|
|
24
|
-
//
|
|
23
|
+
// and a full listener sweep. `startDrag` itself now delivers one move per
|
|
24
|
+
// frame, last position wins, and settles the pending move on release — this
|
|
25
|
+
// file's own rAF coalescer moved there so every chrome drag gets it.
|
|
25
26
|
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
|
|
27
|
+
// ── THE LIFECYCLE IS THE WORKSPACE'S, NOT THIS FILE'S ────────────────────
|
|
28
|
+
//
|
|
29
|
+
// `startDrag` (packages/ui/src/drag.ts) owns pointer capture and all three
|
|
30
|
+
// abort paths: pointercancel, Escape, and the lostpointercapture a mid-drag
|
|
31
|
+
// unmount produces. Hand-rolling capture with React's pointerup/pointercancel
|
|
32
|
+
// props reaches only the first of them, which is what left the panel edge as
|
|
33
|
+
// the one chrome drag an author could not back out of.
|
|
34
|
+
//
|
|
35
|
+
// An abort RESTORES THE BASE, because the coalesced writes already landed on
|
|
36
|
+
// the host: "this gesture did not happen" has to mean the size it started at.
|
|
37
|
+
import { startDrag } from "@dailies-studio/ui";
|
|
29
38
|
|
|
30
39
|
export interface ResizeHandleProps {
|
|
31
40
|
/** "x" drags left-right (a side rail), "y" up-down (a bottom dock). */
|
|
@@ -53,24 +62,8 @@ export function ResizeHandle({
|
|
|
53
62
|
className,
|
|
54
63
|
label,
|
|
55
64
|
}: ResizeHandleProps) {
|
|
56
|
-
const drag = useRef<{ base: number; origin: number } | null>(null);
|
|
57
|
-
const pending = useRef<number | null>(null);
|
|
58
|
-
const raf = useRef(0);
|
|
59
|
-
useEffect(
|
|
60
|
-
() => () => {
|
|
61
|
-
if (raf.current !== 0) cancelAnimationFrame(raf.current);
|
|
62
|
-
},
|
|
63
|
-
[],
|
|
64
|
-
);
|
|
65
65
|
const posOf = (e: { clientX: number; clientY: number }): number =>
|
|
66
66
|
axis === "x" ? e.clientX : e.clientY;
|
|
67
|
-
const flush = (): void => {
|
|
68
|
-
raf.current = 0;
|
|
69
|
-
if (pending.current === null) return;
|
|
70
|
-
const next = pending.current;
|
|
71
|
-
pending.current = null;
|
|
72
|
-
onChange(next);
|
|
73
|
-
};
|
|
74
67
|
|
|
75
68
|
return (
|
|
76
69
|
<div
|
|
@@ -81,32 +74,29 @@ export function ResizeHandle({
|
|
|
81
74
|
role="separator"
|
|
82
75
|
aria-orientation={axis === "x" ? "vertical" : "horizontal"}
|
|
83
76
|
aria-label={label}
|
|
84
|
-
title={`${label}
|
|
77
|
+
title={`${label}: drag to resize, double-click to reset`}
|
|
85
78
|
onDoubleClick={onReset}
|
|
86
79
|
onPointerDown={(e) => {
|
|
87
80
|
// Or the browser starts a text selection across the panels the drag
|
|
88
81
|
// passes over, and the whole chrome flashes blue mid-resize.
|
|
89
82
|
e.preventDefault();
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
onPointerCancel={() => {
|
|
108
|
-
drag.current = null;
|
|
109
|
-
pending.current = null;
|
|
83
|
+
// Both captured at the press, and both live in this closure rather
|
|
84
|
+
// than in a ref: there is exactly one gesture at a time, and a ref
|
|
85
|
+
// that outlives it is the stale base a cancelled pointer used to
|
|
86
|
+
// leave behind.
|
|
87
|
+
const base = getValue();
|
|
88
|
+
const origin = posOf(e);
|
|
89
|
+
startDrag(e, {
|
|
90
|
+
// Already frame-coalesced by startDrag, and the release delivers the
|
|
91
|
+
// pending move before onEnd — so the final size always lands, and an
|
|
92
|
+
// abort's base restore below can never be overwritten by it.
|
|
93
|
+
onMove(ev) {
|
|
94
|
+
onChange(base + (posOf(ev) - origin) * sign);
|
|
95
|
+
},
|
|
96
|
+
onEnd(commit) {
|
|
97
|
+
if (!commit) onChange(base);
|
|
98
|
+
},
|
|
99
|
+
});
|
|
110
100
|
}}
|
|
111
101
|
/>
|
|
112
102
|
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// AN MCP AGENT IS WORKING HERE: three animated dots in the Agent's colour, the
|
|
2
|
+
// one mark every surface uses for it (the component card, the code tab, the
|
|
3
|
+
// layer row, the status chip). Driven by the agent activity store
|
|
4
|
+
// (state/agentActivity.ts), never by a timer of its own.
|
|
5
|
+
import { useSyncExternalStore } from "react";
|
|
6
|
+
import type { ReactNode } from "react";
|
|
7
|
+
import { useShotEditor, useStore } from "../../state/context.js";
|
|
8
|
+
import { agentBuildingParts } from "../../state/agentActivity.js";
|
|
9
|
+
import type { AgentActivityState } from "../../state/agentActivity.js";
|
|
10
|
+
|
|
11
|
+
export function useAgentActivity(): AgentActivityState {
|
|
12
|
+
const { agentActivity } = useStore();
|
|
13
|
+
return useSyncExternalStore(agentActivity.subscribe, agentActivity.getState);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** The dots, with `label` for assistive tech ("Agent is writing this file"). */
|
|
17
|
+
export function AgentDots(props: { label: string }): ReactNode {
|
|
18
|
+
return (
|
|
19
|
+
<span className="agent-dots" role="status" aria-label={props.label} title={props.label} data-testid="agent-dots">
|
|
20
|
+
<span />
|
|
21
|
+
<span />
|
|
22
|
+
<span />
|
|
23
|
+
</span>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** `boardBuilding` plus the parts an MCP agent is building now: what a shot
|
|
28
|
+
* card's Building status reads. */
|
|
29
|
+
export function useBuildingParts(): readonly { part: string }[] {
|
|
30
|
+
const building = useShotEditor((s) => s.boardBuilding);
|
|
31
|
+
const doc = useShotEditor((s) => s.doc);
|
|
32
|
+
const name = useShotEditor((s) => s.name);
|
|
33
|
+
const activity = useAgentActivity();
|
|
34
|
+
const agents = agentBuildingParts(doc, activity, name);
|
|
35
|
+
return agents.length === 0 ? building : [...building, ...agents];
|
|
36
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// A shot proposal is not a diff — a diff of a Doc3D JSON is unreadable and,
|
|
9
9
|
// worse, a lie about what the change IS. What an author has to judge is how
|
|
10
10
|
// LONG the video is now and what moves in it, so that is the card: the intent
|
|
11
|
-
// as the title, the duration and the
|
|
11
|
+
// as the title, the duration and the camera-move count as a chip, and the
|
|
12
12
|
// scene/layer outline the server already rendered.
|
|
13
13
|
//
|
|
14
14
|
// Keydown stops at the panel root so typing a prompt never reaches the global
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import "./agent.css";
|
|
18
18
|
import { useEffect, useRef, useState } from "react";
|
|
19
19
|
import type { KeyboardEvent as ReactKeyboardEvent } from "react";
|
|
20
|
+
import { PanelBoundary, SegmentedControl } from "@dailies-studio/ui";
|
|
20
21
|
import { isDocProposalItem } from "@dailies-studio/agent-client";
|
|
21
22
|
import type {
|
|
22
23
|
AgentFileProposalItem,
|
|
@@ -25,6 +26,10 @@ import type {
|
|
|
25
26
|
AgentTranscriptItem,
|
|
26
27
|
} from "@dailies-studio/agent-client";
|
|
27
28
|
import { useShotEditor, useStore } from "../../state/context.js";
|
|
29
|
+
import { isCloudWorkspace } from "../../state/posterCapture.js";
|
|
30
|
+
import { shortcutFor } from "../../state/shortcuts.js";
|
|
31
|
+
import type { ShotEditorState } from "../../state/types.js";
|
|
32
|
+
import { formatDuration } from "../timeline/model.js";
|
|
28
33
|
import {
|
|
29
34
|
applyAgentProposal,
|
|
30
35
|
askAgent,
|
|
@@ -88,15 +93,45 @@ function Outline(props: { lines: readonly string[] }) {
|
|
|
88
93
|
);
|
|
89
94
|
}
|
|
90
95
|
|
|
96
|
+
/**
|
|
97
|
+
* The Shots a proposal redraws beyond the one an "Add motion" request named
|
|
98
|
+
* (or, without one, the entered Shot), by name. Empty when the card edits
|
|
99
|
+
* another Project, when nothing names a Shot, or on a create.
|
|
100
|
+
*/
|
|
101
|
+
export function strayShotsOf(state: ShotEditorState, item: AgentShotProposalItem): string[] {
|
|
102
|
+
const changed = item.summary.changedShots;
|
|
103
|
+
if (changed === undefined || state.name !== item.docName) return [];
|
|
104
|
+
const target = state.motionRequest?.sceneId ?? state.enteredScene;
|
|
105
|
+
if (target === null) return [];
|
|
106
|
+
return changed
|
|
107
|
+
.filter((id) => id !== target)
|
|
108
|
+
.map((id) => state.doc?.scenesById[id]?.name ?? id);
|
|
109
|
+
}
|
|
110
|
+
|
|
91
111
|
function ShotCard(props: { item: AgentShotProposalItem }) {
|
|
92
112
|
const { item } = props;
|
|
113
|
+
const store = useStore();
|
|
93
114
|
const openName = useShotEditor((s) => s.name);
|
|
115
|
+
const openTitle = useShotEditor((s) => s.doc?.title ?? s.name);
|
|
116
|
+
const motionPart = useShotEditor((s) => s.motionRequest?.partId ?? null);
|
|
117
|
+
// Joined to a string so the selector stays identity-stable between renders.
|
|
118
|
+
const strays = useShotEditor((s) => strayShotsOf(s, item).join("\u0000"));
|
|
119
|
+
const [copied, setCopied] = useState(false);
|
|
94
120
|
const { summary } = item;
|
|
121
|
+
const copyPrompt = (): void => {
|
|
122
|
+
const prompt = motionPart === null ? null : store.motionPromptFor(motionPart);
|
|
123
|
+
if (prompt === null) return;
|
|
124
|
+
void navigator.clipboard.writeText(prompt).then(
|
|
125
|
+
() => setCopied(true),
|
|
126
|
+
() => store.reportError("Could not copy the prompt. The browser refused clipboard access."),
|
|
127
|
+
);
|
|
128
|
+
};
|
|
95
129
|
// Three cases, one of which needs a warning. Same shot: the SSE bus adopts
|
|
96
130
|
// it. A CREATE of another name: applying opens it. An EDIT of another shot:
|
|
97
131
|
// it lands on disk but this editor stays where it is — say so rather than
|
|
98
132
|
// letting the card imply the author is looking at the result.
|
|
99
133
|
const editsElsewhere = openName !== null && openName !== item.docName && item.baseRev !== null;
|
|
134
|
+
const title = summary.title ?? summary.shotName;
|
|
100
135
|
return (
|
|
101
136
|
<div className={`agent-card agent-card-shot agent-card-${item.status}`}>
|
|
102
137
|
<div className="agent-card-head">
|
|
@@ -106,26 +141,22 @@ function ShotCard(props: { item: AgentShotProposalItem }) {
|
|
|
106
141
|
<CardActions item={item} />
|
|
107
142
|
</div>
|
|
108
143
|
<div className="agent-card-meta">
|
|
109
|
-
<span className="agent-card-doc" title={`
|
|
110
|
-
{
|
|
144
|
+
<span className="agent-card-doc" title={`Project “${title}”`}>
|
|
145
|
+
{title}
|
|
111
146
|
</span>
|
|
112
147
|
{/* DURATION first: a shot document is a video, and "how long is it now"
|
|
113
148
|
is the first thing a reviewer asks. */}
|
|
114
|
-
<span className="agent-card-count">
|
|
149
|
+
<span className="agent-card-count">
|
|
150
|
+
{summary.fps === undefined
|
|
151
|
+
? `${summary.durationFrames}f`
|
|
152
|
+
: formatDuration(summary.durationFrames / summary.fps)}
|
|
153
|
+
</span>
|
|
115
154
|
<span className="agent-card-count">
|
|
116
155
|
{summary.sceneCount} {summary.sceneCount === 1 ? "shot" : "shots"}
|
|
117
156
|
</span>
|
|
118
157
|
<span className="agent-card-count">
|
|
119
158
|
{summary.layerCount} {summary.layerCount === 1 ? "layer" : "layers"}
|
|
120
159
|
</span>
|
|
121
|
-
{/* The MOTION half. Silent at zero — a chip reading "0 blocks" on a
|
|
122
|
-
static card is noise, and this lane's whole animation system is
|
|
123
|
-
blocks, so their absence is itself the information. */}
|
|
124
|
-
{summary.blockCount > 0 && (
|
|
125
|
-
<span className="agent-card-count">
|
|
126
|
-
{summary.blockCount} {summary.blockCount === 1 ? "block" : "blocks"}
|
|
127
|
-
</span>
|
|
128
|
-
)}
|
|
129
160
|
{summary.shotCount > 0 && (
|
|
130
161
|
<span className="agent-card-count">
|
|
131
162
|
{summary.shotCount} {summary.shotCount === 1 ? "camera move" : "camera moves"}
|
|
@@ -133,6 +164,17 @@ function ShotCard(props: { item: AgentShotProposalItem }) {
|
|
|
133
164
|
)}
|
|
134
165
|
</div>
|
|
135
166
|
<Outline lines={summary.outline} />
|
|
167
|
+
{strays !== "" && item.status === "pending" && (
|
|
168
|
+
<div className="agent-card-note agent-card-warning">
|
|
169
|
+
Also changes {strays.split("\u0000").map((name) => `“${name}”`).join(", ")}, not only the
|
|
170
|
+
Shot you asked about.
|
|
171
|
+
</div>
|
|
172
|
+
)}
|
|
173
|
+
{motionPart !== null && (
|
|
174
|
+
<button type="button" className="btn agent-copy-prompt" onClick={copyPrompt}>
|
|
175
|
+
{copied ? "Copied" : "Copy prompt"}
|
|
176
|
+
</button>
|
|
177
|
+
)}
|
|
136
178
|
{item.error !== null && <div className="error-strip agent-card-error">{item.error}</div>}
|
|
137
179
|
{/* APPLIED WITH WARNINGS is its own state: the document was written, but
|
|
138
180
|
codegen refused (a hand-edited generated file) — so the component that
|
|
@@ -140,24 +182,24 @@ function ShotCard(props: { item: AgentShotProposalItem }) {
|
|
|
140
182
|
one place a half-landed change reads as a landed one. */}
|
|
141
183
|
{item.status === "applied" && item.warning !== null && (
|
|
142
184
|
<div className="agent-card-note agent-card-warning">
|
|
143
|
-
Applied with warnings
|
|
185
|
+
Applied with warnings. The Project was saved, but: {item.warning}
|
|
144
186
|
</div>
|
|
145
187
|
)}
|
|
146
188
|
{item.status === "applied" && item.error === null && item.warning === null && (
|
|
147
189
|
<div className="agent-card-note">
|
|
148
|
-
Applied
|
|
190
|
+
Applied: the change is live in the editor. {shortcutFor("edit.undo")} takes it back.
|
|
149
191
|
</div>
|
|
150
192
|
)}
|
|
151
193
|
{item.status === "stale" && (
|
|
152
194
|
<div className="agent-card-note">
|
|
153
|
-
The
|
|
154
|
-
|
|
195
|
+
The Project changed after this was proposed. Ask the agent again so it can re-read it
|
|
196
|
+
and re-propose.
|
|
155
197
|
</div>
|
|
156
198
|
)}
|
|
157
199
|
{editsElsewhere && item.status === "pending" && (
|
|
158
200
|
<div className="agent-card-note">
|
|
159
|
-
Edits
|
|
160
|
-
|
|
201
|
+
Edits Project “{title}”, not the open one. Applying writes it, but this editor stays on
|
|
202
|
+
“{openTitle}”.
|
|
161
203
|
</div>
|
|
162
204
|
)}
|
|
163
205
|
</div>
|
|
@@ -198,7 +240,7 @@ function FileCard(props: { item: AgentFileProposalItem }) {
|
|
|
198
240
|
{item.error !== null && <div className="error-strip agent-card-error">{item.error}</div>}
|
|
199
241
|
{item.status === "stale" && (
|
|
200
242
|
<div className="agent-card-note">
|
|
201
|
-
The file changed on disk after this was proposed
|
|
243
|
+
The file changed on disk after this was proposed. Ask the agent again to re-read and
|
|
202
244
|
re-propose.
|
|
203
245
|
</div>
|
|
204
246
|
)}
|
|
@@ -228,7 +270,7 @@ function TranscriptItem(props: { item: AgentTranscriptItem }) {
|
|
|
228
270
|
<span className={`agent-card-status is-${item.status}`}>{item.status}</span>
|
|
229
271
|
</div>
|
|
230
272
|
<div className="agent-card-note">
|
|
231
|
-
A {item.proposalKind} document
|
|
273
|
+
A {item.proposalKind} document: “{item.docName}”. Open that editor to review and apply
|
|
232
274
|
it.
|
|
233
275
|
</div>
|
|
234
276
|
</div>
|
|
@@ -246,6 +288,9 @@ function KeySetup(props: { compact: boolean; onDone?: () => void }) {
|
|
|
246
288
|
const credentialsError = useShotEditor((s) => s.agentCredentialsError);
|
|
247
289
|
const [key, setKey] = useState("");
|
|
248
290
|
const [saving, setSaving] = useState(false);
|
|
291
|
+
// Hosted, the key is one row per workspace that every owner and admin's
|
|
292
|
+
// turns run on, not a file on this machine (`workspaceAgent.ts`).
|
|
293
|
+
const hosted = isCloudWorkspace();
|
|
249
294
|
|
|
250
295
|
const save = async (): Promise<void> => {
|
|
251
296
|
if (key.trim() === "" || saving) return;
|
|
@@ -263,8 +308,18 @@ function KeySetup(props: { compact: boolean; onDone?: () => void }) {
|
|
|
263
308
|
{!props.compact && (
|
|
264
309
|
<p className="agent-setup-blurb">
|
|
265
310
|
The agent builds scenes through the studio's validated document API and needs an Anthropic
|
|
266
|
-
API key.
|
|
267
|
-
|
|
311
|
+
API key.{" "}
|
|
312
|
+
{hosted ? (
|
|
313
|
+
<>
|
|
314
|
+
It is stored encrypted for this workspace, sent only to Anthropic, and never shown
|
|
315
|
+
again. Every owner and admin here uses this key, and saving replaces the current one.
|
|
316
|
+
</>
|
|
317
|
+
) : (
|
|
318
|
+
<>
|
|
319
|
+
Bring your own: it is stored in <code>.studio/agent/</code> (kept out of git) on this
|
|
320
|
+
machine, sent only to Anthropic, and never shown again.
|
|
321
|
+
</>
|
|
322
|
+
)}
|
|
268
323
|
</p>
|
|
269
324
|
)}
|
|
270
325
|
{credentials?.source === "env" && (
|
|
@@ -274,7 +329,7 @@ function KeySetup(props: { compact: boolean; onDone?: () => void }) {
|
|
|
274
329
|
)}
|
|
275
330
|
{credentials?.source === "stored" && (
|
|
276
331
|
<p className="agent-setup-blurb">
|
|
277
|
-
Using your stored key (…{credentials.last4}).{" "}
|
|
332
|
+
{hosted ? "Using this workspace's key" : "Using your stored key"} (…{credentials.last4}).{" "}
|
|
278
333
|
<button type="button" className="btn is-danger" onClick={() => void clearAgentKey(store)}>
|
|
279
334
|
Remove key
|
|
280
335
|
</button>
|
|
@@ -316,10 +371,34 @@ export function AgentPanel() {
|
|
|
316
371
|
const agentError = useShotEditor((s) => s.agentError);
|
|
317
372
|
const agentModel = useShotEditor((s) => s.agentModel);
|
|
318
373
|
const costUsd = useShotEditor((s) => s.agentCostUsd);
|
|
319
|
-
const name = useShotEditor((s) => s.name);
|
|
374
|
+
const name = useShotEditor((s) => s.doc?.title ?? s.name);
|
|
320
375
|
const [prompt, setPrompt] = useState("");
|
|
321
376
|
const [keyOpen, setKeyOpen] = useState(false);
|
|
322
377
|
const listRef = useRef<HTMLDivElement | null>(null);
|
|
378
|
+
const inputRef = useRef<HTMLTextAreaElement | null>(null);
|
|
379
|
+
|
|
380
|
+
// A prefill from the storyboard (a part's motion prompt, or a move's motion notes): adopted once per
|
|
381
|
+
// identity, `appMenu`'s mailbox rule, and the caret lands at its end so the
|
|
382
|
+
// author finishes the sentence rather than finding it.
|
|
383
|
+
const prefill = useShotEditor((s) => s.agentPrefill);
|
|
384
|
+
const focusPrefill = useRef(false);
|
|
385
|
+
useEffect(() => {
|
|
386
|
+
if (prefill === null) return;
|
|
387
|
+
setPrompt(prefill.text);
|
|
388
|
+
focusPrefill.current = true;
|
|
389
|
+
store.consumeAgentPrefill(prefill);
|
|
390
|
+
}, [prefill, store]);
|
|
391
|
+
|
|
392
|
+
useEffect(() => {
|
|
393
|
+
const el = inputRef.current;
|
|
394
|
+
// The first credential probe may still have the composer disabled when
|
|
395
|
+
// its prefill arrives. Focus once the actual input can accept typing.
|
|
396
|
+
if (focusPrefill.current && el !== null && !el.disabled) {
|
|
397
|
+
focusPrefill.current = false;
|
|
398
|
+
el.focus();
|
|
399
|
+
el.setSelectionRange(el.value.length, el.value.length);
|
|
400
|
+
}
|
|
401
|
+
}, [prefill, prompt, credentials?.configured, running]);
|
|
323
402
|
|
|
324
403
|
// One credentials probe per opening; a saved/removed key refreshes through
|
|
325
404
|
// the actions themselves.
|
|
@@ -350,24 +429,19 @@ export function AgentPanel() {
|
|
|
350
429
|
|
|
351
430
|
return (
|
|
352
431
|
<div className="agent-panel" data-testid="agent-panel" onKeyDown={onKeyDown}>
|
|
353
|
-
|
|
354
|
-
|
|
432
|
+
{/* INSIDE the positioned container, per the boundary's placement rule. */}
|
|
433
|
+
<PanelBoundary label="Agent">
|
|
434
|
+
{/* No "Agent" word here: the column head's tab already names the panel. */}
|
|
435
|
+
<div className="agent-title">
|
|
355
436
|
{credentials !== null && credentials.configured && (
|
|
356
|
-
<
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
title={m}
|
|
365
|
-
onClick={() => store.setAgentModel(m === credentials.model ? null : m)}
|
|
366
|
-
>
|
|
367
|
-
{modelLabel(m)}
|
|
368
|
-
</button>
|
|
369
|
-
))}
|
|
370
|
-
</div>
|
|
437
|
+
<SegmentedControl
|
|
438
|
+
className="agent-models"
|
|
439
|
+
ariaLabel="Model"
|
|
440
|
+
value={model}
|
|
441
|
+
options={credentials.models.map((m) => ({ value: m, label: modelLabel(m), title: m }))}
|
|
442
|
+
// Picking the server's default stores null: no override.
|
|
443
|
+
onChange={(m) => store.setAgentModel(m === credentials.model ? null : m)}
|
|
444
|
+
/>
|
|
371
445
|
)}
|
|
372
446
|
<button
|
|
373
447
|
type="button"
|
|
@@ -415,8 +489,8 @@ export function AgentPanel() {
|
|
|
415
489
|
|
|
416
490
|
<div className="agent-transcript" ref={listRef}>
|
|
417
491
|
{items.length === 0 ? (
|
|
418
|
-
<div className="
|
|
419
|
-
Ask for a scene
|
|
492
|
+
<div className="insp-empty">
|
|
493
|
+
Ask for a scene, for example “a product video: the screenshot pushes in while the headline fades
|
|
420
494
|
up”. You get real layers at real depths; nothing lands until you apply it.
|
|
421
495
|
</div>
|
|
422
496
|
) : (
|
|
@@ -437,6 +511,7 @@ export function AgentPanel() {
|
|
|
437
511
|
</span>
|
|
438
512
|
)}
|
|
439
513
|
<textarea
|
|
514
|
+
ref={inputRef}
|
|
440
515
|
className="agent-input"
|
|
441
516
|
rows={2}
|
|
442
517
|
placeholder={
|
|
@@ -473,6 +548,7 @@ export function AgentPanel() {
|
|
|
473
548
|
</button>
|
|
474
549
|
)}
|
|
475
550
|
</div>
|
|
551
|
+
</PanelBoundary>
|
|
476
552
|
</div>
|
|
477
553
|
);
|
|
478
554
|
}
|