@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,400 @@
|
|
|
1
|
+
// ONE ROW PER SHOT, at the head of that shot's group of element rows.
|
|
2
|
+
//
|
|
3
|
+
// ── WHAT THIS REPLACED, AND WHY ────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// `SceneStrip` drew every shot as a bar in ONE 26px lane above the tracks,
|
|
6
|
+
// while `dock-tracks` underneath it already rendered one GROUP per shot,
|
|
7
|
+
// stacked. So the document's coarsest structure was drawn twice, in two
|
|
8
|
+
// different shapes, and only the thin one carried the verbs.
|
|
9
|
+
//
|
|
10
|
+
// It is one drawing now: the group's first row IS its shot. The bar sits at the
|
|
11
|
+
// shot's own master position, the label cell carries the name and the
|
|
12
|
+
// disclosure into that shot's elements, and every verb the strip owned moved
|
|
13
|
+
// here unchanged — create, reorder, trim, delete, transition, open. The strip's
|
|
14
|
+
// argument stands and this is still the one place a verb about a SHOT (rather
|
|
15
|
+
// than about time) lives; it is just no longer a second picture of a list.
|
|
16
|
+
//
|
|
17
|
+
// ── THE THREE THINGS THAT MUST NOT CHANGE IN THE MOVE ──────────────────────
|
|
18
|
+
//
|
|
19
|
+
// POSITIONS STAY DERIVED. `start`/`end` come from `sceneWindows`' prefix sum
|
|
20
|
+
// (through `masterRows`), so trimming writes one field and every shot after
|
|
21
|
+
// it moves for free. Nothing here stores an offset.
|
|
22
|
+
// `originFrames` IS A DRAWING OFFSET. Inside a shot the lane is re-zeroed on
|
|
23
|
+
// it; every edit still speaks master time. Same split every other row in
|
|
24
|
+
// this dock keeps.
|
|
25
|
+
// THE CUT DIAMOND BELONGS TO THE OUTGOING SHOT. A transition is stored on the
|
|
26
|
+
// shot before the seam, so it is drawn at this row's END and the last shot
|
|
27
|
+
// has none.
|
|
28
|
+
import { framesToSeconds } from "@dailies-studio/engine";
|
|
29
|
+
import { frameToPx, startDrag } from "@dailies-studio/timeline";
|
|
30
|
+
import { MIN_SCENE_FRAMES, MIN_TRANSITION_FRAMES } from "@dailies-studio/shot/doc";
|
|
31
|
+
import { useEffect, useRef, useState } from "react";
|
|
32
|
+
import type { DragEvent as ReactDragEvent, PointerEvent as ReactPointerEvent } from "react";
|
|
33
|
+
import { useShotEditor, useShotEditorHot, useStore } from "../../state/context.js";
|
|
34
|
+
import { SHOT_MENU_OPTIONS, shotMenuEntries } from "../../state/menu.js";
|
|
35
|
+
import { formatDuration, frameDelta } from "./model.js";
|
|
36
|
+
import { isSnapSuppressed } from "./snap.js";
|
|
37
|
+
import type { SnapPress } from "./snap.js";
|
|
38
|
+
import type { UseContextMenuResult } from "@dailies-studio/ui";
|
|
39
|
+
|
|
40
|
+
/** A Shot bar's reorder drag. Nothing else in the app sets it. */
|
|
41
|
+
const SHOT_MIME = "application/x-dailies-shot";
|
|
42
|
+
|
|
43
|
+
/** The dock's ONE menu opener, threaded down. One `useContextMenu` for every
|
|
44
|
+
* shot row rather than one each: the hook holds an open/closed state and a
|
|
45
|
+
* focus-restore ref, and only one menu can be open at a time. */
|
|
46
|
+
type OpenMenu = UseContextMenuResult["open"];
|
|
47
|
+
|
|
48
|
+
export function ShotRow({
|
|
49
|
+
id,
|
|
50
|
+
name,
|
|
51
|
+
start,
|
|
52
|
+
end,
|
|
53
|
+
index,
|
|
54
|
+
isLast,
|
|
55
|
+
blendFrames,
|
|
56
|
+
ppf,
|
|
57
|
+
labelWidth,
|
|
58
|
+
originFrames,
|
|
59
|
+
expandable,
|
|
60
|
+
expanded,
|
|
61
|
+
layerCount,
|
|
62
|
+
onToggle,
|
|
63
|
+
openMenu,
|
|
64
|
+
beginSnap,
|
|
65
|
+
}: {
|
|
66
|
+
id: string;
|
|
67
|
+
name: string;
|
|
68
|
+
/** MASTER frames, half-open [start, end) — the prefix sum's own numbers. */
|
|
69
|
+
start: number;
|
|
70
|
+
end: number;
|
|
71
|
+
index: number;
|
|
72
|
+
isLast: boolean;
|
|
73
|
+
/** The stored blend length into the next shot, or null for a hard cut. Fills
|
|
74
|
+
* the cut diamond and sizes the ribbon beside it.
|
|
75
|
+
*
|
|
76
|
+
* THE STORED NUMBER, not the resolved one. `transitionAt` clamps the blend
|
|
77
|
+
* to whatever the incoming shot can hold, and drawing the clamped length
|
|
78
|
+
* would make the ribbon shrink when the author trimmed the NEXT shot — a bar
|
|
79
|
+
* moving because of an edit somewhere else. The inspector says so in words
|
|
80
|
+
* when the two differ. */
|
|
81
|
+
blendFrames: number | null;
|
|
82
|
+
ppf: number;
|
|
83
|
+
labelWidth: number;
|
|
84
|
+
/** The shot context's re-zero. DRAWING ONLY. */
|
|
85
|
+
originFrames: number;
|
|
86
|
+
/** Whether the row offers the fold. The layers fold into the shot's row in
|
|
87
|
+
* the Project and shot contexts alike ("9 layers"). */
|
|
88
|
+
expandable: boolean;
|
|
89
|
+
expanded: boolean;
|
|
90
|
+
/** How many layer rows the fold holds, for its "N layers" readout. */
|
|
91
|
+
layerCount?: number;
|
|
92
|
+
onToggle(): void;
|
|
93
|
+
openMenu: OpenMenu;
|
|
94
|
+
beginSnap: SnapPress;
|
|
95
|
+
}) {
|
|
96
|
+
const store = useStore();
|
|
97
|
+
// HOT, as a boolean: the cold lane sleeps through a cut the transport plays
|
|
98
|
+
// (store `set`), and this is the bar that says what is playing. A row
|
|
99
|
+
// re-renders only when the answer flips, as `useLive`'s bars do.
|
|
100
|
+
const current = useShotEditorHot((s) => s.sceneId === id);
|
|
101
|
+
// A viewer cannot reorder, so the bar does not lift.
|
|
102
|
+
const readOnly = useShotEditor((s) => s.readOnly);
|
|
103
|
+
const entered = useShotEditor((s) => s.enteredScene === id);
|
|
104
|
+
// Two primitives, not the Rational: a selector returning a fresh object
|
|
105
|
+
// would re-render every shot row on every store change.
|
|
106
|
+
const fpsNum = useShotEditor((s) => s.doc?.fps.num ?? 0);
|
|
107
|
+
const fpsDen = useShotEditor((s) => s.doc?.fps.den ?? 1);
|
|
108
|
+
const seconds = fpsNum > 0 ? framesToSeconds(end - start, { num: fpsNum, den: fpsDen }) : null;
|
|
109
|
+
const [renaming, setRenaming] = useState(false);
|
|
110
|
+
const input = useRef<HTMLInputElement | null>(null);
|
|
111
|
+
/** The ribbon's stored length AT THE PRESS, so every move is absolute from
|
|
112
|
+
* it. Read from the store, not the prop: each capture re-renders this row
|
|
113
|
+
* with the new length, and a delta added to that would compound. */
|
|
114
|
+
const pressBlend = useRef<number | null>(null);
|
|
115
|
+
/** The out trim's snap, frozen at the press (`beginSnap`). */
|
|
116
|
+
const snapOut = useRef<((frame: number) => number) | null>(null);
|
|
117
|
+
/** Which side of this bar a dragged shot would land on, for the drop line. */
|
|
118
|
+
const [dropSide, setDropSide] = useState<"before" | "after" | null>(null);
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (renaming) input.current?.select();
|
|
121
|
+
}, [renaming]);
|
|
122
|
+
|
|
123
|
+
/** Select the shot and put the playhead in it. The bar's own click, and the
|
|
124
|
+
* first half of every gesture that follows: the stage draws one shot, so a
|
|
125
|
+
* verb aimed at a shot the playhead is not in would act somewhere the author
|
|
126
|
+
* cannot see. */
|
|
127
|
+
const pick = (): void => {
|
|
128
|
+
store.setScene(id);
|
|
129
|
+
const frame = store.getState().frame;
|
|
130
|
+
if (frame < start || frame >= end) store.seek(start);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const menu = (e: { clientX: number; clientY: number; preventDefault(): void; stopPropagation(): void }): void => {
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
e.stopPropagation();
|
|
136
|
+
pick();
|
|
137
|
+
openMenu(
|
|
138
|
+
{ x: e.clientX, y: e.clientY },
|
|
139
|
+
shotMenuEntries(store, store.getState(), id, () => setRenaming(true)),
|
|
140
|
+
SHOT_MENU_OPTIONS,
|
|
141
|
+
);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const commitName = (next: string): void => {
|
|
145
|
+
setRenaming(false);
|
|
146
|
+
store.renameScene(id, next);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const sideOf = (e: ReactDragEvent<HTMLDivElement>): "before" | "after" => {
|
|
150
|
+
const box = e.currentTarget.getBoundingClientRect();
|
|
151
|
+
return e.clientX < box.left + box.width / 2 ? "before" : "after";
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<div
|
|
156
|
+
className={`shot-row${current ? " is-current" : ""}${entered ? " is-entered" : ""}`}
|
|
157
|
+
data-shot-row={id}
|
|
158
|
+
data-testid={`shot-row-${id}`}
|
|
159
|
+
>
|
|
160
|
+
<div className="shot-label-cell" style={{ width: labelWidth }}>
|
|
161
|
+
<span className="shot-swatch" aria-hidden="true" />
|
|
162
|
+
{renaming ? (
|
|
163
|
+
<input
|
|
164
|
+
ref={input}
|
|
165
|
+
className="shot-rename"
|
|
166
|
+
defaultValue={name}
|
|
167
|
+
aria-label={`Rename ${name}`}
|
|
168
|
+
data-testid={`shot-rename-${id}`}
|
|
169
|
+
// Commit on blur AND on Enter, discard on Escape. Escape has to stop
|
|
170
|
+
// propagating or the dock's drag-cancel listener and `leaveScene`
|
|
171
|
+
// both hear the same key.
|
|
172
|
+
onBlur={(e) => commitName(e.currentTarget.value)}
|
|
173
|
+
onKeyDown={(e) => {
|
|
174
|
+
e.stopPropagation();
|
|
175
|
+
if (e.key === "Enter") commitName(e.currentTarget.value);
|
|
176
|
+
else if (e.key === "Escape") setRenaming(false);
|
|
177
|
+
}}
|
|
178
|
+
/>
|
|
179
|
+
) : (
|
|
180
|
+
<button
|
|
181
|
+
type="button"
|
|
182
|
+
className="shot-name"
|
|
183
|
+
data-testid={`shot-name-${id}`}
|
|
184
|
+
onClick={pick}
|
|
185
|
+
// THE WAY IN. Opening a shot changes the dock, the stage, the
|
|
186
|
+
// breadcrumb and what the playhead can reach, and it is the most
|
|
187
|
+
// common navigation in the product — so it gets the gesture every
|
|
188
|
+
// file browser gives "go inside", on the row and on the bar alike.
|
|
189
|
+
onDoubleClick={() => store.enterScene(id)}
|
|
190
|
+
// F2 (the layers outline's key) or Enter on the focused name renames.
|
|
191
|
+
onKeyDown={(e) => {
|
|
192
|
+
if (e.key !== "F2" && e.key !== "Enter") return;
|
|
193
|
+
e.preventDefault();
|
|
194
|
+
e.stopPropagation();
|
|
195
|
+
if (!store.viewOnly()) setRenaming(true);
|
|
196
|
+
}}
|
|
197
|
+
onContextMenu={menu}
|
|
198
|
+
title={`${name}: double-click to open it, F2 to rename`}
|
|
199
|
+
>
|
|
200
|
+
{entered ? "Shot" : name}
|
|
201
|
+
</button>
|
|
202
|
+
)}
|
|
203
|
+
{/* THE FOLD, at the end of the label: the layer count and its chevron
|
|
204
|
+
in one target. The camera and the sound stay out of it inside a
|
|
205
|
+
shot, so a first look is three rows. */}
|
|
206
|
+
{expandable ? (
|
|
207
|
+
<button
|
|
208
|
+
type="button"
|
|
209
|
+
className="shot-disclosure"
|
|
210
|
+
aria-expanded={expanded}
|
|
211
|
+
aria-label={expanded ? `Hide ${name}'s layers` : `Show ${name}'s layers`}
|
|
212
|
+
title={expanded ? "Fold the layers into the shot" : "Show the layers"}
|
|
213
|
+
onClick={onToggle}
|
|
214
|
+
>
|
|
215
|
+
{layerCount === undefined ? null : (
|
|
216
|
+
<span className="shot-layer-count">
|
|
217
|
+
{layerCount} {layerCount === 1 ? "layer" : "layers"}
|
|
218
|
+
</span>
|
|
219
|
+
)}
|
|
220
|
+
<svg
|
|
221
|
+
className={`shot-fold-chevron${expanded ? " is-open" : ""}`}
|
|
222
|
+
width="12"
|
|
223
|
+
height="12"
|
|
224
|
+
viewBox="0 0 12 12"
|
|
225
|
+
fill="none"
|
|
226
|
+
aria-hidden="true"
|
|
227
|
+
>
|
|
228
|
+
<path d="M4.5 3L7.5 6L4.5 9" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
229
|
+
</svg>
|
|
230
|
+
</button>
|
|
231
|
+
) : null}
|
|
232
|
+
</div>
|
|
233
|
+
<div className="shot-lane">
|
|
234
|
+
<div
|
|
235
|
+
className={`shot-bar${current && !entered ? " is-current" : ""}${dropSide === null ? "" : ` is-drop-${dropSide}`}`}
|
|
236
|
+
style={{ left: frameToPx(start - originFrames, ppf), width: Math.max(8, frameToPx(end - start, ppf)) }}
|
|
237
|
+
data-scene={id}
|
|
238
|
+
// Reorder is HTML5 drag-and-drop: a splice of `doc.scenes`, never a
|
|
239
|
+
// written offset. The hovered half picks the side, and the line on
|
|
240
|
+
// that edge says so before the drop. Only a Shot bar's own MIME
|
|
241
|
+
// lights it: a file or asset drag would promise a reorder.
|
|
242
|
+
draggable={!readOnly}
|
|
243
|
+
onDragStart={(e) => e.dataTransfer.setData(SHOT_MIME, id)}
|
|
244
|
+
onDragOver={(e) => {
|
|
245
|
+
if (!Array.from(e.dataTransfer.types).includes(SHOT_MIME)) return;
|
|
246
|
+
e.preventDefault();
|
|
247
|
+
setDropSide(sideOf(e));
|
|
248
|
+
}}
|
|
249
|
+
onDragLeave={() => setDropSide(null)}
|
|
250
|
+
onDrop={(e) => {
|
|
251
|
+
e.preventDefault();
|
|
252
|
+
setDropSide(null);
|
|
253
|
+
const from = e.dataTransfer.getData(SHOT_MIME);
|
|
254
|
+
const fromIndex = store.getState().doc?.scenes.indexOf(from) ?? -1;
|
|
255
|
+
if (fromIndex < 0 || from === id) return;
|
|
256
|
+
// `reorderScene` takes the index AFTER the shot is lifted out.
|
|
257
|
+
const slot = sideOf(e) === "after" ? index + 1 : index;
|
|
258
|
+
store.reorderScene(from, fromIndex < slot ? slot - 1 : slot);
|
|
259
|
+
}}
|
|
260
|
+
onClick={pick}
|
|
261
|
+
onDoubleClick={() => store.enterScene(id)}
|
|
262
|
+
onContextMenu={menu}
|
|
263
|
+
title={`${name}: double-click to open it, drag to reorder, drag the right edge to trim`}
|
|
264
|
+
>
|
|
265
|
+
<span className="shot-bar-name">{name}</span>
|
|
266
|
+
{/* The length, at the clip's far end ("18.00s"). */}
|
|
267
|
+
{seconds === null ? null : <span className="shot-frames">{formatDuration(seconds)}</span>}
|
|
268
|
+
{/* The aimed target, kept beside the double-click rather than replaced
|
|
269
|
+
by it: a chevron is discoverable and a double-click is fast, and
|
|
270
|
+
the two cost one 12px button between them. */}
|
|
271
|
+
<button
|
|
272
|
+
type="button"
|
|
273
|
+
className="scene-open"
|
|
274
|
+
data-testid={`scene-open-${id}`}
|
|
275
|
+
aria-label={`Open ${name}`}
|
|
276
|
+
title={`Open ${name}: add and animate its elements`}
|
|
277
|
+
onPointerDown={(e) => e.stopPropagation()}
|
|
278
|
+
onClick={(e) => {
|
|
279
|
+
e.stopPropagation();
|
|
280
|
+
store.enterScene(id);
|
|
281
|
+
}}
|
|
282
|
+
>
|
|
283
|
+
›
|
|
284
|
+
</button>
|
|
285
|
+
<ShotTrimHandle
|
|
286
|
+
// Snaps like every other edge, to the targets a ripple trim leaves
|
|
287
|
+
// still: the playhead, the markers, and edges before this shot's end.
|
|
288
|
+
onStart={(e) => {
|
|
289
|
+
snapOut.current = beginSnap(
|
|
290
|
+
{ rippleFromFrame: end },
|
|
291
|
+
isSnapSuppressed(e),
|
|
292
|
+
{ min: start + MIN_SCENE_FRAMES, max: Infinity },
|
|
293
|
+
);
|
|
294
|
+
store.beginBlockDrag();
|
|
295
|
+
}}
|
|
296
|
+
onDrag={(deltaPx) => {
|
|
297
|
+
const out = snapOut.current?.(end + deltaPx / ppf) ?? end + frameDelta(deltaPx, ppf);
|
|
298
|
+
store.trimScene(id, out - start);
|
|
299
|
+
}}
|
|
300
|
+
onEnd={(commit) => {
|
|
301
|
+
snapOut.current = null;
|
|
302
|
+
store.endBlockDrag(commit);
|
|
303
|
+
}}
|
|
304
|
+
/>
|
|
305
|
+
</div>
|
|
306
|
+
{/* No seam inside the ENTERED shot: its out frame is the lane's right
|
|
307
|
+
edge there, so the diamond drew half clipped into the clip's end,
|
|
308
|
+
and the next shot it leads into is not on screen. `isLast` is the
|
|
309
|
+
Project's answer and says nothing about which shot is entered. */}
|
|
310
|
+
{isLast || entered ? null : (
|
|
311
|
+
<button
|
|
312
|
+
type="button"
|
|
313
|
+
className={`scene-cut${blendFrames === null ? "" : " is-blend"}`}
|
|
314
|
+
style={{ left: frameToPx(end - originFrames, ppf) }}
|
|
315
|
+
aria-label={`Transition after ${name}`}
|
|
316
|
+
title={blendFrames === null ? `Cut after ${name}` : `Blend after ${name}`}
|
|
317
|
+
onClick={(e) => {
|
|
318
|
+
e.stopPropagation();
|
|
319
|
+
// Select the OUTGOING shot: that is where the transition is stored
|
|
320
|
+
// and where the inspector edits it. The playhead goes to the last
|
|
321
|
+
// frame it owns, so the stage shows the frame the blend starts from.
|
|
322
|
+
store.setScene(id);
|
|
323
|
+
store.seek(Math.max(start, end - 1));
|
|
324
|
+
}}
|
|
325
|
+
/>
|
|
326
|
+
)}
|
|
327
|
+
{/* ── THE BLEND RIBBON ────────────────────────────────────────────
|
|
328
|
+
Drawn FORWARD from the cut, because that is where the window is:
|
|
329
|
+
`transitionAt` puts it on the INCOMING side, [cut, cut + d), which
|
|
330
|
+
is what keeps the master timeline from retiming when a transition is
|
|
331
|
+
added. A ribbon reaching backwards would draw a Premiere-style
|
|
332
|
+
handle that this lane deliberately does not have.
|
|
333
|
+
|
|
334
|
+
It overhangs this row's own bar on purpose — the blend belongs to
|
|
335
|
+
the seam, not to either shot — and is pointer-transparent except
|
|
336
|
+
for its handle, so it cannot swallow clicks meant for the row under
|
|
337
|
+
it. There is no drag-to-CREATE: the diamond already opens the
|
|
338
|
+
inspector, which is where a preset gets chosen. */}
|
|
339
|
+
{isLast || entered || blendFrames === null ? null : (
|
|
340
|
+
<div
|
|
341
|
+
className="scene-blend"
|
|
342
|
+
style={{
|
|
343
|
+
left: frameToPx(end - originFrames, ppf),
|
|
344
|
+
width: frameToPx(blendFrames, ppf),
|
|
345
|
+
}}
|
|
346
|
+
aria-hidden="true"
|
|
347
|
+
>
|
|
348
|
+
<ShotTrimHandle
|
|
349
|
+
onStart={() => {
|
|
350
|
+
pressBlend.current = store.getState().doc?.scenesById[id]?.transition?.durationFrames ?? null;
|
|
351
|
+
store.beginBlockDrag();
|
|
352
|
+
}}
|
|
353
|
+
onDrag={(deltaPx) => {
|
|
354
|
+
// Read the transition LIVE from the store rather than closing
|
|
355
|
+
// over a prop: a drag re-derives from its own base every move,
|
|
356
|
+
// so the object it spreads has to be the current one. The
|
|
357
|
+
// length is the press's, plus the move from the press.
|
|
358
|
+
const current = store.getState().doc?.scenesById[id]?.transition;
|
|
359
|
+
const base = pressBlend.current;
|
|
360
|
+
if (current === undefined || base === null) return;
|
|
361
|
+
store.setSceneTransition(id, {
|
|
362
|
+
...current,
|
|
363
|
+
durationFrames: Math.max(MIN_TRANSITION_FRAMES, base + frameDelta(deltaPx, ppf)),
|
|
364
|
+
});
|
|
365
|
+
}}
|
|
366
|
+
onEnd={(commit) => {
|
|
367
|
+
pressBlend.current = null;
|
|
368
|
+
store.endBlockDrag(commit);
|
|
369
|
+
}}
|
|
370
|
+
/>
|
|
371
|
+
</div>
|
|
372
|
+
)}
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function ShotTrimHandle({
|
|
379
|
+
onStart,
|
|
380
|
+
onDrag,
|
|
381
|
+
onEnd,
|
|
382
|
+
}: {
|
|
383
|
+
onStart(press: { metaKey: boolean; ctrlKey: boolean }): void;
|
|
384
|
+
onDrag(deltaPx: number): void;
|
|
385
|
+
onEnd(commit: boolean): void;
|
|
386
|
+
}) {
|
|
387
|
+
const onPointerDown = (e: ReactPointerEvent<HTMLSpanElement>): void => {
|
|
388
|
+
e.preventDefault();
|
|
389
|
+
e.stopPropagation();
|
|
390
|
+
const startX = e.clientX;
|
|
391
|
+
onStart(e);
|
|
392
|
+
// Absolute from the PRESS, never cumulative — the rule every drag in this
|
|
393
|
+
// lane follows, and the reason a coalesced move cannot make it drift.
|
|
394
|
+
startDrag(e, {
|
|
395
|
+
onMove: (ev) => onDrag(ev.clientX - startX),
|
|
396
|
+
onEnd: (commit) => onEnd(commit),
|
|
397
|
+
});
|
|
398
|
+
};
|
|
399
|
+
return <span className="scene-trim" data-handle="scene-out" onPointerDown={onPointerDown} aria-hidden="true" />;
|
|
400
|
+
}
|