@adminide-stack/yantra-mobile 12.0.129-alpha.0 → 12.0.129
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 @@
|
|
|
1
|
+
{"version":3,"file":"templateSearch.js","sources":["../../../src/features/canvas/templateSearch.ts"],"sourcesContent":["/**\n * Template search: what a person (or the brain) typed -> the templates that fit\n * it, best first. One implementation for every page that searches a catalog\n * (the Templates page, the chat templates card, the image and audio lanes).\n *\n * The catalog backend matches every word of a search as a substring and keeps\n * only rows that hold ALL of them, unranked. That is a fine way to FIND\n * candidates and a poor way to choose between them:\n *\n * - Style and vibe words (\"clean modern fancy\") filtered a business card search\n * down to nothing, because no row says \"fancy\".\n * - One loose word carried a whole phrase: \"store opening flyer\" fell back to\n * \"opening\" and listed \"Seven opening lines that make people stop and read\".\n *\n * So a query is read here first: filler (\"templates for my\") and the category's\n * own name (\"flyer\") are left out, typos of either are recognised, and what is\n * left splits into SUBJECT words (what the template is about: coffee shop,\n * roadmap, 2030) and STYLE words (how it looks: clean, modern, fancy). Each\n * word brings a few near words (store ~ shop, fancy ~ elegant ~ luxury).\n *\n * Then each candidate is scored on the whole query: subject words in its title\n * or tags (its real subject) count most, the same words only in its visual\n * summary count little, style words rank and never exclude, and subject words\n * that sit together in the title (\"coffee shop\") score as a phrase. A template\n * is an `exact` match when every subject word is its real subject (a style-only\n * query: at least half the looks asked for), `close` when only part of the\n * query fits, and anything else is not a match at all - the category's own\n * best templates follow the matches as `popular`, so a search never comes back\n * empty while the category has templates.\n *\n * Pure: no I/O. The catalog reads that feed it live in ./rankedCatalogSearch.\n *\n * Native port of surface-kit `templateCatalogs/templateSearch` (kit 0.43). Kept\n * Hermes-safe: no Unicode property escapes in literals (built in a try with an\n * ASCII + Latin fallback) and `normalize` guarded.\n */\n\n/** Builds a regex from a Unicode-property source, or its fallback where the engine lacks them. */\nfunction unicodeRegExp(source: string, flags: string, fallback: RegExp): RegExp {\n try {\n return new RegExp(source, `${flags}u`);\n } catch {\n return fallback;\n }\n}\n\n/** A run of anything but letters and digits. */\nexport const NON_WORD: RegExp = unicodeRegExp('[^\\\\p{L}\\\\p{N}]+', '', /[^A-Za-z0-9\\u00C0-\\u024F]+/);\nconst NON_WORD_ALL: RegExp = unicodeRegExp('[^\\\\p{L}\\\\p{N}]+', 'g', /[^A-Za-z0-9\\u00C0-\\u024F]+/g);\n/** Text that ends in a letter or digit (a word still being typed). */\nconst WORD_END: RegExp = unicodeRegExp('[\\\\p{L}\\\\p{N}]$', '', /[A-Za-z0-9\\u00C0-\\u024F]$/);\n\n/** How a listed template relates to the search. */\nexport type TemplateMatch = 'exact' | 'close' | 'popular';\n\nexport type TemplateConceptKind = 'subject' | 'style';\n\n/** One word of a query, with the near words that count for it. */\nexport interface TemplateQueryConcept {\n /** The word as read (lower case, typo fixed). */\n word: string;\n kind: TemplateConceptKind;\n /** Its stem first, then its near words' stems; a multi-word term (\"real estate\") is space-joined. */\n terms: string[];\n /**\n * The last word of a query still being typed (\"coff\"): it also matches the words it starts.\n * Only an unknown word of 3+ letters at the very end, so a finished query never matches loosely.\n */\n prefix?: boolean;\n /**\n * A word the reader does not know, perhaps misspelled (\"cofee\"): it also matches a word one\n * typo away (\"coffee\"). Known words never do, so \"wedding\" does not match \"welding\".\n */\n typo?: boolean;\n}\n\nexport interface TemplateQuery {\n /** What was typed, whitespace collapsed. */\n text: string;\n subjects: TemplateQueryConcept[];\n styles: TemplateQueryConcept[];\n /** Words left out: filler, the category's own name, and typos of either. */\n ignored: string[];\n /** Nothing searchable was typed: list the category as it is. */\n empty: boolean;\n}\n\nexport interface TemplateQueryOptions {\n /**\n * Words and phrases that name the category being searched (\"business card\",\n * \"flyer\", \"slides\"): a search inside the category says nothing by them.\n */\n categoryWords?: readonly string[];\n}\n\n/** At most this many words of one query count; the rest are ignored. */\nconst MAX_CONCEPTS = 8;\n\n// ─── Words ──────────────────────────────────────────────────────────────────\n\n/** Words that say nothing about which template: \"show me some templates for my ...\". */\nconst FILLER = new Set(\n (\n 'a an the and or of for in on at to from by with without about into onto over under as is are be ' +\n 'my our your their his her its me i we you us it this that these those some any all every each ' +\n 'one ones template templates design designs designed idea ideas example examples sample samples ' +\n 'option options show find search make create build need needs want looking look get give please ' +\n 'new best good great nice cool really very something kind type types version style styles styled ' +\n 'theme themed based using use free just also like more other etc page pages custom editable own ' +\n 'quick easy pro printable print ready can could would should will do does help thanks hi hello ' +\n 'want wanted some something someone pick choose choice list see view'\n ).split(' '),\n);\n\n/**\n * How a template looks, as people say it. A style word ranks; it never excludes.\n * Each group is a set of near words: any of them counts for any other.\n */\n// prettier-ignore\nconst STYLE_GROUPS: readonly (readonly string[])[] = [\n ['clean', 'minimal', 'minimalist', 'simple', 'crisp', 'tidy', 'uncluttered'],\n ['minimal', 'minimalist', 'simple', 'clean', 'minimalistic', 'minimalism', 'plain'],\n ['simple', 'minimal', 'minimalist', 'clean', 'basic', 'plain'],\n ['modern', 'contemporary', 'sleek', 'trendy'],\n ['fancy', 'elegant', 'luxury', 'gold', 'premium', 'luxurious', 'golden', 'sophisticated', 'classy', 'glamorous', 'chic', 'ornate', 'upscale'],\n ['elegant', 'sophisticated', 'luxury', 'classy', 'refined', 'graceful', 'chic', 'elegance', 'fancy'],\n ['luxury', 'luxurious', 'premium', 'gold', 'elegant', 'upscale', 'golden', 'fancy'],\n ['bold', 'vibrant', 'striking', 'strong', 'punchy', 'loud'],\n ['playful', 'fun', 'cute', 'colorful', 'whimsical', 'cheerful', 'quirky', 'cartoon'],\n ['fun', 'playful', 'colorful', 'cheerful', 'cute'],\n ['cute', 'playful', 'adorable', 'sweet', 'kawaii'],\n ['warm', 'cozy', 'earthy', 'beige', 'cream', 'terracotta'],\n ['professional', 'corporate', 'formal', 'businesslike'],\n ['corporate', 'professional', 'formal'],\n ['formal', 'professional', 'classic'],\n ['classic', 'timeless', 'traditional', 'vintage'],\n ['vintage', 'retro', 'antique', 'nostalgic', 'classic', 'risograph'],\n ['retro', 'vintage', 'groovy', 'nostalgic'],\n ['rustic', 'kraft', 'wooden', 'farmhouse', 'earthy'],\n ['creative', 'artistic', 'unique', 'abstract'],\n ['colorful', 'vibrant', 'bright', 'colourful', 'rainbow', 'multicolor', 'multicolored'],\n ['bright', 'vibrant', 'colorful', 'neon'],\n ['dark', 'black', 'moody'],\n ['light', 'white', 'airy'],\n ['pastel', 'soft', 'muted', 'gentle'],\n ['soft', 'pastel', 'gentle', 'muted'],\n ['floral', 'flower', 'botanical', 'blossom'],\n ['geometric', 'shapes', 'angular', 'lines'],\n ['abstract', 'shapes', 'artistic'],\n ['gradient', 'ombre'],\n ['watercolor', 'watercolour', 'painted', 'painterly'],\n ['illustrated', 'illustration', 'illustrative', 'drawn', 'handdrawn', 'doodle', 'cartoon', 'sketch'],\n ['futuristic', 'neon', 'cyber', 'scifi'],\n ['feminine', 'pink', 'girly', 'delicate'],\n ['masculine', 'rugged'],\n ['beautiful', 'elegant', 'pretty', 'stunning', 'lovely', 'aesthetic', 'gorgeous'],\n ['stylish', 'chic', 'trendy', 'fashionable'],\n ['friendly', 'approachable', 'welcoming', 'casual'],\n ['casual', 'relaxed', 'friendly'],\n ['calm', 'serene', 'peaceful', 'zen', 'tranquil'],\n ['monochrome', 'monochromatic', 'grayscale'],\n ['grunge', 'textured', 'distressed'],\n ['handwritten', 'script', 'calligraphy'],\n ['typographic', 'typography', 'lettering'],\n ['sleek', 'modern', 'smooth', 'minimal'],\n ['gray', 'grey'],\n ['gold', 'golden'],\n ['purple', 'violet', 'plum', 'lavender'],\n ['beige', 'cream', 'ivory', 'tan'],\n ['black'], ['white'], ['silver'], ['blue'], ['navy'], ['green'], ['red'], ['pink'], ['yellow'], ['orange'],\n ['brown'], ['teal'], ['turquoise'], ['mint'], ['maroon'], ['burgundy'], ['peach'], ['coral'], ['olive'],\n ['sage'], ['mustard'], ['emerald'], ['neon'],\n];\n\n/**\n * What a template is about, with the few near words that mean the same thing\n * in a catalog title (\"store\" ~ \"shop\"). Words not listed are subjects too;\n * they just bring no near words.\n */\n// prettier-ignore\nconst SUBJECT_GROUPS: readonly (readonly string[])[] = [\n ['store', 'shop', 'boutique', 'retail', 'storefront'],\n ['shop', 'store', 'boutique', 'retail', 'shopping'],\n ['opening', 'grand opening', 'launch', 'inauguration', 'reopening'],\n ['coffee', 'cafe', 'espresso', 'barista', 'coffeehouse', 'latte'],\n ['cafe', 'coffee', 'coffeehouse', 'bistro'],\n ['bakery', 'baker', 'baking', 'bakeshop', 'pastry', 'patisserie', 'bread', 'cake', 'cupcake'],\n ['cake', 'cupcake', 'bakery', 'dessert', 'pastry'],\n ['restaurant', 'dining', 'diner', 'bistro', 'eatery', 'cuisine'],\n ['food', 'culinary', 'meal', 'kitchen', 'cooking'],\n ['chef', 'cook', 'culinary', 'catering'],\n ['roadmap', 'road map', 'timeline', 'milestone'],\n ['ice cream', 'gelato', 'dessert'],\n ['social media', 'instagram', 'facebook', 'tiktok'],\n ['strategy', 'strategic', 'planning'],\n ['plan', 'planning', 'planner'],\n ['real estate', 'realtor', 'realty', 'property', 'housing'],\n ['realtor', 'real estate', 'realty', 'property'],\n ['home', 'house'],\n ['lawyer', 'attorney', 'law', 'legal'],\n ['attorney', 'lawyer', 'law', 'legal'],\n ['doctor', 'medical', 'clinic', 'physician', 'healthcare'],\n ['dentist', 'dental', 'orthodontist'],\n ['health', 'healthcare', 'wellness', 'medical'],\n ['fitness', 'gym', 'workout', 'trainer', 'exercise'],\n ['gym', 'fitness', 'workout'],\n ['yoga', 'pilates', 'meditation'],\n ['wedding', 'bridal', 'bride', 'marriage'],\n ['birthday', 'bday'],\n ['party', 'celebration', 'fiesta'],\n ['photography', 'photographer', 'photo', 'camera'],\n ['photographer', 'photography', 'photo'],\n ['beauty', 'salon', 'makeup', 'cosmetics', 'spa'],\n ['salon', 'hair', 'hairdresser', 'hairstylist', 'beauty'],\n ['barber', 'barbershop', 'hair'],\n ['technology', 'tech', 'software', 'digital'],\n ['tech', 'technology', 'software'],\n ['startup', 'venture', 'founder'],\n ['pitch', 'investor', 'funding', 'fundraising'],\n ['marketing', 'advertising', 'campaign', 'promotion'],\n ['brand', 'branding', 'identity'],\n ['sale', 'discount', 'promo', 'offer', 'deal', 'clearance'],\n ['church', 'worship', 'ministry', 'faith'],\n ['school', 'education', 'classroom', 'student', 'teacher'],\n ['education', 'school', 'learning', 'teaching', 'classroom'],\n ['music', 'band', 'concert', 'musician'],\n ['travel', 'trip', 'tourism', 'vacation', 'tour'],\n ['hotel', 'resort', 'hospitality'],\n ['cleaning', 'cleaner', 'janitorial', 'housekeeping', 'maid'],\n ['construction', 'builder', 'contractor', 'renovation'],\n ['car', 'auto', 'automotive', 'mechanic', 'garage', 'vehicle'],\n ['pet', 'dog', 'cat', 'veterinary', 'vet', 'grooming'],\n ['finance', 'financial', 'accounting', 'accountant', 'bank', 'investment'],\n ['accountant', 'accounting', 'bookkeeping', 'tax'],\n ['consulting', 'consultant', 'advisory', 'advisor'],\n ['charity', 'nonprofit', 'fundraiser', 'donation', 'volunteer'],\n ['fashion', 'clothing', 'apparel'],\n ['garden', 'gardening', 'landscaping', 'lawn'],\n ['event', 'conference', 'summit', 'meetup'],\n ['christmas', 'xmas'],\n ['kids', 'children', 'child'],\n ['report', 'review', 'summary'],\n ['webinar', 'workshop', 'seminar'],\n ['farm', 'farming', 'agriculture'],\n ['sustainability', 'sustainable', 'environment', 'eco', 'climate'],\n ['science', 'research', 'laboratory'],\n ['art', 'artist', 'gallery'],\n ['coach', 'coaching', 'mentor'],\n ['therapy', 'therapist', 'counseling', 'counselor'],\n ['massage', 'spa', 'therapist'],\n ['plumber', 'plumbing', 'handyman', 'repair'],\n ['delivery', 'courier', 'logistics', 'shipping'],\n ['bar', 'pub', 'cocktail', 'brewery'],\n ['wine', 'winery', 'vineyard'],\n ['pizza', 'pizzeria'],\n ['tea', 'teahouse'],\n];\n\n/**\n * The words a category is named by, wherever a person may type them: \"logo\n * templates\" inside Logos is just \"templates\". Keyed by the category id (the\n * gallery group key); a caller with another key passes its own words.\n */\n// prettier-ignore\nexport const TEMPLATE_CATEGORY_WORDS: Readonly<Record<string, readonly string[]>> = {\n slideDeck: ['presentation', 'slide', 'slides', 'deck', 'ppt', 'pptx', 'powerpoint', 'keynote', 'slideshow', 'google slides'],\n socialPost: ['social media post', 'social post', 'post', 'posts', 'social media'],\n carousel: ['carousel', 'carousels', 'instagram carousel'],\n flyer: ['flyer', 'flier', 'poster', 'leaflet', 'handout'],\n businessCard: ['business card', 'visiting card', 'calling card', 'card'],\n logo: ['logo', 'logos', 'logotype', 'emblem'],\n banner: ['banner'],\n brochure: ['brochure', 'pamphlet', 'trifold', 'tri fold'],\n branding: ['branding kit', 'stationery'],\n certificate: ['certificate'],\n worksheet: ['worksheet'],\n proposal: ['proposal'],\n newsletter: ['newsletter'],\n menu: ['menu'],\n infographic: ['infographic'],\n imageGeneration: ['image', 'picture', 'prompt'],\n videoGeneration: ['video', 'clip', 'reel'],\n audioGeneration: ['audio', 'sound', 'song', 'track'],\n};\n\n// ─── Text ───────────────────────────────────────────────────────────────────\n\n/** Words that end in \"s\" without being plurals (or whose plural stem collides with filler). */\n// prettier-ignore\nconst KEEP_S = new Set([\n 'news', 'series', 'species', 'physics', 'mathematics', 'economics', 'analytics', 'ethics', 'politics',\n 'athletics', 'aesthetics', 'lyrics', 'diabetes', 'canvas', 'christmas', 'xmas', 'texas', 'paris', 'atlas',\n 'gas', 'bus', 'plus', 'yes', 'its', 'this', 'thus', 'chaos', 'cosmos', 'logistics', 'graphics', 'kids',\n]);\n\n/** A word reduced to the form both sides compare in: plurals folded (\"bakeries\" -> \"bakery\"). */\nexport function stemWord(word: string): string {\n const w = word.toLowerCase();\n if (w.length <= 3 || /\\d/.test(w) || KEEP_S.has(w)) return w;\n if (w.endsWith('ies') && w.length > 4) return `${w.slice(0, -3)}y`;\n if (/(ss|us|is)$/.test(w)) return w;\n if (/(sses|ches|shes|xes|zes)$/.test(w)) return w.slice(0, -2);\n if (w.endsWith('s')) return w.slice(0, -1);\n return w;\n}\n\n/** Lower case, accents off (\"Café\" -> \"cafe\"), curly apostrophes straight, \"&\" read as \"and\". */\nfunction fold(text: string): string {\n let normalized = text;\n try {\n if (typeof text.normalize === 'function') normalized = text.normalize('NFKD');\n } catch {\n // An engine without normalization data: accents stay on.\n }\n return normalized\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[\\u2018\\u2019\\u02bc]/g, \"'\")\n .replace(/&/g, ' and ')\n .toLowerCase();\n}\n\n/**\n * Words of a text, stemmed. Single letters drop out (the \"s\" of \"women's\"); so\n * do single digits (\"5 tips\"), years and codes stay (\"2030\").\n */\nexport function searchWords(text: string): string[] {\n return fold(text)\n .split(NON_WORD)\n .filter((w) => w.length > 1)\n .map(stemWord);\n}\n\n/** Restricted Damerau-Levenshtein distance, giving up past `max`. */\nfunction editDistance(a: string, b: string, max: number): number {\n if (Math.abs(a.length - b.length) > max) return max + 1;\n const rows: number[][] = [];\n for (let i = 0; i <= a.length; i++) {\n rows.push([i]);\n }\n for (let j = 1; j <= b.length; j++) rows[0][j] = j;\n for (let i = 1; i <= a.length; i++) {\n let best = Infinity;\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n let d = Math.min(rows[i - 1][j] + 1, rows[i][j - 1] + 1, rows[i - 1][j - 1] + cost);\n if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1])\n d = Math.min(d, rows[i - 2][j - 2] + 1);\n rows[i][j] = d;\n if (d < best) best = d;\n }\n if (best > max) return max + 1;\n }\n return rows[a.length][b.length];\n}\n\n/**\n * Near words, built once: a group's first word brings the rest of its group; a\n * word that heads no group brings the heads of the groups it is in. So \"gold\"\n * brings \"golden\" (its own group), not every luxury word, while \"minimalist\"\n * brings \"clean\", \"minimal\" and \"simple\".\n */\nfunction nearMap(groups: readonly (readonly string[])[]): Map<string, string[]> {\n const own = new Map<string, string[]>();\n const heads = new Map<string, string[]>();\n const push = (map: Map<string, string[]>, key: string, value: string) => {\n const list = map.get(key) ?? [];\n if (value !== key && !list.includes(value)) list.push(value);\n map.set(key, list);\n };\n for (const group of groups) {\n const [head, ...rest] = group.map((w) => searchWords(w).join(' '));\n if (!own.has(head)) own.set(head, []);\n for (const w of rest) {\n push(own, head, w);\n push(heads, w, head);\n }\n }\n const map = new Map<string, string[]>();\n for (const [word, list] of heads) if (!own.has(word)) map.set(word, list);\n for (const [word, list] of own) map.set(word, list);\n return map;\n}\n\nconst STYLE_NEAR = nearMap(STYLE_GROUPS);\nconst SUBJECT_NEAR = nearMap(SUBJECT_GROUPS);\n\n/** Words as listed, by stem: what a fixed typo reads as. */\nconst LISTED = new Map<string, string>();\n/** Words a typo may be read as: filler, style words and category names. */\nconst TYPO_TARGETS = new Set<string>();\n/** Subject words a LONG typo may be read as (\"resturant\"): few real long words are one typo from another. */\nconst LONG_TYPO_TARGETS = new Set<string>();\n/** Every word the reader knows; a known word is never \"fixed\". */\nconst KNOWN = new Set<string>();\n{\n const add = (w: string, target: boolean) => {\n for (const part of fold(w).split(NON_WORD)) {\n if (part.length < 2) continue;\n const stem = stemWord(part);\n KNOWN.add(stem);\n if (!LISTED.has(stem)) LISTED.set(stem, part);\n if (target) TYPO_TARGETS.add(stem);\n }\n };\n FILLER.forEach((w) => add(w, true));\n for (const g of STYLE_GROUPS) g.forEach((w) => add(w, true));\n for (const words of Object.values(TEMPLATE_CATEGORY_WORDS)) words.forEach((w) => add(w, true));\n ['templates', 'business'].forEach((w) => add(w, true));\n for (const g of SUBJECT_GROUPS) g.forEach((w) => add(w, false));\n for (const g of SUBJECT_GROUPS)\n for (const w of g) if (!w.includes(' ') && w.length >= 8) LONG_TYPO_TARGETS.add(stemWord(w));\n}\n\n/**\n * A word the reader does not know, read as the filler, style or category word\n * it is a typo of (\"templtes\" -> \"templates\", \"elegent\" -> \"elegant\",\n * \"buisness\" -> \"business\"), or as the long subject word it is one typo from\n * (\"resturant\" -> \"restaurant\"). Short words are never changed, the first\n * letter must agree, and a short word never becomes a subject word: \"stone\"\n * stays \"stone\", it is not a typo of \"store\".\n */\nfunction fixTypo(stem: string): string {\n if (stem.length < 5 || /\\d/.test(stem) || KNOWN.has(stem)) return stem;\n let best = '';\n let bestDistance = Infinity;\n const consider = (targets: Set<string>, max: number) => {\n for (const known of targets) {\n if (known[0] !== stem[0] || known.length < 4) continue;\n const d = editDistance(stem, known, max);\n if (d <= max && d < bestDistance) {\n best = known;\n bestDistance = d;\n }\n }\n };\n consider(TYPO_TARGETS, stem.length >= 8 ? 2 : 1);\n if (stem.length >= 8) consider(LONG_TYPO_TARGETS, 1);\n return best || stem;\n}\n\n// ─── Query ──────────────────────────────────────────────────────────────────\n\ninterface Token {\n /** As typed (folded). */\n raw: string;\n stem: string;\n}\n\n/** Remove every run of `phrase` (stems) from `tokens`, typos of it included. */\nfunction removePhrase(tokens: Token[], phrase: string[], removed: string[]): Token[] {\n if (phrase.length === 0) return tokens;\n const out: Token[] = [];\n for (let i = 0; i < tokens.length; ) {\n const hit =\n i + phrase.length <= tokens.length &&\n phrase.every((p, k) => tokens[i + k].stem === p || fixTypo(tokens[i + k].stem) === p);\n if (hit) {\n removed.push(\n tokens\n .slice(i, i + phrase.length)\n .map((t) => t.raw)\n .join(' '),\n );\n i += phrase.length;\n } else {\n out.push(tokens[i]);\n i += 1;\n }\n }\n return out;\n}\n\n/** Every multi-word term the reader knows (\"real estate\", \"grand opening\"). */\nconst PHRASES: Set<string> = new Set(\n [...STYLE_NEAR.keys(), ...SUBJECT_NEAR.keys(), ...[...STYLE_NEAR.values(), ...SUBJECT_NEAR.values()].flat()].filter(\n (term) => term.includes(' '),\n ),\n);\n\n/** Two words that make a known phrase are read as one: \"real estate\" is one subject, not two. */\nfunction joinPhrases(tokens: Token[]): Token[] {\n const out: Token[] = [];\n for (let i = 0; i < tokens.length; i++) {\n const next = tokens[i + 1];\n if (next && PHRASES.has(`${tokens[i].stem} ${next.stem}`)) {\n out.push({ raw: `${tokens[i].raw} ${next.raw}`, stem: `${tokens[i].stem} ${next.stem}` });\n i += 1;\n } else {\n out.push(tokens[i]);\n }\n }\n return out;\n}\n\n/** Read a typed query: its subject and style words, and what was left out. */\nexport function parseTemplateQuery(text: string, options: TemplateQueryOptions = {}): TemplateQuery {\n const typed = (text ?? '').replace(/\\s+/g, ' ').trim();\n const ignored: string[] = [];\n let tokens: Token[] = fold(typed)\n .split(NON_WORD)\n .filter((w) => w.length > 1)\n .map((raw) => ({ raw, stem: stemWord(raw) }));\n // The category's own name, longest phrase first: \"business card\" before \"card\".\n const phrases = [...(options.categoryWords ?? []), 'template']\n .map((p) => searchWords(p))\n .filter((p) => p.length > 0)\n .sort((a, b) => b.length - a.length);\n for (const phrase of phrases) tokens = removePhrase(tokens, phrase, ignored);\n tokens = joinPhrases(tokens);\n // Still typing: a query that does not end in a space or punctuation has a last word in progress.\n const typing = WORD_END.test(text ?? '');\n const last = tokens[tokens.length - 1];\n\n const subjects: TemplateQueryConcept[] = [];\n const styles: TemplateQueryConcept[] = [];\n const seen = new Set<string>();\n for (const token of tokens) {\n const stem = token.stem.includes(' ') ? token.stem : fixTypo(token.stem);\n const fixed = stem !== token.stem;\n if (FILLER.has(stem) || FILLER.has(LISTED.get(stem) ?? '')) {\n ignored.push(token.raw);\n continue;\n }\n if (seen.has(stem)) continue;\n if (subjects.length + styles.length >= MAX_CONCEPTS) {\n ignored.push(token.raw);\n continue;\n }\n seen.add(stem);\n const word = fixed ? (LISTED.get(stem) ?? stem) : token.raw;\n if (STYLE_NEAR.has(stem)) {\n styles.push({ word, kind: 'style', terms: [stem, ...(STYLE_NEAR.get(stem) ?? [])] });\n } else {\n const unknown = !fixed && !KNOWN.has(stem) && !stem.includes(' ') && !/\\d/.test(stem);\n const prefix = unknown && typing && token === last && stem.length >= 3;\n const typo = unknown && stem.length >= 5;\n subjects.push({\n word,\n kind: 'subject',\n terms: [stem, ...(SUBJECT_NEAR.get(stem) ?? [])],\n ...(prefix ? { prefix } : {}),\n ...(typo ? { typo } : {}),\n });\n }\n }\n return { text: typed, subjects, styles, ignored, empty: subjects.length + styles.length === 0 };\n}\n\n/** The words that were read, as a person can be shown them: \"coffee shop modern\". */\nexport function templateQueryLabel(query: TemplateQuery): string {\n return [...query.subjects, ...query.styles].map((c) => c.word).join(' ');\n}\n\n// ─── Candidate reads ────────────────────────────────────────────────────────\n\n/** One backend read that finds candidates: rows holding every word of `words`. */\nexport interface TemplateSearchRead {\n /** The words of the read: the backend keeps rows holding every one of them (as part of any word). */\n words: string[];\n /** The query terms (stems) every row this read returns holds somewhere. */\n terms: string[];\n /** Read deep (a word of the query) or shallow (a near word). */\n wide: boolean;\n /**\n * 1: the query's own words. 2: a near word, read only when its word's own read came back thin\n * (`concept`): \"fancy\" finds no row, so \"elegant\" and \"luxury\" are read; \"shop\" finds plenty.\n */\n stage: 1 | 2;\n /** The word (its stem) a single-word read is for: its own word (stage 1) or a near word of it (stage 2). */\n concept?: string;\n}\n\n/**\n * What the backend is asked for a concept's own word. It matches substrings, so\n * a stem that is the start of the typed word (\"shop\" of \"shops\") finds both\n * forms; \"bakeries\" -> \"bakery\" is not, so the typed word goes as it is.\n */\nfunction backendWord(concept: TemplateQueryConcept): string {\n const stem = concept.terms[0];\n return concept.word.startsWith(stem) ? stem : concept.word;\n}\n\n/**\n * The backend reads that gather candidates for `query`, most telling first, at\n * most `budget` of them. Stage 1: every word together, the subject words\n * together, each subject word, the first subject word with each style word (a\n * style-only query: each style word). Stage 2: near words, one word at a time.\n */\nexport function templateSearchReads(query: TemplateQuery, budget = 10): TemplateSearchRead[] {\n const reads: TemplateSearchRead[] = [];\n const keys = new Set<string>();\n const add = (parts: Array<{ word: string; term: string }>, wide: boolean, stage: 1 | 2, concept?: string) => {\n const words = [...new Set(parts.flatMap((p) => p.word.split(' ')))];\n const key = [...words].sort().join(' ');\n if (reads.length >= budget || words.length === 0 || keys.has(key)) return;\n keys.add(key);\n reads.push({\n words,\n terms: [...new Set(parts.map((p) => p.term))],\n wide,\n stage,\n ...(concept ? { concept } : {}),\n });\n };\n const own = (c: TemplateQueryConcept) => ({ word: backendWord(c), term: c.terms[0] });\n const subjects = query.subjects.map(own);\n const styles = query.styles.map(own);\n if (subjects.length + styles.length > 1) add([...subjects, ...styles], true, 1);\n if (subjects.length > 1 && styles.length > 0) add(subjects, true, 1);\n for (const s of subjects) add([s], true, 1, s.term);\n if (subjects.length > 0) for (const y of styles) add([subjects[0], y], false, 1);\n if (subjects.length === 0) for (const y of styles) add([y], true, 1, y.term);\n // Near words, one per word in turn: store's \"shop\" before opening's second near word.\n const concepts = subjects.length > 0 ? query.subjects : query.styles;\n for (let k = 1; reads.length < budget; k++) {\n let any = false;\n for (const c of concepts) {\n const term = c.terms[k];\n if (term === undefined) continue;\n any = true;\n add([{ word: term, term }], false, 2, c.terms[0]);\n }\n if (!any) break;\n }\n return reads;\n}\n\n// ─── Scoring ────────────────────────────────────────────────────────────────\n\n/** What a template is known by, as far as the caller has it. */\nexport interface TemplateSearchFields {\n title?: string;\n /** Its visual summary (what the cover shows); absent on a light read. */\n summary?: string;\n tags?: readonly string[];\n category?: string;\n description?: string;\n}\n\n/** Tags that describe the catalog, not the template: its group, its kind, its shape. */\nconst STRUCTURAL_TAG =\n /^(canvas-[a-z-]+|video-studio|\\d+:\\d+|presentation|carousel|flyer|business-cards?|logo|banner|brochure|branding|social-post|certificate|worksheet|proposal|newsletter|menu|infographic)$/;\n\n/** A template's words, by where they appear, ready to score against any query. */\nexport interface TemplateSearchText {\n title: string[];\n tags: string[];\n summary: string[];\n /** Every visible text, lower case, for telling a whole word from part of one. */\n visible: string;\n /** False when the title may be cut short (a title read back from a row's name). */\n titleComplete: boolean;\n}\n\nexport function templateSearchText(fields: TemplateSearchFields, titleComplete = true): TemplateSearchText {\n const tags = (fields.tags ?? []).filter((t) => !STRUCTURAL_TAG.test(t.toLowerCase()));\n const tagText = [...tags, fields.category ?? ''].join(' ');\n // A tag spelled as one word (\"realestate\") also matches the two-word term.\n const joinedTags = tags.map((t) => fold(t).replace(NON_WORD_ALL, '')).filter((t) => t.length > 1);\n return {\n title: searchWords(fields.title ?? ''),\n tags: [...searchWords(tagText), ...joinedTags],\n summary: searchWords(`${fields.summary ?? ''} ${fields.description ?? ''}`),\n visible: fold(`${fields.title ?? ''} ${tagText}`),\n titleComplete,\n };\n}\n\n/** \"strategic\" and \"strategy\", \"photographer\" and \"photography\": one word in a title's sense. */\nfunction nearWord(a: string, b: string): boolean {\n const min = Math.min(a.length, b.length);\n if (min < 5 || Math.abs(a.length - b.length) > 3) return false;\n let common = 0;\n while (common < min && a[common] === b[common]) common++;\n return common >= Math.max(5, min - 2);\n}\n\ninterface FindOptions {\n /** Near forms count (\"strategy\" for \"strategic\"). */\n loose?: boolean;\n /** Words it starts count (a word still being typed). */\n prefix?: boolean;\n /** Words one typo away count (a word the reader does not know). */\n typo?: boolean;\n}\n\n/** A word one typo away (two for a long word), first letter alike. */\nfunction typoOf(term: string, word: string): boolean {\n if (word.length < 5 || word[0] !== term[0]) return false;\n const max = term.length >= 8 ? 2 : 1;\n return editDistance(term, word, max) <= max;\n}\n\n/**\n * Where `term` appears in `words`: 1 for the word itself, 0.9 for a near form, 0.85 for a word one\n * typo away, 0.8 for a word it starts; with its position.\n */\nfunction findTerm(\n term: string,\n words: string[],\n { loose = false, prefix = false, typo = false }: FindOptions = {},\n): { quality: number; at: number } | null {\n const parts = term.split(' ');\n if (parts.length > 1) {\n const joined = parts.join('');\n for (let i = 0; i < words.length; i++) {\n if (words[i] === joined) return { quality: 1, at: i };\n if (parts.every((p, k) => words[i + k] === p)) return { quality: 1, at: i };\n }\n return null;\n }\n let near: { quality: number; at: number } | null = null;\n for (let i = 0; i < words.length; i++) {\n if (words[i] === term) return { quality: 1, at: i };\n if (near?.quality === 0.9) continue; // the best a looser form gets; an exact word may still follow\n if (loose && nearWord(term, words[i])) near = { quality: 0.9, at: i };\n else if (typo && (!near || near.quality < 0.85) && typoOf(term, words[i])) near = { quality: 0.85, at: i };\n else if (prefix && !near && words[i].startsWith(term)) near = { quality: 0.8, at: i };\n }\n return near;\n}\n\ntype Field = 'title' | 'tags' | 'summary' | 'elsewhere';\n\ninterface Evidence {\n strength: number;\n field: Field | null;\n /** Position in the title, for phrases. */\n at: number;\n}\n\nconst FIELD_WEIGHT: Record<TemplateConceptKind, Record<Exclude<Field, 'elsewhere'>, number>> = {\n // A subject word in the title or tags is the template's real subject; in the visual summary\n // it is often an accident (\"an opening paragraph\").\n subject: { title: 1, tags: 0.8, summary: 0.35 },\n // A style word in the summary is what the cover looks like: good evidence.\n style: { title: 1, tags: 0.7, summary: 0.75 },\n};\n/** The backend found the word somewhere this side cannot see (a light read has no summary). */\nconst ELSEWHERE_WEIGHT = { subject: { complete: 0.3, cut: 0.45 }, style: 0.6 } as const;\n/** A near word counts a little less than the word itself. */\nconst NEAR_TERM_WEIGHT = 0.85;\n\nfunction evidenceFor(concept: TemplateQueryConcept, text: TemplateSearchText, foundBy?: ReadonlySet<string>): Evidence {\n let best: Evidence = { strength: 0, field: null, at: -1 };\n const loose = concept.kind === 'subject';\n concept.terms.forEach((term, index) => {\n const termWeight = index === 0 ? 1 : NEAR_TERM_WEIGHT;\n for (const field of ['title', 'tags', 'summary'] as const) {\n const hit = findTerm(term, text[field], {\n loose,\n prefix: index === 0 && concept.prefix === true,\n typo: index === 0 && concept.typo === true,\n });\n if (!hit) continue;\n const strength = FIELD_WEIGHT[concept.kind][field] * termWeight * hit.quality;\n if (strength > best.strength) best = { strength, field, at: field === 'title' ? hit.at : -1 };\n }\n // Found by the backend, but not as a word anywhere visible: it is in the summary (or the\n // part of a long title a row name leaves out). Part of a longer visible word (\"workshop\"\n // for \"shop\") is what the backend's substring match found, so that counts for nothing.\n if (foundBy?.has(term) && !term.split(' ').some((p) => text.visible.includes(p))) {\n const strength =\n (concept.kind === 'subject'\n ? text.titleComplete\n ? ELSEWHERE_WEIGHT.subject.complete\n : ELSEWHERE_WEIGHT.subject.cut\n : ELSEWHERE_WEIGHT.style) * termWeight;\n if (strength > best.strength) best = { strength, field: 'elsewhere', at: -1 };\n }\n });\n return best;\n}\n\nexport interface TemplateScore {\n /** Higher is better; exact matches always outrank close ones. */\n score: number;\n /** Null: nothing of the query fits. */\n match: Exclude<TemplateMatch, 'popular'> | null;\n}\n\nconst mean = (xs: number[]) => (xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : 0);\n\n/**\n * How well one template fits `query`. `foundBy` is the set of query terms the\n * backend found in it (light reads), so a word the caller cannot see still counts.\n */\nexport function scoreTemplate(\n query: TemplateQuery,\n text: TemplateSearchText,\n foundBy?: ReadonlySet<string>,\n): TemplateScore {\n if (query.empty) return { score: 0, match: null };\n const subjects = query.subjects.map((c) => evidenceFor(c, text, foundBy));\n const styles = query.styles.map((c) => evidenceFor(c, text, foundBy));\n let match: TemplateScore['match'] = null;\n if (subjects.length > 0) {\n // Every subject word is what the template is about (its title or tags): exact.\n if (subjects.every((e) => e.field === 'title' || e.field === 'tags')) match = 'exact';\n else if (subjects.some((e) => e.strength > 0)) match = 'close';\n } else {\n const present = styles.filter((e) => e.strength >= 0.5).length;\n if (present >= Math.ceil(styles.length / 2)) match = 'exact';\n else if (styles.some((e) => e.strength > 0)) match = 'close';\n }\n if (!match) return { score: 0, match: null };\n // Subject words side by side in the title read as the phrase that was typed (\"coffee shop\").\n let phrase = 0;\n for (let i = 0; i + 1 < subjects.length; i++) {\n const [a, b] = [subjects[i].at, subjects[i + 1].at];\n if (a < 0 || b < 0) continue;\n const gap = b - a;\n phrase += gap === 1 ? 1 : (gap > 1 && gap <= 3) || gap === -1 ? 0.5 : 0;\n }\n if (subjects.length > 1) phrase /= subjects.length - 1;\n const primary = subjects.length > 0 ? mean(subjects.map((e) => e.strength)) : mean(styles.map((e) => e.strength));\n const secondary = subjects.length > 0 ? mean(styles.map((e) => e.strength)) : 0;\n // A title that is mostly what was asked for (\"Birthday party celebration\") is more about it than one\n // that mentions it on the way (\"Home quiz with a birthday-party theme\").\n const words = text.title.filter((w) => !FILLER.has(w));\n const inTitle = [...subjects, ...styles].filter((e) => e.field === 'title').length;\n const focus = words.length > 0 ? Math.min(1, inTitle / words.length) : 0;\n const tier = match === 'exact' ? 2000 : 1000;\n return { score: tier + 100 * primary + 40 * secondary + 15 * phrase + 8 * focus, match };\n}\n\nexport interface RankedTemplate<T> {\n item: T;\n score: number;\n match: Exclude<TemplateMatch, 'popular'>;\n}\n\n/**\n * The items that fit `query`, best first; ties keep the order they came in (the\n * catalog's own). Items nothing of the query fits are left out.\n */\nexport function rankTemplates<T>(\n query: TemplateQuery,\n items: readonly T[],\n textOf: (item: T) => TemplateSearchText,\n foundByOf?: (item: T) => ReadonlySet<string> | undefined,\n): Array<RankedTemplate<T>> {\n const ranked: Array<RankedTemplate<T> & { order: number }> = [];\n items.forEach((item, order) => {\n const { score, match } = scoreTemplate(query, textOf(item), foundByOf?.(item));\n if (match) ranked.push({ item, score, match, order });\n });\n ranked.sort((a, b) => b.score - a.score || a.order - b.order);\n return ranked.map(({ item, score, match }) => ({ item, score, match }));\n}\n\n/**\n * A row name back to the title it was made from: `canvas-flyer-coffee-shop-grand-opening-027fdd2c`\n * -> \"coffee shop grand opening\". The publish lane slugs titles (long ones cut short) and adds a\n * code; a light read has the name and not the title.\n */\nexport function titleFromRowName(name: string, group: string): string {\n const rest = name.startsWith(`${group}-`) ? name.slice(group.length + 1) : name;\n const parts = rest.split('-');\n if (parts.length > 1) parts.pop();\n return parts.join(' ');\n}\n"],"names":["map"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useMemo,useState,useRef,useCallback,useEffect}from'react';import {AppState}from'react-native';import {config}from'../../config/env-config.js';import {usePrerequisiteIds}from'../../hooks/usePrerequisiteIds.js';import {useObtainSystemToken}from'../../hooks/useObtainSystemToken.js';import {resolveSurfaceAuthGraphqlUrl}from'../../hooks/resolveSurfaceAuthGraphqlUrl.js';import {getWarmWebBuilderSession,warmWebBuilderSession,clearWarmWebBuilderSession}from'../../screens/WebBuilder/webbuilderWarmCache.js';import {surfaceIndexUrl,surfaceIndexUrlFromTemplate}from'./surfaceIndex.js';import {tokenExpiryMs}from'./sessionIdentity.js';const RENEW_LEAD_MS = 9e4;
|
|
1
|
+
import {useMemo,useState,useRef,useCallback,useEffect}from'react';import {AppState}from'react-native';import {config}from'../../config/env-config.js';import {usePrerequisiteIds}from'../../hooks/usePrerequisiteIds.js';import {useObtainSystemToken}from'../../hooks/useObtainSystemToken.js';import {resolveSurfaceAuthGraphqlUrl}from'../../hooks/resolveSurfaceAuthGraphqlUrl.js';import {getWarmWebBuilderSession,warmWebBuilderSession,clearWarmWebBuilderSession}from'../../screens/WebBuilder/webbuilderWarmCache.js';import {surfaceIndexUrl,surfaceIndexUrlFromTemplate}from'./surfaceIndex.js';import {tokenExpiryMs}from'./sessionIdentity.js';import {registerSessionRenewer}from'./sessionRenewal.js';const RENEW_LEAD_MS = 9e4;
|
|
2
2
|
const MAX_RENEW_DELAY_MS = 40 * 60 * 1e3;
|
|
3
3
|
const MIN_RENEW_DELAY_MS = 3e4;
|
|
4
4
|
const QUICK_RETRY_MS = [3e3, 1e4];
|
|
@@ -45,6 +45,9 @@ function useCanvasSession() {
|
|
|
45
45
|
const renewTimerRef = useRef(null);
|
|
46
46
|
const tokenExpRef = useRef(null);
|
|
47
47
|
const failuresRef = useRef(0);
|
|
48
|
+
const tokenRef = useRef(token);
|
|
49
|
+
tokenRef.current = token != null ? token : tokenRef.current;
|
|
50
|
+
const renewingRef = useRef(null);
|
|
48
51
|
const clearRenewTimer = useCallback(() => {
|
|
49
52
|
if (renewTimerRef.current) {
|
|
50
53
|
clearTimeout(renewTimerRef.current);
|
|
@@ -53,7 +56,7 @@ function useCanvasSession() {
|
|
|
53
56
|
}, []);
|
|
54
57
|
const mint = useCallback(async (forceFresh) => {
|
|
55
58
|
var _a;
|
|
56
|
-
if (!idsRef.current.orgName || !idsRef.current.projectId) return;
|
|
59
|
+
if (!idsRef.current.orgName || !idsRef.current.projectId) return null;
|
|
57
60
|
if (forceFresh) clearWarmWebBuilderSession();
|
|
58
61
|
try {
|
|
59
62
|
const session = await warmWebBuilderSession({
|
|
@@ -67,7 +70,8 @@ function useCanvasSession() {
|
|
|
67
70
|
obtainSystemToken: crossBackendAuth ? void 0 : obtainSystemToken,
|
|
68
71
|
discoverScope: crossBackendAuth
|
|
69
72
|
});
|
|
70
|
-
if (cancelledRef.current) return;
|
|
73
|
+
if (cancelledRef.current) return null;
|
|
74
|
+
tokenRef.current = session.token;
|
|
71
75
|
setToken(session.token);
|
|
72
76
|
setError(null);
|
|
73
77
|
failuresRef.current = 0;
|
|
@@ -78,11 +82,12 @@ function useCanvasSession() {
|
|
|
78
82
|
renewTimerRef.current = setTimeout(() => {
|
|
79
83
|
void mint(true);
|
|
80
84
|
}, delay);
|
|
85
|
+
return session.token;
|
|
81
86
|
} catch (err) {
|
|
82
|
-
if (cancelledRef.current) return;
|
|
87
|
+
if (cancelledRef.current) return null;
|
|
83
88
|
const message = err instanceof Error ? err.message : String(err);
|
|
84
89
|
const waitingForIds = /waiting for org\/project/i.test(message) || !idsRef.current.orgName;
|
|
85
|
-
if (waitingForIds) return;
|
|
90
|
+
if (waitingForIds) return null;
|
|
86
91
|
setError("Couldn't sign you in.");
|
|
87
92
|
const backoff = (_a = QUICK_RETRY_MS[failuresRef.current]) != null ? _a : Math.min(MAX_RENEW_DELAY_MS, MIN_RENEW_DELAY_MS * 2 ** (failuresRef.current - QUICK_RETRY_MS.length));
|
|
88
93
|
failuresRef.current += 1;
|
|
@@ -90,6 +95,7 @@ function useCanvasSession() {
|
|
|
90
95
|
renewTimerRef.current = setTimeout(() => {
|
|
91
96
|
void mint(true);
|
|
92
97
|
}, backoff);
|
|
98
|
+
return null;
|
|
93
99
|
} finally {
|
|
94
100
|
if (!cancelledRef.current) setReady(true);
|
|
95
101
|
}
|
|
@@ -121,12 +127,28 @@ function useCanvasSession() {
|
|
|
121
127
|
clearRenewTimer();
|
|
122
128
|
void mint(true);
|
|
123
129
|
}, [mint, clearRenewTimer]);
|
|
130
|
+
const renew = useCallback(() => {
|
|
131
|
+
if (renewingRef.current) return renewingRef.current;
|
|
132
|
+
failuresRef.current = 0;
|
|
133
|
+
clearRenewTimer();
|
|
134
|
+
const pending = mint(true).catch(() => null).finally(() => {
|
|
135
|
+
renewingRef.current = null;
|
|
136
|
+
});
|
|
137
|
+
renewingRef.current = pending;
|
|
138
|
+
return pending;
|
|
139
|
+
}, [mint, clearRenewTimer]);
|
|
140
|
+
useEffect(() => registerSessionRenewer({
|
|
141
|
+
current: () => tokenRef.current,
|
|
142
|
+
renew,
|
|
143
|
+
graphqlUrl: canvasGraphqlUrl
|
|
144
|
+
}), [renew, canvasGraphqlUrl]);
|
|
124
145
|
return {
|
|
125
146
|
token,
|
|
126
147
|
indexUrl,
|
|
127
148
|
graphqlUrl: canvasGraphqlUrl,
|
|
128
149
|
error,
|
|
129
150
|
ready,
|
|
130
|
-
retry
|
|
151
|
+
retry,
|
|
152
|
+
renew
|
|
131
153
|
};
|
|
132
154
|
}export{useCanvasSession};//# sourceMappingURL=useCanvasSession.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCanvasSession.js","sources":["../../../src/features/canvas/useCanvasSession.ts"],"sourcesContent":["/**\n * The host half of the canvas: session + endpoint, nothing else.\n *\n * Everything about READING a canvas lives in the federated remote\n * (`CanvasExperience`) so it can be fixed by a surface deploy. What the remote\n * cannot know is this environment's index URL and a token the index accepts —\n * that is what this resolves and hands over.\n *\n * Auth reuses the WebBuilder warm session. When the surface backend is not\n * GRAPHQL_URL (production: `ideback.yantra.app` vs the app's\n * `ideback.yantra-app-v1.yantra.app`; local: the cluster harness), the session\n * is minted there with `discoverScope`, still IN THE APP'S OWN SCOPE - the mint\n * only discovers one when that backend does not know the app's workspace.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AppState } from 'react-native';\nimport { config } from '../../config/env-config';\nimport { usePrerequisiteIds } from '../../hooks/usePrerequisiteIds';\nimport { useObtainSystemToken } from '../../hooks/useObtainSystemToken';\nimport { resolveSurfaceAuthGraphqlUrl } from '../../hooks/resolveSurfaceAuthGraphqlUrl';\nimport {\n clearWarmWebBuilderSession,\n getWarmWebBuilderSession,\n warmWebBuilderSession,\n} from '../../screens/WebBuilder/webbuilderWarmCache';\nimport { surfaceIndexUrl, surfaceIndexUrlFromTemplate } from './surfaceIndex';\nimport { tokenExpiryMs } from './sessionIdentity';\n\n/** Re-mint this long before the token's `exp` so a call never rides an\n * about-to-die JWT. */\nconst RENEW_LEAD_MS = 90_000;\n/** Ceiling on the renewal timer - also the fallback cadence when the token\n * carries no readable `exp`. Comfortably under the 45-min warm-cache TTL so a\n * scheduled renewal always forces a genuinely fresh mint. */\nconst MAX_RENEW_DELAY_MS = 40 * 60 * 1000;\n/** Never schedule a renewal tighter than this (guards an already-expired token\n * from a hot re-mint loop). */\nconst MIN_RENEW_DELAY_MS = 30_000;\n/** First retries after a failed mint: most failures are a beat-behind login token\n * or one dropped request, and waiting 30s on an error screen read as broken. */\nconst QUICK_RETRY_MS = [3_000, 10_000];\n\nfunction backendsEqual(a: string, b: string): boolean {\n return a.trim().replace(/\\/$/, '') === b.trim().replace(/\\/$/, '');\n}\n\nexport interface CanvasSession {\n token: string | null;\n indexUrl: string;\n /** The backend `token` was minted against - the one that accepts it (`.../graphql`). */\n graphqlUrl: string;\n /** Plain sentence when the session could not be established, else null. */\n error: string | null;\n ready: boolean;\n /** Sign in again now, skipping the wait for the next automatic retry. */\n retry: () => void;\n}\n\nexport function useCanvasSession(): CanvasSession {\n const { orgName, projectId, tagId } = usePrerequisiteIds();\n\n // Local GRAPHQL_URL (localhost) cannot derive a surface-index host, and a\n // locally minted JWT 401s against the cluster index. Same pairing Web\n // Builder uses: mint against CANVAS_BACKEND_GRAPHQL_URL, derive the index\n // from that backend. Staging/prod GRAPHQL_URL already is that backend.\n const canvasGraphqlUrl = useMemo(\n () =>\n resolveSurfaceAuthGraphqlUrl(config.CANVAS_SURFACE_URL, config.GRAPHQL_URL, {\n CANVAS_SURFACE_URL: config.CANVAS_SURFACE_URL,\n CANVAS_BACKEND_GRAPHQL_URL: config.CANVAS_BACKEND_GRAPHQL_URL,\n }),\n [],\n );\n const crossBackendAuth = !backendsEqual(canvasGraphqlUrl, config.GRAPHQL_URL);\n const { obtainSystemToken } = useObtainSystemToken(!crossBackendAuth);\n\n const indexUrl = useMemo(() => {\n const derived = surfaceIndexUrl(canvasGraphqlUrl, config.SURFACE_INDEX_URL);\n if (derived) return derived;\n return surfaceIndexUrlFromTemplate(config.SURFACE_URL_TEMPLATE);\n }, [canvasGraphqlUrl]);\n\n const seeded = getWarmWebBuilderSession(canvasGraphqlUrl);\n const [token, setToken] = useState<string | null>(() => seeded?.token ?? null);\n const [error, setError] = useState<string | null>(null);\n const [ready, setReady] = useState(() => Boolean(seeded?.token));\n\n // org/project arrive a beat after mount; hold the latest in a ref so a\n // resolved id does not restart an in-flight mint.\n const idsRef = useRef({ orgName, projectId, tagId });\n idsRef.current = { orgName, projectId, tagId };\n\n // Renewal machinery. `mint` re-mints the surface token; on success it\n // schedules the next mint just before the JWT's `exp`, so a mounted\n // surface never rides an expired session. `forceFresh` clears the shared\n // warm cache first, so a renewal actually gets a new token rather than the\n // stale cached one (the cache is a cross-surface dedupe for the first\n // mint, not a source of freshness).\n const cancelledRef = useRef(false);\n const renewTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const tokenExpRef = useRef<number | null>(null);\n // Consecutive mint failures, for the self-heal backoff below. Reset to 0 on\n // any successful mint.\n const failuresRef = useRef(0);\n\n const clearRenewTimer = useCallback(() => {\n if (renewTimerRef.current) {\n clearTimeout(renewTimerRef.current);\n renewTimerRef.current = null;\n }\n }, []);\n\n const mint = useCallback(\n async (forceFresh: boolean) => {\n // No workspace yet is a not-yet, never a failure: the org/project\n // effect below mints the moment they arrive. Minting without them\n // is how a cross-backend session used to land in the wrong org.\n if (!idsRef.current.orgName || !idsRef.current.projectId) return;\n if (forceFresh) clearWarmWebBuilderSession();\n try {\n const session = await warmWebBuilderSession({\n graphqlUrl: canvasGraphqlUrl,\n // Cross-backend still passes the app's ids: discovery prefers\n // them whenever the surface backend has them (same backend\n // under another host on prod).\n orgName: idsRef.current.orgName,\n projectId: idsRef.current.projectId,\n tagId: idsRef.current.tagId,\n obtainSystemToken: crossBackendAuth ? undefined : obtainSystemToken,\n discoverScope: crossBackendAuth,\n });\n if (cancelledRef.current) return;\n setToken(session.token);\n setError(null);\n failuresRef.current = 0;\n\n // Schedule the next renewal from the token's own expiry.\n const expMs = tokenExpiryMs(session.token);\n tokenExpRef.current = expMs;\n const delay = expMs\n ? Math.min(MAX_RENEW_DELAY_MS, Math.max(MIN_RENEW_DELAY_MS, expMs - Date.now() - RENEW_LEAD_MS))\n : MAX_RENEW_DELAY_MS;\n clearRenewTimer();\n renewTimerRef.current = setTimeout(() => {\n void mint(true);\n }, delay);\n } catch (err) {\n if (cancelledRef.current) return;\n const message = err instanceof Error ? err.message : String(err);\n // Missing org/project is a not-yet, not a failure. The\n // org/project effect re-mints when they arrive, so do not error\n // or schedule a retry here.\n const waitingForIds = /waiting for org\\/project/i.test(message) || !idsRef.current.orgName;\n if (waitingForIds) return;\n setError(\"Couldn't sign you in.\");\n // Self-heal: a failed mint is usually the Auth0 id_token briefly\n // stale after a background/sleep (the app login token renews on\n // foreground, a beat behind). Retry on a capped exponential\n // backoff with forceFresh, so the surface recovers on its own the\n // moment the login token is fresh again - no force-quit needed.\n const backoff =\n QUICK_RETRY_MS[failuresRef.current] ??\n Math.min(\n MAX_RENEW_DELAY_MS,\n MIN_RENEW_DELAY_MS * 2 ** (failuresRef.current - QUICK_RETRY_MS.length),\n );\n failuresRef.current += 1;\n clearRenewTimer();\n renewTimerRef.current = setTimeout(() => {\n void mint(true);\n }, backoff);\n } finally {\n if (!cancelledRef.current) setReady(true);\n }\n },\n [obtainSystemToken, canvasGraphqlUrl, crossBackendAuth, clearRenewTimer],\n );\n\n useEffect(() => {\n cancelledRef.current = false;\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log(\n '[useCanvasSession] graphql=',\n canvasGraphqlUrl,\n 'index=',\n indexUrl,\n 'crossBackend=',\n crossBackendAuth,\n );\n }\n void mint(false);\n\n // iOS suspends timers in the background; a token can lapse while away.\n // On return, re-mint immediately if it is at/near expiry so the first\n // post-foreground index call already carries a fresh JWT.\n const appStateSub = AppState.addEventListener('change', (next) => {\n if (next !== 'active') return;\n const expMs = tokenExpRef.current;\n if (!expMs || Date.now() >= expMs - RENEW_LEAD_MS) void mint(true);\n });\n\n return () => {\n cancelledRef.current = true;\n clearRenewTimer();\n appStateSub.remove();\n };\n }, [mint, canvasGraphqlUrl, indexUrl, crossBackendAuth, clearRenewTimer]);\n\n // First mint can fail while org/project are still hydrating. Retry once they\n // arrive so we do not sit on the spinner until the user leaves and comes back.\n useEffect(() => {\n if (token) return;\n if (!orgName || !projectId) return;\n void mint(false);\n }, [token, orgName, projectId, mint]);\n\n /** Sign in again now, for the \"Try again\" on a surface's error screen. */\n const retry = useCallback(() => {\n failuresRef.current = 0;\n clearRenewTimer();\n void mint(true);\n }, [mint, clearRenewTimer]);\n\n return { token, indexUrl, graphqlUrl: canvasGraphqlUrl, error, ready, retry };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useCanvasSession.js","sources":["../../../src/features/canvas/useCanvasSession.ts"],"sourcesContent":["/**\n * The host half of the canvas: session + endpoint, nothing else.\n *\n * Everything about READING a canvas lives in the federated remote\n * (`CanvasExperience`) so it can be fixed by a surface deploy. What the remote\n * cannot know is this environment's index URL and a token the index accepts —\n * that is what this resolves and hands over.\n *\n * Auth reuses the WebBuilder warm session. When the surface backend is not\n * GRAPHQL_URL (production: `ideback.yantra.app` vs the app's\n * `ideback.yantra-app-v1.yantra.app`; local: the cluster harness), the session\n * is minted there with `discoverScope`, still IN THE APP'S OWN SCOPE - the mint\n * only discovers one when that backend does not know the app's workspace.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AppState } from 'react-native';\nimport { config } from '../../config/env-config';\nimport { usePrerequisiteIds } from '../../hooks/usePrerequisiteIds';\nimport { useObtainSystemToken } from '../../hooks/useObtainSystemToken';\nimport { resolveSurfaceAuthGraphqlUrl } from '../../hooks/resolveSurfaceAuthGraphqlUrl';\nimport {\n clearWarmWebBuilderSession,\n getWarmWebBuilderSession,\n warmWebBuilderSession,\n} from '../../screens/WebBuilder/webbuilderWarmCache';\nimport { surfaceIndexUrl, surfaceIndexUrlFromTemplate } from './surfaceIndex';\nimport { tokenExpiryMs } from './sessionIdentity';\nimport { registerSessionRenewer } from './sessionRenewal';\n\n/** Re-mint this long before the token's `exp` so a call never rides an\n * about-to-die JWT. */\nconst RENEW_LEAD_MS = 90_000;\n/** Ceiling on the renewal timer - also the fallback cadence when the token\n * carries no readable `exp`. Comfortably under the 45-min warm-cache TTL so a\n * scheduled renewal always forces a genuinely fresh mint. */\nconst MAX_RENEW_DELAY_MS = 40 * 60 * 1000;\n/** Never schedule a renewal tighter than this (guards an already-expired token\n * from a hot re-mint loop). */\nconst MIN_RENEW_DELAY_MS = 30_000;\n/** First retries after a failed mint: most failures are a beat-behind login token\n * or one dropped request, and waiting 30s on an error screen read as broken. */\nconst QUICK_RETRY_MS = [3_000, 10_000];\n\nfunction backendsEqual(a: string, b: string): boolean {\n return a.trim().replace(/\\/$/, '') === b.trim().replace(/\\/$/, '');\n}\n\nexport interface CanvasSession {\n token: string | null;\n indexUrl: string;\n /** The backend `token` was minted against - the one that accepts it (`.../graphql`). */\n graphqlUrl: string;\n /** Plain sentence when the session could not be established, else null. */\n error: string | null;\n ready: boolean;\n /** Sign in again now, skipping the wait for the next automatic retry. */\n retry: () => void;\n /**\n * Force a fresh mint now and resolve the new token (null when it failed).\n * Single-flight: concurrent callers share one mint. The connector\n * transport reaches this through the registered renewer\n * (./sessionRenewal) when the backend condemns the bearer it sent.\n */\n renew: () => Promise<string | null>;\n}\n\nexport function useCanvasSession(): CanvasSession {\n const { orgName, projectId, tagId } = usePrerequisiteIds();\n\n // Local GRAPHQL_URL (localhost) cannot derive a surface-index host, and a\n // locally minted JWT 401s against the cluster index. Same pairing Web\n // Builder uses: mint against CANVAS_BACKEND_GRAPHQL_URL, derive the index\n // from that backend. Staging/prod GRAPHQL_URL already is that backend.\n const canvasGraphqlUrl = useMemo(\n () =>\n resolveSurfaceAuthGraphqlUrl(config.CANVAS_SURFACE_URL, config.GRAPHQL_URL, {\n CANVAS_SURFACE_URL: config.CANVAS_SURFACE_URL,\n CANVAS_BACKEND_GRAPHQL_URL: config.CANVAS_BACKEND_GRAPHQL_URL,\n }),\n [],\n );\n const crossBackendAuth = !backendsEqual(canvasGraphqlUrl, config.GRAPHQL_URL);\n const { obtainSystemToken } = useObtainSystemToken(!crossBackendAuth);\n\n const indexUrl = useMemo(() => {\n const derived = surfaceIndexUrl(canvasGraphqlUrl, config.SURFACE_INDEX_URL);\n if (derived) return derived;\n return surfaceIndexUrlFromTemplate(config.SURFACE_URL_TEMPLATE);\n }, [canvasGraphqlUrl]);\n\n const seeded = getWarmWebBuilderSession(canvasGraphqlUrl);\n const [token, setToken] = useState<string | null>(() => seeded?.token ?? null);\n const [error, setError] = useState<string | null>(null);\n const [ready, setReady] = useState(() => Boolean(seeded?.token));\n\n // org/project arrive a beat after mount; hold the latest in a ref so a\n // resolved id does not restart an in-flight mint.\n const idsRef = useRef({ orgName, projectId, tagId });\n idsRef.current = { orgName, projectId, tagId };\n\n // Renewal machinery. `mint` re-mints the surface token; on success it\n // schedules the next mint just before the JWT's `exp`, so a mounted\n // surface never rides an expired session. `forceFresh` clears the shared\n // warm cache first, so a renewal actually gets a new token rather than the\n // stale cached one (the cache is a cross-surface dedupe for the first\n // mint, not a source of freshness).\n const cancelledRef = useRef(false);\n const renewTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const tokenExpRef = useRef<number | null>(null);\n // Consecutive mint failures, for the self-heal backoff below. Reset to 0 on\n // any successful mint.\n const failuresRef = useRef(0);\n /** The token held right now, for the transport's renewer (state lags a render). */\n const tokenRef = useRef<string | null>(token);\n tokenRef.current = token ?? tokenRef.current;\n /** The forced re-mint in flight, shared by every caller that asks meanwhile. */\n const renewingRef = useRef<Promise<string | null> | null>(null);\n\n const clearRenewTimer = useCallback(() => {\n if (renewTimerRef.current) {\n clearTimeout(renewTimerRef.current);\n renewTimerRef.current = null;\n }\n }, []);\n\n const mint = useCallback(\n async (forceFresh: boolean): Promise<string | null> => {\n // No workspace yet is a not-yet, never a failure: the org/project\n // effect below mints the moment they arrive. Minting without them\n // is how a cross-backend session used to land in the wrong org.\n if (!idsRef.current.orgName || !idsRef.current.projectId) return null;\n if (forceFresh) clearWarmWebBuilderSession();\n try {\n const session = await warmWebBuilderSession({\n graphqlUrl: canvasGraphqlUrl,\n // Cross-backend still passes the app's ids: discovery prefers\n // them whenever the surface backend has them (same backend\n // under another host on prod).\n orgName: idsRef.current.orgName,\n projectId: idsRef.current.projectId,\n tagId: idsRef.current.tagId,\n obtainSystemToken: crossBackendAuth ? undefined : obtainSystemToken,\n discoverScope: crossBackendAuth,\n });\n if (cancelledRef.current) return null;\n tokenRef.current = session.token;\n setToken(session.token);\n setError(null);\n failuresRef.current = 0;\n\n // Schedule the next renewal from the token's own expiry.\n const expMs = tokenExpiryMs(session.token);\n tokenExpRef.current = expMs;\n const delay = expMs\n ? Math.min(MAX_RENEW_DELAY_MS, Math.max(MIN_RENEW_DELAY_MS, expMs - Date.now() - RENEW_LEAD_MS))\n : MAX_RENEW_DELAY_MS;\n clearRenewTimer();\n renewTimerRef.current = setTimeout(() => {\n void mint(true);\n }, delay);\n return session.token;\n } catch (err) {\n if (cancelledRef.current) return null;\n const message = err instanceof Error ? err.message : String(err);\n // Missing org/project is a not-yet, not a failure. The\n // org/project effect re-mints when they arrive, so do not error\n // or schedule a retry here.\n const waitingForIds = /waiting for org\\/project/i.test(message) || !idsRef.current.orgName;\n if (waitingForIds) return null;\n setError(\"Couldn't sign you in.\");\n // Self-heal: a failed mint is usually the Auth0 id_token briefly\n // stale after a background/sleep (the app login token renews on\n // foreground, a beat behind). Retry on a capped exponential\n // backoff with forceFresh, so the surface recovers on its own the\n // moment the login token is fresh again - no force-quit needed.\n const backoff =\n QUICK_RETRY_MS[failuresRef.current] ??\n Math.min(\n MAX_RENEW_DELAY_MS,\n MIN_RENEW_DELAY_MS * 2 ** (failuresRef.current - QUICK_RETRY_MS.length),\n );\n failuresRef.current += 1;\n clearRenewTimer();\n renewTimerRef.current = setTimeout(() => {\n void mint(true);\n }, backoff);\n return null;\n } finally {\n if (!cancelledRef.current) setReady(true);\n }\n },\n [obtainSystemToken, canvasGraphqlUrl, crossBackendAuth, clearRenewTimer],\n );\n\n useEffect(() => {\n cancelledRef.current = false;\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log(\n '[useCanvasSession] graphql=',\n canvasGraphqlUrl,\n 'index=',\n indexUrl,\n 'crossBackend=',\n crossBackendAuth,\n );\n }\n void mint(false);\n\n // iOS suspends timers in the background; a token can lapse while away.\n // On return, re-mint immediately if it is at/near expiry so the first\n // post-foreground index call already carries a fresh JWT.\n const appStateSub = AppState.addEventListener('change', (next) => {\n if (next !== 'active') return;\n const expMs = tokenExpRef.current;\n if (!expMs || Date.now() >= expMs - RENEW_LEAD_MS) void mint(true);\n });\n\n return () => {\n cancelledRef.current = true;\n clearRenewTimer();\n appStateSub.remove();\n };\n }, [mint, canvasGraphqlUrl, indexUrl, crossBackendAuth, clearRenewTimer]);\n\n // First mint can fail while org/project are still hydrating. Retry once they\n // arrive so we do not sit on the spinner until the user leaves and comes back.\n useEffect(() => {\n if (token) return;\n if (!orgName || !projectId) return;\n void mint(false);\n }, [token, orgName, projectId, mint]);\n\n /** Sign in again now, for the \"Try again\" on a surface's error screen. */\n const retry = useCallback(() => {\n failuresRef.current = 0;\n clearRenewTimer();\n void mint(true);\n }, [mint, clearRenewTimer]);\n\n /** Single-flight forced re-mint - what the transport calls when the backend condemns its bearer. */\n const renew = useCallback((): Promise<string | null> => {\n if (renewingRef.current) return renewingRef.current;\n failuresRef.current = 0;\n clearRenewTimer();\n const pending = mint(true)\n .catch(() => null)\n .finally(() => {\n renewingRef.current = null;\n });\n renewingRef.current = pending;\n return pending;\n }, [mint, clearRenewTimer]);\n\n // Hand the transport a way to the fresh token (globalThis bridge: the remote\n // bundle reads it). The latest mounted session wins; unmount removes it.\n useEffect(\n () =>\n registerSessionRenewer({\n current: () => tokenRef.current,\n renew,\n graphqlUrl: canvasGraphqlUrl,\n }),\n [renew, canvasGraphqlUrl],\n );\n\n return { token, indexUrl, graphqlUrl: canvasGraphqlUrl, error, ready, retry, renew };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useState,useRef,useEffect,useCallback,useMemo}from'react';import {loadStudioTemplatePage,uniqueTemplatePage,STUDIO_TEMPLATE_PAGE_SIZE}from'./canvasChatTemplates.js';import {studioCatalogFilter,STUDIO_CATALOG_QUERY,studioTemplatesToCatalogNodes,catalogRowToStudioTemplate}from'./studioCatalog.js';function rowsFromData(data) {
|
|
1
|
+
import {useState,useRef,useEffect,useCallback,useMemo}from'react';import {loadStudioTemplatePage,uniqueTemplatePage,STUDIO_TEMPLATE_PAGE_SIZE}from'./canvasChatTemplates.js';import {isRankedStudioSearch,rankedStudioCatalogPage,studioCatalogFilter,STUDIO_CATALOG_QUERY,studioTemplatesToCatalogNodes,catalogRowToStudioTemplate,apolloCatalogRead}from'./studioCatalog.js';function rowsFromData(data) {
|
|
2
2
|
var _a, _b;
|
|
3
3
|
return ((_b = (_a = data == null ? void 0 : data.formTemplateSubmissions) == null ? void 0 : _a.nodes) != null ? _b : []).map(catalogRowToStudioTemplate).filter((row) => row !== null);
|
|
4
4
|
}
|
|
@@ -31,6 +31,7 @@ function writeCachedTemplates(client, search, rows) {
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
+
const MAX_RANKED_SKIPS = 3;
|
|
34
35
|
function isFullPage(count) {
|
|
35
36
|
return count > 0 && count % STUDIO_TEMPLATE_PAGE_SIZE === 0;
|
|
36
37
|
}
|
|
@@ -48,6 +49,8 @@ function useStudioCatalogTemplates(search, client, runAction, corpus) {
|
|
|
48
49
|
runActionRef.current = runAction;
|
|
49
50
|
const corpusRef = useRef(corpus);
|
|
50
51
|
corpusRef.current = corpus;
|
|
52
|
+
const ranked = Boolean(client) && isRankedStudioSearch(term);
|
|
53
|
+
const rankedNextRef = useRef(void 0);
|
|
51
54
|
useEffect(() => {
|
|
52
55
|
endedRef.current = false;
|
|
53
56
|
setEnded(false);
|
|
@@ -59,23 +62,55 @@ function useStudioCatalogTemplates(search, client, runAction, corpus) {
|
|
|
59
62
|
setLoading(true);
|
|
60
63
|
}
|
|
61
64
|
let live = true;
|
|
62
|
-
|
|
65
|
+
rankedNextRef.current = void 0;
|
|
66
|
+
const plain = () => loadStudioTemplatePage(term || void 0, 0, runActionRef.current, corpusRef.current).then((page) => {
|
|
63
67
|
if (!live) return;
|
|
64
68
|
setTemplates(page.rows);
|
|
65
69
|
writeCachedTemplates(client, term, page.rows);
|
|
66
|
-
})
|
|
70
|
+
});
|
|
71
|
+
const first = ranked && client ? rankedStudioCatalogPage(term, 0, apolloCatalogRead(client)).then((page) => {
|
|
72
|
+
if (!live) return;
|
|
73
|
+
rankedNextRef.current = page.next;
|
|
74
|
+
const done = page.next === null;
|
|
75
|
+
endedRef.current = done;
|
|
76
|
+
setEnded(done);
|
|
77
|
+
setTemplates(page.rows);
|
|
78
|
+
writeCachedTemplates(client, term, page.rows);
|
|
79
|
+
}).catch(plain) : plain();
|
|
80
|
+
void first.catch(() => void 0).finally(() => {
|
|
67
81
|
if (live) setLoading(false);
|
|
68
82
|
});
|
|
69
83
|
return () => {
|
|
70
84
|
live = false;
|
|
71
85
|
};
|
|
72
|
-
}, [client, term]);
|
|
86
|
+
}, [client, ranked, term]);
|
|
73
87
|
const loadMore = useCallback(() => {
|
|
74
88
|
const already = templatesRef.current;
|
|
75
89
|
if (loadMoreLock.current || already.length === 0) return;
|
|
76
90
|
loadMoreLock.current = true;
|
|
77
91
|
setLoadingMore(true);
|
|
78
92
|
void (async () => {
|
|
93
|
+
if (ranked && client && rankedNextRef.current !== void 0) {
|
|
94
|
+
const seen = new Set(already.map((row) => row.id));
|
|
95
|
+
let fresh = [];
|
|
96
|
+
const read = apolloCatalogRead(client);
|
|
97
|
+
for (let i = 0; i < MAX_RANKED_SKIPS && fresh.length === 0; i++) {
|
|
98
|
+
const from = rankedNextRef.current;
|
|
99
|
+
if (from === null || from === void 0) break;
|
|
100
|
+
const page = await rankedStudioCatalogPage(term, from, read);
|
|
101
|
+
rankedNextRef.current = page.next;
|
|
102
|
+
fresh = page.rows.filter((row) => !seen.has(row.id));
|
|
103
|
+
}
|
|
104
|
+
const done = rankedNextRef.current === null;
|
|
105
|
+
endedRef.current = done || fresh.length === 0;
|
|
106
|
+
setEnded(endedRef.current);
|
|
107
|
+
if (fresh.length === 0) return;
|
|
108
|
+
const merged2 = [...already, ...fresh];
|
|
109
|
+
templatesRef.current = merged2;
|
|
110
|
+
setTemplates(merged2);
|
|
111
|
+
writeCachedTemplates(client, term, merged2);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
79
114
|
let incoming = [];
|
|
80
115
|
if (client) {
|
|
81
116
|
try {
|
|
@@ -116,9 +151,10 @@ function useStudioCatalogTemplates(search, client, runAction, corpus) {
|
|
|
116
151
|
loadMoreLock.current = false;
|
|
117
152
|
setLoadingMore(false);
|
|
118
153
|
});
|
|
119
|
-
}, [client, term]);
|
|
154
|
+
}, [client, ranked, term]);
|
|
120
155
|
const hydrate = useCallback((rows, _offset) => {
|
|
121
156
|
setTemplates([...rows]);
|
|
157
|
+
rankedNextRef.current = void 0;
|
|
122
158
|
endedRef.current = !isFullPage(rows.length);
|
|
123
159
|
setEnded(!isFullPage(rows.length));
|
|
124
160
|
writeCachedTemplates(client, term, rows);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStudioCatalogTemplates.js","sources":["../../../src/features/canvas/useStudioCatalogTemplates.ts"],"sourcesContent":["import type { ApolloClient } from '@apollo/client';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { RunMediaAction } from './videoEditor/mediaActions';\nimport { loadStudioTemplatePage, uniqueTemplatePage, type CanvasPromptTemplate } from './canvasChatTemplates';\nimport { STUDIO_TEMPLATE_PAGE_SIZE } from './canvasChatTemplates';\nimport {\n STUDIO_CATALOG_QUERY,\n catalogRowToStudioTemplate,\n studioCatalogFilter,\n studioTemplatesToCatalogNodes,\n type StudioCatalogRow,\n} from './studioCatalog';\n\ninterface StudioCatalogData {\n formTemplateSubmissions?: { nodes?: StudioCatalogRow[] | null } | null;\n}\n\n/** Host Apollo client — passed in so the federated remote writes the host cache. */\nexport type StudioCatalogClient = Pick<ApolloClient<object>, 'readQuery' | 'writeQuery' | 'query'>;\n\nfunction rowsFromData(data: StudioCatalogData | null | undefined): CanvasPromptTemplate[] {\n return (data?.formTemplateSubmissions?.nodes ?? [])\n .map(catalogRowToStudioTemplate)\n .filter((row): row is CanvasPromptTemplate => row !== null);\n}\n\nfunction readCachedTemplates(client: StudioCatalogClient | null | undefined, search: string): CanvasPromptTemplate[] {\n if (!client) return [];\n try {\n const data = client.readQuery<StudioCatalogData>({\n query: STUDIO_CATALOG_QUERY,\n variables: { filter: studioCatalogFilter(search, 0) },\n });\n return rowsFromData(data);\n } catch {\n return [];\n }\n}\n\nfunction writeCachedTemplates(\n client: StudioCatalogClient | null | undefined,\n search: string,\n rows: readonly CanvasPromptTemplate[],\n) {\n if (!client) return;\n client.writeQuery({\n query: STUDIO_CATALOG_QUERY,\n variables: { filter: studioCatalogFilter(search, 0) },\n data: {\n formTemplateSubmissions: {\n __typename: 'FormTemplateSubmissionConnection',\n nodes: studioTemplatesToCatalogNodes(rows),\n },\n },\n });\n}\n\nfunction isFullPage(count: number): boolean {\n return count > 0 && count % STUDIO_TEMPLATE_PAGE_SIZE === 0;\n}\n\nexport function useStudioCatalogTemplates(\n search: string,\n client: StudioCatalogClient | null | undefined,\n runAction: RunMediaAction | undefined,\n corpus: CanvasPromptTemplate[],\n) {\n const term = search.trim();\n const [templates, setTemplates] = useState<CanvasPromptTemplate[]>(() => readCachedTemplates(client, term));\n const [loading, setLoading] = useState(() => readCachedTemplates(client, term).length === 0);\n const [loadingMore, setLoadingMore] = useState(false);\n const [ended, setEnded] = useState(false);\n const templatesRef = useRef(templates);\n templatesRef.current = templates;\n const endedRef = useRef(false);\n const loadMoreLock = useRef(false);\n const runActionRef = useRef(runAction);\n runActionRef.current = runAction;\n const corpusRef = useRef(corpus);\n corpusRef.current = corpus;\n\n useEffect(() => {\n endedRef.current = false;\n setEnded(false);\n const cached = readCachedTemplates(client, term);\n if (cached.length > 0) {\n setTemplates(cached);\n setLoading(false);\n } else {\n setLoading(true);\n }\n let live = true;\n void loadStudioTemplatePage(term || undefined, 0, runActionRef.current, corpusRef.current)\n .then((page) => {\n if (!live) return;\n setTemplates(page.rows);\n writeCachedTemplates(client, term, page.rows);\n })\n .finally(() => {\n if (live) setLoading(false);\n });\n return () => {\n live = false;\n };\n }, [client, term]);\n\n const loadMore = useCallback(() => {\n const already = templatesRef.current;\n if (loadMoreLock.current || already.length === 0) return;\n loadMoreLock.current = true;\n setLoadingMore(true);\n void (async () => {\n let incoming: CanvasPromptTemplate[] = [];\n if (client) {\n try {\n const { data } = await client.query({\n query: STUDIO_CATALOG_QUERY,\n variables: { filter: studioCatalogFilter(term, already.length) },\n fetchPolicy: 'network-only',\n });\n incoming = rowsFromData(data as StudioCatalogData);\n } catch {\n incoming = [];\n }\n }\n let next = uniqueTemplatePage(already, incoming, [], term || undefined);\n if (next.rows.length === 0) {\n const page = await loadStudioTemplatePage(\n term || undefined,\n already.length,\n runActionRef.current,\n corpusRef.current,\n );\n next = uniqueTemplatePage(already, page.rows, corpusRef.current, term || undefined);\n }\n if (next.rows.length === 0) {\n endedRef.current = true;\n setEnded(true);\n return;\n }\n endedRef.current = false;\n setEnded(false);\n const merged = [...already, ...next.rows];\n templatesRef.current = merged;\n setTemplates(merged);\n writeCachedTemplates(client, term, merged);\n })()\n .catch(() => {\n endedRef.current = true;\n setEnded(true);\n })\n .finally(() => {\n loadMoreLock.current = false;\n setLoadingMore(false);\n });\n }, [client, term]);\n\n const hydrate = useCallback(\n (rows: readonly CanvasPromptTemplate[], _offset: number) => {\n setTemplates([...rows]);\n endedRef.current = !isFullPage(rows.length);\n setEnded(!isFullPage(rows.length));\n writeCachedTemplates(client, term, rows);\n },\n [client, term],\n );\n\n return useMemo(\n () => ({\n templates,\n loading: loading && templates.length === 0,\n loadingMore,\n hasMore: !ended,\n loadMore,\n hydrate,\n }),\n [ended, hydrate, loadMore, loading, loadingMore, templates],\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useStudioCatalogTemplates.js","sources":["../../../src/features/canvas/useStudioCatalogTemplates.ts"],"sourcesContent":["import type { ApolloClient } from '@apollo/client';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { RunMediaAction } from './videoEditor/mediaActions';\nimport { loadStudioTemplatePage, uniqueTemplatePage, type CanvasPromptTemplate } from './canvasChatTemplates';\nimport { STUDIO_TEMPLATE_PAGE_SIZE } from './canvasChatTemplates';\nimport {\n STUDIO_CATALOG_QUERY,\n apolloCatalogRead,\n catalogRowToStudioTemplate,\n isRankedStudioSearch,\n rankedStudioCatalogPage,\n studioCatalogFilter,\n studioTemplatesToCatalogNodes,\n type StudioCatalogRow,\n} from './studioCatalog';\n\ninterface StudioCatalogData {\n formTemplateSubmissions?: { nodes?: StudioCatalogRow[] | null } | null;\n}\n\n/** Host Apollo client — passed in so the federated remote writes the host cache. */\nexport type StudioCatalogClient = Pick<ApolloClient<object>, 'readQuery' | 'writeQuery' | 'query'>;\n\nfunction rowsFromData(data: StudioCatalogData | null | undefined): CanvasPromptTemplate[] {\n return (data?.formTemplateSubmissions?.nodes ?? [])\n .map(catalogRowToStudioTemplate)\n .filter((row): row is CanvasPromptTemplate => row !== null);\n}\n\nfunction readCachedTemplates(client: StudioCatalogClient | null | undefined, search: string): CanvasPromptTemplate[] {\n if (!client) return [];\n try {\n const data = client.readQuery<StudioCatalogData>({\n query: STUDIO_CATALOG_QUERY,\n variables: { filter: studioCatalogFilter(search, 0) },\n });\n return rowsFromData(data);\n } catch {\n return [];\n }\n}\n\nfunction writeCachedTemplates(\n client: StudioCatalogClient | null | undefined,\n search: string,\n rows: readonly CanvasPromptTemplate[],\n) {\n if (!client) return;\n client.writeQuery({\n query: STUDIO_CATALOG_QUERY,\n variables: { filter: studioCatalogFilter(search, 0) },\n data: {\n formTemplateSubmissions: {\n __typename: 'FormTemplateSubmissionConnection',\n nodes: studioTemplatesToCatalogNodes(rows),\n },\n },\n });\n}\n\n/** Ranked pages read until one adds a template not listed yet (a page may hold only duplicates). */\nconst MAX_RANKED_SKIPS = 3;\n\nfunction isFullPage(count: number): boolean {\n return count > 0 && count % STUDIO_TEMPLATE_PAGE_SIZE === 0;\n}\n\nexport function useStudioCatalogTemplates(\n search: string,\n client: StudioCatalogClient | null | undefined,\n runAction: RunMediaAction | undefined,\n corpus: CanvasPromptTemplate[],\n) {\n const term = search.trim();\n const [templates, setTemplates] = useState<CanvasPromptTemplate[]>(() => readCachedTemplates(client, term));\n const [loading, setLoading] = useState(() => readCachedTemplates(client, term).length === 0);\n const [loadingMore, setLoadingMore] = useState(false);\n const [ended, setEnded] = useState(false);\n const templatesRef = useRef(templates);\n templatesRef.current = templates;\n const endedRef = useRef(false);\n const loadMoreLock = useRef(false);\n const runActionRef = useRef(runAction);\n runActionRef.current = runAction;\n const corpusRef = useRef(corpus);\n corpusRef.current = corpus;\n // A typed search ranks (surface-kit 0.43 ranked catalog search); no search keeps plain paging.\n const ranked = Boolean(client) && isRankedStudioSearch(term);\n /** Where the next ranked page starts: undefined = not ranked (plain paging), null = the end. */\n const rankedNextRef = useRef<number | null | undefined>(undefined);\n\n useEffect(() => {\n endedRef.current = false;\n setEnded(false);\n const cached = readCachedTemplates(client, term);\n if (cached.length > 0) {\n setTemplates(cached);\n setLoading(false);\n } else {\n setLoading(true);\n }\n let live = true;\n rankedNextRef.current = undefined;\n const plain = () =>\n loadStudioTemplatePage(term || undefined, 0, runActionRef.current, corpusRef.current).then((page) => {\n if (!live) return;\n setTemplates(page.rows);\n writeCachedTemplates(client, term, page.rows);\n });\n const first =\n ranked && client\n ? rankedStudioCatalogPage(term, 0, apolloCatalogRead(client))\n .then((page) => {\n if (!live) return;\n rankedNextRef.current = page.next;\n const done = page.next === null;\n endedRef.current = done;\n setEnded(done);\n setTemplates(page.rows);\n writeCachedTemplates(client, term, page.rows);\n })\n .catch(plain)\n : plain();\n void first\n .catch(() => undefined)\n .finally(() => {\n if (live) setLoading(false);\n });\n return () => {\n live = false;\n };\n }, [client, ranked, term]);\n\n const loadMore = useCallback(() => {\n const already = templatesRef.current;\n if (loadMoreLock.current || already.length === 0) return;\n loadMoreLock.current = true;\n setLoadingMore(true);\n void (async () => {\n if (ranked && client && rankedNextRef.current !== undefined) {\n const seen = new Set(already.map((row) => row.id));\n let fresh: CanvasPromptTemplate[] = [];\n const read = apolloCatalogRead(client);\n for (let i = 0; i < MAX_RANKED_SKIPS && fresh.length === 0; i++) {\n const from = rankedNextRef.current;\n if (from === null || from === undefined) break;\n const page = await rankedStudioCatalogPage(term, from, read);\n rankedNextRef.current = page.next;\n fresh = page.rows.filter((row) => !seen.has(row.id));\n }\n const done = rankedNextRef.current === null;\n endedRef.current = done || fresh.length === 0;\n setEnded(endedRef.current);\n if (fresh.length === 0) return;\n const merged = [...already, ...fresh];\n templatesRef.current = merged;\n setTemplates(merged);\n writeCachedTemplates(client, term, merged);\n return;\n }\n let incoming: CanvasPromptTemplate[] = [];\n if (client) {\n try {\n const { data } = await client.query({\n query: STUDIO_CATALOG_QUERY,\n variables: { filter: studioCatalogFilter(term, already.length) },\n fetchPolicy: 'network-only',\n });\n incoming = rowsFromData(data as StudioCatalogData);\n } catch {\n incoming = [];\n }\n }\n let next = uniqueTemplatePage(already, incoming, [], term || undefined);\n if (next.rows.length === 0) {\n const page = await loadStudioTemplatePage(\n term || undefined,\n already.length,\n runActionRef.current,\n corpusRef.current,\n );\n next = uniqueTemplatePage(already, page.rows, corpusRef.current, term || undefined);\n }\n if (next.rows.length === 0) {\n endedRef.current = true;\n setEnded(true);\n return;\n }\n endedRef.current = false;\n setEnded(false);\n const merged = [...already, ...next.rows];\n templatesRef.current = merged;\n setTemplates(merged);\n writeCachedTemplates(client, term, merged);\n })()\n .catch(() => {\n endedRef.current = true;\n setEnded(true);\n })\n .finally(() => {\n loadMoreLock.current = false;\n setLoadingMore(false);\n });\n }, [client, ranked, term]);\n\n const hydrate = useCallback(\n (rows: readonly CanvasPromptTemplate[], _offset: number) => {\n setTemplates([...rows]);\n rankedNextRef.current = undefined;\n endedRef.current = !isFullPage(rows.length);\n setEnded(!isFullPage(rows.length));\n writeCachedTemplates(client, term, rows);\n },\n [client, term],\n );\n\n return useMemo(\n () => ({\n templates,\n loading: loading && templates.length === 0,\n loadingMore,\n hasMore: !ended,\n loadMore,\n hydrate,\n }),\n [ended, hydrate, loadMore, loading, loadingMore, templates],\n );\n}\n"],"names":["merged"],"mappings":"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"}
|