@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,60 @@
|
|
|
1
|
+
// The way out when a Project's file is gone from storage (F3). The server
|
|
2
|
+
// lists such rows in `assetUsage.missing` and still saves; this names the
|
|
3
|
+
// first one and offers Relink (upload it again, same row) and Remove (the
|
|
4
|
+
// row and the layers that show it). One at a time: fixing one shows the next.
|
|
5
|
+
import { useRef } from "react";
|
|
6
|
+
import { useShotEditor, useStore } from "../../state/context.js";
|
|
7
|
+
import { UPLOAD_ACCEPT, fileNameOf } from "./resourceParts.js";
|
|
8
|
+
|
|
9
|
+
export function MissingAssetsNotice() {
|
|
10
|
+
const store = useStore();
|
|
11
|
+
const doc = useShotEditor((state) => state.doc);
|
|
12
|
+
const missing = useShotEditor((state) => state.assetUsage?.missing);
|
|
13
|
+
const picker = useRef<HTMLInputElement | null>(null);
|
|
14
|
+
// Only rows the document still has at that path: a relink or a remove
|
|
15
|
+
// clears the notice now, not at the next save's refresh.
|
|
16
|
+
const rows = (missing ?? []).flatMap((row) => {
|
|
17
|
+
const asset = doc?.assets[row.id];
|
|
18
|
+
return asset !== undefined && asset.path === row.path ? [asset] : [];
|
|
19
|
+
});
|
|
20
|
+
const first = rows[0];
|
|
21
|
+
if (first === undefined) return null;
|
|
22
|
+
const name = fileNameOf(first);
|
|
23
|
+
const more = rows.length - 1;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className="overlay-message is-sticky" data-testid="missing-assets">
|
|
27
|
+
<span>
|
|
28
|
+
{more === 0
|
|
29
|
+
? `${name} is missing from this Project. Saving still works.`
|
|
30
|
+
: `${name} and ${more} more ${more === 1 ? "file are" : "files are"} missing from this Project. Saving still works.`}
|
|
31
|
+
</span>
|
|
32
|
+
<input
|
|
33
|
+
ref={picker}
|
|
34
|
+
type="file"
|
|
35
|
+
hidden
|
|
36
|
+
accept={UPLOAD_ACCEPT}
|
|
37
|
+
data-testid="missing-assets-input"
|
|
38
|
+
onChange={(event) => {
|
|
39
|
+
const file = event.target.files?.[0];
|
|
40
|
+
event.target.value = "";
|
|
41
|
+
if (file === undefined) return;
|
|
42
|
+
store.relinkAsset(first.id, file).catch((error: unknown) => {
|
|
43
|
+
store.reportError(error instanceof Error ? error.message : String(error));
|
|
44
|
+
});
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
<button type="button" className="overlay-action" onClick={() => picker.current?.click()}>
|
|
48
|
+
Relink file
|
|
49
|
+
</button>
|
|
50
|
+
<button
|
|
51
|
+
type="button"
|
|
52
|
+
className="overlay-action"
|
|
53
|
+
title={`Take ${name} and the layers that show it out of this Project. Undo brings them back.`}
|
|
54
|
+
onClick={() => store.removeMissingAsset(first.id)}
|
|
55
|
+
>
|
|
56
|
+
Remove
|
|
57
|
+
</button>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// DRAGGING A FILE OUT OF THE BOARD'S ASSETS PANEL AND ONTO THE BOARD.
|
|
2
|
+
//
|
|
3
|
+
// ── THE PAYLOAD IS THE STORYBOARD'S SHAPE, AND A SEPARATE MIME ──────────
|
|
4
|
+
//
|
|
5
|
+
// `storyboardDrop.ts` established the format: one vendor MIME carrying JSON,
|
|
6
|
+
// mirrored to `text/plain` because Safari drops custom types on some paths, and
|
|
7
|
+
// `text/plain` trusted only when it parses as OUR json so the outliner's plain
|
|
8
|
+
// layer ids never read as a card. This lane copies that rule and NOT that MIME.
|
|
9
|
+
//
|
|
10
|
+
// A separate type is what keeps the targets honest about what they accept: a
|
|
11
|
+
// file lands as a new card made for it (`addReferenceForAsset`), never as a
|
|
12
|
+
// move of a card that exists. Sharing one MIME would make that a parse of the
|
|
13
|
+
// payload's `kind` at each target, a type test written twice. Two MIMEs, and
|
|
14
|
+
// `dataTransfer.types` answers "can I take this" before anything is read.
|
|
15
|
+
import type { ShotEditorState } from "../../state/types.js";
|
|
16
|
+
|
|
17
|
+
export const ASSET_MIME = "application/x-dailies-asset";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether a drop target for an asset drag is ON SCREEN, which is the only
|
|
21
|
+
* condition under which a tile may be picked up.
|
|
22
|
+
*
|
|
23
|
+
* The readers of `ASSET_MIME` are the board's canvas and its shot cards
|
|
24
|
+
* (BoardCanvas, ShotCard), so a tile drags while the board is open. Anywhere
|
|
25
|
+
* else a pickup is a gesture with nowhere to land, and "Use in shot" is the
|
|
26
|
+
* way in.
|
|
27
|
+
*/
|
|
28
|
+
export function assetDropTargetShown(s: Pick<ShotEditorState, "doc" | "storyboardOpen">): boolean {
|
|
29
|
+
return s.doc !== null && s.storyboardOpen;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** What a tile says while it can be dragged: what the board's drop does. */
|
|
33
|
+
export const ASSET_DROP_COPY = "Drag onto the board or a shot to pin it";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* What an asset drag CARRIES: the registry id, and nothing else.
|
|
37
|
+
*
|
|
38
|
+
* Not the path, not the kind, not the size. All three are on the `ShotAsset`
|
|
39
|
+
* row the id addresses, and a drop resolves the id against the document it is
|
|
40
|
+
* landing in — so a payload that carried a copy could disagree with the
|
|
41
|
+
* registry after an undo, and the disagreement would be invisible until the
|
|
42
|
+
* layer drew the wrong file.
|
|
43
|
+
*/
|
|
44
|
+
export interface AssetDragPayload {
|
|
45
|
+
asset: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Only `setData` and `effectAllowed`, which is all a jsdom test can hand a
|
|
49
|
+
* synthetic drag. */
|
|
50
|
+
export type DragWriter = Pick<DataTransfer, "setData"> & { effectAllowed?: string };
|
|
51
|
+
|
|
52
|
+
export function writeAssetDrag(dataTransfer: DragWriter, payload: AssetDragPayload): void {
|
|
53
|
+
const text = JSON.stringify(payload);
|
|
54
|
+
dataTransfer.setData(ASSET_MIME, text);
|
|
55
|
+
dataTransfer.setData("text/plain", text);
|
|
56
|
+
// COPY, not move. The registry row stays where it is: placing an asset mints
|
|
57
|
+
// a layer that points at it, and the same file may be placed many times.
|
|
58
|
+
dataTransfer.effectAllowed = "copy";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Reads only `types` and `getData`, for the reason above. */
|
|
62
|
+
export function readAssetDrag(
|
|
63
|
+
dataTransfer: Pick<DataTransfer, "types" | "getData">,
|
|
64
|
+
): AssetDragPayload | null {
|
|
65
|
+
const types = Array.from(dataTransfer.types ?? []);
|
|
66
|
+
if (types.includes(ASSET_MIME)) return parsePayload(dataTransfer.getData(ASSET_MIME));
|
|
67
|
+
return types.includes("text/plain") ? parsePayload(dataTransfer.getData("text/plain")) : null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function parsePayload(text: string): AssetDragPayload | null {
|
|
71
|
+
try {
|
|
72
|
+
const parsed = JSON.parse(text) as unknown;
|
|
73
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
74
|
+
const asset = (parsed as Record<string, unknown>)["asset"];
|
|
75
|
+
return typeof asset === "string" && asset !== "" ? { asset } : null;
|
|
76
|
+
} catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
// THE PARTS THE RESOURCE PANELS SHARE: the lane, the add form, a brand row,
|
|
2
|
+
// the thumb, and the readers over the registry they all ask.
|
|
3
|
+
//
|
|
4
|
+
// One home, so the board's AssetsTab and the inspector render the same row
|
|
5
|
+
// the same way. Each panel decides WHICH rows it lists and
|
|
6
|
+
// where an add lands. These parts only draw a row and say what it can do.
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { IconChevron } from "@dailies-studio/ui";
|
|
9
|
+
import type {
|
|
10
|
+
BrandItem3D,
|
|
11
|
+
Doc3D,
|
|
12
|
+
Layer3D,
|
|
13
|
+
ScopedBrandItem3D,
|
|
14
|
+
ScopedReferenceItem3D,
|
|
15
|
+
ShotAsset,
|
|
16
|
+
} from "@dailies-studio/shot/doc";
|
|
17
|
+
import { formatBytes } from "../../api.js";
|
|
18
|
+
|
|
19
|
+
/** What a file input on a resource panel offers. The server is the gate. */
|
|
20
|
+
export const UPLOAD_ACCEPT = "image/*,video/*,audio/*,.glb,.gltf,.woff,.woff2,.ttf,.otf";
|
|
21
|
+
|
|
22
|
+
export type AddFormKind = "color" | "guidance" | "reference";
|
|
23
|
+
|
|
24
|
+
/** What a brand row's one action is, or null when it has none here. */
|
|
25
|
+
export type ResourceAction = { label: "Use" | "Apply"; enabled: boolean; reason?: string };
|
|
26
|
+
|
|
27
|
+
export function ResourceLane({
|
|
28
|
+
title,
|
|
29
|
+
count,
|
|
30
|
+
meta,
|
|
31
|
+
actions,
|
|
32
|
+
readOnly,
|
|
33
|
+
foldable,
|
|
34
|
+
children,
|
|
35
|
+
}: {
|
|
36
|
+
title: string;
|
|
37
|
+
count: number;
|
|
38
|
+
meta?: string;
|
|
39
|
+
actions: React.ReactNode;
|
|
40
|
+
readOnly: boolean;
|
|
41
|
+
/** Fold a WRITABLE lane, closed by default. `readOnly` already folds, and
|
|
42
|
+
* the two are separate questions: the board's Parts lane has an add button
|
|
43
|
+
* and still wants to start out of the way, because the material an author
|
|
44
|
+
* handles is the lane above it. */
|
|
45
|
+
foldable?: boolean;
|
|
46
|
+
children: React.ReactNode;
|
|
47
|
+
}) {
|
|
48
|
+
const heading = (
|
|
49
|
+
<span className="resource-lane-title">
|
|
50
|
+
<span>{title}</span>
|
|
51
|
+
<span className="resource-count">{count}</span>
|
|
52
|
+
{meta === undefined ? null : <span className="resource-usage">{meta}</span>}
|
|
53
|
+
</span>
|
|
54
|
+
);
|
|
55
|
+
return readOnly || foldable === true ? (
|
|
56
|
+
<details className="resource-lane">
|
|
57
|
+
{/* The house chevron, same as the outline tree and the MCP lane. */}
|
|
58
|
+
<summary>
|
|
59
|
+
<IconChevron className="chevron" />
|
|
60
|
+
{heading}
|
|
61
|
+
{actions}
|
|
62
|
+
</summary>
|
|
63
|
+
<div className="resource-lane-body">{children}</div>
|
|
64
|
+
</details>
|
|
65
|
+
) : (
|
|
66
|
+
<section className="resource-lane">
|
|
67
|
+
<div className="resource-lane-head">
|
|
68
|
+
{heading}
|
|
69
|
+
{actions}
|
|
70
|
+
</div>
|
|
71
|
+
<div className="resource-lane-body">{children}</div>
|
|
72
|
+
</section>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function ResourceForm({
|
|
77
|
+
kind,
|
|
78
|
+
onSubmit,
|
|
79
|
+
onCancel,
|
|
80
|
+
}: {
|
|
81
|
+
kind: AddFormKind;
|
|
82
|
+
onSubmit: (label: string, value: string) => void;
|
|
83
|
+
onCancel: () => void;
|
|
84
|
+
}) {
|
|
85
|
+
const [label, setLabel] = useState("");
|
|
86
|
+
const [value, setValue] = useState(kind === "color" ? "#ffffff" : "");
|
|
87
|
+
const noun = kind === "color" ? "Color" : kind === "reference" ? "Reference note" : "Guidance";
|
|
88
|
+
return (
|
|
89
|
+
<form
|
|
90
|
+
className="resource-form"
|
|
91
|
+
onSubmit={(event) => {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
if (label.trim().length === 0 || value.trim().length === 0) return;
|
|
94
|
+
onSubmit(label, value);
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
97
|
+
<input autoFocus value={label} placeholder={`${noun} name`} aria-label={`${noun} name`} onChange={(e) => setLabel(e.target.value)} />
|
|
98
|
+
<div className="resource-form-value">
|
|
99
|
+
{kind === "color" ? (
|
|
100
|
+
<input type="color" value={value} aria-label="Brand color" onChange={(e) => setValue(e.target.value)} />
|
|
101
|
+
) : null}
|
|
102
|
+
<input
|
|
103
|
+
value={value}
|
|
104
|
+
placeholder={kind === "color" ? "#rrggbb" : kind === "reference" ? "What should the agent notice?" : "How should this be used?"}
|
|
105
|
+
aria-label={`${noun} value`}
|
|
106
|
+
onChange={(e) => setValue(e.target.value)}
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
<div className="resource-form-actions">
|
|
110
|
+
<button type="button" onClick={onCancel}>Cancel</button>
|
|
111
|
+
<button type="submit" className="is-primary">Add</button>
|
|
112
|
+
</div>
|
|
113
|
+
</form>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function BrandRow({
|
|
118
|
+
item,
|
|
119
|
+
asset,
|
|
120
|
+
used,
|
|
121
|
+
canOverride,
|
|
122
|
+
shadowed,
|
|
123
|
+
readOnly,
|
|
124
|
+
action,
|
|
125
|
+
onUse,
|
|
126
|
+
onOverride,
|
|
127
|
+
onRemove,
|
|
128
|
+
}: {
|
|
129
|
+
item: ScopedBrandItem3D;
|
|
130
|
+
asset?: ShotAsset;
|
|
131
|
+
used: boolean;
|
|
132
|
+
/** A Project row, with a Shot entered to copy it into. */
|
|
133
|
+
canOverride: boolean;
|
|
134
|
+
/** The entered Shot has its own row for this key, so it gets that one. */
|
|
135
|
+
shadowed: boolean;
|
|
136
|
+
readOnly: boolean;
|
|
137
|
+
action: ResourceAction | null;
|
|
138
|
+
onUse: () => void;
|
|
139
|
+
onOverride: () => void;
|
|
140
|
+
onRemove: () => void;
|
|
141
|
+
}) {
|
|
142
|
+
return (
|
|
143
|
+
<li className={`resource-row is-${item.scope}`} data-resource={item.id}>
|
|
144
|
+
<details>
|
|
145
|
+
<summary>
|
|
146
|
+
<ResourceThumb item={item} {...(asset === undefined ? {} : { asset })} />
|
|
147
|
+
<span className="resource-label">{item.label}</span>
|
|
148
|
+
<span className="resource-badge">{item.scope === "shot" ? "Shot" : "Project"}</span>
|
|
149
|
+
{used ? <span className="resource-used">Used</span> : null}
|
|
150
|
+
{shadowed ? (
|
|
151
|
+
<span className="resource-used" title="This shot has its own row for this role">
|
|
152
|
+
Overridden
|
|
153
|
+
</span>
|
|
154
|
+
) : null}
|
|
155
|
+
</summary>
|
|
156
|
+
<div className="resource-detail">
|
|
157
|
+
<div><span>Role</span><code>{item.key}</code></div>
|
|
158
|
+
{asset === undefined ? null : <div><span>File</span><code>{asset.path}</code></div>}
|
|
159
|
+
{item.type === "asset" && item.guidance !== undefined ? <p>{item.guidance}</p> : null}
|
|
160
|
+
{item.type === "guidance" ? <p>{item.text}</p> : null}
|
|
161
|
+
<div className="resource-row-actions">
|
|
162
|
+
{readOnly || action === null ? null : (
|
|
163
|
+
<button type="button" disabled={!action.enabled} title={action.reason} onClick={onUse}>{action.label}</button>
|
|
164
|
+
)}
|
|
165
|
+
{readOnly || !canOverride ? null : (
|
|
166
|
+
<button type="button" onClick={onOverride}>Override</button>
|
|
167
|
+
)}
|
|
168
|
+
{/* Every row the tab shows is one it owns: the Project's lanes
|
|
169
|
+
and the Shot's lane each remove from their own scope. */}
|
|
170
|
+
{readOnly ? null : (
|
|
171
|
+
<button type="button" className="is-danger" onClick={onRemove}>Remove</button>
|
|
172
|
+
)}
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</details>
|
|
176
|
+
</li>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function ResourceThumb({ item, asset }: { item: BrandItem3D | ScopedReferenceItem3D; asset?: ShotAsset }) {
|
|
181
|
+
if (item.type === "color") {
|
|
182
|
+
return <span className="resource-thumb is-swatch" style={{ backgroundColor: item.value }} aria-hidden="true" />;
|
|
183
|
+
}
|
|
184
|
+
if (item.type === "asset" && asset?.kind === "image") {
|
|
185
|
+
return <img className="resource-thumb" src={`/studio/assets/${encodeURIComponent(asset.path)}`} alt="" />;
|
|
186
|
+
}
|
|
187
|
+
const glyph =
|
|
188
|
+
item.type === "note" ? "N" : item.type === "guidance" ? "G" : item.type === "component" ? "</>" : assetGlyph(asset);
|
|
189
|
+
return <span className="resource-thumb is-kind" aria-hidden="true">{glyph}</span>;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** The glyph a file with no picture of its own shows in a row's thumb. */
|
|
193
|
+
export function assetGlyph(asset: ShotAsset | undefined): string {
|
|
194
|
+
return asset?.kind === "font" ? "Aa" : asset?.kind === "video" ? "▶" : asset?.kind === "audio" ? "♪" : asset?.kind === "model" ? "3D" : "·";
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function actionForResource(
|
|
198
|
+
item: ScopedBrandItem3D,
|
|
199
|
+
asset: ShotAsset | undefined,
|
|
200
|
+
selected: readonly Layer3D[],
|
|
201
|
+
inShot: boolean,
|
|
202
|
+
): ResourceAction | null {
|
|
203
|
+
if (!inShot || item.type === "guidance") return null;
|
|
204
|
+
if (item.type === "color") {
|
|
205
|
+
const enabled = selected.some((layer) => ["text", "rect", "ellipse", "path", "line", "arrow"].includes(layer.kind));
|
|
206
|
+
return enabled ? { label: "Apply", enabled } : { label: "Apply", enabled, reason: "Select text or a vector layer" };
|
|
207
|
+
}
|
|
208
|
+
if (asset?.kind === "font") {
|
|
209
|
+
const enabled = selected.some((layer) => layer.kind === "text");
|
|
210
|
+
return enabled ? { label: "Apply", enabled } : { label: "Apply", enabled, reason: "Select a text layer" };
|
|
211
|
+
}
|
|
212
|
+
if (asset === undefined) return { label: "Use", enabled: false, reason: "The file is missing" };
|
|
213
|
+
return { label: "Use", enabled: true };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function selectedLayers(doc: Doc3D, containerId: string | null, selection: readonly string[]): Layer3D[] {
|
|
217
|
+
if (containerId === null) return [];
|
|
218
|
+
const home = doc.components?.[containerId] ?? doc.scenesById[containerId];
|
|
219
|
+
if (home === undefined) return [];
|
|
220
|
+
return selection.flatMap((id) => {
|
|
221
|
+
const layer = home.layersById[id];
|
|
222
|
+
return layer === undefined ? [] : [layer];
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function assetUsedInComposition(doc: Doc3D, assetId: string): boolean {
|
|
227
|
+
if (Object.values(doc.audio).some((clip) => clip.asset === assetId)) return true;
|
|
228
|
+
for (const scene of Object.values(doc.scenesById)) {
|
|
229
|
+
if (Object.values(scene.audio ?? {}).some((clip) => clip.asset === assetId)) return true;
|
|
230
|
+
if (containsAsset(scene.layersById, assetId)) return true;
|
|
231
|
+
}
|
|
232
|
+
return containsAsset(doc.components ?? {}, assetId);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function containsAsset(value: unknown, assetId: string): boolean {
|
|
236
|
+
if (value === assetId) return true;
|
|
237
|
+
if (Array.isArray(value)) return value.some((entry) => containsAsset(entry, assetId));
|
|
238
|
+
if (typeof value !== "object" || value === null) return false;
|
|
239
|
+
return Object.values(value as Readonly<Record<string, unknown>>).some((entry) => containsAsset(entry, assetId));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** The name without its content-hash prefix, as the audio lane shows it. */
|
|
243
|
+
export function fileNameOf(asset: ShotAsset): string {
|
|
244
|
+
return asset.path.replace(/^[0-9a-f]{8}-/, "");
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** The shown name, with the stored one (and the size, when given) in the
|
|
248
|
+
* tooltip. */
|
|
249
|
+
export function NameOf({ asset, bytes }: { asset: ShotAsset; bytes?: number | undefined }) {
|
|
250
|
+
return (
|
|
251
|
+
<span className="resource-label" title={bytes === undefined ? asset.path : `${asset.path} · ${formatBytes(bytes)}`}>
|
|
252
|
+
{fileNameOf(asset)}
|
|
253
|
+
</span>
|
|
254
|
+
);
|
|
255
|
+
}
|