@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,91 @@
|
|
|
1
|
+
// THE INSPECTOR'S STATUS FOOTER, pinned under the scroller: the container the
|
|
2
|
+
// panel is inside, as two facts. Its place on the left ("Shot 03",
|
|
3
|
+
// "Component", "4 shots"), its length and rate on the right ("540 frames ·
|
|
4
|
+
// 30 fps").
|
|
5
|
+
//
|
|
6
|
+
// ── THE CONTAINER, NEVER THE SELECTION ─────────────────────────────────────
|
|
7
|
+
//
|
|
8
|
+
// The head above names the subject, and the subject changes with every click.
|
|
9
|
+
// The footer names what the subject lives IN, which is the one thing that is
|
|
10
|
+
// true for every selection the panel can hold: a rect inside shot 3 is still in
|
|
11
|
+
// shot 3, a layer picked inside a definition is still on the definition's
|
|
12
|
+
// clock. So the ladder is the context bits alone, in `InspectorPanel`'s order
|
|
13
|
+
// for containers: an open definition, then the entered shot, then the project.
|
|
14
|
+
// The Storyboard falls through to the project, because the board plans the
|
|
15
|
+
// whole film and the project's length and rate are its facts too.
|
|
16
|
+
//
|
|
17
|
+
// ── NO FOOTER IS BETTER THAN A WRONG ONE ───────────────────────────────────
|
|
18
|
+
//
|
|
19
|
+
// In Components the subject is a component, not the document, so no document
|
|
20
|
+
// fact describes it: the footer there is the component's own
|
|
21
|
+
// (`ComponentFooter`, "Made by you · private · vN"). With no document open
|
|
22
|
+
// there is nothing to state, and it renders nothing rather than a placeholder.
|
|
23
|
+
//
|
|
24
|
+
// The rate is `fpsLabel`, the Tool footer's own wording, and the length is in
|
|
25
|
+
// frames because frames are what the Project section and the Shot section
|
|
26
|
+
// type into.
|
|
27
|
+
import type { Doc3D } from "@dailies-studio/shot/doc";
|
|
28
|
+
import { defDurationFrames, docDurationFramesCached } from "@dailies-studio/shot/doc";
|
|
29
|
+
import { useShotEditor } from "../../state/context.js";
|
|
30
|
+
import { shotNumberOf } from "../../state/storyboardModel.js";
|
|
31
|
+
import { workspaceOf } from "../../state/workspace.js";
|
|
32
|
+
import { fpsLabel } from "../toolbar/ToolFooter.js";
|
|
33
|
+
import { ComponentFooter } from "../studio/ComponentSidePanel.js";
|
|
34
|
+
|
|
35
|
+
const frames = (n: number): string => `${n} ${n === 1 ? "frame" : "frames"}`;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The footer's two lines for one context, or null where no fact is true.
|
|
39
|
+
* Pure, so the ladder is tested without a store.
|
|
40
|
+
*/
|
|
41
|
+
export function inspectorFooterFacts(
|
|
42
|
+
doc: Doc3D | null,
|
|
43
|
+
enteredScene: string | null,
|
|
44
|
+
editingDef: string | null,
|
|
45
|
+
board = false,
|
|
46
|
+
): { subject: string; meta: string } | null {
|
|
47
|
+
if (doc === null) return null;
|
|
48
|
+
const rate = `${fpsLabel(doc.fps)} fps`;
|
|
49
|
+
if (editingDef !== null) {
|
|
50
|
+
const def = doc.components?.[editingDef];
|
|
51
|
+
if (def === undefined) return null;
|
|
52
|
+
return { subject: "Component", meta: `${frames(defDurationFrames(def))} · ${rate}` };
|
|
53
|
+
}
|
|
54
|
+
if (enteredScene !== null) {
|
|
55
|
+
const scene = doc.scenesById[enteredScene];
|
|
56
|
+
const index = doc.scenes.indexOf(enteredScene);
|
|
57
|
+
if (scene === undefined || index === -1) return null;
|
|
58
|
+
// On the board a Shot is numbered as its strip card is (`shotNumberOf`,
|
|
59
|
+
// planned shots included), so the footer and the card agree.
|
|
60
|
+
const number = (board ? shotNumberOf(doc, enteredScene) : null) ?? String(index + 1).padStart(2, "0");
|
|
61
|
+
return {
|
|
62
|
+
subject: `Shot ${number}`,
|
|
63
|
+
meta: `${frames(scene.durationFrames)} · ${rate}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const count = doc.scenes.length;
|
|
67
|
+
return {
|
|
68
|
+
subject: `${count} ${count === 1 ? "shot" : "shots"}`,
|
|
69
|
+
meta: `${frames(docDurationFramesCached(doc))} · ${rate}`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function InspectorFooter() {
|
|
74
|
+
// Stable references and primitives only. The facts are derived in render,
|
|
75
|
+
// which runs on a document edit or a context change and never on a frame.
|
|
76
|
+
const doc = useShotEditor((s) => s.doc);
|
|
77
|
+
const enteredScene = useShotEditor((s) => s.enteredScene);
|
|
78
|
+
const editingDef = useShotEditor((s) => s.editingDef);
|
|
79
|
+
const board = useShotEditor((s) => s.storyboardOpen);
|
|
80
|
+
const code = useShotEditor((s) => workspaceOf(s) === "components");
|
|
81
|
+
// Components states whose component it is and which version is live.
|
|
82
|
+
if (code) return <ComponentFooter />;
|
|
83
|
+
const facts = inspectorFooterFacts(doc, enteredScene, editingDef, board);
|
|
84
|
+
if (facts === null) return null;
|
|
85
|
+
return (
|
|
86
|
+
<footer className="inspector-footer" data-testid="inspector-footer">
|
|
87
|
+
<span className="inspector-footer-subject">{facts.subject}</span>
|
|
88
|
+
<span className="inspector-footer-meta">{facts.meta}</span>
|
|
89
|
+
</footer>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
// WHAT THIS PANEL IS DESCRIBING, said once at the top.
|
|
2
|
+
//
|
|
3
|
+
// ── THE PANEL KNEW ITS SUBJECT AND NEVER NAMED IT ───────────────────────
|
|
4
|
+
//
|
|
5
|
+
// The rail resolves a subject on every render (`InspectorPanel`'s ladder) and
|
|
6
|
+
// then mounts a stack of sections whose TITLES are the only thing on screen.
|
|
7
|
+
// So the author read "Shot / Camera / Effects" in one context and "Transform /
|
|
8
|
+
// Appearance" in another, with nothing saying that the first set belongs to a
|
|
9
|
+
// shot and the second to the rectangle they clicked. Two subjects looked like
|
|
10
|
+
// two unrelated panels, and the one case where it actually matters (a layer
|
|
11
|
+
// selected INSIDE a component definition, where the sections are identical to
|
|
12
|
+
// the scene's) had no tell at all.
|
|
13
|
+
//
|
|
14
|
+
// ── THE LADDER IS `InspectorPanel`'s, NOT A SECOND OPINION ──────────────
|
|
15
|
+
//
|
|
16
|
+
// Every branch below answers the same question the panel's own fork answers,
|
|
17
|
+
// in the same order, so the head can never name something the sections are not
|
|
18
|
+
// describing. In particular the SELECTION WINS OVER `editingDef`: with a layer
|
|
19
|
+
// picked inside a definition the panel mounts the layer's design sections, so
|
|
20
|
+
// the head says "Text", not "Component". The definition is the subject only
|
|
21
|
+
// when nothing inside it is selected, which is exactly when
|
|
22
|
+
// `DefinitionSection` is what renders.
|
|
23
|
+
//
|
|
24
|
+
// ── THE NAME IS THE RENAME ──────────────────────────────────────────────
|
|
25
|
+
//
|
|
26
|
+
// For the subjects that own a rename verb (a single layer, the open shot and
|
|
27
|
+
// the Project) the name IS the field. That is what let the Shot section drop its Name
|
|
28
|
+
// row: a heading and a "Name" row two lines below it, both holding the same
|
|
29
|
+
// string, is the panel restating itself. The other subjects render a span,
|
|
30
|
+
// because a title that looks editable and is not is worse than a plain one.
|
|
31
|
+
import { useRef, useState } from "react";
|
|
32
|
+
import type { KeyboardEvent, ReactElement } from "react";
|
|
33
|
+
import { homeOf, maskTargetOf, visibleStills } from "@dailies-studio/shot/doc";
|
|
34
|
+
import {
|
|
35
|
+
CAMERA_ICON,
|
|
36
|
+
COMPONENT_ICON,
|
|
37
|
+
DOCK_TOOL_ICONS,
|
|
38
|
+
MASK_ICON,
|
|
39
|
+
MOTION_NOTE_ICON,
|
|
40
|
+
RECORD_ICON,
|
|
41
|
+
REFERENCE_ICONS,
|
|
42
|
+
SCENE_ICON,
|
|
43
|
+
STORYBOARD_ICON,
|
|
44
|
+
TRANSITION_ICON,
|
|
45
|
+
iconFor,
|
|
46
|
+
isComponentGlyph,
|
|
47
|
+
} from "../../icons.js";
|
|
48
|
+
import { wordFor } from "../../layerWords.js";
|
|
49
|
+
import { useShotEditor, useStore } from "../../state/context.js";
|
|
50
|
+
import { boardSubjectOf, cardKindOf, isReferenceId, shotNameOf, stillNameOf } from "../../state/storyboardModel.js";
|
|
51
|
+
import { useSelectedLayers } from "./useDocWrite.js";
|
|
52
|
+
import { componentEditOpen, workspaceOf } from "../../state/workspace.js";
|
|
53
|
+
import { framesToSeconds } from "@dailies-studio/engine";
|
|
54
|
+
import { formatDuration, timecode } from "../timeline/model.js";
|
|
55
|
+
|
|
56
|
+
/** The Studio face's selection: none (see `studioFace`). */
|
|
57
|
+
const NO_LAYERS: ReturnType<typeof useSelectedLayers> = [];
|
|
58
|
+
|
|
59
|
+
interface Rename {
|
|
60
|
+
ariaLabel: string;
|
|
61
|
+
/** The subject's identity, and the field's remount key. See `RenameField`. */
|
|
62
|
+
id: string;
|
|
63
|
+
commit(next: string): void;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface Subject {
|
|
67
|
+
/** The stable half, shown above the name: which set of sections is about to
|
|
68
|
+
* be read. Not drawn on the shot's head, whose `meta` line says it. */
|
|
69
|
+
kind: string;
|
|
70
|
+
/** THE SHOT'S HEAD ONLY: a fact line under the name ("Shot 03 · 0:18"), and
|
|
71
|
+
* the glyph on a tile instead of bare. The open shot is the container the
|
|
72
|
+
* author works inside, so its head reads as a place with a size rather than
|
|
73
|
+
* as one more object kind. Null on every other subject. */
|
|
74
|
+
meta: string | null;
|
|
75
|
+
/** Null for a subject with no name of its own. A marker is a frame, a label
|
|
76
|
+
* and a colour, and the label is a field in the section below. */
|
|
77
|
+
name: string | null;
|
|
78
|
+
/** NULL FOR A SUBJECT NO GLYPH DESCRIBES. Every other one here is a thing on
|
|
79
|
+
* the stage or on the timeline and has a glyph the outliner already uses for
|
|
80
|
+
* it; the Project is the panel's own frame and had to borrow one. See the
|
|
81
|
+
* Project branch. */
|
|
82
|
+
icon: ReactElement | null;
|
|
83
|
+
/** Paints the glyph in the accent, the outliner's rule for the component
|
|
84
|
+
* family. */
|
|
85
|
+
component: boolean;
|
|
86
|
+
/** Null where no store verb renames this subject. */
|
|
87
|
+
rename: Rename | null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The name, in place, committing on blur and on Enter.
|
|
92
|
+
*
|
|
93
|
+
* NOT `TextField`, which solves exactly this and is used for every other text
|
|
94
|
+
* value in the rail. It hard-codes `text-input` onto its input, and that class
|
|
95
|
+
* is a control pill: a `--control-h` box, a filled ground and a focus ring.
|
|
96
|
+
* The head's name is a TITLE that happens to be editable, which is why
|
|
97
|
+
* `.insp-head-rename` is transparent until it is pointed at, and the two rule
|
|
98
|
+
* sets would fight over height and focus paint. One bare input is cheaper than
|
|
99
|
+
* a second styling escape hatch on a shared widget.
|
|
100
|
+
*
|
|
101
|
+
* The two traps `TextField` documents are real and are handled the same way:
|
|
102
|
+
* Enter BLURS and does not also commit (the blur handler is the same closure,
|
|
103
|
+
* so committing here as well pushes two history entries for one keystroke and
|
|
104
|
+
* the first Ctrl-Z appears to do nothing), and Escape sets a ref the blur
|
|
105
|
+
* commit reads, because `setDraft(null)` has only been queued by the time the
|
|
106
|
+
* synchronous blur runs.
|
|
107
|
+
*/
|
|
108
|
+
function RenameField(props: { value: string; ariaLabel: string; onCommit: (next: string) => void }) {
|
|
109
|
+
const [draft, setDraft] = useState<string | null>(null);
|
|
110
|
+
const ref = useRef<HTMLInputElement | null>(null);
|
|
111
|
+
const cancelling = useRef(false);
|
|
112
|
+
|
|
113
|
+
const commit = (): void => {
|
|
114
|
+
if (cancelling.current) {
|
|
115
|
+
cancelling.current = false;
|
|
116
|
+
setDraft(null);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (draft === null) return;
|
|
120
|
+
setDraft(null);
|
|
121
|
+
if (draft !== props.value) props.onCommit(draft);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const onKeyDown = (e: KeyboardEvent<HTMLInputElement>): void => {
|
|
125
|
+
if (e.key === "Enter") ref.current?.blur();
|
|
126
|
+
else if (e.key === "Escape") {
|
|
127
|
+
cancelling.current = true;
|
|
128
|
+
ref.current?.blur();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<input
|
|
134
|
+
ref={ref}
|
|
135
|
+
className="insp-head-rename"
|
|
136
|
+
type="text"
|
|
137
|
+
value={draft ?? props.value}
|
|
138
|
+
aria-label={props.ariaLabel}
|
|
139
|
+
onChange={(e) => setDraft(e.target.value)}
|
|
140
|
+
onBlur={commit}
|
|
141
|
+
onKeyDown={onKeyDown}
|
|
142
|
+
/>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function InspectorHead() {
|
|
147
|
+
const store = useStore();
|
|
148
|
+
const doc = useShotEditor((s) => s.doc);
|
|
149
|
+
const sceneId = useShotEditor((s) => s.sceneId);
|
|
150
|
+
const editingDef = useShotEditor((s) => s.editingDef);
|
|
151
|
+
/** Inside a shot. NOT `sceneId !== null`, which is never null with a document
|
|
152
|
+
* open: this is the context bit, written only by enter/leave. */
|
|
153
|
+
const inShot = useShotEditor((s) => s.enteredScene !== null);
|
|
154
|
+
const selectedMarker = useShotEditor((s) => s.selectedMarker);
|
|
155
|
+
const focused = useShotEditor((s) => s.selectedMove);
|
|
156
|
+
const storyboardOpen = useShotEditor((s) => s.storyboardOpen);
|
|
157
|
+
const storyboardSelection = useShotEditor((s) => s.storyboardSelection);
|
|
158
|
+
// Components' Preview tab names the definition whatever is selected inside
|
|
159
|
+
// it: `InspectorPanel`'s rule, so the head and the stack agree.
|
|
160
|
+
const studioFace = useShotEditor(
|
|
161
|
+
(s) => workspaceOf(s) === "components" && s.codeComponent === null && !componentEditOpen(s),
|
|
162
|
+
);
|
|
163
|
+
const selectedLayers = useSelectedLayers();
|
|
164
|
+
const layers = studioFace ? NO_LAYERS : selectedLayers;
|
|
165
|
+
if (doc === null) return null;
|
|
166
|
+
|
|
167
|
+
// RESOLVED, not merely selected, for both focused objects, the same rule
|
|
168
|
+
// `InspectorPanel` applies to each. A selection pointing at a marker or a
|
|
169
|
+
// camera move that an undo removed would otherwise name a subject with
|
|
170
|
+
// nothing behind it, while the panel below had already fallen through to the
|
|
171
|
+
// next branch.
|
|
172
|
+
const marker =
|
|
173
|
+
selectedMarker !== null && (doc.markers ?? []).some((m) => m.id === selectedMarker);
|
|
174
|
+
const cameraShot =
|
|
175
|
+
focused !== null && focused.sceneId === sceneId
|
|
176
|
+
? (doc.scenesById[focused.sceneId]?.shots.find((s) => s.id === focused.shotId) ?? null)
|
|
177
|
+
: null;
|
|
178
|
+
const scene = sceneId === null ? undefined : doc.scenesById[sceneId];
|
|
179
|
+
const one = layers.length === 1 ? layers[0] : undefined;
|
|
180
|
+
|
|
181
|
+
const subject = ((): Subject => {
|
|
182
|
+
// THE BOARD FIRST, `InspectorPanel`'s ladder: while it is open nothing on
|
|
183
|
+
// screen is a layer, a marker or a camera move.
|
|
184
|
+
if (storyboardOpen) {
|
|
185
|
+
const only = storyboardSelection.length === 1 ? storyboardSelection[0]! : null;
|
|
186
|
+
if (only !== null && isReferenceId(only)) {
|
|
187
|
+
const item = doc.resources?.references?.find((r) => r.id === only);
|
|
188
|
+
if (item !== undefined) {
|
|
189
|
+
return {
|
|
190
|
+
kind: "Reference",
|
|
191
|
+
name: item.label,
|
|
192
|
+
icon: REFERENCE_ICONS[cardKindOf(item, doc.assets)],
|
|
193
|
+
component: item.type === "component",
|
|
194
|
+
meta: null,
|
|
195
|
+
rename: {
|
|
196
|
+
ariaLabel: "Reference name",
|
|
197
|
+
id: `sb|${item.id}`,
|
|
198
|
+
commit: (label) => {
|
|
199
|
+
const trimmed = label.trim();
|
|
200
|
+
if (trimmed.length > 0) store.updateReference(item.id, { label: trimmed });
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// NO PLANNED-SHOT BRANCH. One planned shot picked is the Plan panel's
|
|
207
|
+
// (`boardRightPanel`), whose head names and renames it (`PartName`), so
|
|
208
|
+
// this panel never shows one alone.
|
|
209
|
+
const board = boardSubjectOf(doc, storyboardSelection);
|
|
210
|
+
if (board !== null && board.kind === "cut") {
|
|
211
|
+
// Named by the two Shots either side, and saved on the first:
|
|
212
|
+
// `StoryboardCutSection` edits the outgoing Shot's transition.
|
|
213
|
+
const a = shotNameOf(doc, board.sceneId);
|
|
214
|
+
return {
|
|
215
|
+
kind: "Transition",
|
|
216
|
+
name: `Between ${a} and ${shotNameOf(doc, board.cut.incoming)}`,
|
|
217
|
+
icon: TRANSITION_ICON,
|
|
218
|
+
component: false,
|
|
219
|
+
meta: `Transition · saved on ${a}`,
|
|
220
|
+
rename: null,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
if (board !== null && board.kind === "gap") {
|
|
224
|
+
// The move between two stills, named by them and placed by their
|
|
225
|
+
// times.
|
|
226
|
+
const stills = visibleStills(doc.scenesById[board.sceneId]!);
|
|
227
|
+
return {
|
|
228
|
+
kind: "Move",
|
|
229
|
+
name: `${stillNameOf(stills, board.gap.from)} → ${stillNameOf(stills, board.gap.to)}`,
|
|
230
|
+
icon: MOTION_NOTE_ICON,
|
|
231
|
+
component: false,
|
|
232
|
+
meta: `Move · ${shotNameOf(doc, board.sceneId)} · ${timecode(board.gap.from, doc.fps)} to ${timecode(board.gap.to, doc.fps)}`,
|
|
233
|
+
rename: null,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
if (storyboardSelection.length > 1) {
|
|
237
|
+
return {
|
|
238
|
+
kind: "Selection",
|
|
239
|
+
name: `${storyboardSelection.length} items`,
|
|
240
|
+
icon: DOCK_TOOL_ICONS.select,
|
|
241
|
+
component: false,
|
|
242
|
+
meta: null,
|
|
243
|
+
rename: null,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
kind: "Storyboard",
|
|
248
|
+
name: doc.title ?? doc.name,
|
|
249
|
+
icon: STORYBOARD_ICON,
|
|
250
|
+
component: false,
|
|
251
|
+
meta: null,
|
|
252
|
+
rename: null,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
if (marker && !storyboardOpen) {
|
|
256
|
+
// A dot in a ring is the transport grammar for a mark, and it is the one
|
|
257
|
+
// glyph in the set that reads as a point on a timeline rather than as a
|
|
258
|
+
// thing on the stage. A marker owns no icon of its own because it is not
|
|
259
|
+
// a layer kind.
|
|
260
|
+
return { kind: "Marker", name: null, icon: RECORD_ICON, component: false, meta: null, rename: null };
|
|
261
|
+
}
|
|
262
|
+
// BELOW THE SELECTION, for the same reason `editingDef` is. A camera move
|
|
263
|
+
// is only ever the panel's FOCUSED-OBJECT SLOT (`ShotSection` sits above
|
|
264
|
+
// the design stack, it does not replace it), and clicking a camera bar
|
|
265
|
+
// leaves the layer selection alone: the camera row never calls `select`,
|
|
266
|
+
// and `selectMove` clears only the marker, the keyframes and the audio.
|
|
267
|
+
// So with a rect selected and a camera bar focused, the head said "Camera
|
|
268
|
+
// move" over nine sections describing the rect. The marker branch above
|
|
269
|
+
// stays first because that one DOES replace the panel.
|
|
270
|
+
if (cameraShot !== null && layers.length === 0) {
|
|
271
|
+
return {
|
|
272
|
+
kind: "Camera move",
|
|
273
|
+
name: cameraShot.label,
|
|
274
|
+
icon: CAMERA_ICON,
|
|
275
|
+
component: false,
|
|
276
|
+
meta: null,
|
|
277
|
+
rename: null,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
if (one !== undefined) {
|
|
281
|
+
// A MASK SAYS SO (gap 7, Paper page 25): "Ellipse · mask" on the mask,
|
|
282
|
+
// "Group · masked by Circle" on the group that holds one.
|
|
283
|
+
const home = homeOf(doc, editingDef ?? sceneId ?? "");
|
|
284
|
+
const maskId = home === null ? null : maskTargetOf(home, one.id);
|
|
285
|
+
const maskWord =
|
|
286
|
+
maskId === null ? "" : maskId === one.id ? " · mask" : ` · masked by ${home!.layersById[maskId]!.label}`;
|
|
287
|
+
const kind = wordFor(one) + maskWord;
|
|
288
|
+
return {
|
|
289
|
+
kind,
|
|
290
|
+
name: one.label,
|
|
291
|
+
icon: maskId === null ? iconFor(one) : MASK_ICON,
|
|
292
|
+
component: maskId === null && isComponentGlyph(one),
|
|
293
|
+
meta: null,
|
|
294
|
+
rename: {
|
|
295
|
+
ariaLabel: "Layer name",
|
|
296
|
+
// The CONTAINER is in the key as well as the layer id: layer ids are
|
|
297
|
+
// scene-local, so the same id names a different layer after the
|
|
298
|
+
// playhead crosses a cut or the author enters a definition. Without
|
|
299
|
+
// it a draft typed here would commit into whatever layer inherited
|
|
300
|
+
// the id. Same reasoning as the panel's `subjectKey`.
|
|
301
|
+
id: `${editingDef ?? sceneId ?? "-"}|${one.id}`,
|
|
302
|
+
commit: (label) => store.renameLayer(one.id, label),
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
if (layers.length > 1) {
|
|
307
|
+
// The pointer, which is what "a selection" means everywhere else in this
|
|
308
|
+
// chrome. The layers do not agree on a kind, so no kind glyph can stand
|
|
309
|
+
// for them.
|
|
310
|
+
return {
|
|
311
|
+
kind: "Selection",
|
|
312
|
+
name: `${layers.length} layers`,
|
|
313
|
+
icon: DOCK_TOOL_ICONS.select,
|
|
314
|
+
component: false,
|
|
315
|
+
meta: null,
|
|
316
|
+
rename: null,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
if (editingDef !== null) {
|
|
320
|
+
const def = doc.components?.[editingDef];
|
|
321
|
+
// No rename here even though `renameComponent` exists: a definition's
|
|
322
|
+
// name is the name codegen emits, so it is edited where its other
|
|
323
|
+
// published facts are, in the section below.
|
|
324
|
+
return {
|
|
325
|
+
kind: "Component",
|
|
326
|
+
name: def?.name ?? editingDef,
|
|
327
|
+
icon: COMPONENT_ICON,
|
|
328
|
+
component: true,
|
|
329
|
+
meta: null,
|
|
330
|
+
rename: null,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
if (inShot && scene !== undefined && sceneId !== null) {
|
|
334
|
+
// The number is the shot's place in `doc.scenes` and the length is
|
|
335
|
+
// `formatDuration`, the same two strings the Tool footer and the left column's
|
|
336
|
+
// shot rows print, so one shot is never numbered or timed two ways.
|
|
337
|
+
const number = String(doc.scenes.indexOf(sceneId) + 1).padStart(2, "0");
|
|
338
|
+
return {
|
|
339
|
+
kind: "Shot",
|
|
340
|
+
name: scene.name,
|
|
341
|
+
icon: SCENE_ICON,
|
|
342
|
+
component: false,
|
|
343
|
+
meta: `Shot ${number} · ${formatDuration(framesToSeconds(scene.durationFrames, doc.fps))}`,
|
|
344
|
+
rename: {
|
|
345
|
+
ariaLabel: "Shot name",
|
|
346
|
+
id: sceneId,
|
|
347
|
+
commit: (name) => store.renameScene(sceneId, name),
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
// The scene context. `title` is optional through v13, so the generated
|
|
352
|
+
// component name is the fallback every other surface already falls back to.
|
|
353
|
+
//
|
|
354
|
+
// ── AND NO GLYPH, BECAUSE THE BORROWED ONE READ AS A BUTTON ─────────
|
|
355
|
+
//
|
|
356
|
+
// This was `kindIcon("group")` on the argument that a Project is the one
|
|
357
|
+
// thing here made OF the others. The glyph for that is two offset
|
|
358
|
+
// rectangles, which is also the universal glyph for DUPLICATE — sitting at
|
|
359
|
+
// 16px immediately left of the project's name, at the top of a panel whose
|
|
360
|
+
// every other small square is a control, it was read as a copy button and
|
|
361
|
+
// reported as one.
|
|
362
|
+
//
|
|
363
|
+
// No other icon is right either: the clapperboard is a single shot's and
|
|
364
|
+
// reusing it names the wrong altitude, and inventing a glyph for the one
|
|
365
|
+
// subject that is not on the stage teaches a symbol that appears nowhere
|
|
366
|
+
// else. The word PROJECT is already on the line, above the name, saying the same
|
|
367
|
+
// thing without the ambiguity — so the head runs without one here.
|
|
368
|
+
return {
|
|
369
|
+
kind: "Project",
|
|
370
|
+
name: doc.title ?? doc.name,
|
|
371
|
+
icon: null,
|
|
372
|
+
component: false,
|
|
373
|
+
meta: null,
|
|
374
|
+
// The title only: `doc.name` is the generated component's name, and
|
|
375
|
+
// SceneDocSection's Component row is its one writer.
|
|
376
|
+
rename: {
|
|
377
|
+
ariaLabel: "Project title",
|
|
378
|
+
id: "project",
|
|
379
|
+
commit: (title) => store.setProjectTitle(title),
|
|
380
|
+
},
|
|
381
|
+
};
|
|
382
|
+
})();
|
|
383
|
+
|
|
384
|
+
const name =
|
|
385
|
+
subject.name === null ? null : subject.rename === null ? (
|
|
386
|
+
// The title carries the full string, because the name is the one thing
|
|
387
|
+
// here that ellipsises and a truncated title with no way to read it is
|
|
388
|
+
// the defect this head exists to stop repeating.
|
|
389
|
+
<span className="insp-head-name" title={subject.name}>
|
|
390
|
+
{subject.name}
|
|
391
|
+
</span>
|
|
392
|
+
) : (
|
|
393
|
+
// KEYED ON THE SUBJECT so the draft dies with it. The head itself sits
|
|
394
|
+
// outside the panel's subject-keyed sections on purpose (InspectorPanel
|
|
395
|
+
// keys each section `${subjectKey}:${id}`; the head must not replay its
|
|
396
|
+
// entrance on every selection change), so this is where the
|
|
397
|
+
// "a draft must never commit into the next subject" rule is kept:
|
|
398
|
+
// crossing a cut mid-rename remounts the field and drops the text
|
|
399
|
+
// instead of writing shot A's name into shot B.
|
|
400
|
+
<RenameField
|
|
401
|
+
key={subject.rename.id}
|
|
402
|
+
value={subject.name}
|
|
403
|
+
ariaLabel={subject.rename.ariaLabel}
|
|
404
|
+
onCommit={subject.rename.commit}
|
|
405
|
+
/>
|
|
406
|
+
);
|
|
407
|
+
const shotHead = subject.meta !== null;
|
|
408
|
+
|
|
409
|
+
return (
|
|
410
|
+
<div className={`insp-head${shotHead ? " is-shot" : ""}`} data-testid="insp-head">
|
|
411
|
+
{subject.icon === null ? null : (
|
|
412
|
+
<span
|
|
413
|
+
className={`insp-head-icon${shotHead ? " is-tile" : ""}${subject.component ? " is-component" : ""}`}
|
|
414
|
+
>
|
|
415
|
+
{subject.icon}
|
|
416
|
+
</span>
|
|
417
|
+
)}
|
|
418
|
+
<div className="insp-head-text">
|
|
419
|
+
{shotHead ? null : <span className="insp-head-kind">{subject.kind}</span>}
|
|
420
|
+
{name}
|
|
421
|
+
{shotHead ? <span className="insp-head-meta">{subject.meta}</span> : null}
|
|
422
|
+
</div>
|
|
423
|
+
</div>
|
|
424
|
+
);
|
|
425
|
+
}
|