@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,341 @@
|
|
|
1
|
+
// The parts both Components tabs share (C1, C2, C7): the way back and the
|
|
2
|
+
// breadcrumb in the canvas bar (whose "used in N places" opens Every use), the
|
|
3
|
+
// Preview tab's transport, and the hooks the right panel and Every use read.
|
|
4
|
+
import { useEffect, useMemo, useState } from "react";
|
|
5
|
+
import type { ReactNode } from "react";
|
|
6
|
+
import { SegmentedControl } from "@dailies-studio/ui";
|
|
7
|
+
import { framesToSeconds, secondsToFrame } from "@dailies-studio/engine";
|
|
8
|
+
import type { Rational } from "@dailies-studio/engine";
|
|
9
|
+
import { componentUsesOf } from "@dailies-studio/shot/doc";
|
|
10
|
+
import * as api from "../../api.js";
|
|
11
|
+
import type { ShotComponentBackground } from "../../bridgeTypes.js";
|
|
12
|
+
import { CHEVRON_LEFT_ICON } from "../../icons.js";
|
|
13
|
+
import { useShotEditor, useShotEditorHot, useStore } from "../../state/context.js";
|
|
14
|
+
import { defClockFrames } from "../../state/types.js";
|
|
15
|
+
import type { ComponentsOrigin, ComponentsSelection } from "../../state/types.js";
|
|
16
|
+
import {
|
|
17
|
+
componentsSubject,
|
|
18
|
+
newPropKeys,
|
|
19
|
+
sameComponent,
|
|
20
|
+
shotLabel,
|
|
21
|
+
useByKey,
|
|
22
|
+
usesViewOf,
|
|
23
|
+
workspaceRowOf,
|
|
24
|
+
} from "../../state/workspace.js";
|
|
25
|
+
import { clock, formatDuration } from "../timeline/model.js";
|
|
26
|
+
import { PlayButton } from "../timeline/PlayButton.js";
|
|
27
|
+
|
|
28
|
+
const FALLBACK_FPS: Rational = { num: 30, den: 1 };
|
|
29
|
+
|
|
30
|
+
/** The open component's workspace row, when the store has one for it. */
|
|
31
|
+
export function useSubjectRow(): api.WorkspaceComponent | undefined {
|
|
32
|
+
const list = useShotEditor((s) => s.workspaceComponents);
|
|
33
|
+
const projectId = useShotEditor((s) => s.doc?.id);
|
|
34
|
+
const codeComponent = useShotEditor((s) => s.codeComponent);
|
|
35
|
+
const editingDef = useShotEditor((s) => s.editingDef);
|
|
36
|
+
return useMemo(
|
|
37
|
+
() => workspaceRowOf(list, projectId, componentsSubject({ codeComponent, editingDef })),
|
|
38
|
+
[list, projectId, codeComponent, editingDef],
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The subject's recorded versions, newest first, loaded again whenever its
|
|
43
|
+
* workspace row moves to a new version. */
|
|
44
|
+
export function useSubjectVersions(): readonly api.WorkspaceComponentVersionInfo[] | undefined {
|
|
45
|
+
const store = useStore();
|
|
46
|
+
const row = useSubjectRow();
|
|
47
|
+
const id = row?.id ?? null;
|
|
48
|
+
const version = row?.version ?? 0;
|
|
49
|
+
const versions = useShotEditor((s) => (id === null ? undefined : s.componentVersions[id]));
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (id !== null) void store.loadComponentVersions(id);
|
|
52
|
+
}, [store, id, version]);
|
|
53
|
+
return versions;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** The keys that were not in the previous version: the "New" badge's rows. */
|
|
57
|
+
export function useNewPropKeys(keys: readonly string[]): string[] {
|
|
58
|
+
const versions = useSubjectVersions();
|
|
59
|
+
// Keyed on the names, not the array a caller may build per render.
|
|
60
|
+
const joined = keys.join(" ");
|
|
61
|
+
return useMemo(() => newPropKeys(joined === "" ? [] : joined.split(" "), versions), [joined, versions]);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The usage index's rows for the open component, across every Project the
|
|
65
|
+
* caller may see, or null until it answers (or when the store does not
|
|
66
|
+
* know the component yet). Read again when the component records a new
|
|
67
|
+
* version, since a save is what rewrites the index. */
|
|
68
|
+
export function useIndexedUses(): readonly api.IndexedComponentUse[] | null {
|
|
69
|
+
const row = useSubjectRow();
|
|
70
|
+
const [indexed, setIndexed] = useState<{ id: string; uses: api.IndexedComponentUse[] } | null>(null);
|
|
71
|
+
const id = row?.id ?? null;
|
|
72
|
+
const version = row?.version ?? 0;
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (id === null) return;
|
|
75
|
+
let live = true;
|
|
76
|
+
api.workspaceComponentUses(id).then(
|
|
77
|
+
(uses) => {
|
|
78
|
+
if (live) setIndexed({ id, uses });
|
|
79
|
+
},
|
|
80
|
+
() => {
|
|
81
|
+
// No other Projects listed; this document's own uses stand.
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
return () => {
|
|
85
|
+
live = false;
|
|
86
|
+
};
|
|
87
|
+
}, [id, version]);
|
|
88
|
+
return indexed !== null && indexed.id === id ? indexed.uses : null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** The index's uses in OTHER Projects. This document's own come from the
|
|
92
|
+
* live document instead, which the index only sees at its last save. */
|
|
93
|
+
export function useOtherProjectUses(): readonly api.IndexedComponentUse[] {
|
|
94
|
+
const indexed = useIndexedUses();
|
|
95
|
+
const projectId = useShotEditor((s) => s.doc?.id);
|
|
96
|
+
return useMemo(() => (indexed ?? []).filter((u) => u.projectId !== projectId), [indexed, projectId]);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** How many places use the component: this document's own uses, live, plus
|
|
100
|
+
* the usage index's uses in every other Project. */
|
|
101
|
+
export function useUsedIn(sel: ComponentsSelection | null): number {
|
|
102
|
+
const doc = useShotEditor((s) => s.doc);
|
|
103
|
+
// Keyed on the id, not the selection object a caller may build per render.
|
|
104
|
+
const kind = sel?.kind ?? null;
|
|
105
|
+
const target = sel === null ? null : sel.kind === "studio" ? sel.def : sel.module;
|
|
106
|
+
const local = useMemo(() => {
|
|
107
|
+
if (doc === null || target === null) return 0;
|
|
108
|
+
return componentUsesOf(doc).filter((u) => (kind === "studio" ? u.def === target : u.component === target)).length;
|
|
109
|
+
}, [doc, kind, target]);
|
|
110
|
+
return local + useOtherProjectUses().length;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** The Shot door this component came through (C7), while it is on screen:
|
|
114
|
+
* null once the author picks another component. */
|
|
115
|
+
export function useOriginOf(sel: ComponentsSelection | null): ComponentsOrigin | null {
|
|
116
|
+
return useShotEditor((s) =>
|
|
117
|
+
s.componentsOrigin !== null && sameComponent(s.componentsOrigin.sel, sel) ? s.componentsOrigin : null,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* THE WAY BACK, first in every Components bar.
|
|
123
|
+
*
|
|
124
|
+
* came from a Shot "Back to Shot" (C7): that Shot, its frame and its
|
|
125
|
+
* selection, as the author left them (`backToShot`).
|
|
126
|
+
* Kept while they browse other components.
|
|
127
|
+
* a component open the chevron to All components (`openComponents`).
|
|
128
|
+
* the home the chevron out of Components (`leaveComponents`).
|
|
129
|
+
*
|
|
130
|
+
* `guard` asks before a code component's unsaved buffers go.
|
|
131
|
+
*/
|
|
132
|
+
export function ComponentsBack(props: { testId: string; guard: (then: () => void) => void }) {
|
|
133
|
+
const store = useStore();
|
|
134
|
+
const fromShot = useShotEditor((s) => s.componentsOrigin !== null);
|
|
135
|
+
const home = useShotEditor((s) => componentsSubject(s) === null);
|
|
136
|
+
if (fromShot) {
|
|
137
|
+
return (
|
|
138
|
+
<button
|
|
139
|
+
type="button"
|
|
140
|
+
className="btn components-back-to-shot"
|
|
141
|
+
data-testid="components-back-to-shot"
|
|
142
|
+
title="Back to the Shot, at the frame you left (Esc)"
|
|
143
|
+
onClick={() => props.guard(() => void store.backToShot())}
|
|
144
|
+
>
|
|
145
|
+
<span className="tool-icon" aria-hidden="true">
|
|
146
|
+
{CHEVRON_LEFT_ICON}
|
|
147
|
+
</span>
|
|
148
|
+
Back to Shot
|
|
149
|
+
</button>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
const label = home ? "Leave Components" : "All components";
|
|
153
|
+
return (
|
|
154
|
+
<button
|
|
155
|
+
type="button"
|
|
156
|
+
className="back-chip component-studio-back"
|
|
157
|
+
data-testid={props.testId}
|
|
158
|
+
title={home ? "Leave Components (Esc)" : "All components"}
|
|
159
|
+
aria-label={label}
|
|
160
|
+
onClick={() => props.guard(() => (home ? store.leaveComponents() : void store.openComponents()))}
|
|
161
|
+
>
|
|
162
|
+
<span className="tool-icon" aria-hidden="true">
|
|
163
|
+
{CHEVRON_LEFT_ICON}
|
|
164
|
+
</span>
|
|
165
|
+
</button>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** "All components / <name> · used in N places", the canvas bar's lead, or,
|
|
170
|
+
* for the use a Shot door opened (C7), "03 Phone reveal / <name> · this use
|
|
171
|
+
* · frame 00:01.08". `name` is a slot so the Studio's Edit tab can make it
|
|
172
|
+
* the rename button. The Edit tabs drop the "All components /" root: the
|
|
173
|
+
* chevron before it and the left column's back row already say where up
|
|
174
|
+
* is, so the bar reads the chevron and the name. */
|
|
175
|
+
export function ComponentCrumb(props: { sel: ComponentsSelection; name: ReactNode }) {
|
|
176
|
+
const origin = useOriginOf(props.sel);
|
|
177
|
+
if (origin !== null) return <OriginCrumb origin={origin} name={props.name} />;
|
|
178
|
+
return <SubjectCrumb sel={props.sel} name={props.name} />;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function OriginCrumb(props: { origin: ComponentsOrigin; name: ReactNode }) {
|
|
182
|
+
const doc = useShotEditor((s) => s.doc);
|
|
183
|
+
const fps = doc?.fps ?? FALLBACK_FPS;
|
|
184
|
+
const use = useMemo(() => (doc === null ? null : useByKey(doc, props.origin.useKey)), [doc, props.origin.useKey]);
|
|
185
|
+
const shot = doc !== null && use?.sceneId != null ? shotLabel(doc, use.sceneId) : "Shot";
|
|
186
|
+
return (
|
|
187
|
+
<div className="components-crumb" data-testid="components-crumb">
|
|
188
|
+
<span className="components-crumb-root" data-testid="components-crumb-shot">
|
|
189
|
+
{shot} /
|
|
190
|
+
</span>
|
|
191
|
+
{props.name}
|
|
192
|
+
<span className="components-crumb-use" data-testid="components-crumb-use">
|
|
193
|
+
this use · frame {clock(props.origin.shotFrame, fps)}
|
|
194
|
+
</span>
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function SubjectCrumb(props: { sel: ComponentsSelection; name: ReactNode }) {
|
|
200
|
+
const store = useStore();
|
|
201
|
+
const used = useUsedIn(props.sel);
|
|
202
|
+
const open = useShotEditor((s) => usesViewOf(s) !== null);
|
|
203
|
+
const preview = useShotEditor((s) => s.componentsTab === "preview");
|
|
204
|
+
// A door to Every use (C4), which takes the preview's place; pressed again
|
|
205
|
+
// it closes.
|
|
206
|
+
return (
|
|
207
|
+
<div className="components-crumb" data-testid="components-crumb">
|
|
208
|
+
{preview ? <span className="components-crumb-root">All components /</span> : null}
|
|
209
|
+
{props.name}
|
|
210
|
+
<button
|
|
211
|
+
type="button"
|
|
212
|
+
className="components-crumb-uses"
|
|
213
|
+
data-testid="components-used-in"
|
|
214
|
+
aria-pressed={open}
|
|
215
|
+
title={open ? "Back to the preview" : "Every place that uses this component"}
|
|
216
|
+
onClick={() => store.openComponentUses(!open)}
|
|
217
|
+
>
|
|
218
|
+
used in {used} {used === 1 ? "place" : "places"}
|
|
219
|
+
</button>
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** The loop lengths the transport offers, in seconds, after the component's own. */
|
|
225
|
+
const LOOP_SECONDS = [1, 2, 3, 4, 6, 8];
|
|
226
|
+
|
|
227
|
+
const BACKDROPS: { value: ShotComponentBackground; label: string }[] = [
|
|
228
|
+
{ value: "dark", label: "Dark" },
|
|
229
|
+
{ value: "light", label: "Light" },
|
|
230
|
+
{ value: "brand", label: "Brand" },
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
/** The loop's length on screen, and the component's own length (no loop set). */
|
|
234
|
+
export function useLoopLength(): { frames: number; own: number; fps: Rational } {
|
|
235
|
+
const frames = useShotEditor((s) => defClockFrames(s) ?? 0);
|
|
236
|
+
const own = useShotEditor((s) => defClockFrames({ ...s, componentPreview: { ...s.componentPreview, loopFrames: null } }) ?? 0);
|
|
237
|
+
const fps = useShotEditor((s) => s.doc?.fps ?? FALLBACK_FPS);
|
|
238
|
+
return { frames, own, fps };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* The Preview tab's 48 transport, under the stage in the canvas cell: pause,
|
|
243
|
+
* the loop length, the progress (a scrub), and the backdrop. The header's
|
|
244
|
+
* playback loop already plays the component clock (`defClockFrames`), so this
|
|
245
|
+
* is the dock's play button in another place (`PlayButton`, the same
|
|
246
|
+
* component), not a second playback path.
|
|
247
|
+
*/
|
|
248
|
+
export function PreviewTransport() {
|
|
249
|
+
const store = useStore();
|
|
250
|
+
const frame = useShotEditorHot((s) => s.defFrame);
|
|
251
|
+
const loopFrames = useShotEditor((s) => s.componentPreview.loopFrames);
|
|
252
|
+
const background = useShotEditor((s) => s.componentPreview.background);
|
|
253
|
+
const { frames, own, fps } = useLoopLength();
|
|
254
|
+
const label = (n: number): string => `Loop · ${formatDuration(framesToSeconds(n, fps))}`;
|
|
255
|
+
const choices = LOOP_SECONDS.map((sec) => secondsToFrame(sec, fps)).filter((n) => n !== own);
|
|
256
|
+
const last = Math.max(0, frames - 1);
|
|
257
|
+
return (
|
|
258
|
+
<div className="components-transport" data-testid="components-transport">
|
|
259
|
+
<PlayButton className="components-play" testId="components-play" />
|
|
260
|
+
<select
|
|
261
|
+
className="select components-loop"
|
|
262
|
+
data-testid="components-loop"
|
|
263
|
+
aria-label="Loop length"
|
|
264
|
+
value={loopFrames === null ? "" : String(loopFrames)}
|
|
265
|
+
onChange={(e) => {
|
|
266
|
+
const v = e.currentTarget.value;
|
|
267
|
+
store.setComponentPreview({ loopFrames: v === "" ? null : Number(v) });
|
|
268
|
+
}}
|
|
269
|
+
>
|
|
270
|
+
<option value="">{label(own)}</option>
|
|
271
|
+
{choices.map((n) => (
|
|
272
|
+
<option key={n} value={String(n)}>
|
|
273
|
+
{label(n)}
|
|
274
|
+
</option>
|
|
275
|
+
))}
|
|
276
|
+
{loopFrames !== null && !choices.includes(loopFrames) && loopFrames !== own ? (
|
|
277
|
+
<option value={String(loopFrames)}>{label(loopFrames)}</option>
|
|
278
|
+
) : null}
|
|
279
|
+
</select>
|
|
280
|
+
<input
|
|
281
|
+
className="transport-scrub components-progress"
|
|
282
|
+
type="range"
|
|
283
|
+
min={0}
|
|
284
|
+
max={last}
|
|
285
|
+
step={1}
|
|
286
|
+
value={Math.min(frame, last)}
|
|
287
|
+
aria-label="Loop position"
|
|
288
|
+
data-testid="components-progress"
|
|
289
|
+
onChange={(e) => {
|
|
290
|
+
store.pauseForScrub();
|
|
291
|
+
store.seekDef(Number(e.currentTarget.value));
|
|
292
|
+
}}
|
|
293
|
+
/>
|
|
294
|
+
{/* The state's own value, with no default of its own: the look starts
|
|
295
|
+
on Dark (`INITIAL_STATE`), so what is lit is what the stage draws. */}
|
|
296
|
+
<SegmentedControl
|
|
297
|
+
ariaLabel="Backdrop"
|
|
298
|
+
className="components-backdrop"
|
|
299
|
+
value={background ?? ""}
|
|
300
|
+
options={BACKDROPS.map((b) => ({ value: b.value, label: b.label, testId: `components-backdrop-${b.value}` }))}
|
|
301
|
+
onChange={(next) => store.setComponentPreview({ background: next as ShotComponentBackground })}
|
|
302
|
+
/>
|
|
303
|
+
</div>
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* The props panel's "Apply to all instances" checkbox, shared by the code
|
|
309
|
+
* and the definition panels (Framer's component panel: values are tried
|
|
310
|
+
* first, saved on purpose).
|
|
311
|
+
*
|
|
312
|
+
* Off: every edit is TRIED (`componentPlay`), drawn in the preview and saved
|
|
313
|
+
* nowhere. On: edits save to the component, which every instance without its
|
|
314
|
+
* own value follows; ticking it also saves whatever was being tried.
|
|
315
|
+
*/
|
|
316
|
+
export function ApplyAllToggle({ disabled, disabledReason }: { disabled: boolean; disabledReason?: string }) {
|
|
317
|
+
const store = useStore();
|
|
318
|
+
const on = useShotEditor((s) => s.componentApplyAll);
|
|
319
|
+
const tried = useShotEditor((s) => Object.keys(s.componentPlay).length);
|
|
320
|
+
return (
|
|
321
|
+
<div className="props-apply" data-testid="props-apply-all">
|
|
322
|
+
<label className="props-apply-row" title={disabled ? disabledReason : undefined}>
|
|
323
|
+
<input
|
|
324
|
+
type="checkbox"
|
|
325
|
+
className="checkbox"
|
|
326
|
+
checked={on && !disabled}
|
|
327
|
+
disabled={disabled}
|
|
328
|
+
onChange={(e) => store.setComponentApplyAll(e.currentTarget.checked)}
|
|
329
|
+
/>
|
|
330
|
+
<span>Apply to all instances</span>
|
|
331
|
+
</label>
|
|
332
|
+
<p className="insp-note props-apply-note" data-testid="props-apply-note">
|
|
333
|
+
{on && !disabled
|
|
334
|
+
? "Changes save to the component. Every instance without its own value follows."
|
|
335
|
+
: tried === 0
|
|
336
|
+
? "Try values in the preview. Nothing is saved."
|
|
337
|
+
: `Trying ${tried === 1 ? "1 change" : `${tried} changes`} in the preview. Tick to save to every instance.`}
|
|
338
|
+
</p>
|
|
339
|
+
</div>
|
|
340
|
+
);
|
|
341
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// THE COMPONENTS WORKSPACE'S CHUNK: All components, a component's Preview tab
|
|
2
|
+
// and a Studio-made component's Edit tab. Loaded on demand through
|
|
3
|
+
// app/lazySurfaces.tsx. Code Studio is a chunk of its own, because it carries
|
|
4
|
+
// the CodeMirror editor.
|
|
5
|
+
export { ComponentStudio } from "./ComponentStudio.js";
|
|
6
|
+
export { ComponentsPreview } from "./ComponentsPreview.js";
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// What Components' New › Code writes: the "component-three" template and the
|
|
2
|
+
// export-name rule, RESTATED from packages/store/src/componentTemplates.ts
|
|
3
|
+
// (the chrome cannot import the store package). Keep the two in step:
|
|
4
|
+
// test/newCodeComponent.test.ts holds them equal.
|
|
5
|
+
|
|
6
|
+
/** PascalCase identifier from whatever the author typed. A component's NAME
|
|
7
|
+
* is its export name, so an invalid identifier is a syntax error. */
|
|
8
|
+
export function componentNameOf(input: string): string {
|
|
9
|
+
const base = input.slice(input.lastIndexOf("/") + 1).replace(/\..*$/, "");
|
|
10
|
+
const words = base.split(/[^A-Za-z0-9]+/).filter(Boolean);
|
|
11
|
+
const name = words.map((w) => w[0]!.toUpperCase() + w.slice(1)).join("");
|
|
12
|
+
return /^[A-Za-z]/.test(name) ? name : `C${name}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// The starter's r3f specifier, held apart from its `from` so sourceHygiene's
|
|
16
|
+
// three-free scan reads the template as the text it is, not an import.
|
|
17
|
+
const FIBER = "@react-three/fiber";
|
|
18
|
+
|
|
19
|
+
/** The react-three-fiber starter: typed optional props with defaults, so the
|
|
20
|
+
* extractor infers a usable contract with no controls file. It keeps the
|
|
21
|
+
* shot lane's three rules, so it shows the moment it is made: it draws in
|
|
22
|
+
* design px (the lane's world unit), its material needs no light (the lane
|
|
23
|
+
* has none), and its time is the studio clock, read in render. Its empty r3f
|
|
24
|
+
* type import is what declares its JSX: a new workspace has no other file
|
|
25
|
+
* that loads r3f's types. */
|
|
26
|
+
export function threeComponentSource(name: string): string {
|
|
27
|
+
return `// r3f's JSX types, so <mesh> and the other three elements type-check even
|
|
28
|
+
// when no other file in the Project imports r3f. It loads no code.
|
|
29
|
+
import type {} from "${FIBER}";
|
|
30
|
+
import { useStudioClock } from "@dailies-studio/runtime";
|
|
31
|
+
|
|
32
|
+
export interface ${name}Props {
|
|
33
|
+
/**
|
|
34
|
+
* How fast it turns. The angle comes from the studio clock and is never
|
|
35
|
+
* added up per frame, so a scrub or an export lands on the same pose.
|
|
36
|
+
* @min 0
|
|
37
|
+
* @max 5
|
|
38
|
+
*/
|
|
39
|
+
speed?: number;
|
|
40
|
+
color?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Across, in design px. One world unit on the stage is one design pixel.
|
|
43
|
+
* @min 1
|
|
44
|
+
* @max 2000
|
|
45
|
+
* @unit px
|
|
46
|
+
*/
|
|
47
|
+
size?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// torusKnotGeometry(0.7, 0.24) reaches 1.29 units from its centre, so at any
|
|
51
|
+
// angle it stays inside a circle 2.58 units across.
|
|
52
|
+
const SPAN = 2.58;
|
|
53
|
+
|
|
54
|
+
export function ${name}({ speed = 1, color = "#4f8cff", size = 360 }: ${name}Props) {
|
|
55
|
+
const t = (useStudioClock()?.timeSeconds ?? 0) * speed;
|
|
56
|
+
// The stage has no lights, so the material must need none: a matcap shades
|
|
57
|
+
// the form from the view alone and still reads as 3D.
|
|
58
|
+
return (
|
|
59
|
+
<mesh rotation={[t * 0.7, t, 0]} scale={size / SPAN}>
|
|
60
|
+
<torusKnotGeometry args={[0.7, 0.24, 160, 32]} />
|
|
61
|
+
<meshMatcapMaterial color={color} />
|
|
62
|
+
</mesh>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
66
|
+
}
|