@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,361 @@
|
|
|
1
|
+
// A VIDEO CLIP'S OWN FRAMES, UNDER ITS BAR.
|
|
2
|
+
//
|
|
3
|
+
// The picture half of a video row. The sound half is the waveform `AudioLane`
|
|
4
|
+
// already draws, and this file keeps that file's one non-negotiable rule:
|
|
5
|
+
//
|
|
6
|
+
// A DECORATION NEVER FAILS AN EDIT.
|
|
7
|
+
//
|
|
8
|
+
// No sidecar, no ffmpeg on the host, a 2d context jsdom will not give, an
|
|
9
|
+
// `Image` that does not exist: each ends as a bar with no thumbnails in it,
|
|
10
|
+
// which still trims, slips, splits and plays. Every throwing surface in here is
|
|
11
|
+
// wrapped, and `filmstrip.ts` takes the same posture one layer down.
|
|
12
|
+
//
|
|
13
|
+
// ── WHY THIS IS A CANVAS IN A DOM LANE ────────────────────────────────────
|
|
14
|
+
//
|
|
15
|
+
// `panels/timeline/` is DOM and stays DOM: the bars are divs, the handles are
|
|
16
|
+
// spans, and the gestures are pointer events on real elements. The two
|
|
17
|
+
// exceptions are both PICTURES rather than controls (the waveform and this),
|
|
18
|
+
// and both are the same argument. Sixty thumbnails is sixty `<img>` elements
|
|
19
|
+
// per row with sixty layout boxes and sixty repaints per scroll, against one
|
|
20
|
+
// element and one `drawImage` loop. Nothing here is clickable, so nothing here
|
|
21
|
+
// loses a hit target by not being an element.
|
|
22
|
+
//
|
|
23
|
+
// ── WHAT MAKES IT CHEAP ───────────────────────────────────────────────────
|
|
24
|
+
//
|
|
25
|
+
// Three things, and all three are load-bearing:
|
|
26
|
+
//
|
|
27
|
+
// 1. IT DOES NOT SUBSCRIBE TO THE FRAME. Not to `useShotEditorHot`, not to the
|
|
28
|
+
// playhead, not to anything on the shot store at all. A strip drawn thirty
|
|
29
|
+
// times a second would cost more than the rows it decorates. See
|
|
30
|
+
// `useLive.ts`'s header for the rule; this component is stricter than it,
|
|
31
|
+
// because it has no live state to carry.
|
|
32
|
+
// 2. IT ONLY DRAWS WHAT IS ON SCREEN. `viewport.ts` answers which content
|
|
33
|
+
// pixels are visible, quantised to 64 px, and a bar further than 512 px
|
|
34
|
+
// outside that skips its draw AND its tile request. A fifty-second film at a
|
|
35
|
+
// deep zoom is six figures of bar pixels; this is what keeps the canvas a
|
|
36
|
+
// screen wide instead.
|
|
37
|
+
// 3. IT REDRAWS ONLY ON A REAL INPUT. The viewport quantum, a tile arrival, the
|
|
38
|
+
// zoom, the clip's window, the clip's source placement, and its measured
|
|
39
|
+
// box. Nothing else can invalidate the pixels, because nothing else is in
|
|
40
|
+
// them. In particular the THEME is not an input: the strip paints tiles and
|
|
41
|
+
// reads no token, so the bar's own four fills (rest, hover, live, selected)
|
|
42
|
+
// show through the gaps as the bar's own CSS and an appearance swap has
|
|
43
|
+
// nothing here to restate. The day a token is read in this file it joins the
|
|
44
|
+
// dependency list.
|
|
45
|
+
//
|
|
46
|
+
// ── WHERE THE TILES GO IS NOT THIS FILE'S ARITHMETIC ──────────────────────
|
|
47
|
+
//
|
|
48
|
+
// `filmstripLayout` in model.ts owns it, and its header states the property
|
|
49
|
+
// that makes a trim read correctly. The summary: a column is a SOURCE FRAME
|
|
50
|
+
// placed at the scene frame that shows it, so trimming the head slides the
|
|
51
|
+
// footage under the window instead of re-cutting the strip.
|
|
52
|
+
import { pickTile, requestFilmstrip, subscribeFilmstrip } from "@dailies-studio/timeline";
|
|
53
|
+
import type { FilmstripTile } from "@dailies-studio/timeline";
|
|
54
|
+
import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from "react";
|
|
55
|
+
import type { Rational } from "@dailies-studio/engine";
|
|
56
|
+
import type { ShotAsset, VideoLayer3D } from "@dailies-studio/shot/doc";
|
|
57
|
+
import { FILMSTRIP_TILE_PX, filmstripLayout } from "./model.js";
|
|
58
|
+
import type { FilmstripPlan } from "./model.js";
|
|
59
|
+
import {
|
|
60
|
+
DOCK_VIEWPORT_UNMEASURED,
|
|
61
|
+
dockScrollerOf,
|
|
62
|
+
readDockViewport,
|
|
63
|
+
subscribeDockViewport,
|
|
64
|
+
visibleSlice,
|
|
65
|
+
} from "./viewport.js";
|
|
66
|
+
import type { DockViewport } from "./viewport.js";
|
|
67
|
+
|
|
68
|
+
/** The backing store is capped at 2x. Past that a strip costs four times the
|
|
69
|
+
* memory and the fill rate of a 1x one to add detail to a 48 px thumbnail
|
|
70
|
+
* nobody is reading detail off. The same ceiling the stage's raster rungs
|
|
71
|
+
* keep, and for the same reason. */
|
|
72
|
+
export const FILMSTRIP_MAX_DPR = 2;
|
|
73
|
+
|
|
74
|
+
/** This row's scroller, and its quantised visible range.
|
|
75
|
+
*
|
|
76
|
+
* The scroller is found by walking UP from the canvas rather than threaded
|
|
77
|
+
* down as a prop: the rows between the dock and this component are owned by
|
|
78
|
+
* other files, and a decoration may not make them carry a ref for it. */
|
|
79
|
+
function useDockViewport(el: Element | null): DockViewport {
|
|
80
|
+
const scroller = useMemo(() => dockScrollerOf(el), [el]);
|
|
81
|
+
const subscribe = useCallback((cb: () => void) => subscribeDockViewport(scroller, cb), [scroller]);
|
|
82
|
+
const snapshot = useCallback(() => readDockViewport(scroller), [scroller]);
|
|
83
|
+
// The server snapshot is the unmeasured one: there is no layout to measure
|
|
84
|
+
// without a browser, and it is the value that admits the whole bar.
|
|
85
|
+
return useSyncExternalStore(subscribe, snapshot, () => DOCK_VIEWPORT_UNMEASURED);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** The canvas's CSS box. `null` until the observer has delivered one, which is
|
|
89
|
+
* what stops a first paint sizing a backing store from a zero-height box. */
|
|
90
|
+
function useMeasured(el: Element | null): { width: number; height: number } | null {
|
|
91
|
+
const [box, setBox] = useState<{ width: number; height: number } | null>(null);
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (el === null || typeof ResizeObserver !== "function") return;
|
|
94
|
+
const ro = new ResizeObserver((entries) => {
|
|
95
|
+
const rect = entries[entries.length - 1]?.contentRect;
|
|
96
|
+
if (rect === undefined) return;
|
|
97
|
+
// Identity-stable: a `setState` with an equal box on every observation
|
|
98
|
+
// would re-run the draw effect on every scroll of a row whose size never
|
|
99
|
+
// changed.
|
|
100
|
+
setBox((prev) =>
|
|
101
|
+
prev !== null && prev.width === rect.width && prev.height === rect.height
|
|
102
|
+
? prev
|
|
103
|
+
: { width: rect.width, height: rect.height },
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
ro.observe(el);
|
|
107
|
+
return () => ro.disconnect();
|
|
108
|
+
}, [el]);
|
|
109
|
+
return box;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Bumps when tiles land for this asset. A counter and not the tiles
|
|
113
|
+
* themselves: the sheet lives in the loader's cache, and the only thing this
|
|
114
|
+
* component needs to know is that `pickTile` will answer differently now. */
|
|
115
|
+
function useTileArrivals(assetPath: string | undefined): number {
|
|
116
|
+
const [epoch, setEpoch] = useState(0);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (assetPath === undefined) return;
|
|
119
|
+
return subscribeFilmstrip(assetPath, () => setEpoch((n) => n + 1));
|
|
120
|
+
}, [assetPath]);
|
|
121
|
+
return epoch;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* One tile into one column, COVER-cropped.
|
|
126
|
+
*
|
|
127
|
+
* The sheet's tiles carry the recording's own aspect (the CLI scales to a fixed
|
|
128
|
+
* width and an even computed height), and a column is the row's height by the
|
|
129
|
+
* strip's fixed pitch, so the two rarely agree. Stretching to fit would lie
|
|
130
|
+
* about the framing of every shot in the film, which is the one thing an author
|
|
131
|
+
* reads a filmstrip for. A centre crop loses the edges of the frame and keeps
|
|
132
|
+
* the subject, which is the trade every NLE makes here.
|
|
133
|
+
*/
|
|
134
|
+
function drawTile(
|
|
135
|
+
ctx: CanvasRenderingContext2D,
|
|
136
|
+
tile: FilmstripTile,
|
|
137
|
+
x: number,
|
|
138
|
+
width: number,
|
|
139
|
+
height: number,
|
|
140
|
+
): void {
|
|
141
|
+
if (!(tile.width > 0) || !(tile.height > 0) || !(width > 0) || !(height > 0)) return;
|
|
142
|
+
const want = width / height;
|
|
143
|
+
const have = tile.width / tile.height;
|
|
144
|
+
let sx = tile.sx;
|
|
145
|
+
let sy = 0;
|
|
146
|
+
let sw = tile.width;
|
|
147
|
+
let sh = tile.height;
|
|
148
|
+
if (have > want) {
|
|
149
|
+
sw = tile.height * want;
|
|
150
|
+
sx = tile.sx + (tile.width - sw) / 2;
|
|
151
|
+
} else {
|
|
152
|
+
sh = tile.width / want;
|
|
153
|
+
sy = (tile.height - sh) / 2;
|
|
154
|
+
}
|
|
155
|
+
ctx.drawImage(tile.image, sx, sy, sw, sh, x, 0, width, height);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Paint the plan.
|
|
160
|
+
*
|
|
161
|
+
* STALE TILES ARE DRAWN AS THEY ARE. Not dimmed, not hatched, not held back
|
|
162
|
+
* behind a spinner: a dimmed strip reads as a broken asset, and the pixels of
|
|
163
|
+
* the sheet the loader has moved past are approximately right, which is the
|
|
164
|
+
* whole standard a filmstrip is held to. The loader's subscription is what
|
|
165
|
+
* replaces them when the fresh sheet lands.
|
|
166
|
+
*/
|
|
167
|
+
function paint(
|
|
168
|
+
canvas: HTMLCanvasElement,
|
|
169
|
+
assetPath: string,
|
|
170
|
+
plan: FilmstripPlan,
|
|
171
|
+
fromPx: number,
|
|
172
|
+
height: number,
|
|
173
|
+
dpr: number,
|
|
174
|
+
): void {
|
|
175
|
+
// THE TILES BEFORE THE CONTEXT. A row whose sheet has not arrived, or whose
|
|
176
|
+
// asset has no strip at all (every video on a host with no ffmpeg), then costs
|
|
177
|
+
// no 2d context, no clear and no transform. It is also the only reason this is
|
|
178
|
+
// safe to skip: `pickTile` clamps, so a loaded sheet always answers, and "no
|
|
179
|
+
// tiles" therefore means "never had any" rather than "had some a moment ago".
|
|
180
|
+
// There is nothing stale left on the canvas to erase.
|
|
181
|
+
const drawable: { tile: FilmstripTile; x: number }[] = [];
|
|
182
|
+
for (const column of plan.columns) {
|
|
183
|
+
const tile = pickTile(assetPath, column.sourceFrame, plan.intervalFrames);
|
|
184
|
+
if (tile !== null) drawable.push({ tile, x: column.x - fromPx });
|
|
185
|
+
}
|
|
186
|
+
if (drawable.length === 0) return;
|
|
187
|
+
|
|
188
|
+
const ctx = canvas.getContext("2d");
|
|
189
|
+
// A browser answers null for a context already taken as webgl, and jsdom
|
|
190
|
+
// answers UNDEFINED: its `getContext` is a not-implemented stub that returns
|
|
191
|
+
// nothing at all, against a type that promises `… | null`. Both are "no
|
|
192
|
+
// strip", so the check is loose on purpose: `=== null` passes an undefined
|
|
193
|
+
// straight into `setTransform` and turns a decoration into a thrown render.
|
|
194
|
+
if (ctx === null || ctx === undefined) return;
|
|
195
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
196
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
197
|
+
ctx.scale(dpr, dpr);
|
|
198
|
+
for (const { tile, x } of drawable) drawTile(ctx, tile, x, FILMSTRIP_TILE_PX, height);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface FilmstripProps {
|
|
202
|
+
/** The row's layer, for `video.asset`, `video.offsetFrames` and
|
|
203
|
+
* `video.timeScale`. Its `lifetime` is NOT read here, see `lifetimeIn`. */
|
|
204
|
+
layer: VideoLayer3D;
|
|
205
|
+
/** The asset row `layer.video.asset` names, for its content-addressed
|
|
206
|
+
* `path`. Absent (a reference the document no longer carries) draws
|
|
207
|
+
* nothing and asks for nothing. */
|
|
208
|
+
asset: ShotAsset | undefined;
|
|
209
|
+
/** The document's rate, which is what turns a source frame into the time the
|
|
210
|
+
* sheet is indexed by. */
|
|
211
|
+
fps: Rational;
|
|
212
|
+
/**
|
|
213
|
+
* The bar's left edge in SCENE-LOCAL frames: the same `row.lifespan.in` the
|
|
214
|
+
* caller computed the bar's `left` from.
|
|
215
|
+
*
|
|
216
|
+
* Passed rather than read off `layer.lifetime`, because an absent lifetime is
|
|
217
|
+
* materialised by `lifespanOf` against the container's duration and the strip
|
|
218
|
+
* must be laid out from the number the bar was DRAWN from. One arithmetic,
|
|
219
|
+
* the rule `useLive` states for the same reason.
|
|
220
|
+
*/
|
|
221
|
+
lifetimeIn: number;
|
|
222
|
+
ppf: number;
|
|
223
|
+
/** The bar's left edge in LANE pixels, exactly as the caller placed it. */
|
|
224
|
+
barLeftPx: number;
|
|
225
|
+
/** The bar's width in pixels, exactly as the caller placed it. */
|
|
226
|
+
barWidthPx: number;
|
|
227
|
+
/** The dock's label column, which is the offset between a lane pixel and a
|
|
228
|
+
* content pixel. The viewport is measured in content pixels. */
|
|
229
|
+
labelWidth: number;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Mount inside the clip's bar. The bar is already a containing block (it is
|
|
234
|
+
* absolutely positioned itself) and is `overflow: hidden`, so this positions
|
|
235
|
+
* itself absolutely against it and lets the bar's own rounded clip cut the
|
|
236
|
+
* columns at both ends.
|
|
237
|
+
*
|
|
238
|
+
* The canvas sits at the VISIBLE slice of the bar, not across the whole bar: at
|
|
239
|
+
* 60 px/frame a fifty-second film is past the width a browser will allocate for
|
|
240
|
+
* a canvas at all, and a canvas that fails to allocate draws nothing with no
|
|
241
|
+
* error anywhere.
|
|
242
|
+
*
|
|
243
|
+
* ── TWO THINGS THE MOUNT OWES IT ──────────────────────────────────────────
|
|
244
|
+
*
|
|
245
|
+
* 1. THE BAR'S OWN CONTENT HAS TO OUTRANK IT. This is a positioned box, and
|
|
246
|
+
* CSS paints positioned descendants over in-flow content regardless of
|
|
247
|
+
* document order, so `.lifespan-bar-name` needs a position of its own (it
|
|
248
|
+
* is a plain span today) or the label disappears under the footage. The two
|
|
249
|
+
* handles are already absolute and already later in the tree, so they are
|
|
250
|
+
* fine as they are.
|
|
251
|
+
* 2. IT IS OFF BY THE BAR'S BORDER. An absolutely positioned child is placed
|
|
252
|
+
* against the PADDING box, so `left: 0` here is the inner edge of the bar's
|
|
253
|
+
* 1px border rather than its outer edge. Left uncorrected on purpose: one
|
|
254
|
+
* pixel of phase on a 48px thumbnail is not visible, and subtracting a
|
|
255
|
+
* border width in here would put a second copy of a CSS number into the
|
|
256
|
+
* geometry, where a stylesheet change could silently invalidate it.
|
|
257
|
+
*/
|
|
258
|
+
export function Filmstrip({
|
|
259
|
+
layer,
|
|
260
|
+
asset,
|
|
261
|
+
fps,
|
|
262
|
+
lifetimeIn,
|
|
263
|
+
ppf,
|
|
264
|
+
barLeftPx,
|
|
265
|
+
barWidthPx,
|
|
266
|
+
labelWidth,
|
|
267
|
+
}: FilmstripProps) {
|
|
268
|
+
const [canvas, setCanvas] = useState<HTMLCanvasElement | null>(null);
|
|
269
|
+
const view = useDockViewport(canvas);
|
|
270
|
+
const measured = useMeasured(canvas);
|
|
271
|
+
const assetPath = asset?.path;
|
|
272
|
+
const epoch = useTileArrivals(assetPath);
|
|
273
|
+
|
|
274
|
+
const slice = visibleSlice(view, labelWidth + barLeftPx, barWidthPx);
|
|
275
|
+
const fromPx = slice?.fromPx ?? 0;
|
|
276
|
+
const toPx = slice?.toPx ?? 0;
|
|
277
|
+
|
|
278
|
+
const offsetFrames = layer.video.offsetFrames ?? 0;
|
|
279
|
+
const timeScale = layer.video.timeScale ?? 1;
|
|
280
|
+
const rate = fps.den > 0 ? fps.num / fps.den : 0;
|
|
281
|
+
const height = measured?.height ?? 0;
|
|
282
|
+
|
|
283
|
+
useEffect(() => {
|
|
284
|
+
if (canvas === null || assetPath === undefined) return;
|
|
285
|
+
// The skip is the whole point of the viewport store: a row off screen draws
|
|
286
|
+
// nothing AND asks for nothing, so a scroll past forty video rows does not
|
|
287
|
+
// queue forty derives on a server that has to run ffmpeg for each.
|
|
288
|
+
if (!(toPx > fromPx) || !(height > 0)) return;
|
|
289
|
+
|
|
290
|
+
const plan = filmstripLayout({
|
|
291
|
+
lifetimeIn,
|
|
292
|
+
offsetFrames,
|
|
293
|
+
timeScale,
|
|
294
|
+
ppf,
|
|
295
|
+
tileWidth: FILMSTRIP_TILE_PX,
|
|
296
|
+
fromPx,
|
|
297
|
+
toPx,
|
|
298
|
+
});
|
|
299
|
+
if (plan.columns.length === 0) return;
|
|
300
|
+
|
|
301
|
+
const first = plan.columns[0];
|
|
302
|
+
const last = plan.columns[plan.columns.length - 1];
|
|
303
|
+
if (first === undefined || last === undefined) return;
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
requestFilmstrip({
|
|
307
|
+
assetPath,
|
|
308
|
+
fps: rate,
|
|
309
|
+
firstSourceFrame: first.sourceFrame,
|
|
310
|
+
lastSourceFrame: last.sourceFrame,
|
|
311
|
+
intervalFrames: plan.intervalFrames,
|
|
312
|
+
tileWidth: FILMSTRIP_TILE_PX,
|
|
313
|
+
tileHeight: height,
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
const width = toPx - fromPx;
|
|
317
|
+
const dpr = Math.min(FILMSTRIP_MAX_DPR, Math.max(1, globalThis.devicePixelRatio || 1));
|
|
318
|
+
const backingW = Math.max(1, Math.round(width * dpr));
|
|
319
|
+
const backingH = Math.max(1, Math.round(height * dpr));
|
|
320
|
+
// Written only when it MOVED: assigning `canvas.width` clears the whole
|
|
321
|
+
// surface even when the value is unchanged, so an unconditional write
|
|
322
|
+
// would blank the strip on every redraw that had nothing new to say.
|
|
323
|
+
if (canvas.width !== backingW) canvas.width = backingW;
|
|
324
|
+
if (canvas.height !== backingH) canvas.height = backingH;
|
|
325
|
+
paint(canvas, assetPath, plan, fromPx, height, dpr);
|
|
326
|
+
} catch {
|
|
327
|
+
// A decoration never fails an edit.
|
|
328
|
+
}
|
|
329
|
+
// `epoch` is in the list for its side effect alone: it is the loader saying
|
|
330
|
+
// `pickTile` answers differently now.
|
|
331
|
+
}, [canvas, assetPath, fromPx, toPx, height, lifetimeIn, offsetFrames, timeScale, ppf, rate, epoch]);
|
|
332
|
+
|
|
333
|
+
// The ONLY early return, and it deliberately does not test the slice.
|
|
334
|
+
//
|
|
335
|
+
// An off-screen bar collapses its canvas to zero width and keeps the element
|
|
336
|
+
// mounted, because unmounting it would unmount the node the viewport is
|
|
337
|
+
// measured through: `canvas` would go null, the scroller with it, the
|
|
338
|
+
// unmeasured viewport would admit the bar again, and the row would mount and
|
|
339
|
+
// unmount its canvas forever. The skip that matters is the draw and the fetch
|
|
340
|
+
// above, both of which are already off.
|
|
341
|
+
if (assetPath === undefined) return null;
|
|
342
|
+
|
|
343
|
+
return (
|
|
344
|
+
<canvas
|
|
345
|
+
ref={setCanvas}
|
|
346
|
+
className="filmstrip"
|
|
347
|
+
aria-hidden="true"
|
|
348
|
+
// Inline, because the geometry is computed: `left` and `width` change with
|
|
349
|
+
// every viewport quantum, and the rest is what makes a canvas a backdrop
|
|
350
|
+
// rather than a box in the flow.
|
|
351
|
+
style={{
|
|
352
|
+
position: "absolute",
|
|
353
|
+
top: 0,
|
|
354
|
+
bottom: 0,
|
|
355
|
+
left: fromPx,
|
|
356
|
+
width: Math.max(0, toPx - fromPx),
|
|
357
|
+
pointerEvents: "none",
|
|
358
|
+
}}
|
|
359
|
+
/>
|
|
360
|
+
);
|
|
361
|
+
}
|