@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,235 @@
|
|
|
1
|
+
// THE ONE LIVE COMPONENT PREVIEW: the inspector lead of a selected component
|
|
2
|
+
// card, drawn by the SHOT STAGE, framed exactly as a Shot frames it.
|
|
3
|
+
//
|
|
4
|
+
// The stage itself (the second `/shot-stage.html`, the hosted epoch, the
|
|
5
|
+
// loop, the live budget and the poster) is `StagePreview`. This file builds
|
|
6
|
+
// the ONE-INSTANCE document it draws: the Project's size, fps and assets, one
|
|
7
|
+
// Shot, one instance layer the size of the frame. Nothing is saved.
|
|
8
|
+
//
|
|
9
|
+
// LOOPING, OR THE CARD'S FRAME. The preview loops over the component's length,
|
|
10
|
+
// at the Project's fps. A card that names a frame (the inspector's Frame row)
|
|
11
|
+
// shows that frame and holds it.
|
|
12
|
+
//
|
|
13
|
+
// IN BUDGET BY THE CARD'S ID, so a card that already holds that slot shares it
|
|
14
|
+
// rather than taking a second, and the poster is keyed by the component, its
|
|
15
|
+
// content hash and the card's props (posterCache.ts).
|
|
16
|
+
//
|
|
17
|
+
// A CODE COMPONENT OR A STUDIO DEFINITION. A card naming `def` draws a slim
|
|
18
|
+
// document of that definition's closure (`defClosureOf`), placed once with
|
|
19
|
+
// the card's props as its overrides, so an edit elsewhere in the Project
|
|
20
|
+
// never reloads the preview.
|
|
21
|
+
import { useMemo, useState } from "react";
|
|
22
|
+
import type { ReactNode } from "react";
|
|
23
|
+
import { canonicalJSON, fnv1a64 } from "@dailies-studio/contract";
|
|
24
|
+
import type { Contract, EmbedContractRef } from "@dailies-studio/contract";
|
|
25
|
+
import {
|
|
26
|
+
addComponentInstance,
|
|
27
|
+
componentPreviewDoc,
|
|
28
|
+
defClosureOf,
|
|
29
|
+
defDurationFrames,
|
|
30
|
+
previewBaseDoc,
|
|
31
|
+
previewBindingOf,
|
|
32
|
+
} from "@dailies-studio/shot/doc";
|
|
33
|
+
import type { DefClosure, Doc3D, ReferenceItem3D } from "@dailies-studio/shot/doc";
|
|
34
|
+
import { brandBackdrop } from "../../bridgeTypes.js";
|
|
35
|
+
import type { ShotComponentBackground } from "../../bridgeTypes.js";
|
|
36
|
+
import { posterKey } from "./posterCache.js";
|
|
37
|
+
import { StagePreview } from "./StagePreview.js";
|
|
38
|
+
|
|
39
|
+
type ComponentCard = Extract<ReferenceItem3D, { type: "component" }>;
|
|
40
|
+
|
|
41
|
+
/** How long a preview loops when the catalog names no length: two seconds. */
|
|
42
|
+
export const DEFAULT_LOOP_SECONDS = 2;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The one-instance document the preview stage draws. Pure, so the suite pins
|
|
46
|
+
* it without a stage.
|
|
47
|
+
*
|
|
48
|
+
* The CARD'S RAW PROPS, never harness-resolved paths: the stage maps an
|
|
49
|
+
* asset-kind value through `doc.assets` itself, so the Project's asset table
|
|
50
|
+
* rides along. The contract rides as the binding an instance layer would get
|
|
51
|
+
* (`contractBinding`), because without one the stage spreads raw contract
|
|
52
|
+
* keys as React prop names.
|
|
53
|
+
*/
|
|
54
|
+
export function cardStageDoc(
|
|
55
|
+
doc: Pick<Doc3D, "size" | "fps" | "assets">,
|
|
56
|
+
item: ComponentCard,
|
|
57
|
+
binding: EmbedContractRef | undefined,
|
|
58
|
+
lengthFrames: number,
|
|
59
|
+
backdrop?: string,
|
|
60
|
+
): Doc3D {
|
|
61
|
+
// The shot package's builder, which `preview_component` draws too.
|
|
62
|
+
return componentPreviewDoc(
|
|
63
|
+
doc,
|
|
64
|
+
{ component: item.component ?? "", label: item.label, props: item.props, binding },
|
|
65
|
+
lengthFrames,
|
|
66
|
+
backdrop,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The one-instance document for a STUDIO DEFINITION's card: the closure's
|
|
72
|
+
* definitions, assets and material graphs, one placement of the definition at
|
|
73
|
+
* 1:1 in the middle of the Project's frame, the card's props as its
|
|
74
|
+
* overrides. Pure, like `cardStageDoc`. Null when the placement is refused.
|
|
75
|
+
*/
|
|
76
|
+
export function defStageDoc(
|
|
77
|
+
doc: Pick<Doc3D, "size" | "fps">,
|
|
78
|
+
closure: DefClosure,
|
|
79
|
+
props: ComponentCard["props"],
|
|
80
|
+
lengthFrames: number,
|
|
81
|
+
backdrop?: string,
|
|
82
|
+
): Doc3D | null {
|
|
83
|
+
const { sized, sceneId } = previewBaseDoc({ size: doc.size, fps: doc.fps, assets: closure.assets }, lengthFrames, backdrop);
|
|
84
|
+
const withDefs: Doc3D = {
|
|
85
|
+
...sized,
|
|
86
|
+
components: { ...closure.nested, [closure.def.id]: closure.def },
|
|
87
|
+
...(Object.keys(closure.materials).length === 0 ? {} : { materials: closure.materials }),
|
|
88
|
+
};
|
|
89
|
+
const placed = addComponentInstance(withDefs, sceneId, closure.def.id);
|
|
90
|
+
if (placed.instanceId === null) return null;
|
|
91
|
+
const scene = placed.doc.scenesById[sceneId]!;
|
|
92
|
+
const layer = scene.layersById[placed.instanceId];
|
|
93
|
+
if (layer?.kind !== "component") return null;
|
|
94
|
+
return {
|
|
95
|
+
...placed.doc,
|
|
96
|
+
scenesById: {
|
|
97
|
+
...placed.doc.scenesById,
|
|
98
|
+
[sceneId]: {
|
|
99
|
+
...scene,
|
|
100
|
+
layersById: { ...scene.layersById, [layer.id]: { ...layer, component: { ...layer.component, overrides: props } } },
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** A closure's content as a hash: what the poster key and the stage document
|
|
107
|
+
* follow, so an unrelated edit leaves both alone. */
|
|
108
|
+
export function closureHash(closure: DefClosure | null): string {
|
|
109
|
+
if (closure === null) return "none";
|
|
110
|
+
try {
|
|
111
|
+
return fnv1a64(canonicalJSON(closure));
|
|
112
|
+
} catch {
|
|
113
|
+
return fnv1a64(JSON.stringify(closure));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Closures and their hashes, per document revision: a doc is immutable, so
|
|
118
|
+
* every card and the sheet that render one revision walk and hash each
|
|
119
|
+
* definition once, and the revision's entries go with it. */
|
|
120
|
+
const closures = new WeakMap<Doc3D, Map<string, { closure: DefClosure | null; hash: string }>>();
|
|
121
|
+
|
|
122
|
+
/** `defClosureOf` and its `closureHash`, memoized per document revision. */
|
|
123
|
+
export function closureFor(doc: Doc3D, defId: string): { closure: DefClosure | null; hash: string } {
|
|
124
|
+
let byDef = closures.get(doc);
|
|
125
|
+
if (byDef === undefined) {
|
|
126
|
+
byDef = new Map();
|
|
127
|
+
closures.set(doc, byDef);
|
|
128
|
+
}
|
|
129
|
+
let hit = byDef.get(defId);
|
|
130
|
+
if (hit === undefined) {
|
|
131
|
+
const closure = defClosureOf(doc, defId);
|
|
132
|
+
hit = { closure, hash: closureHash(closure) };
|
|
133
|
+
byDef.set(defId, hit);
|
|
134
|
+
}
|
|
135
|
+
return hit;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** `value` as it was the last time `key` changed: derived state held across
|
|
139
|
+
* renders the React way (a set during render). */
|
|
140
|
+
function useStableBy<T>(value: T, key: string): T {
|
|
141
|
+
const [held, setHeld] = useState({ key, value });
|
|
142
|
+
if (held.key !== key) {
|
|
143
|
+
setHeld({ key, value });
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
return held.value;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* The preview's ground as a colour (bridge v45): dark is the desk token,
|
|
151
|
+
* light the paper token, brand the Project's first brand colour or else dark.
|
|
152
|
+
* Read off the chrome's own tokens, since the card document is a plain Shot.
|
|
153
|
+
*/
|
|
154
|
+
export function cardBackdrop(background: ShotComponentBackground, doc: Pick<Doc3D, "resources"> | null): string {
|
|
155
|
+
const token = (name: string, fallback: string): string =>
|
|
156
|
+
typeof document === "undefined"
|
|
157
|
+
? fallback
|
|
158
|
+
: getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
|
|
159
|
+
const desk = token("--surface-sunken", "#080808");
|
|
160
|
+
if (background === "light") return token("--paper-97", "#f5f5f8");
|
|
161
|
+
if (background === "brand") return brandBackdrop(doc) ?? desk;
|
|
162
|
+
return desk;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* THE BINDING A PLACED INSTANCE WOULD CARRY, `store.bindingFor`'s rule: the
|
|
167
|
+
* server's availability decides import or snapshot. Null when there is no
|
|
168
|
+
* contract, or when it cannot be frozen (a snapshot refuses a contract whose
|
|
169
|
+
* hashes do not describe its keys): the preview then draws with raw props
|
|
170
|
+
* rather than throwing inside a render and taking the inspector down.
|
|
171
|
+
*/
|
|
172
|
+
export function contractBinding(
|
|
173
|
+
contract: Contract | undefined,
|
|
174
|
+
availability: "sibling" | "colocated" | "inferred" | undefined,
|
|
175
|
+
): EmbedContractRef | undefined {
|
|
176
|
+
return contract === undefined ? undefined : previewBindingOf({ availability: availability ?? "inferred", contract });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function ComponentStage(props: {
|
|
180
|
+
doc: Doc3D;
|
|
181
|
+
item: ComponentCard;
|
|
182
|
+
contract: Contract | undefined;
|
|
183
|
+
/** The registry row's verdict: import the contract, or freeze it. */
|
|
184
|
+
availability: "sibling" | "colocated" | "inferred" | undefined;
|
|
185
|
+
/** The shipped item's length, when the catalog says; else two seconds. */
|
|
186
|
+
lengthFrames: number | undefined;
|
|
187
|
+
/** The ground behind the component (bridge v45). Omitted keeps the Shot's. */
|
|
188
|
+
background?: ShotComponentBackground;
|
|
189
|
+
/** Loops over this many frames instead of the component's length. */
|
|
190
|
+
loopFrames?: number;
|
|
191
|
+
/** Whether the stage may go live. False shows the poster (default true). */
|
|
192
|
+
live?: boolean;
|
|
193
|
+
/** What shows while the stage is not live and no poster is cached yet. */
|
|
194
|
+
fallback?: ReactNode;
|
|
195
|
+
}) {
|
|
196
|
+
const { doc, item, contract, availability } = props;
|
|
197
|
+
const fps = doc.fps.num / doc.fps.den;
|
|
198
|
+
// A STUDIO DEFINITION'S closure, held while its content is the same.
|
|
199
|
+
const defId = item.component === undefined ? item.def : undefined;
|
|
200
|
+
const own = defId === undefined ? null : closureFor(doc, defId);
|
|
201
|
+
const freshClosure = own?.closure ?? null;
|
|
202
|
+
const contentHash = own === null ? (contract?.contractHash ?? item.contractHash ?? "none") : own.hash;
|
|
203
|
+
const closure = useStableBy(freshClosure, contentHash);
|
|
204
|
+
const ownLength = closure === null ? props.lengthFrames : defDurationFrames(closure.def);
|
|
205
|
+
const length = Math.max(1, Math.round(props.loopFrames ?? ownLength ?? DEFAULT_LOOP_SECONDS * fps));
|
|
206
|
+
const backdrop = props.background === undefined ? undefined : cardBackdrop(props.background, doc);
|
|
207
|
+
const binding = useMemo(() => contractBinding(contract, availability), [contract, availability]);
|
|
208
|
+
// KEYED ON WHAT THE CARD DOCUMENT READS, never on `doc` itself: every edit
|
|
209
|
+
// anywhere in the Project is a new `doc`, and a new stage document reloads
|
|
210
|
+
// the preview.
|
|
211
|
+
const { width, height } = doc.size;
|
|
212
|
+
const { num, den } = doc.fps;
|
|
213
|
+
const assets = doc.assets;
|
|
214
|
+
const stageDoc = useMemo(
|
|
215
|
+
() =>
|
|
216
|
+
closure !== null
|
|
217
|
+
? defStageDoc({ size: { width, height }, fps: { num, den } }, closure, item.props, length, backdrop)
|
|
218
|
+
: cardStageDoc({ size: { width, height }, fps: { num, den }, assets }, item, binding, length, backdrop),
|
|
219
|
+
[width, height, num, den, assets, item, closure, binding, length, backdrop],
|
|
220
|
+
);
|
|
221
|
+
const size = useMemo(() => ({ width, height }), [width, height]);
|
|
222
|
+
return (
|
|
223
|
+
<StagePreview
|
|
224
|
+
doc={stageDoc}
|
|
225
|
+
size={size}
|
|
226
|
+
lengthFrames={length}
|
|
227
|
+
{...(item.frame === undefined ? {} : { frame: item.frame })}
|
|
228
|
+
{...(props.live === undefined ? {} : { live: props.live })}
|
|
229
|
+
slotKey={item.id}
|
|
230
|
+
posterKey={posterKey(item.component ?? item.def ?? item.id, contentHash, item.props)}
|
|
231
|
+
title={`Preview of ${item.label}`}
|
|
232
|
+
fallback={props.fallback}
|
|
233
|
+
/>
|
|
234
|
+
);
|
|
235
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// A SKETCH, SMALL (Paper SB1 card pictures, SB2 strip thumbs, the Brief's
|
|
2
|
+
// thumbs): the board's shot cards and any thumbnail of a sketch. It only
|
|
3
|
+
// draws: no selection, no handles, no pointer.
|
|
4
|
+
//
|
|
5
|
+
// THE STAGE'S PICTURE FIRST. Its caller passes `picture`, the sketch as the
|
|
6
|
+
// still stage draws it (state/stillThumbs.ts, `useSketchThumbs`: brand font,
|
|
7
|
+
// components and all, the same picture the agent's screenshot_shot
|
|
8
|
+
// `{sketch}` returns). Once it is ready it fills the box. Until then, and when
|
|
9
|
+
// it failed, the sketch is drawn in the DOM, below.
|
|
10
|
+
//
|
|
11
|
+
// ONE BOX, ANY WIDTH. Items sit in percentages of the Project's size (layer
|
|
12
|
+
// units: design px, origin at the centre, +y down), and type sizes in `cqw`
|
|
13
|
+
// of the box, so the same markup is right at 128 or at 346 wide and nothing
|
|
14
|
+
// measures. Back to front, as stored: a later item draws on top.
|
|
15
|
+
//
|
|
16
|
+
// ref an image card's picture (`useImageThumb`), a video's poster, a
|
|
17
|
+
// component's name tile, or "Missing" for a card that is gone
|
|
18
|
+
// text the words at their role's size (`SKETCH_TEXT_SIZE`)
|
|
19
|
+
// box the light sketch fill with its edge, dark, or the accent; the
|
|
20
|
+
// label in its corner
|
|
21
|
+
// arrow one SVG line with an open head, its label over the head
|
|
22
|
+
import type { CSSProperties } from "react";
|
|
23
|
+
import { SKETCH_TEXT_SIZE, sketchCardOf } from "@dailies-studio/shot/doc";
|
|
24
|
+
import type { Doc3D, SketchItem3D, SketchRef3D, StoryboardSketch3D } from "@dailies-studio/shot/doc";
|
|
25
|
+
import { useImageThumb } from "../../state/imageThumbs.js";
|
|
26
|
+
import type { StillThumb } from "../../state/stillThumbs.js";
|
|
27
|
+
import { MediaPoster } from "./ReferencePreview.js";
|
|
28
|
+
|
|
29
|
+
const assetUrl = (path: string): string => `/studio/assets/${encodeURIComponent(path)}`;
|
|
30
|
+
|
|
31
|
+
/** A box label's size, design px: the stage's label size (sketch.ts). */
|
|
32
|
+
const LABEL_SIZE = 24;
|
|
33
|
+
/** The open head's arm, design px. */
|
|
34
|
+
const ARROW_HEAD = 36;
|
|
35
|
+
|
|
36
|
+
export function MiniSketch(props: {
|
|
37
|
+
doc: Doc3D;
|
|
38
|
+
sketch: StoryboardSketch3D;
|
|
39
|
+
/** The longest side the pictures inside are fetched for, CSS px. */
|
|
40
|
+
width: number;
|
|
41
|
+
className?: string;
|
|
42
|
+
/** The sketch as the still stage draws it; shown once ready. */
|
|
43
|
+
picture?: StillThumb | null;
|
|
44
|
+
}) {
|
|
45
|
+
const { doc, sketch } = props;
|
|
46
|
+
const { width: w, height: h } = doc.size;
|
|
47
|
+
const arrows = sketch.items.filter((item) => item.kind === "arrow");
|
|
48
|
+
const box = {
|
|
49
|
+
className: `mini-sketch${props.className === undefined ? "" : ` ${props.className}`}`,
|
|
50
|
+
"data-ground": sketch.ground ?? "paper",
|
|
51
|
+
"data-testid": "mini-sketch",
|
|
52
|
+
style: { aspectRatio: `${w} / ${h}` },
|
|
53
|
+
"aria-hidden": true,
|
|
54
|
+
} as const;
|
|
55
|
+
if (props.picture?.status === "ready") {
|
|
56
|
+
return (
|
|
57
|
+
<div {...box} data-picture="stage">
|
|
58
|
+
<img className="mini-sketch-picture" src={props.picture.url} alt="" draggable={false} />
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
return (
|
|
63
|
+
<div {...box} data-picture="dom">
|
|
64
|
+
{sketch.items.map((item) =>
|
|
65
|
+
item.kind === "arrow" ? null : <MiniItem key={item.id} doc={doc} item={item} width={props.width} />,
|
|
66
|
+
)}
|
|
67
|
+
{arrows.length === 0 ? null : (
|
|
68
|
+
<svg className="mini-sketch-arrows" viewBox={`${-w / 2} ${-h / 2} ${w} ${h}`} preserveAspectRatio="none">
|
|
69
|
+
{arrows.map((item) => (item.kind === "arrow" ? <path key={item.id} d={arrowPath(item.from, item.to)} /> : null))}
|
|
70
|
+
</svg>
|
|
71
|
+
)}
|
|
72
|
+
{arrows.map((item) =>
|
|
73
|
+
item.kind !== "arrow" || item.label === undefined ? null : (
|
|
74
|
+
<span key={`${item.id}-label`} className="mini-sketch-label is-arrow" style={labelAt(doc, item.to)}>
|
|
75
|
+
{item.label}
|
|
76
|
+
</span>
|
|
77
|
+
),
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** The arrow's line and its open head, in design px. */
|
|
84
|
+
export function arrowPath(from: readonly [number, number], to: readonly [number, number]): string {
|
|
85
|
+
const angle = Math.atan2(to[1] - from[1], to[0] - from[0]);
|
|
86
|
+
const arm = (turn: number): string =>
|
|
87
|
+
`${to[0] - ARROW_HEAD * Math.cos(angle + turn)} ${to[1] - ARROW_HEAD * Math.sin(angle + turn)}`;
|
|
88
|
+
return `M ${from[0]} ${from[1]} L ${to[0]} ${to[1]} M ${arm(Math.PI / 6)} L ${to[0]} ${to[1]} L ${arm(-Math.PI / 6)}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** An item's box as percentages of the sketch: position is its centre. */
|
|
92
|
+
export function boxStyle(doc: Doc3D, position: readonly [number, number], size: readonly [number, number]): CSSProperties {
|
|
93
|
+
const { width: w, height: h } = doc.size;
|
|
94
|
+
return {
|
|
95
|
+
left: `${((position[0] - size[0] / 2) / w + 0.5) * 100}%`,
|
|
96
|
+
top: `${((position[1] - size[1] / 2) / h + 0.5) * 100}%`,
|
|
97
|
+
width: `${(size[0] / w) * 100}%`,
|
|
98
|
+
height: `${(size[1] / h) * 100}%`,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Type of `px` design px, as a share of the box's width. */
|
|
103
|
+
const typeSize = (doc: Doc3D, px: number): string => `${(px / doc.size.width) * 100}cqw`;
|
|
104
|
+
|
|
105
|
+
/** An arrow's label, centred over its head. */
|
|
106
|
+
const labelAt = (doc: Doc3D, to: readonly [number, number]): CSSProperties => ({
|
|
107
|
+
left: `${(to[0] / doc.size.width + 0.5) * 100}%`,
|
|
108
|
+
top: `${((to[1] - 40) / doc.size.height + 0.5) * 100}%`,
|
|
109
|
+
fontSize: typeSize(doc, LABEL_SIZE),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
function MiniItem({ doc, item, width }: { doc: Doc3D; item: Exclude<SketchItem3D, { kind: "arrow" }>; width: number }) {
|
|
113
|
+
const box = boxStyle(doc, item.position, item.size);
|
|
114
|
+
if (item.kind === "text") {
|
|
115
|
+
return (
|
|
116
|
+
<span
|
|
117
|
+
className={`mini-sketch-text is-${item.role}`}
|
|
118
|
+
data-align={item.align ?? "start"}
|
|
119
|
+
style={{ ...box, fontSize: typeSize(doc, SKETCH_TEXT_SIZE[item.role]) }}
|
|
120
|
+
>
|
|
121
|
+
{item.text}
|
|
122
|
+
</span>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
if (item.kind === "box") {
|
|
126
|
+
return (
|
|
127
|
+
<span className="mini-sketch-box" data-tone={item.tone ?? "light"} style={box}>
|
|
128
|
+
{item.label === undefined ? null : (
|
|
129
|
+
<span className="mini-sketch-label" style={{ fontSize: typeSize(doc, LABEL_SIZE) }}>
|
|
130
|
+
{item.label}
|
|
131
|
+
</span>
|
|
132
|
+
)}
|
|
133
|
+
</span>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
return <MiniRef doc={doc} item={item} style={box} px={(item.size[0] / doc.size.width) * width} />;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function MiniRef({ doc, item, style, px }: { doc: Doc3D; item: SketchRef3D; style: CSSProperties; px: number }) {
|
|
140
|
+
const card = sketchCardOf(doc, item);
|
|
141
|
+
const asset = card?.type === "asset" ? doc.assets[card.asset] : undefined;
|
|
142
|
+
const image = asset?.kind === "image" ? asset : undefined;
|
|
143
|
+
const thumb = useImageThumb(image === undefined ? "" : assetUrl(image.path), image?.hash ?? "", px);
|
|
144
|
+
const fit = item.fit ?? "cover";
|
|
145
|
+
if (image !== undefined) {
|
|
146
|
+
return (
|
|
147
|
+
<span className="mini-sketch-ref" style={style}>
|
|
148
|
+
{thumb === null ? null : <img src={thumb} alt="" draggable={false} style={{ objectFit: fit }} />}
|
|
149
|
+
</span>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
if (asset?.kind === "video" && card?.type === "asset") {
|
|
153
|
+
const at = card.frame === undefined ? null : (card.frame * doc.fps.den) / doc.fps.num;
|
|
154
|
+
return (
|
|
155
|
+
<span className="mini-sketch-ref" style={style}>
|
|
156
|
+
<MediaPoster className="mini-sketch-media" src={assetUrl(asset.path)} atSeconds={at} />
|
|
157
|
+
</span>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
const name =
|
|
161
|
+
card === undefined
|
|
162
|
+
? "Missing"
|
|
163
|
+
: card.type === "component"
|
|
164
|
+
? ((card.def === undefined ? undefined : doc.components?.[card.def]?.name) ?? card.label)
|
|
165
|
+
: card.label;
|
|
166
|
+
return (
|
|
167
|
+
<span className={`mini-sketch-ref is-tile${card === undefined ? " is-missing" : ""}`} style={style}>
|
|
168
|
+
<span className="mini-sketch-label" style={{ fontSize: typeSize(doc, LABEL_SIZE) }}>
|
|
169
|
+
{name}
|
|
170
|
+
</span>
|
|
171
|
+
</span>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// ATTACHED TO WHICH PART: the one control a Group, a card and the card's own
|
|
2
|
+
// chip on the canvas all need, in one place.
|
|
3
|
+
//
|
|
4
|
+
// A COMBOBOX, by the house line written at `scene/TransitionSection.tsx`: four
|
|
5
|
+
// options or fewer is a segmented control, a list that grows wants the filter
|
|
6
|
+
// box. Parts are author-created and unbounded, and their labels are unbounded
|
|
7
|
+
// prose in a 252px row.
|
|
8
|
+
//
|
|
9
|
+
// It replaced `<select className="insp-select">`, and that class matched NO
|
|
10
|
+
// rule anywhere in the repo, so the element fell back to user-agent styling
|
|
11
|
+
// with three visible consequences: the OS dropdown arrow instead of the
|
|
12
|
+
// painted chevron (`.select { appearance: none }`), no `max-width: 100%`, and
|
|
13
|
+
// no `min-width: 0` from the in-pill flattener. A native select's automatic
|
|
14
|
+
// minimum size is its longest option, so one long part label pushed the whole
|
|
15
|
+
// inspector into a horizontal scrollbar. The comment over `.select` in
|
|
16
|
+
// `shot-editor/styles.css` is that same failure's earlier postmortem.
|
|
17
|
+
//
|
|
18
|
+
// An UNKNOWN part id is shown rather than silently read as "none": a document
|
|
19
|
+
// can name a part this board no longer has, and a picker that displayed the
|
|
20
|
+
// placeholder would rewrite the binding on the next unrelated edit. Same
|
|
21
|
+
// courtesy `TransitionSection` pays an unknown preset.
|
|
22
|
+
import { Combobox } from "@dailies-studio/ui";
|
|
23
|
+
import type { ComboboxOption } from "@dailies-studio/ui";
|
|
24
|
+
import type { StoryboardPart3D } from "@dailies-studio/shot/doc";
|
|
25
|
+
|
|
26
|
+
/** The empty value IS "no part". `Combobox` shows the placeholder for it, so
|
|
27
|
+
* the trigger reads the none-label without a sentinel id that could ever be
|
|
28
|
+
* mistaken for one. */
|
|
29
|
+
const NONE = "";
|
|
30
|
+
|
|
31
|
+
export function PartPicker(props: {
|
|
32
|
+
parts: readonly StoryboardPart3D[];
|
|
33
|
+
value: string | null;
|
|
34
|
+
/** What "no part" is called here: a group becomes plain, a card unassigned.
|
|
35
|
+
* Choosing it IS the unlink, which is why no menu puts an Unlink button
|
|
36
|
+
* beside a picker whose empty value already says so. */
|
|
37
|
+
noneLabel: string;
|
|
38
|
+
ariaLabel: string;
|
|
39
|
+
onChange: (part: string | null) => void;
|
|
40
|
+
/** Open on mount and take focus: for the card chip, which SWAPS itself for
|
|
41
|
+
* this control on a press and would otherwise drop focus to `<body>`. */
|
|
42
|
+
autoOpen?: boolean;
|
|
43
|
+
/** Dismissed without choosing, so a swapping caller can put its own control
|
|
44
|
+
* back rather than leaving a closed picker in its place. */
|
|
45
|
+
onClose?: () => void;
|
|
46
|
+
}) {
|
|
47
|
+
const known = props.value !== null && props.parts.some((part) => part.id === props.value);
|
|
48
|
+
const options: ComboboxOption[] = [
|
|
49
|
+
{ value: NONE, label: props.noneLabel },
|
|
50
|
+
...props.parts.map((part) => ({ value: part.id, label: part.label })),
|
|
51
|
+
...(props.value !== null && !known ? [{ value: props.value, label: `${props.value} (unknown)` }] : []),
|
|
52
|
+
];
|
|
53
|
+
return (
|
|
54
|
+
<Combobox
|
|
55
|
+
options={options}
|
|
56
|
+
value={props.value ?? NONE}
|
|
57
|
+
ariaLabel={props.ariaLabel}
|
|
58
|
+
placeholder={props.noneLabel}
|
|
59
|
+
onChange={(value) => props.onChange(value === NONE ? null : value)}
|
|
60
|
+
{...(props.autoOpen === undefined ? {} : { autoOpen: props.autoOpen })}
|
|
61
|
+
{...(props.onClose === undefined ? {} : { onClose: props.onClose })}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}
|