@adminide-stack/yantra-mobile 12.0.128 → 12.0.129-alpha.1
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/lib/compute.js +57 -1
- package/lib/compute.js.map +1 -1
- package/lib/features/agent-chat/NativeAgentChat.js +3 -2
- package/lib/features/agent-chat/NativeAgentChat.js.map +1 -1
- package/lib/features/apps/AppsCatalog.js +10 -0
- package/lib/features/apps/AppsCatalog.js.map +1 -1
- package/lib/features/apps/mobileAppCatalog.js +11 -0
- package/lib/features/apps/mobileAppCatalog.js.map +1 -1
- package/lib/features/canvas/AudioEditorExperience.js +448 -105
- package/lib/features/canvas/AudioEditorExperience.js.map +1 -1
- package/lib/features/canvas/CanvasAgentChatPane.js +33 -14
- package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -1
- package/lib/features/canvas/CanvasBoardsGrid.js +493 -41
- package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
- package/lib/features/canvas/CanvasChatResultCard.js.map +1 -1
- package/lib/features/canvas/CanvasEditToolsPanel.js +37 -1
- package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -1
- package/lib/features/canvas/CanvasExperience.js +237 -22
- package/lib/features/canvas/CanvasExperience.js.map +1 -1
- package/lib/features/canvas/CanvasGeneratePanel.js +119 -26
- package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -1
- package/lib/features/canvas/CanvasLooksPanel.js +17 -6
- package/lib/features/canvas/CanvasLooksPanel.js.map +1 -1
- package/lib/features/canvas/CanvasTasksPanel.js +18 -1
- package/lib/features/canvas/CanvasTasksPanel.js.map +1 -1
- package/lib/features/canvas/DesignCategoryGallery.js +423 -0
- package/lib/features/canvas/DesignCategoryGallery.js.map +1 -0
- package/lib/features/canvas/ImageEditorExperience.js +763 -187
- package/lib/features/canvas/ImageEditorExperience.js.map +1 -1
- package/lib/features/canvas/SetStudioExperience.js +199 -11
- package/lib/features/canvas/SetStudioExperience.js.map +1 -1
- package/lib/features/canvas/VideoEditorExperience.js +59 -40
- package/lib/features/canvas/VideoEditorExperience.js.map +1 -1
- package/lib/features/canvas/VideoGeneratorExperience.js +134 -34
- package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -1
- package/lib/features/canvas/aiEdit.js +4 -2
- package/lib/features/canvas/aiEdit.js.map +1 -1
- package/lib/features/canvas/audioEditor/AudioWaveform.js +96 -0
- package/lib/features/canvas/audioEditor/AudioWaveform.js.map +1 -0
- package/lib/features/canvas/audioEditor/audioPeaks.js +93 -0
- package/lib/features/canvas/audioEditor/audioPeaks.js.map +1 -0
- package/lib/features/canvas/canvasTaskSync.js +34 -7
- package/lib/features/canvas/canvasTaskSync.js.map +1 -1
- package/lib/features/canvas/canvasTasks.js +23 -3
- package/lib/features/canvas/canvasTasks.js.map +1 -1
- package/lib/features/canvas/canvasTheme.js +10 -24
- package/lib/features/canvas/canvasTheme.js.map +1 -1
- package/lib/features/canvas/canvasUi.js +1 -1
- package/lib/features/canvas/canvasUi.js.map +1 -1
- package/lib/features/canvas/createTiles.js +17 -9
- package/lib/features/canvas/createTiles.js.map +1 -1
- package/lib/features/canvas/deepLinks.js +35 -5
- package/lib/features/canvas/deepLinks.js.map +1 -1
- package/lib/features/canvas/designCatalog.js +165 -0
- package/lib/features/canvas/designCatalog.js.map +1 -0
- package/lib/features/canvas/designCategories.js +262 -0
- package/lib/features/canvas/designCategories.js.map +1 -0
- package/lib/features/canvas/editorControls.js +406 -0
- package/lib/features/canvas/editorControls.js.map +1 -0
- package/lib/features/canvas/generationModels.js +5 -3
- package/lib/features/canvas/generationModels.js.map +1 -1
- package/lib/features/canvas/generationTasks.js +162 -0
- package/lib/features/canvas/generationTasks.js.map +1 -0
- package/lib/features/canvas/generator/BottomSheet.js +167 -0
- package/lib/features/canvas/generator/BottomSheet.js.map +1 -0
- package/lib/features/canvas/generator/BusinessCardChatCard.js +155 -0
- package/lib/features/canvas/generator/BusinessCardChatCard.js.map +1 -0
- package/lib/features/canvas/generator/DirectorSheet.js +163 -0
- package/lib/features/canvas/generator/DirectorSheet.js.map +1 -0
- package/lib/features/canvas/generator/ReframePreview.js +122 -0
- package/lib/features/canvas/generator/ReframePreview.js.map +1 -0
- package/lib/features/canvas/generator/RunLogCard.js +119 -0
- package/lib/features/canvas/generator/RunLogCard.js.map +1 -0
- package/lib/features/canvas/generator/ShotPanel.js +261 -0
- package/lib/features/canvas/generator/ShotPanel.js.map +1 -0
- package/lib/features/canvas/generator/businessCardWidget.js +117 -0
- package/lib/features/canvas/generator/businessCardWidget.js.map +1 -0
- package/lib/features/canvas/generator/cameraVocabulary.js +142 -0
- package/lib/features/canvas/generator/cameraVocabulary.js.map +1 -0
- package/lib/features/canvas/generator/cinematicVocabulary.js +416 -0
- package/lib/features/canvas/generator/cinematicVocabulary.js.map +1 -0
- package/lib/features/canvas/generator/direction.js +41 -0
- package/lib/features/canvas/generator/direction.js.map +1 -0
- package/lib/features/canvas/generator/reframeGeometry.js +108 -0
- package/lib/features/canvas/generator/reframeGeometry.js.map +1 -0
- package/lib/features/canvas/generator/runLog.js +71 -0
- package/lib/features/canvas/generator/runLog.js.map +1 -0
- package/lib/features/canvas/generator/shot.js +133 -0
- package/lib/features/canvas/generator/shot.js.map +1 -0
- package/lib/features/canvas/generator/useShotSpec.js +87 -0
- package/lib/features/canvas/generator/useShotSpec.js.map +1 -0
- package/lib/features/canvas/home/HeroComposer.js +214 -0
- package/lib/features/canvas/home/HeroComposer.js.map +1 -0
- package/lib/features/canvas/home/HeroMonitor.js +225 -0
- package/lib/features/canvas/home/HeroMonitor.js.map +1 -0
- package/lib/features/canvas/home/LookDetail.js +185 -0
- package/lib/features/canvas/home/LookDetail.js.map +1 -0
- package/lib/features/canvas/home/LoopingVideo.js +37 -0
- package/lib/features/canvas/home/LoopingVideo.js.map +1 -0
- package/lib/features/canvas/home/TemplatesGallery.js +253 -0
- package/lib/features/canvas/home/TemplatesGallery.js.map +1 -0
- package/lib/features/canvas/home/heroShots.js +100 -0
- package/lib/features/canvas/home/heroShots.js.map +1 -0
- package/lib/features/canvas/homeWork.js +62 -3
- package/lib/features/canvas/homeWork.js.map +1 -1
- package/lib/features/canvas/imageEditor/ImageMarkup.js +195 -0
- package/lib/features/canvas/imageEditor/ImageMarkup.js.map +1 -0
- package/lib/features/canvas/imageEditor/imageEditOps.js +367 -0
- package/lib/features/canvas/imageEditor/imageEditOps.js.map +1 -0
- package/lib/features/canvas/nativeViewerRegistry.js.map +1 -1
- package/lib/features/canvas/rankedCatalogSearch.js +375 -0
- package/lib/features/canvas/rankedCatalogSearch.js.map +1 -0
- package/lib/features/canvas/recorder/CameraRecorderExperience.js +68 -20
- package/lib/features/canvas/recorder/CameraRecorderExperience.js.map +1 -1
- package/lib/features/canvas/recorder/RecordingReview.js +272 -0
- package/lib/features/canvas/recorder/RecordingReview.js.map +1 -0
- package/lib/features/canvas/recorder/RecordingsList.js +179 -0
- package/lib/features/canvas/recorder/RecordingsList.js.map +1 -0
- package/lib/features/canvas/recorder/recorderOps.js +99 -0
- package/lib/features/canvas/recorder/recorderOps.js.map +1 -0
- package/lib/features/canvas/seedanceShowcase.js +314 -0
- package/lib/features/canvas/seedanceShowcase.js.map +1 -0
- package/lib/features/canvas/serverTasks.js +149 -15
- package/lib/features/canvas/serverTasks.js.map +1 -1
- package/lib/features/canvas/sessionRenewal.js +114 -0
- package/lib/features/canvas/sessionRenewal.js.map +1 -0
- package/lib/features/canvas/set/SetViewportWebView.js +34 -1
- package/lib/features/canvas/set/SetViewportWebView.js.map +1 -1
- package/lib/features/canvas/set/agent/setTurn.js +4 -2
- package/lib/features/canvas/set/agent/setTurn.js.map +1 -1
- package/lib/features/canvas/set/setPresets.js +85 -0
- package/lib/features/canvas/set/setPresets.js.map +1 -0
- package/lib/features/canvas/set/setProject.js +4 -1
- package/lib/features/canvas/set/setProject.js.map +1 -1
- package/lib/features/canvas/studioCatalog.js +59 -4
- package/lib/features/canvas/studioCatalog.js.map +1 -1
- package/lib/features/canvas/studioLooks.js +31 -4
- package/lib/features/canvas/studioLooks.js.map +1 -1
- package/lib/features/canvas/surfaceIndex.js +1 -14
- package/lib/features/canvas/surfaceIndex.js.map +1 -1
- package/lib/features/canvas/templateSearch.js +489 -0
- package/lib/features/canvas/templateSearch.js.map +1 -0
- package/lib/features/canvas/useCanvasSession.js +28 -6
- package/lib/features/canvas/useCanvasSession.js.map +1 -1
- package/lib/features/canvas/useStudioCatalogTemplates.js +41 -5
- package/lib/features/canvas/useStudioCatalogTemplates.js.map +1 -1
- package/lib/features/canvas/videoEditor/EditorPanels.js +531 -0
- package/lib/features/canvas/videoEditor/EditorPanels.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +48 -4
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/agentLoop.js +2 -0
- package/lib/features/canvas/videoEditor/agent/agentLoop.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/brainClient.js +97 -27
- package/lib/features/canvas/videoEditor/agent/brainClient.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/cutTools.js +707 -3
- package/lib/features/canvas/videoEditor/agent/cutTools.js.map +1 -1
- package/lib/features/canvas/videoEditor/audioServices.js +165 -0
- package/lib/features/canvas/videoEditor/audioServices.js.map +1 -0
- package/lib/features/canvas/videoEditor/captions.js +144 -0
- package/lib/features/canvas/videoEditor/captions.js.map +1 -0
- package/lib/features/canvas/videoEditor/compileTimeline.js +24 -16
- package/lib/features/canvas/videoEditor/compileTimeline.js.map +1 -1
- package/lib/features/canvas/videoEditor/editorModel.js +12 -2
- package/lib/features/canvas/videoEditor/editorModel.js.map +1 -1
- package/lib/features/canvas/videoEditor/exportTask.js +89 -7
- package/lib/features/canvas/videoEditor/exportTask.js.map +1 -1
- package/lib/features/canvas/videoEditor/layers.js +117 -0
- package/lib/features/canvas/videoEditor/layers.js.map +1 -0
- package/lib/features/canvas/videoEditor/remoteMediaClient.js +45 -18
- package/lib/features/canvas/videoEditor/remoteMediaClient.js.map +1 -1
- package/lib/features/canvas/videoEditor/renderTimeline.js +18 -6
- package/lib/features/canvas/videoEditor/renderTimeline.js.map +1 -1
- package/lib/features/canvas/videoEditor/revoice.js +138 -0
- package/lib/features/canvas/videoEditor/revoice.js.map +1 -0
- package/lib/features/canvas/videoEditor/storageUpload.js +34 -0
- package/lib/features/canvas/videoEditor/storageUpload.js.map +1 -0
- package/lib/features/canvas/videoEditor/textMotion.js +109 -0
- package/lib/features/canvas/videoEditor/textMotion.js.map +1 -0
- package/lib/features/canvas/videoEditor/transitions.js +31 -0
- package/lib/features/canvas/videoEditor/transitions.js.map +1 -0
- package/lib/features/chat/TemplatesChatCards.js +8 -3
- package/lib/features/chat/TemplatesChatCards.js.map +1 -1
- package/lib/features/design/DesignEditorExperience.js +674 -644
- package/lib/features/design/DesignEditorExperience.js.map +1 -1
- package/lib/features/design/DesignExperience.js +285 -538
- package/lib/features/design/DesignExperience.js.map +1 -1
- package/lib/features/design/designCore.js +2 -212
- package/lib/features/design/designCore.js.map +1 -1
- package/lib/features/design/designIndex.js +1 -50
- package/lib/features/design/designIndex.js.map +1 -1
- package/lib/features/design/doc/aiDesign.js +247 -0
- package/lib/features/design/doc/aiDesign.js.map +1 -0
- package/lib/features/design/doc/artifacts.js +280 -0
- package/lib/features/design/doc/artifacts.js.map +1 -0
- package/lib/features/design/doc/chart.js +98 -0
- package/lib/features/design/doc/chart.js.map +1 -0
- package/lib/features/design/doc/crop.js +104 -0
- package/lib/features/design/doc/crop.js.map +1 -0
- package/lib/features/design/doc/curve.js +49 -0
- package/lib/features/design/doc/curve.js.map +1 -0
- package/lib/features/design/doc/docOps.js +397 -0
- package/lib/features/design/doc/docOps.js.map +1 -0
- package/lib/features/design/doc/findReplace.js +112 -0
- package/lib/features/design/doc/findReplace.js.map +1 -0
- package/lib/features/design/doc/fonts.js +79 -0
- package/lib/features/design/doc/fonts.js.map +1 -0
- package/lib/features/design/doc/frames.js +17 -0
- package/lib/features/design/doc/frames.js.map +1 -0
- package/lib/features/design/doc/geometry.js +133 -0
- package/lib/features/design/doc/geometry.js.map +1 -0
- package/lib/features/design/doc/imageAdjust.js +203 -0
- package/lib/features/design/doc/imageAdjust.js.map +1 -0
- package/lib/features/design/doc/legacyDoc.js +107 -0
- package/lib/features/design/doc/legacyDoc.js.map +1 -0
- package/lib/features/design/doc/newDoc.js +335 -0
- package/lib/features/design/doc/newDoc.js.map +1 -0
- package/lib/features/design/doc/pageRange.js +17 -0
- package/lib/features/design/doc/pageRange.js.map +1 -0
- package/lib/features/design/doc/pathScale.js +68 -0
- package/lib/features/design/doc/pathScale.js.map +1 -0
- package/lib/features/design/doc/qr.js +62 -0
- package/lib/features/design/doc/qr.js.map +1 -0
- package/lib/features/design/doc/shapes.js +366 -0
- package/lib/features/design/doc/shapes.js.map +1 -0
- package/lib/features/design/doc/sizes.js +230 -0
- package/lib/features/design/doc/sizes.js.map +1 -0
- package/lib/features/design/doc/textEffects.js +134 -0
- package/lib/features/design/doc/textEffects.js.map +1 -0
- package/lib/features/design/doc/textLayout.js +182 -0
- package/lib/features/design/doc/textLayout.js.map +1 -0
- package/lib/features/design/doc/types.js +30 -0
- package/lib/features/design/doc/types.js.map +1 -0
- package/lib/features/design/editor/AiPanel.js +194 -0
- package/lib/features/design/editor/AiPanel.js.map +1 -0
- package/lib/features/design/editor/ChartDataPanel.js +182 -0
- package/lib/features/design/editor/ChartDataPanel.js.map +1 -0
- package/lib/features/design/editor/CropOverlay.js +199 -0
- package/lib/features/design/editor/CropOverlay.js.map +1 -0
- package/lib/features/design/editor/DesignCanvas.js +363 -0
- package/lib/features/design/editor/DesignCanvas.js.map +1 -0
- package/lib/features/design/editor/ExportSheet.js +123 -0
- package/lib/features/design/editor/ExportSheet.js.map +1 -0
- package/lib/features/design/editor/FindReplacePanel.js +93 -0
- package/lib/features/design/editor/FindReplacePanel.js.map +1 -0
- package/lib/features/design/editor/ImageTools.js +188 -0
- package/lib/features/design/editor/ImageTools.js.map +1 -0
- package/lib/features/design/editor/LayerTools.js +485 -0
- package/lib/features/design/editor/LayerTools.js.map +1 -0
- package/lib/features/design/editor/PageStrip.js +203 -0
- package/lib/features/design/editor/PageStrip.js.map +1 -0
- package/lib/features/design/editor/Slideshow.js +97 -0
- package/lib/features/design/editor/Slideshow.js.map +1 -0
- package/lib/features/design/editor/ToolPanels.js +695 -0
- package/lib/features/design/editor/ToolPanels.js.map +1 -0
- package/lib/features/design/editor/controls.js +630 -0
- package/lib/features/design/editor/controls.js.map +1 -0
- package/lib/features/design/editor/useDesignSave.js +91 -0
- package/lib/features/design/editor/useDesignSave.js.map +1 -0
- package/lib/features/design/export/exportDesign.js +170 -0
- package/lib/features/design/export/exportDesign.js.map +1 -0
- package/lib/features/design/export/pdf.js +143 -0
- package/lib/features/design/export/pdf.js.map +1 -0
- package/lib/features/design/home/DesignHome.js +688 -0
- package/lib/features/design/home/DesignHome.js.map +1 -0
- package/lib/features/design/home/studioHome.js +61 -0
- package/lib/features/design/home/studioHome.js.map +1 -0
- package/lib/features/design/pickDesignImage.js +60 -0
- package/lib/features/design/pickDesignImage.js.map +1 -0
- package/lib/features/design/render/DesignPageView.js +69 -0
- package/lib/features/design/render/DesignPageView.js.map +1 -0
- package/lib/features/design/render/PageCapture.js +288 -0
- package/lib/features/design/render/PageCapture.js.map +1 -0
- package/lib/features/design/render/TextMeasure.js +115 -0
- package/lib/features/design/render/TextMeasure.js.map +1 -0
- package/lib/features/design/render/fontRegistry.js +110 -0
- package/lib/features/design/render/fontRegistry.js.map +1 -0
- package/lib/features/design/render/layers.js +392 -0
- package/lib/features/design/render/layers.js.map +1 -0
- package/lib/features/design/render/svg.js +35 -0
- package/lib/features/design/render/svg.js.map +1 -0
- package/lib/features/design/render/svgParts.js +435 -0
- package/lib/features/design/render/svgParts.js.map +1 -0
- package/lib/features/design/surface/BoardScreen.js +529 -0
- package/lib/features/design/surface/BoardScreen.js.map +1 -0
- package/lib/features/design/surface/CompareView.js +138 -0
- package/lib/features/design/surface/CompareView.js.map +1 -0
- package/lib/features/design/surface/CreationScreen.js +294 -0
- package/lib/features/design/surface/CreationScreen.js.map +1 -0
- package/lib/features/design/surface/DesignAgentChatPane.js +444 -0
- package/lib/features/design/surface/DesignAgentChatPane.js.map +1 -0
- package/lib/features/design/surface/DesignBoards.js +441 -0
- package/lib/features/design/surface/DesignBoards.js.map +1 -0
- package/lib/features/design/surface/DesignPreview.js +159 -0
- package/lib/features/design/surface/DesignPreview.js.map +1 -0
- package/lib/features/design/surface/DesignSurfaceExperience.js +80 -0
- package/lib/features/design/surface/DesignSurfaceExperience.js.map +1 -0
- package/lib/features/design/surface/FullScreenPreview.js +59 -0
- package/lib/features/design/surface/FullScreenPreview.js.map +1 -0
- package/lib/features/design/surface/NewSystemDialog.js +122 -0
- package/lib/features/design/surface/NewSystemDialog.js.map +1 -0
- package/lib/features/design/surface/PickerSheet.js +175 -0
- package/lib/features/design/surface/PickerSheet.js.map +1 -0
- package/lib/features/design/surface/TemplatesGallery.js +156 -0
- package/lib/features/design/surface/TemplatesGallery.js.map +1 -0
- package/lib/features/design/surface/WetPaint.js +140 -0
- package/lib/features/design/surface/WetPaint.js.map +1 -0
- package/lib/features/design/surface/agentTurn.js +229 -0
- package/lib/features/design/surface/agentTurn.js.map +1 -0
- package/lib/features/design/surface/designBoard.js +218 -0
- package/lib/features/design/surface/designBoard.js.map +1 -0
- package/lib/features/design/surface/designChannel.js +186 -0
- package/lib/features/design/surface/designChannel.js.map +1 -0
- package/lib/features/design/surface/designChat.js +141 -0
- package/lib/features/design/surface/designChat.js.map +1 -0
- package/lib/features/design/surface/designConnector.js +266 -0
- package/lib/features/design/surface/designConnector.js.map +1 -0
- package/lib/features/design/surface/designDocument.js +40 -0
- package/lib/features/design/surface/designDocument.js.map +1 -0
- package/lib/features/design/surface/designExport.js +55 -0
- package/lib/features/design/surface/designExport.js.map +1 -0
- package/lib/features/design/surface/designLinks.js +64 -0
- package/lib/features/design/surface/designLinks.js.map +1 -0
- package/lib/features/design/surface/designPalette.js +24 -0
- package/lib/features/design/surface/designPalette.js.map +1 -0
- package/lib/features/design/surface/designRun.js +161 -0
- package/lib/features/design/surface/designRun.js.map +1 -0
- package/lib/features/design/surface/designTheme.js +119 -0
- package/lib/features/design/surface/designTheme.js.map +1 -0
- package/lib/features/design/surface/execStream.js +206 -0
- package/lib/features/design/surface/execStream.js.map +1 -0
- package/lib/features/design/surface/metaball.js +48 -0
- package/lib/features/design/surface/metaball.js.map +1 -0
- package/lib/features/design/surface/pickReferenceFiles.js +35 -0
- package/lib/features/design/surface/pickReferenceFiles.js.map +1 -0
- package/lib/features/design/surface/useDesignSurface.js +379 -0
- package/lib/features/design/surface/useDesignSurface.js.map +1 -0
- package/lib/features/docs/DocBlockRow.js +336 -0
- package/lib/features/docs/DocBlockRow.js.map +1 -0
- package/lib/features/docs/DocsEditorExperience.js +949 -0
- package/lib/features/docs/DocsEditorExperience.js.map +1 -0
- package/lib/features/docs/DocsToolbar.js +247 -0
- package/lib/features/docs/DocsToolbar.js.map +1 -0
- package/lib/features/docs/blocks.js +560 -0
- package/lib/features/docs/blocks.js.map +1 -0
- package/lib/features/docs/docArtifacts.js +129 -0
- package/lib/features/docs/docArtifacts.js.map +1 -0
- package/lib/features/docs/docEdits.js +201 -0
- package/lib/features/docs/docEdits.js.map +1 -0
- package/lib/features/docs/docExport.js +235 -0
- package/lib/features/docs/docExport.js.map +1 -0
- package/lib/features/docs/docShare.js +62 -0
- package/lib/features/docs/docShare.js.map +1 -0
- package/lib/features/links/openInApp.js +38 -2
- package/lib/features/links/openInApp.js.map +1 -1
- package/lib/routes.json +54 -0
- package/lib/screens/DesignNative/index.js +35 -0
- package/lib/screens/DesignNative/index.js.map +1 -0
- package/package.json +4 -4
- package/lib/features/design/exportDesign.js +0 -133
- package/lib/features/design/exportDesign.js.map +0 -1
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {useMemo,useState}from'react';import {View,Text,ActivityIndicator,TextInput,StyleSheet}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {useCanvasTheme,themedStyles}from'../canvasTheme.js';import {Pressable,pressedStyle,RADIUS,SPACE,HIT,TYPE}from'../canvasUi.js';import {compileShot,SHOT_SIZE_CHOICES,SHOT_MOVE_CHOICES,SHOT_LENS_CHOICES,addNegatives,withCamera}from'./shot.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
function ShotPanel({
|
|
21
|
+
spec,
|
|
22
|
+
constraints,
|
|
23
|
+
onChange,
|
|
24
|
+
onDiscard,
|
|
25
|
+
onRestructure,
|
|
26
|
+
busy
|
|
27
|
+
}) {
|
|
28
|
+
const theme = useCanvasTheme();
|
|
29
|
+
const styles = useMemo(() => makeStyles(theme), [theme]);
|
|
30
|
+
const [negativeDraft, setNegativeDraft] = useState("");
|
|
31
|
+
const compiled = useMemo(() => compileShot(spec, {
|
|
32
|
+
supportsAudio: constraints.supportsAudio
|
|
33
|
+
}), [spec, constraints.supportsAudio]);
|
|
34
|
+
const commitNegative = () => {
|
|
35
|
+
if (!negativeDraft.trim()) return;
|
|
36
|
+
onChange(__spreadProps(__spreadValues({}, spec), {
|
|
37
|
+
negative: addNegatives(spec.negative, negativeDraft)
|
|
38
|
+
}));
|
|
39
|
+
setNegativeDraft("");
|
|
40
|
+
};
|
|
41
|
+
const chips = (options, current, pick, label = String) => /* @__PURE__ */ jsx(View, { style: styles.chips, children: options.map((o) => {
|
|
42
|
+
const on = current === o;
|
|
43
|
+
return /* @__PURE__ */ jsx(Pressable, { onPress: () => pick(on ? void 0 : o), style: ({
|
|
44
|
+
pressed
|
|
45
|
+
}) => [styles.chip, on && styles.chipOn, pressedStyle(pressed)], accessibilityRole: "button", accessibilityState: {
|
|
46
|
+
selected: on
|
|
47
|
+
}, children: /* @__PURE__ */ jsx(Text, { style: [styles.chipLabel, on && styles.chipLabelOn], children: label(o) }) }, String(o));
|
|
48
|
+
}) });
|
|
49
|
+
return /* @__PURE__ */ jsxs(View, { style: styles.card, testID: "shot-panel", children: [
|
|
50
|
+
/* @__PURE__ */ jsxs(View, { style: styles.head, children: [
|
|
51
|
+
/* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "creation", size: 14, color: theme.foreground }),
|
|
52
|
+
/* @__PURE__ */ jsx(Text, { style: styles.headTitle, children: "Shot" }),
|
|
53
|
+
/* @__PURE__ */ jsx(Text, { style: styles.headSub, children: "sorted from your brief" }),
|
|
54
|
+
/* @__PURE__ */ jsxs(View, { style: styles.headActions, children: [
|
|
55
|
+
onRestructure ? /* @__PURE__ */ jsx(Pressable, { onPress: onRestructure, disabled: busy, style: ({
|
|
56
|
+
pressed
|
|
57
|
+
}) => [styles.headBtn, pressedStyle(pressed && !busy)], accessibilityRole: "button", accessibilityLabel: "Sort the brief again", children: busy ? /* @__PURE__ */ jsx(ActivityIndicator, { size: "small", color: theme.mutedForeground }) : /* @__PURE__ */ jsx(Text, { style: styles.headBtnLabel, children: "Redo" }) }) : null,
|
|
58
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: onDiscard, hitSlop: 6, style: ({
|
|
59
|
+
pressed
|
|
60
|
+
}) => [styles.headIcon, pressedStyle(pressed)], accessibilityRole: "button", accessibilityLabel: "Back to a plain prompt", children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "close", size: 16, color: theme.mutedForeground }) })
|
|
61
|
+
] })
|
|
62
|
+
] }),
|
|
63
|
+
/* @__PURE__ */ jsx(Text, { style: styles.label, children: "Subject" }),
|
|
64
|
+
/* @__PURE__ */ jsx(TextInput, { value: spec.subject, onChangeText: (v) => onChange(__spreadProps(__spreadValues({}, spec), {
|
|
65
|
+
subject: v
|
|
66
|
+
})), placeholder: "what the shot is of", placeholderTextColor: theme.mutedForeground, style: styles.field }),
|
|
67
|
+
/* @__PURE__ */ jsx(Text, { style: styles.label, children: "Action" }),
|
|
68
|
+
/* @__PURE__ */ jsx(TextInput, { value: spec.action, onChangeText: (v) => onChange(__spreadProps(__spreadValues({}, spec), {
|
|
69
|
+
action: v
|
|
70
|
+
})), placeholder: "what happens", placeholderTextColor: theme.mutedForeground, style: styles.field }),
|
|
71
|
+
/* @__PURE__ */ jsx(Text, { style: styles.label, children: "Shot size" }),
|
|
72
|
+
chips(SHOT_SIZE_CHOICES, spec.camera.shot, (v) => onChange(withCamera(spec, "shot", v))),
|
|
73
|
+
/* @__PURE__ */ jsx(Text, { style: styles.label, children: "Camera move" }),
|
|
74
|
+
chips(SHOT_MOVE_CHOICES, spec.camera.move, (v) => onChange(withCamera(spec, "move", v))),
|
|
75
|
+
/* @__PURE__ */ jsx(Text, { style: styles.label, children: "Lens" }),
|
|
76
|
+
chips(SHOT_LENS_CHOICES, spec.camera.lensMm, (v) => onChange(withCamera(spec, "lensMm", v)), (mm) => `${mm}mm`),
|
|
77
|
+
constraints.durations.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
78
|
+
/* @__PURE__ */ jsx(Text, { style: styles.label, children: "Duration" }),
|
|
79
|
+
chips(constraints.durations, spec.durationSeconds, (v) => {
|
|
80
|
+
const next = __spreadValues({}, spec);
|
|
81
|
+
if (v === void 0) delete next.durationSeconds;
|
|
82
|
+
else next.durationSeconds = v;
|
|
83
|
+
onChange(next);
|
|
84
|
+
}, (s) => `${s}s`)
|
|
85
|
+
] }) : null,
|
|
86
|
+
/* @__PURE__ */ jsx(Text, { style: styles.label, children: "Must not appear" }),
|
|
87
|
+
spec.negative.length ? /* @__PURE__ */ jsx(View, { style: styles.chips, children: spec.negative.map((item) => /* @__PURE__ */ jsxs(Pressable, { onPress: () => onChange(__spreadProps(__spreadValues({}, spec), {
|
|
88
|
+
negative: spec.negative.filter((n) => n !== item)
|
|
89
|
+
})), style: ({
|
|
90
|
+
pressed
|
|
91
|
+
}) => [styles.chip, styles.negChip, pressedStyle(pressed)], accessibilityRole: "button", accessibilityLabel: `Remove ${item}`, children: [
|
|
92
|
+
/* @__PURE__ */ jsx(Text, { style: styles.chipLabel, children: item }),
|
|
93
|
+
/* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "close", size: 12, color: theme.mutedForeground })
|
|
94
|
+
] }, item)) }) : null,
|
|
95
|
+
/* @__PURE__ */ jsx(TextInput, { value: negativeDraft, onChangeText: (v) => {
|
|
96
|
+
if (v.endsWith(",")) {
|
|
97
|
+
onChange(__spreadProps(__spreadValues({}, spec), {
|
|
98
|
+
negative: addNegatives(spec.negative, v)
|
|
99
|
+
}));
|
|
100
|
+
setNegativeDraft("");
|
|
101
|
+
} else setNegativeDraft(v);
|
|
102
|
+
}, onSubmitEditing: commitNegative, onBlur: commitNegative, placeholder: "text, watermark, extra fingers", placeholderTextColor: theme.mutedForeground, accessibilityLabel: "Add something that must not appear", returnKeyType: "done", style: styles.field }),
|
|
103
|
+
/* @__PURE__ */ jsx(Text, { style: styles.note, children: "These are sent as the model's negative prompt. Written into the prompt instead, the same words make it more likely to show them." }),
|
|
104
|
+
/* @__PURE__ */ jsxs(View, { style: styles.sent, children: [
|
|
105
|
+
/* @__PURE__ */ jsxs(View, { style: styles.sentHead, children: [
|
|
106
|
+
/* @__PURE__ */ jsx(Text, { style: styles.label, children: "Prompt sent" }),
|
|
107
|
+
/* @__PURE__ */ jsxs(Text, { style: styles.count, children: [
|
|
108
|
+
compiled.prompt.length,
|
|
109
|
+
" chars"
|
|
110
|
+
] })
|
|
111
|
+
] }),
|
|
112
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.sentText, !compiled.prompt && styles.sentEmpty], children: compiled.prompt || "Fill in a subject to build the prompt." }),
|
|
113
|
+
compiled.negativePrompt ? /* @__PURE__ */ jsxs(Text, { style: styles.note, children: [
|
|
114
|
+
"Negative: ",
|
|
115
|
+
compiled.negativePrompt
|
|
116
|
+
] }) : null
|
|
117
|
+
] })
|
|
118
|
+
] });
|
|
119
|
+
}
|
|
120
|
+
function ShotStructureButton({
|
|
121
|
+
busy,
|
|
122
|
+
onPress
|
|
123
|
+
}) {
|
|
124
|
+
const theme = useCanvasTheme();
|
|
125
|
+
const styles = useMemo(() => makeStyles(theme), [theme]);
|
|
126
|
+
return /* @__PURE__ */ jsxs(Pressable, { onPress, disabled: busy, style: ({
|
|
127
|
+
pressed
|
|
128
|
+
}) => [styles.structure, pressedStyle(pressed && !busy)], accessibilityRole: "button", accessibilityHint: "Sort the brief into subject, scene, camera and constraints", children: [
|
|
129
|
+
busy ? /* @__PURE__ */ jsx(ActivityIndicator, { size: "small", color: theme.foreground }) : /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "creation", size: 14, color: theme.foreground }),
|
|
130
|
+
/* @__PURE__ */ jsx(Text, { style: styles.chipLabel, children: busy ? "Sorting\u2026" : "Sort the brief" })
|
|
131
|
+
] });
|
|
132
|
+
}
|
|
133
|
+
const makeStyles = themedStyles((theme) => StyleSheet.create({
|
|
134
|
+
card: {
|
|
135
|
+
gap: SPACE.sm,
|
|
136
|
+
padding: SPACE.md,
|
|
137
|
+
borderRadius: RADIUS.lg,
|
|
138
|
+
backgroundColor: theme.card,
|
|
139
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
140
|
+
borderColor: theme.border
|
|
141
|
+
},
|
|
142
|
+
head: {
|
|
143
|
+
flexDirection: "row",
|
|
144
|
+
alignItems: "center",
|
|
145
|
+
gap: SPACE.sm - 2
|
|
146
|
+
},
|
|
147
|
+
headTitle: __spreadProps(__spreadValues({}, TYPE.label), {
|
|
148
|
+
color: theme.foreground
|
|
149
|
+
}),
|
|
150
|
+
headSub: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
151
|
+
fontWeight: "400",
|
|
152
|
+
color: theme.mutedForeground,
|
|
153
|
+
flexShrink: 1
|
|
154
|
+
}),
|
|
155
|
+
headActions: {
|
|
156
|
+
marginLeft: "auto",
|
|
157
|
+
flexDirection: "row",
|
|
158
|
+
alignItems: "center",
|
|
159
|
+
gap: SPACE.xs
|
|
160
|
+
},
|
|
161
|
+
headBtn: {
|
|
162
|
+
minHeight: 28,
|
|
163
|
+
paddingHorizontal: SPACE.sm,
|
|
164
|
+
justifyContent: "center",
|
|
165
|
+
borderRadius: RADIUS.pill
|
|
166
|
+
},
|
|
167
|
+
headBtnLabel: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
168
|
+
color: theme.mutedForeground
|
|
169
|
+
}),
|
|
170
|
+
headIcon: {
|
|
171
|
+
width: 28,
|
|
172
|
+
height: 28,
|
|
173
|
+
borderRadius: 14,
|
|
174
|
+
alignItems: "center",
|
|
175
|
+
justifyContent: "center"
|
|
176
|
+
},
|
|
177
|
+
label: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
178
|
+
color: theme.mutedForeground,
|
|
179
|
+
marginTop: SPACE.xs
|
|
180
|
+
}),
|
|
181
|
+
field: {
|
|
182
|
+
minHeight: HIT - 4,
|
|
183
|
+
borderRadius: RADIUS.md,
|
|
184
|
+
paddingHorizontal: SPACE.md,
|
|
185
|
+
paddingVertical: SPACE.sm,
|
|
186
|
+
fontSize: 15,
|
|
187
|
+
color: theme.foreground,
|
|
188
|
+
backgroundColor: theme.background
|
|
189
|
+
},
|
|
190
|
+
chips: {
|
|
191
|
+
flexDirection: "row",
|
|
192
|
+
flexWrap: "wrap",
|
|
193
|
+
gap: SPACE.sm - 2
|
|
194
|
+
},
|
|
195
|
+
chip: {
|
|
196
|
+
flexDirection: "row",
|
|
197
|
+
alignItems: "center",
|
|
198
|
+
gap: SPACE.xs,
|
|
199
|
+
minHeight: 32,
|
|
200
|
+
paddingHorizontal: SPACE.md,
|
|
201
|
+
borderRadius: RADIUS.pill,
|
|
202
|
+
backgroundColor: theme.background
|
|
203
|
+
},
|
|
204
|
+
chipOn: {
|
|
205
|
+
backgroundColor: theme.foreground
|
|
206
|
+
},
|
|
207
|
+
negChip: {
|
|
208
|
+
backgroundColor: theme.isDark ? theme.secondary : theme.surface
|
|
209
|
+
},
|
|
210
|
+
chipLabel: __spreadProps(__spreadValues({}, TYPE.label), {
|
|
211
|
+
color: theme.foreground
|
|
212
|
+
}),
|
|
213
|
+
chipLabelOn: {
|
|
214
|
+
color: theme.background
|
|
215
|
+
},
|
|
216
|
+
note: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
217
|
+
fontWeight: "400",
|
|
218
|
+
lineHeight: 17,
|
|
219
|
+
color: theme.mutedForeground
|
|
220
|
+
}),
|
|
221
|
+
sent: {
|
|
222
|
+
gap: SPACE.xs,
|
|
223
|
+
marginTop: SPACE.sm,
|
|
224
|
+
paddingTop: SPACE.sm,
|
|
225
|
+
borderTopWidth: StyleSheet.hairlineWidth,
|
|
226
|
+
borderTopColor: theme.border
|
|
227
|
+
},
|
|
228
|
+
sentHead: {
|
|
229
|
+
flexDirection: "row",
|
|
230
|
+
alignItems: "center",
|
|
231
|
+
justifyContent: "space-between"
|
|
232
|
+
},
|
|
233
|
+
count: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
234
|
+
fontWeight: "400",
|
|
235
|
+
fontVariant: ["tabular-nums"],
|
|
236
|
+
color: theme.mutedForeground
|
|
237
|
+
}),
|
|
238
|
+
sentText: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
239
|
+
fontWeight: "400",
|
|
240
|
+
lineHeight: 18,
|
|
241
|
+
padding: SPACE.sm,
|
|
242
|
+
borderRadius: RADIUS.md,
|
|
243
|
+
backgroundColor: theme.background,
|
|
244
|
+
color: theme.foreground
|
|
245
|
+
}),
|
|
246
|
+
sentEmpty: {
|
|
247
|
+
color: theme.mutedForeground
|
|
248
|
+
},
|
|
249
|
+
structure: {
|
|
250
|
+
alignSelf: "flex-start",
|
|
251
|
+
flexDirection: "row",
|
|
252
|
+
alignItems: "center",
|
|
253
|
+
gap: SPACE.sm - 2,
|
|
254
|
+
minHeight: 36,
|
|
255
|
+
paddingHorizontal: SPACE.md + 2,
|
|
256
|
+
borderRadius: RADIUS.pill,
|
|
257
|
+
backgroundColor: theme.card,
|
|
258
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
259
|
+
borderColor: theme.border
|
|
260
|
+
}
|
|
261
|
+
}));export{ShotPanel,ShotStructureButton};//# sourceMappingURL=ShotPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShotPanel.js","sources":["../../../../src/features/canvas/generator/ShotPanel.tsx"],"sourcesContent":["/**\n * Shot controls (native twin of web `components/shot/ShotPanel.tsx`): the\n * brief, taken apart so it can be aimed. Constraints leave the prompt for\n * negative_prompt, camera direction becomes values, timing becomes a\n * parameter. The compiled prompt is shown in full, so the structuring is never\n * a rewrite the person cannot see.\n */\nimport React, { useMemo, useState } from 'react';\nimport { ActivityIndicator, StyleSheet, Text, TextInput, View } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { useCanvasTheme, themedStyles, type CanvasPalette } from '../canvasTheme';\nimport { Pressable, HIT, RADIUS, SPACE, TYPE, pressedStyle } from '../canvasUi';\nimport {\n SHOT_LENS_CHOICES,\n SHOT_MOVE_CHOICES,\n SHOT_SIZE_CHOICES,\n addNegatives,\n compileShot,\n withCamera,\n type ShotConstraints,\n type ShotSpec,\n} from './shot';\n\nexport function ShotPanel({\n spec,\n constraints,\n onChange,\n onDiscard,\n onRestructure,\n busy,\n}: {\n spec: ShotSpec;\n constraints: ShotConstraints;\n onChange: (spec: ShotSpec) => void;\n /** Back to the plain prompt. */\n onDiscard: () => void;\n /** Re-run the structuring on the original brief. */\n onRestructure?: () => void;\n busy?: boolean;\n}) {\n const theme = useCanvasTheme();\n const styles = useMemo(() => makeStyles(theme), [theme]);\n const [negativeDraft, setNegativeDraft] = useState('');\n const compiled = useMemo(\n () => compileShot(spec, { supportsAudio: constraints.supportsAudio }),\n [spec, constraints.supportsAudio],\n );\n const commitNegative = () => {\n if (!negativeDraft.trim()) return;\n onChange({ ...spec, negative: addNegatives(spec.negative, negativeDraft) });\n setNegativeDraft('');\n };\n\n const chips = <T extends string | number>(\n options: readonly T[],\n current: T | undefined,\n pick: (next: T | undefined) => void,\n label: (v: T) => string = String,\n ) => (\n <View style={styles.chips}>\n {options.map((o) => {\n const on = current === o;\n return (\n <Pressable\n key={String(o)}\n onPress={() => pick(on ? undefined : o)}\n style={({ pressed }) => [styles.chip, on && styles.chipOn, pressedStyle(pressed)]}\n accessibilityRole=\"button\"\n accessibilityState={{ selected: on }}\n >\n <Text style={[styles.chipLabel, on && styles.chipLabelOn]}>{label(o)}</Text>\n </Pressable>\n );\n })}\n </View>\n );\n\n return (\n <View style={styles.card} testID=\"shot-panel\">\n <View style={styles.head}>\n <MaterialCommunityIcons name=\"creation\" size={14} color={theme.foreground} />\n <Text style={styles.headTitle}>Shot</Text>\n <Text style={styles.headSub}>sorted from your brief</Text>\n <View style={styles.headActions}>\n {onRestructure ? (\n <Pressable\n onPress={onRestructure}\n disabled={busy}\n style={({ pressed }) => [styles.headBtn, pressedStyle(pressed && !busy)]}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Sort the brief again\"\n >\n {busy ? (\n <ActivityIndicator size=\"small\" color={theme.mutedForeground} />\n ) : (\n <Text style={styles.headBtnLabel}>Redo</Text>\n )}\n </Pressable>\n ) : null}\n <Pressable\n onPress={onDiscard}\n hitSlop={6}\n style={({ pressed }) => [styles.headIcon, pressedStyle(pressed)]}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Back to a plain prompt\"\n >\n <MaterialCommunityIcons name=\"close\" size={16} color={theme.mutedForeground} />\n </Pressable>\n </View>\n </View>\n\n <Text style={styles.label}>Subject</Text>\n <TextInput\n value={spec.subject}\n onChangeText={(v) => onChange({ ...spec, subject: v })}\n placeholder=\"what the shot is of\"\n placeholderTextColor={theme.mutedForeground}\n style={styles.field}\n />\n <Text style={styles.label}>Action</Text>\n <TextInput\n value={spec.action}\n onChangeText={(v) => onChange({ ...spec, action: v })}\n placeholder=\"what happens\"\n placeholderTextColor={theme.mutedForeground}\n style={styles.field}\n />\n\n <Text style={styles.label}>Shot size</Text>\n {chips(SHOT_SIZE_CHOICES, spec.camera.shot as (typeof SHOT_SIZE_CHOICES)[number] | undefined, (v) =>\n onChange(withCamera(spec, 'shot', v)),\n )}\n <Text style={styles.label}>Camera move</Text>\n {chips(SHOT_MOVE_CHOICES, spec.camera.move as (typeof SHOT_MOVE_CHOICES)[number] | undefined, (v) =>\n onChange(withCamera(spec, 'move', v)),\n )}\n <Text style={styles.label}>Lens</Text>\n {chips(\n SHOT_LENS_CHOICES,\n spec.camera.lensMm as (typeof SHOT_LENS_CHOICES)[number] | undefined,\n (v) => onChange(withCamera(spec, 'lensMm', v)),\n (mm) => `${mm}mm`,\n )}\n {constraints.durations.length > 0 ? (\n <>\n <Text style={styles.label}>Duration</Text>\n {chips(\n constraints.durations,\n spec.durationSeconds,\n (v) => {\n const next = { ...spec };\n if (v === undefined) delete next.durationSeconds;\n else next.durationSeconds = v;\n onChange(next);\n },\n (s) => `${s}s`,\n )}\n </>\n ) : null}\n\n <Text style={styles.label}>Must not appear</Text>\n {spec.negative.length ? (\n <View style={styles.chips}>\n {spec.negative.map((item) => (\n <Pressable\n key={item}\n onPress={() => onChange({ ...spec, negative: spec.negative.filter((n) => n !== item) })}\n style={({ pressed }) => [styles.chip, styles.negChip, pressedStyle(pressed)]}\n accessibilityRole=\"button\"\n accessibilityLabel={`Remove ${item}`}\n >\n <Text style={styles.chipLabel}>{item}</Text>\n <MaterialCommunityIcons name=\"close\" size={12} color={theme.mutedForeground} />\n </Pressable>\n ))}\n </View>\n ) : null}\n <TextInput\n value={negativeDraft}\n onChangeText={(v) => {\n if (v.endsWith(',')) {\n onChange({ ...spec, negative: addNegatives(spec.negative, v) });\n setNegativeDraft('');\n } else setNegativeDraft(v);\n }}\n onSubmitEditing={commitNegative}\n onBlur={commitNegative}\n placeholder=\"text, watermark, extra fingers\"\n placeholderTextColor={theme.mutedForeground}\n accessibilityLabel=\"Add something that must not appear\"\n returnKeyType=\"done\"\n style={styles.field}\n />\n <Text style={styles.note}>\n These are sent as the model's negative prompt. Written into the prompt instead, the same words make it\n more likely to show them.\n </Text>\n\n <View style={styles.sent}>\n <View style={styles.sentHead}>\n <Text style={styles.label}>Prompt sent</Text>\n <Text style={styles.count}>{compiled.prompt.length} chars</Text>\n </View>\n <Text style={[styles.sentText, !compiled.prompt && styles.sentEmpty]}>\n {compiled.prompt || 'Fill in a subject to build the prompt.'}\n </Text>\n {compiled.negativePrompt ? <Text style={styles.note}>Negative: {compiled.negativePrompt}</Text> : null}\n </View>\n </View>\n );\n}\n\n/** The \"Sort the brief\" button shown under a long video brief. */\nexport function ShotStructureButton({ busy, onPress }: { busy: boolean; onPress: () => void }) {\n const theme = useCanvasTheme();\n const styles = useMemo(() => makeStyles(theme), [theme]);\n return (\n <Pressable\n onPress={onPress}\n disabled={busy}\n style={({ pressed }) => [styles.structure, pressedStyle(pressed && !busy)]}\n accessibilityRole=\"button\"\n accessibilityHint=\"Sort the brief into subject, scene, camera and constraints\"\n >\n {busy ? (\n <ActivityIndicator size=\"small\" color={theme.foreground} />\n ) : (\n <MaterialCommunityIcons name=\"creation\" size={14} color={theme.foreground} />\n )}\n <Text style={styles.chipLabel}>{busy ? 'Sorting…' : 'Sort the brief'}</Text>\n </Pressable>\n );\n}\n\nconst makeStyles = themedStyles((theme: CanvasPalette) =>\n StyleSheet.create({\n card: {\n gap: SPACE.sm,\n padding: SPACE.md,\n borderRadius: RADIUS.lg,\n backgroundColor: theme.card,\n borderWidth: StyleSheet.hairlineWidth,\n borderColor: theme.border,\n },\n head: { flexDirection: 'row', alignItems: 'center', gap: SPACE.sm - 2 },\n headTitle: { ...TYPE.label, color: theme.foreground },\n headSub: { ...TYPE.caption, fontWeight: '400', color: theme.mutedForeground, flexShrink: 1 },\n headActions: { marginLeft: 'auto', flexDirection: 'row', alignItems: 'center', gap: SPACE.xs },\n headBtn: { minHeight: 28, paddingHorizontal: SPACE.sm, justifyContent: 'center', borderRadius: RADIUS.pill },\n headBtnLabel: { ...TYPE.caption, color: theme.mutedForeground },\n headIcon: { width: 28, height: 28, borderRadius: 14, alignItems: 'center', justifyContent: 'center' },\n label: { ...TYPE.caption, color: theme.mutedForeground, marginTop: SPACE.xs },\n field: {\n minHeight: HIT - 4,\n borderRadius: RADIUS.md,\n paddingHorizontal: SPACE.md,\n paddingVertical: SPACE.sm,\n fontSize: 15,\n color: theme.foreground,\n backgroundColor: theme.background,\n },\n chips: { flexDirection: 'row', flexWrap: 'wrap', gap: SPACE.sm - 2 },\n chip: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: SPACE.xs,\n minHeight: 32,\n paddingHorizontal: SPACE.md,\n borderRadius: RADIUS.pill,\n backgroundColor: theme.background,\n },\n chipOn: { backgroundColor: theme.foreground },\n negChip: { backgroundColor: theme.isDark ? theme.secondary : theme.surface },\n chipLabel: { ...TYPE.label, color: theme.foreground },\n chipLabelOn: { color: theme.background },\n note: { ...TYPE.caption, fontWeight: '400', lineHeight: 17, color: theme.mutedForeground },\n sent: {\n gap: SPACE.xs,\n marginTop: SPACE.sm,\n paddingTop: SPACE.sm,\n borderTopWidth: StyleSheet.hairlineWidth,\n borderTopColor: theme.border,\n },\n sentHead: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' },\n count: { ...TYPE.caption, fontWeight: '400', fontVariant: ['tabular-nums'], color: theme.mutedForeground },\n sentText: {\n ...TYPE.caption,\n fontWeight: '400',\n lineHeight: 18,\n padding: SPACE.sm,\n borderRadius: RADIUS.md,\n backgroundColor: theme.background,\n color: theme.foreground,\n },\n sentEmpty: { color: theme.mutedForeground },\n structure: {\n alignSelf: 'flex-start',\n flexDirection: 'row',\n alignItems: 'center',\n gap: SPACE.sm - 2,\n minHeight: 36,\n paddingHorizontal: SPACE.md + 2,\n borderRadius: RADIUS.pill,\n backgroundColor: theme.card,\n borderWidth: StyleSheet.hairlineWidth,\n borderColor: theme.border,\n },\n }),\n);\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const BUSINESS_CARD_KIND = "business-card";
|
|
2
|
+
const ARTIFACT_ID_RE = /^(deck|flyer):[0-9A-Za-z][0-9A-Za-z-]{7,63}$/;
|
|
3
|
+
const FENCE = /```(?:yantra:widget|json)\s*([\s\S]*?)```/gi;
|
|
4
|
+
const BARE = /\{\s*"propsComponent"\s*:/g;
|
|
5
|
+
const MAX_LABEL = 140;
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function parseArtifactId(raw) {
|
|
10
|
+
if (typeof raw !== "string") return null;
|
|
11
|
+
const id = raw.trim();
|
|
12
|
+
return ARTIFACT_ID_RE.test(id) ? id : null;
|
|
13
|
+
}
|
|
14
|
+
const text = (value) => {
|
|
15
|
+
if (typeof value !== "string") return void 0;
|
|
16
|
+
const t = value.replace(/\s+/g, " ").trim().slice(0, MAX_LABEL);
|
|
17
|
+
return t || void 0;
|
|
18
|
+
};
|
|
19
|
+
const picture = (value) => {
|
|
20
|
+
if (typeof value !== "string" || value.length > 4096) return void 0;
|
|
21
|
+
return /^https?:\/\/[^\s]+$/i.test(value.trim()) ? value.trim() : void 0;
|
|
22
|
+
};
|
|
23
|
+
function peel(value, depth = 0) {
|
|
24
|
+
if (!isRecord(value)) return null;
|
|
25
|
+
const keys = Object.keys(value);
|
|
26
|
+
if (keys.length === 0) return null;
|
|
27
|
+
if (keys.length === 1 && depth < 3) {
|
|
28
|
+
if (keys[0] === "attachment") return peel(value.attachment, depth + 1);
|
|
29
|
+
if (keys[0] === "contents") {
|
|
30
|
+
const contents = value.contents;
|
|
31
|
+
return peel(isRecord(contents) && "attachment" in contents ? contents.attachment : contents, depth + 1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
function widgetAttachment(widget) {
|
|
37
|
+
if (!isRecord(widget)) return null;
|
|
38
|
+
const config = isRecord(widget.propsConfiguration) ? widget.propsConfiguration : null;
|
|
39
|
+
const contents = config && isRecord(config.contents) ? config.contents : null;
|
|
40
|
+
const candidates = [contents == null ? void 0 : contents.attachment, config == null ? void 0 : config.attachment, widget.attachment, contents && !("attachment" in contents) ? contents : void 0, config && !("contents" in config) && !("attachment" in config) ? config : void 0];
|
|
41
|
+
for (const candidate of candidates) {
|
|
42
|
+
const found = peel(candidate);
|
|
43
|
+
if (found) return found;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
function jsonObjectFrom(source, from) {
|
|
48
|
+
const start = source.indexOf("{", from);
|
|
49
|
+
if (start === -1 || !/^\s*$/.test(source.slice(from, start))) return null;
|
|
50
|
+
let depth = 0;
|
|
51
|
+
let inString = false;
|
|
52
|
+
let escaped = false;
|
|
53
|
+
for (let i = start; i < source.length; i += 1) {
|
|
54
|
+
const ch = source[i];
|
|
55
|
+
if (inString) {
|
|
56
|
+
if (escaped) escaped = false;
|
|
57
|
+
else if (ch === "\\") escaped = true;
|
|
58
|
+
else if (ch === '"') inString = false;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (ch === '"') inString = true;
|
|
62
|
+
else if (ch === "{") depth += 1;
|
|
63
|
+
else if (ch === "}") {
|
|
64
|
+
depth -= 1;
|
|
65
|
+
if (depth === 0) return source.slice(start, i + 1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
function businessCardOfEnvelope(envelope) {
|
|
71
|
+
var _a;
|
|
72
|
+
if (!isRecord(envelope) || envelope.propsComponent !== BUSINESS_CARD_KIND) return null;
|
|
73
|
+
const a = widgetAttachment(envelope);
|
|
74
|
+
if (!a) return null;
|
|
75
|
+
if (typeof a.kind === "string" && a.kind !== BUSINESS_CARD_KIND) return null;
|
|
76
|
+
const artifactId = parseArtifactId(a.artifactId);
|
|
77
|
+
if (!artifactId) return null;
|
|
78
|
+
const fields = isRecord(a.fields) ? a.fields : {};
|
|
79
|
+
const name = text(fields.name);
|
|
80
|
+
const company = text(fields.company);
|
|
81
|
+
const card = {
|
|
82
|
+
artifactId,
|
|
83
|
+
title: (_a = text(a.title)) != null ? _a : name ? `${name} business card` : "Business card"
|
|
84
|
+
};
|
|
85
|
+
const front = picture(a.previewUrl);
|
|
86
|
+
const back = picture(a.backPreviewUrl);
|
|
87
|
+
const size = text(a.sizeLabel);
|
|
88
|
+
if (front) card.previewUrl = front;
|
|
89
|
+
if (back) card.backPreviewUrl = back;
|
|
90
|
+
if (size) card.sizeLabel = size;
|
|
91
|
+
if (name) card.name = name;
|
|
92
|
+
if (company) card.company = company;
|
|
93
|
+
return card;
|
|
94
|
+
}
|
|
95
|
+
function businessCardWidgetsOf(content) {
|
|
96
|
+
var _a;
|
|
97
|
+
if (!content || !content.includes(BUSINESS_CARD_KIND)) return [];
|
|
98
|
+
const found = [];
|
|
99
|
+
const add = (raw) => {
|
|
100
|
+
if (!raw) return;
|
|
101
|
+
let parsed;
|
|
102
|
+
try {
|
|
103
|
+
parsed = JSON.parse(raw);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const card = businessCardOfEnvelope(parsed);
|
|
108
|
+
if (card && !found.some((c) => c.artifactId === card.artifactId)) found.push(card);
|
|
109
|
+
};
|
|
110
|
+
for (const m of content.matchAll(FENCE)) add(m[1].trim());
|
|
111
|
+
for (const m of content.matchAll(BARE)) add(jsonObjectFrom(content, (_a = m.index) != null ? _a : 0));
|
|
112
|
+
return found;
|
|
113
|
+
}
|
|
114
|
+
function businessCardLine(card) {
|
|
115
|
+
const who = [card.name, card.company].filter(Boolean).join(", ");
|
|
116
|
+
return [card.sizeLabel, who].filter(Boolean).join(" \xB7 ");
|
|
117
|
+
}export{BUSINESS_CARD_KIND,businessCardLine,businessCardOfEnvelope,businessCardWidgetsOf,jsonObjectFrom,parseArtifactId,widgetAttachment};//# sourceMappingURL=businessCardWidget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"businessCardWidget.js","sources":["../../../../src/features/canvas/generator/businessCardWidget.ts"],"sourcesContent":["/**\n * The `business-card` chat widget, read out of an agent reply (native twin of\n * web `components/chat/businessCardWidget.ts`).\n *\n * The agent that makes a card from chat ends its reply with a\n * ```yantra:widget fence holding {\"propsComponent\":\"business-card\", ...} whose\n * attachment names the saved design (`flyer:<uuid>`), its rendered front and\n * back, the size and the main fields. Pure: the surface-kit helpers the web\n * uses (`widgetAttachment`, `jsonObjectFrom`) are inlined so the OTA remote\n * carries no kit dependency.\n */\n\nexport const BUSINESS_CARD_KIND = 'business-card';\n\nexport interface BusinessCardWidget {\n /** The saved design, `flyer:<uuid>`. */\n artifactId: string;\n title: string;\n previewUrl?: string;\n backPreviewUrl?: string;\n /** \"3.5 x 2 in\". */\n sizeLabel?: string;\n name?: string;\n company?: string;\n}\n\nconst ARTIFACT_ID_RE = /^(deck|flyer):[0-9A-Za-z][0-9A-Za-z-]{7,63}$/;\nconst FENCE = /```(?:yantra:widget|json)\\s*([\\s\\S]*?)```/gi;\nconst BARE = /\\{\\s*\"propsComponent\"\\s*:/g;\nconst MAX_LABEL = 140;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function parseArtifactId(raw: unknown): string | null {\n if (typeof raw !== 'string') return null;\n const id = raw.trim();\n return ARTIFACT_ID_RE.test(id) ? id : null;\n}\n\nconst text = (value: unknown): string | undefined => {\n if (typeof value !== 'string') return undefined;\n const t = value.replace(/\\s+/g, ' ').trim().slice(0, MAX_LABEL);\n return t || undefined;\n};\n\n/** A picture the card can show: an absolute http(s) URL, nothing else. */\nconst picture = (value: unknown): string | undefined => {\n if (typeof value !== 'string' || value.length > 4096) return undefined;\n return /^https?:\\/\\/[^\\s]+$/i.test(value.trim()) ? value.trim() : undefined;\n};\n\nfunction peel(value: unknown, depth = 0): Record<string, unknown> | null {\n if (!isRecord(value)) return null;\n const keys = Object.keys(value);\n if (keys.length === 0) return null;\n if (keys.length === 1 && depth < 3) {\n if (keys[0] === 'attachment') return peel(value.attachment, depth + 1);\n if (keys[0] === 'contents') {\n const contents = value.contents;\n return peel(isRecord(contents) && 'attachment' in contents ? contents.attachment : contents, depth + 1);\n }\n }\n return value;\n}\n\n/** A widget's attachment, however the agent nested it (surface-kit `widgetAttachment`). */\nexport function widgetAttachment(widget: unknown): Record<string, unknown> | null {\n if (!isRecord(widget)) return null;\n const config = isRecord(widget.propsConfiguration) ? widget.propsConfiguration : null;\n const contents = config && isRecord(config.contents) ? config.contents : null;\n const candidates: unknown[] = [\n contents?.attachment,\n config?.attachment,\n widget.attachment,\n contents && !('attachment' in contents) ? contents : undefined,\n config && !('contents' in config) && !('attachment' in config) ? config : undefined,\n ];\n for (const candidate of candidates) {\n const found = peel(candidate);\n if (found) return found;\n }\n return null;\n}\n\n/** The balanced JSON object starting at `from` (only whitespace before its brace), or null. */\nexport function jsonObjectFrom(source: string, from: number): string | null {\n const start = source.indexOf('{', from);\n if (start === -1 || !/^\\s*$/.test(source.slice(from, start))) return null;\n let depth = 0;\n let inString = false;\n let escaped = false;\n for (let i = start; i < source.length; i += 1) {\n const ch = source[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') inString = true;\n else if (ch === '{') depth += 1;\n else if (ch === '}') {\n depth -= 1;\n if (depth === 0) return source.slice(start, i + 1);\n }\n }\n return null;\n}\n\n/** One envelope as a card, or null when it is another widget or names no design. */\nexport function businessCardOfEnvelope(envelope: unknown): BusinessCardWidget | null {\n if (!isRecord(envelope) || envelope.propsComponent !== BUSINESS_CARD_KIND) return null;\n const a = widgetAttachment(envelope);\n if (!a) return null;\n if (typeof a.kind === 'string' && a.kind !== BUSINESS_CARD_KIND) return null;\n const artifactId = parseArtifactId(a.artifactId);\n if (!artifactId) return null;\n const fields = isRecord(a.fields) ? a.fields : {};\n const name = text(fields.name);\n const company = text(fields.company);\n const card: BusinessCardWidget = {\n artifactId,\n title: text(a.title) ?? (name ? `${name} business card` : 'Business card'),\n };\n const front = picture(a.previewUrl);\n const back = picture(a.backPreviewUrl);\n const size = text(a.sizeLabel);\n if (front) card.previewUrl = front;\n if (back) card.backPreviewUrl = back;\n if (size) card.sizeLabel = size;\n if (name) card.name = name;\n if (company) card.company = company;\n return card;\n}\n\n/** Every business card a reply carries, once each, in the order written. */\nexport function businessCardWidgetsOf(content: string): BusinessCardWidget[] {\n if (!content || !content.includes(BUSINESS_CARD_KIND)) return [];\n const found: BusinessCardWidget[] = [];\n const add = (raw: string | null) => {\n if (!raw) return;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return; // half-streamed, or prose in a json fence\n }\n const card = businessCardOfEnvelope(parsed);\n if (card && !found.some((c) => c.artifactId === card.artifactId)) found.push(card);\n };\n for (const m of content.matchAll(FENCE)) add(m[1].trim());\n for (const m of content.matchAll(BARE)) add(jsonObjectFrom(content, m.index ?? 0));\n return found;\n}\n\n/** The line under the card's title: size, then whose card it is. */\nexport function businessCardLine(card: BusinessCardWidget): string {\n const who = [card.name, card.company].filter(Boolean).join(', ');\n return [card.sizeLabel, who].filter(Boolean).join(' · ');\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const SHOT_SIZES = [{
|
|
2
|
+
label: "Extreme wide",
|
|
3
|
+
phrase: "extreme wide shot, subject small in the frame"
|
|
4
|
+
}, {
|
|
5
|
+
label: "Wide",
|
|
6
|
+
phrase: "wide shot"
|
|
7
|
+
}, {
|
|
8
|
+
label: "Medium",
|
|
9
|
+
phrase: "medium shot, subject from the waist up"
|
|
10
|
+
}, {
|
|
11
|
+
label: "Close-up",
|
|
12
|
+
phrase: "close-up shot"
|
|
13
|
+
}, {
|
|
14
|
+
label: "Extreme close-up",
|
|
15
|
+
phrase: "extreme close-up, filling the frame"
|
|
16
|
+
}];
|
|
17
|
+
const CAMERA_MOVES = [{
|
|
18
|
+
label: "Static",
|
|
19
|
+
phrase: "locked-off static camera, no movement"
|
|
20
|
+
}, {
|
|
21
|
+
label: "Dolly in",
|
|
22
|
+
phrase: "camera dollies in toward the subject"
|
|
23
|
+
}, {
|
|
24
|
+
label: "Dolly out",
|
|
25
|
+
phrase: "camera dollies back away from the subject"
|
|
26
|
+
}, {
|
|
27
|
+
label: "Pan left",
|
|
28
|
+
phrase: "camera pans left"
|
|
29
|
+
}, {
|
|
30
|
+
label: "Pan right",
|
|
31
|
+
phrase: "camera pans right"
|
|
32
|
+
}, {
|
|
33
|
+
label: "Tilt up",
|
|
34
|
+
phrase: "camera tilts upward"
|
|
35
|
+
}, {
|
|
36
|
+
label: "Tilt down",
|
|
37
|
+
phrase: "camera tilts downward"
|
|
38
|
+
}, {
|
|
39
|
+
label: "Crane up",
|
|
40
|
+
phrase: "camera cranes upward, rising above the scene"
|
|
41
|
+
}, {
|
|
42
|
+
label: "Orbit",
|
|
43
|
+
phrase: "camera orbits around the subject"
|
|
44
|
+
}, {
|
|
45
|
+
label: "Tracking",
|
|
46
|
+
phrase: "camera tracks alongside the subject"
|
|
47
|
+
}, {
|
|
48
|
+
label: "Handheld",
|
|
49
|
+
phrase: "handheld camera, subtle natural shake"
|
|
50
|
+
}, {
|
|
51
|
+
label: "Zoom in",
|
|
52
|
+
phrase: "slow zoom in"
|
|
53
|
+
}];
|
|
54
|
+
const CAMERA_ANGLES = [{
|
|
55
|
+
label: "Eye level",
|
|
56
|
+
phrase: "eye-level angle"
|
|
57
|
+
}, {
|
|
58
|
+
label: "Low angle",
|
|
59
|
+
phrase: "low angle, looking up at the subject"
|
|
60
|
+
}, {
|
|
61
|
+
label: "High angle",
|
|
62
|
+
phrase: "high angle, looking down at the subject"
|
|
63
|
+
}, {
|
|
64
|
+
label: "Overhead",
|
|
65
|
+
phrase: "overhead top-down angle"
|
|
66
|
+
}, {
|
|
67
|
+
label: "Dutch tilt",
|
|
68
|
+
phrase: "dutch angle, tilted horizon"
|
|
69
|
+
}, {
|
|
70
|
+
label: "Over the shoulder",
|
|
71
|
+
phrase: "over-the-shoulder angle"
|
|
72
|
+
}];
|
|
73
|
+
const FOCAL_LENGTHS = [{
|
|
74
|
+
mm: 14,
|
|
75
|
+
label: "14mm",
|
|
76
|
+
phrase: "14mm lens, ultra-wide perspective"
|
|
77
|
+
}, {
|
|
78
|
+
mm: 24,
|
|
79
|
+
label: "24mm",
|
|
80
|
+
phrase: "24mm lens, wide-angle dynamic perspective"
|
|
81
|
+
}, {
|
|
82
|
+
mm: 35,
|
|
83
|
+
label: "35mm",
|
|
84
|
+
phrase: "35mm lens, natural cinematic perspective"
|
|
85
|
+
}, {
|
|
86
|
+
mm: 50,
|
|
87
|
+
label: "50mm",
|
|
88
|
+
phrase: "50mm lens, standard perspective"
|
|
89
|
+
}, {
|
|
90
|
+
mm: 85,
|
|
91
|
+
label: "85mm",
|
|
92
|
+
phrase: "85mm lens, classic portrait compression"
|
|
93
|
+
}, {
|
|
94
|
+
mm: 135,
|
|
95
|
+
label: "135mm",
|
|
96
|
+
phrase: "135mm lens, strong telephoto compression"
|
|
97
|
+
}];
|
|
98
|
+
const APERTURES = [{
|
|
99
|
+
label: "f/1.4",
|
|
100
|
+
phrase: "f/1.4, shallow depth of field, creamy bokeh"
|
|
101
|
+
}, {
|
|
102
|
+
label: "f/2.8",
|
|
103
|
+
phrase: "f/2.8, soft background separation"
|
|
104
|
+
}, {
|
|
105
|
+
label: "f/4",
|
|
106
|
+
phrase: "f/4, balanced depth of field"
|
|
107
|
+
}, {
|
|
108
|
+
label: "f/8",
|
|
109
|
+
phrase: "f/8, most of the scene in focus"
|
|
110
|
+
}, {
|
|
111
|
+
label: "f/16",
|
|
112
|
+
phrase: "f/16, deep focus, sharp foreground to background"
|
|
113
|
+
}];
|
|
114
|
+
const FILM_STOCKS = [{
|
|
115
|
+
label: "Modern digital",
|
|
116
|
+
phrase: "shot on a full-frame digital cinema camera, clean modern image"
|
|
117
|
+
}, {
|
|
118
|
+
label: "70mm large format",
|
|
119
|
+
phrase: "shot on 70mm large-format film, fine grain, enormous detail"
|
|
120
|
+
}, {
|
|
121
|
+
label: "Super 35",
|
|
122
|
+
phrase: "shot on Super 35, classic cinema texture"
|
|
123
|
+
}, {
|
|
124
|
+
label: "16mm",
|
|
125
|
+
phrase: "shot on 16mm film, visible grain, organic texture"
|
|
126
|
+
}, {
|
|
127
|
+
label: "Anamorphic",
|
|
128
|
+
phrase: "anamorphic lens, oval bokeh, horizontal flares"
|
|
129
|
+
}, {
|
|
130
|
+
label: "Vintage prime",
|
|
131
|
+
phrase: "vintage prime lens, gentle falloff, softer contrast"
|
|
132
|
+
}];
|
|
133
|
+
const phraseOf = (list, label) => {
|
|
134
|
+
var _a;
|
|
135
|
+
return label && ((_a = list.find((o) => o.label === label)) == null ? void 0 : _a.phrase) || "";
|
|
136
|
+
};
|
|
137
|
+
function composeCameraPhrase(s) {
|
|
138
|
+
var _a;
|
|
139
|
+
const focal = ((_a = FOCAL_LENGTHS.find((f) => f.mm === s.lensMm)) == null ? void 0 : _a.phrase) || "";
|
|
140
|
+
return [phraseOf(SHOT_SIZES, s.shot), phraseOf(CAMERA_MOVES, s.move), phraseOf(CAMERA_ANGLES, s.angle), focal, phraseOf(APERTURES, s.aperture), phraseOf(FILM_STOCKS, s.stock)].filter((p) => p.trim() !== "").join(", ");
|
|
141
|
+
}
|
|
142
|
+
const cameraCount = (s) => [s.shot, s.move, s.angle, s.lensMm, s.aperture, s.stock].filter((v) => v !== void 0 && v !== "").length;export{APERTURES,CAMERA_ANGLES,CAMERA_MOVES,FILM_STOCKS,FOCAL_LENGTHS,SHOT_SIZES,cameraCount,composeCameraPhrase};//# sourceMappingURL=cameraVocabulary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cameraVocabulary.js","sources":["../../../../src/features/canvas/generator/cameraVocabulary.ts"],"sourcesContent":["/**\n * The camera vocabulary, and the one function that turns it into prompt text.\n *\n * The connector's shot builder already emits\n * `camera: { shot, move, lensMm, aperture, angle }` - but nothing ever SET\n * those: they were whatever an LLM inferred from the brief. So \"push in slowly\"\n * worked and \"35mm at f/1.4\" did not, because there was no control to say it.\n * This is that control's vocabulary.\n *\n * Every entry is a label the user picks and the phrase a model actually\n * understands. They are separate on purpose: \"Dolly in\" is what a director\n * says, \"camera dollies in toward the subject\" is what a diffusion model reads.\n * Shipping only the label would put the burden of prompt-speak on the user,\n * which is the thing a camera panel exists to remove.\n *\n * Kept as data, in one file, with no React in it: the same vocabulary has to be\n * usable from a panel, from a test, and eventually from the connector's shot\n * builder without dragging a component tree along.\n */\n\nexport interface CameraOption {\n /** What the control shows. */\n label: string;\n /** What the prompt says. Empty means \"add nothing\" - the honest default. */\n phrase: string;\n}\n\n/** How much of the subject the frame holds. */\nexport const SHOT_SIZES: readonly CameraOption[] = [\n { label: 'Extreme wide', phrase: 'extreme wide shot, subject small in the frame' },\n { label: 'Wide', phrase: 'wide shot' },\n { label: 'Medium', phrase: 'medium shot, subject from the waist up' },\n { label: 'Close-up', phrase: 'close-up shot' },\n { label: 'Extreme close-up', phrase: 'extreme close-up, filling the frame' },\n];\n\n/**\n * What the camera DOES. This is the field most worth exposing: it is the one\n * thing a still cannot express, and the one models most often ignore unless it\n * is stated as motion rather than as a noun.\n */\nexport const CAMERA_MOVES: readonly CameraOption[] = [\n { label: 'Static', phrase: 'locked-off static camera, no movement' },\n { label: 'Dolly in', phrase: 'camera dollies in toward the subject' },\n { label: 'Dolly out', phrase: 'camera dollies back away from the subject' },\n { label: 'Pan left', phrase: 'camera pans left' },\n { label: 'Pan right', phrase: 'camera pans right' },\n { label: 'Tilt up', phrase: 'camera tilts upward' },\n { label: 'Tilt down', phrase: 'camera tilts downward' },\n { label: 'Crane up', phrase: 'camera cranes upward, rising above the scene' },\n { label: 'Orbit', phrase: 'camera orbits around the subject' },\n { label: 'Tracking', phrase: 'camera tracks alongside the subject' },\n { label: 'Handheld', phrase: 'handheld camera, subtle natural shake' },\n { label: 'Zoom in', phrase: 'slow zoom in' },\n];\n\n/** Where the camera sits relative to the subject. */\nexport const CAMERA_ANGLES: readonly CameraOption[] = [\n { label: 'Eye level', phrase: 'eye-level angle' },\n { label: 'Low angle', phrase: 'low angle, looking up at the subject' },\n { label: 'High angle', phrase: 'high angle, looking down at the subject' },\n { label: 'Overhead', phrase: 'overhead top-down angle' },\n { label: 'Dutch tilt', phrase: 'dutch angle, tilted horizon' },\n { label: 'Over the shoulder', phrase: 'over-the-shoulder angle' },\n];\n\n/**\n * Focal length carries its own perspective, which is the part that actually\n * changes the picture - a number alone means little to a model.\n */\nexport const FOCAL_LENGTHS: readonly (CameraOption & { mm: number })[] = [\n { mm: 14, label: '14mm', phrase: '14mm lens, ultra-wide perspective' },\n { mm: 24, label: '24mm', phrase: '24mm lens, wide-angle dynamic perspective' },\n { mm: 35, label: '35mm', phrase: '35mm lens, natural cinematic perspective' },\n { mm: 50, label: '50mm', phrase: '50mm lens, standard perspective' },\n { mm: 85, label: '85mm', phrase: '85mm lens, classic portrait compression' },\n { mm: 135, label: '135mm', phrase: '135mm lens, strong telephoto compression' },\n];\n\n/** Aperture is only worth saying for the depth of field it produces. */\nexport const APERTURES: readonly CameraOption[] = [\n { label: 'f/1.4', phrase: 'f/1.4, shallow depth of field, creamy bokeh' },\n { label: 'f/2.8', phrase: 'f/2.8, soft background separation' },\n { label: 'f/4', phrase: 'f/4, balanced depth of field' },\n { label: 'f/8', phrase: 'f/8, most of the scene in focus' },\n { label: 'f/16', phrase: 'f/16, deep focus, sharp foreground to background' },\n];\n\n/**\n * The look of the format itself. Named by CHARACTER, not by manufacturer:\n * \"Classic 16mm\" tells you what you get, a brand name only tells you who to\n * pay. It also keeps us out of trading on someone else's trademark.\n */\nexport const FILM_STOCKS: readonly CameraOption[] = [\n { label: 'Modern digital', phrase: 'shot on a full-frame digital cinema camera, clean modern image' },\n { label: '70mm large format', phrase: 'shot on 70mm large-format film, fine grain, enormous detail' },\n { label: 'Super 35', phrase: 'shot on Super 35, classic cinema texture' },\n { label: '16mm', phrase: 'shot on 16mm film, visible grain, organic texture' },\n { label: 'Anamorphic', phrase: 'anamorphic lens, oval bokeh, horizontal flares' },\n { label: 'Vintage prime', phrase: 'vintage prime lens, gentle falloff, softer contrast' },\n];\n\n/** One camera setup. Every field optional - an unset field says nothing. */\nexport interface CameraSettings {\n shot?: string;\n move?: string;\n angle?: string;\n lensMm?: number;\n aperture?: string;\n stock?: string;\n}\n\nconst phraseOf = (list: readonly CameraOption[], label: string | undefined): string =>\n (label && list.find((o) => o.label === label)?.phrase) || '';\n\n/**\n * The camera setup as a prompt fragment, in the order a cinematographer would\n * say it: framing, then movement, then angle, then glass, then format.\n *\n * Returns '' when nothing is set. That matters more than it looks: an empty\n * setup must add NOTHING to the prompt, not a trailing comma and not a string\n * of defaults the user never chose. A camera panel that silently appends\n * \"eye-level, 50mm, f/4\" to every run is editorialising, not assisting.\n */\nexport function composeCameraPhrase(s: CameraSettings): string {\n const focal = FOCAL_LENGTHS.find((f) => f.mm === s.lensMm)?.phrase || '';\n return [\n phraseOf(SHOT_SIZES, s.shot),\n phraseOf(CAMERA_MOVES, s.move),\n phraseOf(CAMERA_ANGLES, s.angle),\n focal,\n phraseOf(APERTURES, s.aperture),\n phraseOf(FILM_STOCKS, s.stock),\n ]\n .filter((p) => p.trim() !== '')\n .join(', ');\n}\n\n/**\n * The prompt the run should actually use. The camera fragment is APPENDED, so\n * the user's own words stay first and stay intact - a camera setup describes\n * how to shoot the thing, never what the thing is.\n */\nexport function applyCamera(prompt: string, s: CameraSettings): string {\n const camera = composeCameraPhrase(s);\n const base = prompt.trim();\n if (!camera) return base;\n if (!base) return camera;\n // A brief that already ends in punctuation should not gain a stray comma.\n return /[.!?]$/.test(base) ? `${base} ${camera}` : `${base}, ${camera}`;\n}\n\n/** How many fields are set - the pill shows this so the setup is never invisible. */\nexport const cameraCount = (s: CameraSettings): number =>\n [s.shot, s.move, s.angle, s.lensMm, s.aperture, s.stock].filter((v) => v !== undefined && v !== '').length;\n\n/**\n * The setup in a few words for the chip that opens the panel: the first two\n * labels a director would say, then how many more. '' when nothing is set,\n * so the chip can say \"Auto\" instead.\n */\nexport function cameraSummary(s: CameraSettings): string {\n const labels = [\n s.shot,\n s.move,\n s.angle,\n FOCAL_LENGTHS.find((f) => f.mm === s.lensMm)?.label,\n s.aperture,\n s.stock,\n ].filter((v): v is string => Boolean(v));\n if (labels.length === 0) return '';\n const shown = labels.slice(0, 2).join(' · ');\n return labels.length > 2 ? `${shown} +${labels.length - 2}` : shown;\n}\n"],"names":[],"mappings":"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"}
|