@parhelia/core 0.1.12554 → 0.1.12555
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents-view/AgentCard.d.ts +4 -6
- package/dist/agents-view/AgentCard.js +24 -143
- package/dist/agents-view/AgentCard.js.map +1 -1
- package/dist/agents-view/AgentsInbox.d.ts +1 -1
- package/dist/agents-view/AgentsInbox.js +92 -7
- package/dist/agents-view/AgentsInbox.js.map +1 -1
- package/dist/agents-view/AgentsTitlebar.js +2 -3
- package/dist/agents-view/AgentsTitlebar.js.map +1 -1
- package/dist/agents-view/AgentsView.d.ts +7 -6
- package/dist/agents-view/AgentsView.js +98 -187
- package/dist/agents-view/AgentsView.js.map +1 -1
- package/dist/agents-view/AgentsWorkspaceView.d.ts +6 -2
- package/dist/agents-view/AgentsWorkspaceView.js +113 -266
- package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
- package/dist/agents-view/ProfileAgentsGroup.d.ts +1 -2
- package/dist/agents-view/ProfileAgentsGroup.js +3 -4
- package/dist/agents-view/ProfileAgentsGroup.js.map +1 -1
- package/dist/components/ActionButton.d.ts +1 -1
- package/dist/components/ActionButton.js.map +1 -1
- package/dist/components/FilterInput.d.ts +1 -1
- package/dist/components/FilterInput.js +1 -1
- package/dist/components/FilterInput.js.map +1 -1
- package/dist/components/ui/LanguageSelector.js +4 -2
- package/dist/components/ui/LanguageSelector.js.map +1 -1
- package/dist/components/ui/PlaceholderInput.js +3 -3
- package/dist/components/ui/PlaceholderInput.js.map +1 -1
- package/dist/components/ui/PlaceholderInputTypes.js +1 -1
- package/dist/components/ui/PlaceholderInputTypes.js.map +1 -1
- package/dist/components/ui/alert-dialog.d.ts +1 -1
- package/dist/components/ui/alert-dialog.js +10 -6
- package/dist/components/ui/alert-dialog.js.map +1 -1
- package/dist/components/ui/button.d.ts +4 -4
- package/dist/components/ui/button.js +1 -4
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/context-menu.d.ts +1 -1
- package/dist/components/ui/context-menu.js +4 -12
- package/dist/components/ui/context-menu.js.map +1 -1
- package/dist/components/ui/copy-button.d.ts +1 -2
- package/dist/components/ui/copy-button.js +2 -2
- package/dist/components/ui/copy-button.js.map +1 -1
- package/dist/components/ui/dialog.d.ts +1 -1
- package/dist/components/ui/dialog.js +126 -21
- package/dist/components/ui/dialog.js.map +1 -1
- package/dist/components/ui/input.d.ts +1 -1
- package/dist/components/ui/input.js +3 -5
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/paste-button.d.ts +1 -2
- package/dist/components/ui/paste-button.js +2 -2
- package/dist/components/ui/paste-button.js.map +1 -1
- package/dist/components/ui/popover.js +9 -1
- package/dist/components/ui/popover.js.map +1 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/select.js.map +1 -1
- package/dist/components/ui/styled-dialog-title.js +1 -1
- package/dist/components/ui/styled-dialog-title.js.map +1 -1
- package/dist/components/ui/tabs.d.ts +1 -1
- package/dist/components/ui/tabs.js +11 -4
- package/dist/components/ui/tabs.js.map +1 -1
- package/dist/config/config.d.ts +2 -4
- package/dist/config/config.js +70 -250
- package/dist/config/config.js.map +1 -1
- package/dist/config/types/workspace.d.ts +0 -6
- package/dist/config/types.d.ts +12 -63
- package/dist/config/types.js.map +1 -1
- package/dist/editor/ComponentInfo.d.ts +4 -0
- package/dist/editor/ComponentInfo.js +41 -0
- package/dist/editor/ComponentInfo.js.map +1 -0
- package/dist/editor/ConfirmationDialog.js +4 -20
- package/dist/editor/ConfirmationDialog.js.map +1 -1
- package/dist/editor/ContentTree.d.ts +1 -2
- package/dist/editor/ContentTree.js +32 -93
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/Editor.js +22 -87
- package/dist/editor/Editor.js.map +1 -1
- package/dist/editor/FieldHistory.js +36 -84
- package/dist/editor/FieldHistory.js.map +1 -1
- package/dist/editor/FieldListField.js +9 -21
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/FieldListFieldWithFallbacks.js +2 -23
- package/dist/editor/FieldListFieldWithFallbacks.js.map +1 -1
- package/dist/editor/GlobalMenuBar.js +2 -29
- package/dist/editor/GlobalMenuBar.js.map +1 -1
- package/dist/editor/ImageEditor.js +2 -5
- package/dist/editor/ImageEditor.js.map +1 -1
- package/dist/editor/ItemInfo.js +1 -36
- package/dist/editor/ItemInfo.js.map +1 -1
- package/dist/editor/LinkEditorDialog.js +0 -3
- package/dist/editor/LinkEditorDialog.js.map +1 -1
- package/dist/editor/MainLayout.d.ts +2 -0
- package/dist/editor/MainLayout.js +8 -65
- package/dist/editor/MainLayout.js.map +1 -1
- package/dist/editor/MigrationsView.js +5 -29
- package/dist/editor/MigrationsView.js.map +1 -1
- package/dist/editor/MobileLayout.js +12 -37
- package/dist/editor/MobileLayout.js.map +1 -1
- package/dist/editor/PictureCropper.js +45 -54
- package/dist/editor/PictureCropper.js.map +1 -1
- package/dist/editor/PictureEditor.js +15 -17
- package/dist/editor/PictureEditor.js.map +1 -1
- package/dist/editor/QuickItemSwitcher.js +21 -21
- package/dist/editor/QuickItemSwitcher.js.map +1 -1
- package/dist/editor/SetupWizard.js +12 -52
- package/dist/editor/SetupWizard.js.map +1 -1
- package/dist/editor/Titlebar.js +2 -7
- package/dist/editor/Titlebar.js.map +1 -1
- package/dist/editor/ai/AgentCostDisplay.d.ts +0 -1
- package/dist/editor/ai/AgentCostDisplay.js +1 -1
- package/dist/editor/ai/AgentCostDisplay.js.map +1 -1
- package/dist/editor/ai/AgentDocumentList.js +14 -32
- package/dist/editor/ai/AgentDocumentList.js.map +1 -1
- package/dist/editor/ai/AgentGreeting.js +2 -3
- package/dist/editor/ai/AgentGreeting.js.map +1 -1
- package/dist/editor/ai/AgentProfileSelector.js +1 -2
- package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
- package/dist/editor/ai/AgentStatusBadge.d.ts +5 -0
- package/dist/editor/ai/AgentStatusBadge.js +65 -67
- package/dist/editor/ai/AgentStatusBadge.js.map +1 -1
- package/dist/editor/ai/AgentTerminal.d.ts +2 -14
- package/dist/editor/ai/AgentTerminal.js +483 -2377
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/AgentTerminalStatusBar.d.ts +3 -8
- package/dist/editor/ai/AgentTerminalStatusBar.js +56 -460
- package/dist/editor/ai/AgentTerminalStatusBar.js.map +1 -1
- package/dist/editor/ai/Agents.js +113 -150
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.d.ts +1 -10
- package/dist/editor/ai/AiResponseMessage.js +23 -238
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/ContextInfoBar.d.ts +3 -2
- package/dist/editor/ai/ContextInfoBar.js +7 -64
- package/dist/editor/ai/ContextInfoBar.js.map +1 -1
- package/dist/editor/ai/GuidanceOverlay.js +11 -17
- package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
- package/dist/editor/ai/HelpTerminal.d.ts +5 -0
- package/dist/editor/ai/HelpTerminal.js +166 -0
- package/dist/editor/ai/HelpTerminal.js.map +1 -0
- package/dist/editor/ai/InlineAiDialog.d.ts +1 -1
- package/dist/editor/ai/InlineAiDialog.js +192 -514
- package/dist/editor/ai/InlineAiDialog.js.map +1 -1
- package/dist/editor/ai/InlineAiTrigger.js +12 -115
- package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
- package/dist/editor/ai/MediaImage.js +8 -40
- package/dist/editor/ai/MediaImage.js.map +1 -1
- package/dist/editor/ai/SpawnedAgentsPanel.js +12 -10
- package/dist/editor/ai/SpawnedAgentsPanel.js.map +1 -1
- package/dist/editor/ai/ToolCallDisplay.d.ts +2 -22
- package/dist/editor/ai/ToolCallDisplay.js +147 -518
- package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
- package/dist/editor/ai/dialogs/AgentDialogHandler.d.ts +8 -1
- package/dist/editor/ai/dialogs/AgentDialogHandler.js +42 -379
- package/dist/editor/ai/dialogs/AgentDialogHandler.js.map +1 -1
- package/dist/editor/ai/dialogs/QuestionnaireInline.d.ts +1 -5
- package/dist/editor/ai/dialogs/QuestionnaireInline.js +60 -628
- package/dist/editor/ai/dialogs/QuestionnaireInline.js.map +1 -1
- package/dist/editor/ai/dialogs/agentDialogTypes.d.ts +0 -115
- package/dist/editor/ai/dialogs/agentDialogTypes.js +0 -2
- package/dist/editor/ai/dialogs/agentDialogTypes.js.map +1 -1
- package/dist/editor/ai/types.d.ts +1 -3
- package/dist/editor/ai/useAgentStatus.d.ts +1 -2
- package/dist/editor/ai/useAgentStatus.js +99 -86
- package/dist/editor/ai/useAgentStatus.js.map +1 -1
- package/dist/editor/ai/useInlineAiPosition.js +5 -45
- package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
- package/dist/editor/client/AboutDialog.js +2 -4
- package/dist/editor/client/AboutDialog.js.map +1 -1
- package/dist/editor/client/EditorShell.d.ts +1 -4
- package/dist/editor/client/EditorShell.js +230 -730
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +19 -33
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/helpers.js +0 -6
- package/dist/editor/client/helpers.js.map +1 -1
- package/dist/editor/client/hooks/useEditorUrlSync.js +2 -1
- package/dist/editor/client/hooks/useEditorUrlSync.js.map +1 -1
- package/dist/editor/client/hooks/useEditorWebSocket.d.ts +0 -10
- package/dist/editor/client/hooks/useEditorWebSocket.js +14 -209
- package/dist/editor/client/hooks/useEditorWebSocket.js.map +1 -1
- package/dist/editor/client/hooks/useQuota.d.ts +0 -8
- package/dist/editor/client/hooks/useQuota.js.map +1 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js +7 -68
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/itemsRepository.js +6 -10
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/client/operations.d.ts +3 -6
- package/dist/editor/client/operations.js +30 -208
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/client/pageModelBuilder.js +31 -4
- package/dist/editor/client/pageModelBuilder.js.map +1 -1
- package/dist/editor/client/ui/DevModeIndicator.js +2 -2
- package/dist/editor/client/ui/DevModeIndicator.js.map +1 -1
- package/dist/editor/client/ui/EditorChrome.d.ts +6 -0
- package/dist/editor/client/ui/EditorChrome.js +72 -55
- package/dist/editor/client/ui/EditorChrome.js.map +1 -1
- package/dist/editor/client/ui/FullscreenControls.js +3 -5
- package/dist/editor/client/ui/FullscreenControls.js.map +1 -1
- package/dist/editor/commands/commands.d.ts +1 -11
- package/dist/editor/commands/commands.js +1 -12
- package/dist/editor/commands/commands.js.map +1 -1
- package/dist/editor/commands/componentCommands.js +55 -109
- package/dist/editor/commands/componentCommands.js.map +1 -1
- package/dist/editor/commands/customCommandConverter.d.ts +1 -8
- package/dist/editor/commands/customCommandConverter.js +5 -35
- package/dist/editor/commands/customCommandConverter.js.map +1 -1
- package/dist/editor/commands/handlers/agentHandler.js +1 -2
- package/dist/editor/commands/handlers/agentHandler.js.map +1 -1
- package/dist/editor/commands/itemCommands.d.ts +0 -3
- package/dist/editor/commands/itemCommands.js +10 -93
- package/dist/editor/commands/itemCommands.js.map +1 -1
- package/dist/editor/commands/undo.d.ts +15 -9
- package/dist/editor/commands/undo.js +0 -24
- package/dist/editor/commands/undo.js.map +1 -1
- package/dist/editor/context-menu/InsertMenu.js +39 -83
- package/dist/editor/context-menu/InsertMenu.js.map +1 -1
- package/dist/editor/field-types/MultiLineText.js +1 -1
- package/dist/editor/field-types/MultiLineText.js.map +1 -1
- package/dist/editor/field-types/RawEditor.js +1 -1
- package/dist/editor/field-types/ReactQuill.d.ts +125 -0
- package/dist/editor/field-types/ReactQuill.js +385 -0
- package/dist/editor/field-types/ReactQuill.js.map +1 -0
- package/dist/editor/field-types/RichTextEditor.js +5 -13
- package/dist/editor/field-types/RichTextEditor.js.map +1 -1
- package/dist/editor/field-types/RichTextEditorComponent.js +3 -37
- package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js +1 -1
- package/dist/editor/field-types/TreeListEditor.js +2 -3
- package/dist/editor/field-types/TreeListEditor.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ReactSlate.css +5 -23
- package/dist/editor/field-types/richtext/components/ReactSlate.d.ts +0 -2
- package/dist/editor/field-types/richtext/components/ReactSlate.js +4 -28
- package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ToolbarButton.js +2 -4
- package/dist/editor/field-types/richtext/components/ToolbarButton.js.map +1 -1
- package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +0 -13
- package/dist/editor/field-types/richtext/contextMenuFactory.js +24 -181
- package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
- package/dist/editor/field-types/richtext/types.d.ts +0 -2
- package/dist/editor/field-types/richtext/types.js.map +1 -1
- package/dist/editor/field-types/richtext/utils/plugins.js +0 -4
- package/dist/editor/field-types/richtext/utils/plugins.js.map +1 -1
- package/dist/editor/field-types/textContextMenuFactory.js +2 -3
- package/dist/editor/field-types/textContextMenuFactory.js.map +1 -1
- package/dist/editor/media-selector/AiImageSearchPrompt.js +2 -4
- package/dist/editor/media-selector/AiImageSearchPrompt.js.map +1 -1
- package/dist/editor/media-selector/MediaFolderBrowser.js +1 -1
- package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
- package/dist/editor/media-selector/MediaSelector.js +1 -7
- package/dist/editor/media-selector/MediaSelector.js.map +1 -1
- package/dist/editor/media-selector/TreeSelector.js +35 -40
- package/dist/editor/media-selector/TreeSelector.js.map +1 -1
- package/dist/editor/menubar/ActiveUsers.js +1 -1
- package/dist/editor/menubar/ActiveUsers.js.map +1 -1
- package/dist/editor/menubar/GenericToolbar.js +2 -4
- package/dist/editor/menubar/GenericToolbar.js.map +1 -1
- package/dist/editor/menubar/ItemLanguageVersion.js +2 -2
- package/dist/editor/menubar/ItemLanguageVersion.js.map +1 -1
- package/dist/editor/menubar/PageSelector.js +147 -26
- package/dist/editor/menubar/PageSelector.js.map +1 -1
- package/dist/editor/menubar/Separator.js +1 -1
- package/dist/editor/menubar/VersionSelector.js +4 -2
- package/dist/editor/menubar/VersionSelector.js.map +1 -1
- package/dist/editor/menubar/WorkflowButton.js +12 -39
- package/dist/editor/menubar/WorkflowButton.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js +38 -16
- package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/EditControls.js +3 -3
- package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/HelpButton.js +0 -1
- package/dist/editor/menubar/toolbar-sections/HelpButton.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.d.ts +10 -6
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +220 -597
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js +2 -13
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlighting.js +1 -42
- package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/InlineEditor.js +48 -97
- package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +17 -38
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +11 -17
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js +301 -301
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -1
- package/dist/editor/page-viewer/DeviceToolbar.js +1 -1
- package/dist/editor/page-viewer/DeviceToolbar.js.map +1 -1
- package/dist/editor/page-viewer/EditorForm.js +11 -69
- package/dist/editor/page-viewer/EditorForm.js.map +1 -1
- package/dist/editor/page-viewer/MiniMap.d.ts +4 -2
- package/dist/editor/page-viewer/MiniMap.js +28 -91
- package/dist/editor/page-viewer/MiniMap.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.d.ts +1 -3
- package/dist/editor/page-viewer/PageViewer.js +19 -92
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.d.ts +1 -2
- package/dist/editor/page-viewer/PageViewerFrame.js +115 -348
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +49 -114
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -1
- package/dist/editor/page-viewer/pageViewContext.d.ts +0 -1
- package/dist/editor/page-viewer/pageViewContext.js +14 -51
- package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
- package/dist/editor/pageModel.d.ts +1 -14
- package/dist/editor/reviews/Comment.js +12 -26
- package/dist/editor/reviews/Comment.js.map +1 -1
- package/dist/editor/reviews/CommentDisplayPopover.js +5 -7
- package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/CommentView.js +4 -19
- package/dist/editor/reviews/CommentView.js.map +1 -1
- package/dist/editor/reviews/Comments.js +72 -89
- package/dist/editor/reviews/Comments.js.map +1 -1
- package/dist/editor/reviews/CreateReviewDialog.js +177 -281
- package/dist/editor/reviews/CreateReviewDialog.js.map +1 -1
- package/dist/editor/reviews/DecisionsMatrix.js +25 -96
- package/dist/editor/reviews/DecisionsMatrix.js.map +1 -1
- package/dist/editor/reviews/DiffView.js +14 -7
- package/dist/editor/reviews/DiffView.js.map +1 -1
- package/dist/editor/reviews/EditReviewSettingsDialog.js +4 -6
- package/dist/editor/reviews/EditReviewSettingsDialog.js.map +1 -1
- package/dist/editor/reviews/MultiReviewManager.js +3 -25
- package/dist/editor/reviews/MultiReviewManager.js.map +1 -1
- package/dist/editor/reviews/PagesPanel.js +15 -31
- package/dist/editor/reviews/PagesPanel.js.map +1 -1
- package/dist/editor/reviews/PreviewInfo.js +4 -1
- package/dist/editor/reviews/PreviewInfo.js.map +1 -1
- package/dist/editor/reviews/ReviewCard.js +7 -13
- package/dist/editor/reviews/ReviewCard.js.map +1 -1
- package/dist/editor/reviews/ReviewDetail.js +2 -3
- package/dist/editor/reviews/ReviewDetail.js.map +1 -1
- package/dist/editor/reviews/ReviewsList.js +3 -7
- package/dist/editor/reviews/ReviewsList.js.map +1 -1
- package/dist/editor/reviews/SuggestedEdit.js +3 -34
- package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
- package/dist/editor/reviews/SuggestionDisplayPopover.js +5 -31
- package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/commentAi.js +6 -25
- package/dist/editor/reviews/commentAi.js.map +1 -1
- package/dist/editor/reviews/reviewCommands.js +1 -4
- package/dist/editor/reviews/reviewCommands.js.map +1 -1
- package/dist/editor/reviews/useMultiReview.js +2 -2
- package/dist/editor/reviews/useMultiReview.js.map +1 -1
- package/dist/editor/reviews/useReviews.d.ts +2 -2
- package/dist/editor/reviews/useReviews.js +30 -12
- package/dist/editor/reviews/useReviews.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +5 -229
- package/dist/editor/services/agentService.js +39 -292
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +1 -57
- package/dist/editor/services/aiService.js +6 -79
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/services/contentService.d.ts +3 -6
- package/dist/editor/services/contentService.js +12 -13
- package/dist/editor/services/contentService.js.map +1 -1
- package/dist/editor/services/editService.d.ts +1 -52
- package/dist/editor/services/editService.js +2 -94
- package/dist/editor/services/editService.js.map +1 -1
- package/dist/editor/services/indexService.js +1 -1
- package/dist/editor/services/indexService.js.map +1 -1
- package/dist/editor/services/reviewsService.d.ts +6 -3
- package/dist/editor/services/reviewsService.js +11 -2
- package/dist/editor/services/reviewsService.js.map +1 -1
- package/dist/editor/services/serviceHelper.d.ts +1 -2
- package/dist/editor/services/serviceHelper.js +20 -112
- package/dist/editor/services/serviceHelper.js.map +1 -1
- package/dist/editor/services/systemService.d.ts +1 -2
- package/dist/editor/services/systemService.js +0 -3
- package/dist/editor/services/systemService.js.map +1 -1
- package/dist/editor/services-server/api.d.ts +2 -1
- package/dist/editor/services-server/api.js +6 -11
- package/dist/editor/services-server/api.js.map +1 -1
- package/dist/editor/services-server/graphQL.d.ts +29 -0
- package/dist/editor/services-server/graphQL.js +53 -0
- package/dist/editor/services-server/graphQL.js.map +1 -0
- package/dist/editor/settings/About.js +3 -317
- package/dist/editor/settings/About.js.map +1 -1
- package/dist/editor/settings/AllAgentsPanel.d.ts +5 -0
- package/dist/editor/settings/AllAgentsPanel.js +139 -0
- package/dist/editor/settings/AllAgentsPanel.js.map +1 -0
- package/dist/editor/settings/LatestFeedback.d.ts +1 -0
- package/dist/editor/settings/LatestFeedback.js +136 -0
- package/dist/editor/settings/LatestFeedback.js.map +1 -0
- package/dist/editor/settings/QuotaInfo.js +4 -210
- package/dist/editor/settings/QuotaInfo.js.map +1 -1
- package/dist/editor/settings/SettingsView.js +23 -25
- package/dist/editor/settings/SettingsView.js.map +1 -1
- package/dist/editor/settings/Setup.d.ts +1 -0
- package/dist/editor/settings/Setup.js +211 -0
- package/dist/editor/settings/Setup.js.map +1 -0
- package/dist/editor/settings/Status.js +6 -7
- package/dist/editor/settings/Status.js.map +1 -1
- package/dist/editor/settings/index/useIndexStatus.js +22 -20
- package/dist/editor/settings/index/useIndexStatus.js.map +1 -1
- package/dist/editor/settings/panels/AgentsPanel.d.ts +4 -0
- package/dist/editor/settings/panels/AgentsPanel.js +121 -95
- package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
- package/dist/editor/settings/panels/DatabasePanel.d.ts +6 -0
- package/dist/editor/settings/panels/DatabasePanel.js +50 -0
- package/dist/editor/settings/panels/DatabasePanel.js.map +1 -0
- package/dist/editor/settings/panels/ModelsPanel.js +108 -329
- package/dist/editor/settings/panels/ModelsPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProvidersPanel.d.ts +1 -1
- package/dist/editor/settings/panels/ProvidersPanel.js +59 -86
- package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
- package/dist/editor/settings/panels/SearchConfigPanel.js +4 -4
- package/dist/editor/settings/panels/SearchConfigPanel.js.map +1 -1
- package/dist/editor/settings/panels/index.d.ts +2 -3
- package/dist/editor/settings/panels/index.js +2 -3
- package/dist/editor/settings/panels/index.js.map +1 -1
- package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.d.ts +2 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js +195 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/index.d.ts +2 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/index.js +21 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/index.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.d.ts +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js +233 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.d.ts +15 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js +14 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.d.ts +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js +94 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/types.d.ts +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/types.js +2 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/types.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/utils.d.ts +5 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/utils.js +44 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/utils.js.map +1 -0
- package/dist/editor/settings/setup-steps/IndexSetupStep.d.ts +2 -0
- package/dist/editor/settings/setup-steps/IndexSetupStep.js +36 -0
- package/dist/editor/settings/setup-steps/IndexSetupStep.js.map +1 -0
- package/dist/editor/settings/setup-steps/SettingsSetupStep.d.ts +2 -0
- package/dist/editor/settings/setup-steps/SettingsSetupStep.js +111 -0
- package/dist/editor/settings/setup-steps/SettingsSetupStep.js.map +1 -0
- package/dist/editor/settings/setup-steps/SetupOverview.d.ts +14 -0
- package/dist/editor/settings/setup-steps/SetupOverview.js +38 -0
- package/dist/editor/settings/setup-steps/SetupOverview.js.map +1 -0
- package/dist/editor/settings/status/coreStatusChecks.js +19 -124
- package/dist/editor/settings/status/coreStatusChecks.js.map +1 -1
- package/dist/editor/settings/status/useStartupChecks.d.ts +1 -3
- package/dist/editor/settings/status/useStartupChecks.js +5 -9
- package/dist/editor/settings/status/useStartupChecks.js.map +1 -1
- package/dist/editor/setup-wizard/steps/CompleteStep.d.ts +1 -2
- package/dist/editor/setup-wizard/steps/CompleteStep.js +1 -2
- package/dist/editor/setup-wizard/steps/CompleteStep.js.map +1 -1
- package/dist/editor/sidebar/ComponentPalette.js +1 -2
- package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.d.ts +1 -8
- package/dist/editor/sidebar/ComponentTree.js +69 -216
- package/dist/editor/sidebar/ComponentTree.js.map +1 -1
- package/dist/editor/sidebar/Debug.d.ts +1 -0
- package/dist/editor/sidebar/Debug.js +70 -0
- package/dist/editor/sidebar/Debug.js.map +1 -0
- package/dist/editor/sidebar/EditHistory.js +46 -22
- package/dist/editor/sidebar/EditHistory.js.map +1 -1
- package/dist/editor/sidebar/Favorites.js +8 -4
- package/dist/editor/sidebar/Favorites.js.map +1 -1
- package/dist/editor/sidebar/GraphQL.d.ts +2 -0
- package/dist/editor/sidebar/GraphQL.js +234 -0
- package/dist/editor/sidebar/GraphQL.js.map +1 -0
- package/dist/editor/sidebar/LeftToolbar.d.ts +1 -0
- package/dist/editor/sidebar/LeftToolbar.js +12 -0
- package/dist/editor/sidebar/LeftToolbar.js.map +1 -0
- package/dist/editor/sidebar/MainContentTree.js +3 -4
- package/dist/editor/sidebar/MainContentTree.js.map +1 -1
- package/dist/editor/sidebar/NavigationSidebar.d.ts +4 -0
- package/dist/editor/sidebar/NavigationSidebar.js +254 -0
- package/dist/editor/sidebar/NavigationSidebar.js.map +1 -0
- package/dist/editor/sidebar/OperationItem.js +7 -21
- package/dist/editor/sidebar/OperationItem.js.map +1 -1
- package/dist/editor/sidebar/SidebarPanel.d.ts +1 -3
- package/dist/editor/sidebar/SidebarPanel.js +12 -44
- package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
- package/dist/editor/sidebar/SidebarStack.d.ts +1 -2
- package/dist/editor/sidebar/SidebarStack.js +3 -4
- package/dist/editor/sidebar/SidebarStack.js.map +1 -1
- package/dist/editor/sidebar/Validation.js +12 -22
- package/dist/editor/sidebar/Validation.js.map +1 -1
- package/dist/editor/sidebar/Workbox.js +3 -53
- package/dist/editor/sidebar/Workbox.js.map +1 -1
- package/dist/editor/sidebar/WorkspaceRail.d.ts +1 -0
- package/dist/editor/sidebar/WorkspaceRail.js +167 -56
- package/dist/editor/sidebar/WorkspaceRail.js.map +1 -1
- package/dist/editor/tree-indicators/GutterColumns.d.ts +1 -3
- package/dist/editor/tree-indicators/GutterColumns.js +5 -26
- package/dist/editor/tree-indicators/GutterColumns.js.map +1 -1
- package/dist/editor/tree-indicators/GutterContext.d.ts +0 -4
- package/dist/editor/tree-indicators/GutterContext.js +0 -23
- package/dist/editor/tree-indicators/GutterContext.js.map +1 -1
- package/dist/editor/tree-indicators/GutterSelector.d.ts +5 -0
- package/dist/editor/tree-indicators/GutterSelector.js +91 -0
- package/dist/editor/tree-indicators/GutterSelector.js.map +1 -0
- package/dist/editor/tree-indicators/index.d.ts +1 -0
- package/dist/editor/tree-indicators/index.js +1 -0
- package/dist/editor/tree-indicators/index.js.map +1 -1
- package/dist/editor/tree-indicators/types.d.ts +1 -12
- package/dist/editor/ui/CopyMoveTargetSelectorDialog.js +1 -1
- package/dist/editor/ui/CopyMoveTargetSelectorDialog.js.map +1 -1
- package/dist/editor/ui/Icons.js +1 -1
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/ItemNameDialogNew.d.ts +0 -2
- package/dist/editor/ui/ItemNameDialogNew.js +17 -33
- package/dist/editor/ui/ItemNameDialogNew.js.map +1 -1
- package/dist/editor/ui/ItemSearch.js +11 -7
- package/dist/editor/ui/ItemSearch.js.map +1 -1
- package/dist/editor/ui/SimpleIconButton.js +1 -1
- package/dist/editor/ui/SimpleIconButton.js.map +1 -1
- package/dist/editor/ui/SimpleTabs.d.ts +0 -1
- package/dist/editor/ui/SimpleTabs.js +25 -45
- package/dist/editor/ui/SimpleTabs.js.map +1 -1
- package/dist/editor/ui/Splitter.d.ts +0 -1
- package/dist/editor/ui/Splitter.js +86 -102
- package/dist/editor/ui/Splitter.js.map +1 -1
- package/dist/editor/ui/TemplateSelectorDialog.js +4 -4
- package/dist/editor/ui/TemplateSelectorDialog.js.map +1 -1
- package/dist/editor/ui/TreeListSelector.d.ts +1 -6
- package/dist/editor/ui/TreeListSelector.js +2 -2
- package/dist/editor/ui/TreeListSelector.js.map +1 -1
- package/dist/editor/utils/keyboardNavigation.d.ts +20 -6
- package/dist/editor/utils/keyboardNavigation.js +140 -48
- package/dist/editor/utils/keyboardNavigation.js.map +1 -1
- package/dist/editor/utils.js +9 -19
- package/dist/editor/utils.js.map +1 -1
- package/dist/editor/views/CompareView.d.ts +1 -3
- package/dist/editor/views/CompareView.js +5 -7
- package/dist/editor/views/CompareView.js.map +1 -1
- package/dist/editor/views/EditView.js +1 -1
- package/dist/editor/views/EditView.js.map +1 -1
- package/dist/editor/views/EditorSlot.js +34 -27
- package/dist/editor/views/EditorSlot.js.map +1 -1
- package/dist/editor/views/ItemEditor.js +3 -7
- package/dist/editor/views/ItemEditor.js.map +1 -1
- package/dist/editor/views/MediaFolderEditView.js +1 -1
- package/dist/editor/views/MediaFolderEditView.js.map +1 -1
- package/dist/editor/views/ParheliaView.js +6 -5
- package/dist/editor/views/ParheliaView.js.map +1 -1
- package/dist/editor/views/SingleEditView.d.ts +1 -2
- package/dist/editor/views/SingleEditView.js +8 -10
- package/dist/editor/views/SingleEditView.js.map +1 -1
- package/dist/editor/views/editorSlotContext.js +6 -35
- package/dist/editor/views/editorSlotContext.js.map +1 -1
- package/dist/index.d.ts +2 -16
- package/dist/index.js +0 -11
- package/dist/index.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/setup/services/setupWizardService.d.ts +13 -40
- package/dist/setup/services/setupWizardService.js +17 -32
- package/dist/setup/services/setupWizardService.js.map +1 -1
- package/dist/setup/wizard/steps/AddModelDialog.js +3 -12
- package/dist/setup/wizard/steps/AddModelDialog.js.map +1 -1
- package/dist/setup/wizard/steps/ImportModelDialog.js +22 -39
- package/dist/setup/wizard/steps/ImportModelDialog.js.map +1 -1
- package/dist/splash-screen/ModernSplashScreen.js +32 -112
- package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
- package/dist/splash-screen/NewPage.js +50 -33
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/OpenPage.js +6 -2
- package/dist/splash-screen/OpenPage.js.map +1 -1
- package/dist/splash-screen/ParheliaAssistantChat.js +29 -12
- package/dist/splash-screen/ParheliaAssistantChat.js.map +1 -1
- package/dist/splash-screen/ParheliaLogo.js +37 -87
- package/dist/splash-screen/ParheliaLogo.js.map +1 -1
- package/dist/splash-screen/RecentPages.js +3 -3
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/dist/tour/Tour.d.ts +1 -2
- package/dist/tour/Tour.js +75 -256
- package/dist/tour/Tour.js.map +1 -1
- package/dist/tour/default-tour.js +96 -222
- package/dist/tour/default-tour.js.map +1 -1
- package/dist/types.d.ts +29 -63
- package/package.json +15 -19
- package/styles.css +10 -14
|
@@ -1,27 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import { Book,
|
|
2
|
+
import { useState, useEffect, useCallback, useMemo, useRef, } from "react";
|
|
3
|
+
import { Book, Loader2, Edit, ArrowLeft } from "lucide-react";
|
|
4
4
|
import { loadManualToc, loadManualSection, invalidateManualSectionCache, } from "../../services/aiService";
|
|
5
|
-
import {
|
|
6
|
-
import { FilterInput } from "../../../components/FilterInput";
|
|
7
|
-
import { MarkdownDisplay, } from "../../../components/MarkdownDisplay";
|
|
5
|
+
import { Select } from "../../../components/ui/select";
|
|
8
6
|
import { Tooltip, TooltipTrigger, TooltipContent, } from "../../../components/ui/tooltip";
|
|
9
7
|
import { useEditContext } from "../../client/editContext";
|
|
10
8
|
import { cn } from "../../../lib/utils";
|
|
11
|
-
import { sanitizeSvg } from "../../../lib/sanitize";
|
|
12
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "../../../components/ui/dropdown-menu";
|
|
13
|
-
/** Render a sanitized SVG string at a specific pixel size. */
|
|
14
|
-
function SvgIcon({ svg, size, className, }) {
|
|
15
|
-
const sanitizedSvg = sanitizeSvg(svg).trim();
|
|
16
|
-
return (_jsx("span", { className: cn("inline-flex items-center justify-center [&>svg]:block [&>svg]:h-full [&>svg]:w-full", className), style: { width: size, height: size }, dangerouslySetInnerHTML: { __html: sanitizedSvg } }));
|
|
17
|
-
}
|
|
18
|
-
const HIGHLIGHT_DURATION_MS = 2000;
|
|
19
|
-
const manualMarkdownComponents = {
|
|
20
|
-
h1: ({ children }) => (_jsx("h1", { className: "mt-4 mb-0 text-xl font-bold text-gray-900", children: children })),
|
|
21
|
-
h2: ({ children }) => (_jsx("h2", { className: "mt-3 mb-0 text-lg font-semibold text-gray-800", children: children })),
|
|
22
|
-
h3: ({ children }) => (_jsx("h3", { className: "mt-2 mb-0 text-base font-semibold text-gray-700", children: children })),
|
|
23
|
-
h4: ({ children }) => (_jsx("h4", { className: "mt-2 mb-0 text-sm font-semibold text-gray-700", children: children })),
|
|
24
|
-
};
|
|
25
9
|
// Parse the uiSelectors field
|
|
26
10
|
// Formats:
|
|
27
11
|
// - @selector-name: Description | Not found message
|
|
@@ -30,10 +14,7 @@ export function parseUiSelectors(uiSelectors) {
|
|
|
30
14
|
const map = new Map();
|
|
31
15
|
if (!uiSelectors)
|
|
32
16
|
return map;
|
|
33
|
-
const lines = uiSelectors
|
|
34
|
-
.split(/\r?\n/)
|
|
35
|
-
.map((line) => line.trim())
|
|
36
|
-
.filter(Boolean);
|
|
17
|
+
const lines = uiSelectors.split("\n").filter((line) => line.trim());
|
|
37
18
|
for (const line of lines) {
|
|
38
19
|
// Format: @selector-name: ...
|
|
39
20
|
const match = line.match(/^@([\w\-]+):\s*(.+)$/);
|
|
@@ -42,34 +23,10 @@ export function parseUiSelectors(uiSelectors) {
|
|
|
42
23
|
const rest = match[2];
|
|
43
24
|
if (!name || !rest)
|
|
44
25
|
continue;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const description = segments.shift() ?? "";
|
|
50
|
-
let notFoundMessage;
|
|
51
|
-
let beforeAction;
|
|
52
|
-
let afterAction;
|
|
53
|
-
let availabilitySelector;
|
|
54
|
-
for (const segment of segments) {
|
|
55
|
-
if (segment.startsWith("beforeAction=")) {
|
|
56
|
-
beforeAction = segment.substring("beforeAction=".length).trim();
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
if (segment.startsWith("afterAction=")) {
|
|
60
|
-
afterAction = segment.substring("afterAction=".length).trim();
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
if (segment.startsWith("availabilitySelector=")) {
|
|
64
|
-
availabilitySelector = segment
|
|
65
|
-
.substring("availabilitySelector=".length)
|
|
66
|
-
.trim();
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
if (!notFoundMessage) {
|
|
70
|
-
notFoundMessage = segment;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
26
|
+
// Split by | for optional not-found message
|
|
27
|
+
const pipeIndex = rest.indexOf("|");
|
|
28
|
+
const description = pipeIndex >= 0 ? rest.substring(0, pipeIndex).trim() : rest.trim();
|
|
29
|
+
const notFoundMessage = pipeIndex >= 0 ? rest.substring(pipeIndex + 1).trim() : undefined;
|
|
73
30
|
// Check if this is a sidebar-only selector (e.g., @reviews-sidebar)
|
|
74
31
|
// These end with -sidebar
|
|
75
32
|
const isSidebarOnly = name.endsWith("-sidebar");
|
|
@@ -80,13 +37,10 @@ export function parseUiSelectors(uiSelectors) {
|
|
|
80
37
|
const parsed = {
|
|
81
38
|
name,
|
|
82
39
|
selector: isSidebarOnly ? "" : `@${name}`, // Empty selector for sidebar-only
|
|
83
|
-
availabilitySelector,
|
|
84
40
|
description,
|
|
85
41
|
notFoundMessage: notFoundMessage || undefined,
|
|
86
42
|
location: isSidebarOnly ? sidebarId : undefined, // Use actual sidebar ID (without -sidebar suffix) for sidebar-only
|
|
87
43
|
isSidebarOnly,
|
|
88
|
-
beforeAction,
|
|
89
|
-
afterAction,
|
|
90
44
|
};
|
|
91
45
|
// Primary key remains the selector name
|
|
92
46
|
map.set(name, parsed);
|
|
@@ -140,122 +94,59 @@ export function expandSelector(selectorShorthand) {
|
|
|
140
94
|
// Default: data-testid selector: @name → [data-testid="name"]
|
|
141
95
|
return `[data-testid="${selector}"]`;
|
|
142
96
|
}
|
|
143
|
-
|
|
97
|
+
// Highlight an element temporarily
|
|
98
|
+
export function highlightElement(selector, duration = 2000) {
|
|
144
99
|
const cssSelector = expandSelector(selector);
|
|
100
|
+
// Handle iframe selectors
|
|
145
101
|
if (cssSelector.startsWith("iframe:")) {
|
|
146
102
|
const iframeSelector = cssSelector.substring(7);
|
|
147
103
|
const iframe = document.querySelector("iframe.page-iframe");
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const viewportPadding = 24;
|
|
159
|
-
const isFixedLike = computedStyle.position === "fixed" || computedStyle.position === "sticky";
|
|
160
|
-
const isFullyVisible = rect.top >= viewportPadding &&
|
|
161
|
-
rect.bottom <= window.innerHeight - viewportPadding &&
|
|
162
|
-
rect.left >= 0 &&
|
|
163
|
-
rect.right <= window.innerWidth;
|
|
164
|
-
const isLargeTarget = rect.height >= window.innerHeight * 0.6;
|
|
165
|
-
return isFixedLike || isFullyVisible || isLargeTarget;
|
|
166
|
-
}
|
|
167
|
-
function waitForNextFrame() {
|
|
168
|
-
return new Promise((resolve) => {
|
|
169
|
-
window.requestAnimationFrame(() => resolve());
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
async function waitForScrollToFinish(element) {
|
|
173
|
-
let stableFrames = 0;
|
|
174
|
-
let previousRect = element.getBoundingClientRect();
|
|
175
|
-
for (let frame = 0; frame < 30; frame++) {
|
|
176
|
-
await waitForNextFrame();
|
|
177
|
-
const currentRect = element.getBoundingClientRect();
|
|
178
|
-
const moved = Math.abs(currentRect.top - previousRect.top) > 0.5 ||
|
|
179
|
-
Math.abs(currentRect.left - previousRect.left) > 0.5;
|
|
180
|
-
if (moved) {
|
|
181
|
-
stableFrames = 0;
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
stableFrames += 1;
|
|
185
|
-
if (stableFrames >= 2) {
|
|
186
|
-
return;
|
|
104
|
+
if (iframe?.contentDocument) {
|
|
105
|
+
const elements = iframe.contentDocument.querySelectorAll(iframeSelector);
|
|
106
|
+
if (elements.length > 0) {
|
|
107
|
+
const iframeRect = iframe.getBoundingClientRect();
|
|
108
|
+
elements.forEach((element) => {
|
|
109
|
+
const elementRect = element.getBoundingClientRect();
|
|
110
|
+
showHighlightOverlay(elementRect.left + iframeRect.left, elementRect.top + iframeRect.top, elementRect.width, elementRect.height, duration);
|
|
111
|
+
});
|
|
112
|
+
// Scroll the first element into view
|
|
113
|
+
elements[0]?.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
187
114
|
}
|
|
188
115
|
}
|
|
189
|
-
previousRect = currentRect;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
async function scrollElementForHighlight(element) {
|
|
193
|
-
if (shouldSkipHighlightScroll(element)) {
|
|
194
116
|
return;
|
|
195
117
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
inline: "nearest",
|
|
200
|
-
});
|
|
201
|
-
await waitForScrollToFinish(element);
|
|
202
|
-
}
|
|
203
|
-
// Highlight an element temporarily
|
|
204
|
-
export async function highlightElement(selector, duration = HIGHLIGHT_DURATION_MS) {
|
|
205
|
-
const cssSelector = expandSelector(selector);
|
|
206
|
-
const elements = getElementsForSelector(selector);
|
|
207
|
-
if (elements.length === 0)
|
|
208
|
-
return;
|
|
209
|
-
if (cssSelector.startsWith("iframe:")) {
|
|
210
|
-
const iframe = document.querySelector("iframe.page-iframe");
|
|
211
|
-
const iframeRect = iframe?.getBoundingClientRect();
|
|
212
|
-
if (elements[0]) {
|
|
213
|
-
await scrollElementForHighlight(elements[0]);
|
|
214
|
-
}
|
|
118
|
+
// Regular selectors - highlight all matching elements
|
|
119
|
+
const elements = document.querySelectorAll(cssSelector);
|
|
120
|
+
if (elements.length > 0) {
|
|
215
121
|
elements.forEach((element) => {
|
|
216
|
-
const
|
|
217
|
-
showHighlightOverlay(
|
|
122
|
+
const rect = element.getBoundingClientRect();
|
|
123
|
+
showHighlightOverlay(rect.left, rect.top, rect.width, rect.height, duration);
|
|
218
124
|
});
|
|
219
|
-
|
|
125
|
+
// Scroll the first element into view
|
|
126
|
+
elements[0]?.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
220
127
|
}
|
|
221
|
-
if (elements[0]) {
|
|
222
|
-
await scrollElementForHighlight(elements[0]);
|
|
223
|
-
}
|
|
224
|
-
elements.forEach((element) => {
|
|
225
|
-
const rect = element.getBoundingClientRect();
|
|
226
|
-
showHighlightOverlay(rect.left, rect.top, rect.width, rect.height, duration);
|
|
227
|
-
});
|
|
228
128
|
}
|
|
229
129
|
// Check if an element is currently available in the DOM
|
|
230
130
|
function isElementAvailable(selector) {
|
|
231
|
-
|
|
131
|
+
const cssSelector = expandSelector(selector);
|
|
132
|
+
if (cssSelector.startsWith("iframe:")) {
|
|
133
|
+
const iframeSelector = cssSelector.substring(7);
|
|
134
|
+
const iframe = document.querySelector("iframe.page-iframe");
|
|
135
|
+
return !!iframe?.contentDocument?.querySelector(iframeSelector);
|
|
136
|
+
}
|
|
137
|
+
return !!document.querySelector(cssSelector);
|
|
232
138
|
}
|
|
233
139
|
// Create a temporary highlight overlay
|
|
234
140
|
function showHighlightOverlay(x, y, width, height, duration) {
|
|
235
141
|
const padding = 4;
|
|
236
|
-
const viewportWidth = window.innerWidth;
|
|
237
|
-
const viewportHeight = window.innerHeight;
|
|
238
|
-
const rawLeft = x - padding;
|
|
239
|
-
const rawTop = y - padding;
|
|
240
|
-
const rawRight = x + width + padding;
|
|
241
|
-
const rawBottom = y + height + padding;
|
|
242
|
-
const left = Math.max(0, Math.min(rawLeft, viewportWidth));
|
|
243
|
-
const top = Math.max(0, Math.min(rawTop, viewportHeight));
|
|
244
|
-
const right = Math.max(0, Math.min(rawRight, viewportWidth));
|
|
245
|
-
const bottom = Math.max(0, Math.min(rawBottom, viewportHeight));
|
|
246
|
-
const clampedWidth = right - left;
|
|
247
|
-
const clampedHeight = bottom - top;
|
|
248
|
-
// Skip if target is fully outside the viewport after clamping.
|
|
249
|
-
if (clampedWidth <= 0 || clampedHeight <= 0)
|
|
250
|
-
return;
|
|
251
142
|
const overlay = document.createElement("div");
|
|
252
143
|
overlay.className = "selector-highlight-overlay";
|
|
253
144
|
overlay.style.cssText = `
|
|
254
145
|
position: fixed;
|
|
255
|
-
left: ${
|
|
256
|
-
top: ${
|
|
257
|
-
width: ${
|
|
258
|
-
height: ${
|
|
146
|
+
left: ${x - padding}px;
|
|
147
|
+
top: ${y - padding}px;
|
|
148
|
+
width: ${width + padding * 2}px;
|
|
149
|
+
height: ${height + padding * 2}px;
|
|
259
150
|
border: 2px solid #3b82f6;
|
|
260
151
|
border-radius: 4px;
|
|
261
152
|
background: rgba(59, 130, 246, 0.1);
|
|
@@ -284,8 +175,6 @@ function showHighlightOverlay(x, y, width, height, duration) {
|
|
|
284
175
|
// Button component for "Show me" functionality with availability detection
|
|
285
176
|
function SelectorButton({ selectorDef, keyProp, }) {
|
|
286
177
|
const editContext = useEditContext();
|
|
287
|
-
const manualActions = editContext?.configuration.editor.manualActions;
|
|
288
|
-
const availabilitySelector = selectorDef.availabilitySelector || selectorDef.selector;
|
|
289
178
|
// For sidebar-only selectors, we don't need to check for an element
|
|
290
179
|
const isSidebarOnly = selectorDef.isSidebarOnly;
|
|
291
180
|
// Initialize to true for sidebar-only, false otherwise to avoid hydration mismatch
|
|
@@ -293,12 +182,9 @@ function SelectorButton({ selectorDef, keyProp, }) {
|
|
|
293
182
|
const [isAvailable, setIsAvailable] = useState(isSidebarOnly ? true : false);
|
|
294
183
|
// Can open sidebar if: sidebar-only selector
|
|
295
184
|
const canAutoOpenSidebar = Boolean(isSidebarOnly && editContext?.openSidebar && selectorDef.location);
|
|
296
|
-
const hasBeforeAction = Boolean(selectorDef.beforeAction &&
|
|
297
|
-
manualActions?.[selectorDef.beforeAction] &&
|
|
298
|
-
editContext);
|
|
299
185
|
const isActionable = isSidebarOnly
|
|
300
|
-
? canAutoOpenSidebar
|
|
301
|
-
: isAvailable || canAutoOpenSidebar
|
|
186
|
+
? canAutoOpenSidebar
|
|
187
|
+
: isAvailable || canAutoOpenSidebar;
|
|
302
188
|
// Monitor for element availability changes (skip for sidebar-only selectors)
|
|
303
189
|
useEffect(() => {
|
|
304
190
|
// Sidebar-only selectors are always "available" if openSidebar exists
|
|
@@ -307,11 +193,10 @@ function SelectorButton({ selectorDef, keyProp, }) {
|
|
|
307
193
|
return;
|
|
308
194
|
}
|
|
309
195
|
// Initial check
|
|
310
|
-
|
|
311
|
-
setIsAvailable(initialAvailable);
|
|
196
|
+
setIsAvailable(isElementAvailable(selectorDef.selector));
|
|
312
197
|
// Set up MutationObserver to watch for DOM changes
|
|
313
198
|
const checkAvailability = () => {
|
|
314
|
-
const available = isElementAvailable(
|
|
199
|
+
const available = isElementAvailable(selectorDef.selector);
|
|
315
200
|
setIsAvailable(available);
|
|
316
201
|
};
|
|
317
202
|
// Watch the main document for changes
|
|
@@ -341,31 +226,13 @@ function SelectorButton({ selectorDef, keyProp, }) {
|
|
|
341
226
|
iframeObserver?.disconnect();
|
|
342
227
|
clearInterval(intervalId);
|
|
343
228
|
};
|
|
344
|
-
}, [
|
|
345
|
-
const tooltipText =
|
|
229
|
+
}, [selectorDef.selector, isSidebarOnly]);
|
|
230
|
+
const tooltipText = isAvailable
|
|
346
231
|
? selectorDef.description
|
|
347
232
|
: selectorDef.notFoundMessage || selectorDef.description;
|
|
348
|
-
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children:
|
|
233
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: async () => {
|
|
349
234
|
if (!isActionable)
|
|
350
235
|
return;
|
|
351
|
-
const runId = globalThis.crypto?.randomUUID?.() ??
|
|
352
|
-
`manual-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
353
|
-
const resolveElements = (selector = selectorDef.selector) => selector ? getElementsForSelector(selector) : [];
|
|
354
|
-
const runManualAction = async (actionName, elements) => {
|
|
355
|
-
if (!actionName || !editContext || !manualActions?.[actionName]) {
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
const action = manualActions[actionName];
|
|
359
|
-
const actionProps = {
|
|
360
|
-
editContext,
|
|
361
|
-
selectorDef,
|
|
362
|
-
duration: HIGHLIGHT_DURATION_MS,
|
|
363
|
-
runId,
|
|
364
|
-
elements,
|
|
365
|
-
resolveElements,
|
|
366
|
-
};
|
|
367
|
-
await action(actionProps);
|
|
368
|
-
};
|
|
369
236
|
// If this selector is sidebar-only, open the sidebar before highlighting.
|
|
370
237
|
// For sidebar-only selectors, location is the sidebar ID (without -sidebar suffix)
|
|
371
238
|
if (selectorDef.isSidebarOnly &&
|
|
@@ -379,68 +246,164 @@ function SelectorButton({ selectorDef, keyProp, }) {
|
|
|
379
246
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
380
247
|
}
|
|
381
248
|
}
|
|
382
|
-
const resolvedElements = !isSidebarOnly ? resolveElements() : [];
|
|
383
|
-
await runManualAction(selectorDef.beforeAction, resolvedElements);
|
|
384
249
|
// For sidebar-only selectors, we just open the sidebar (done above)
|
|
385
250
|
// For regular selectors, also highlight the element
|
|
386
251
|
if (!isSidebarOnly && selectorDef.selector) {
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
if (selectorDef.afterAction) {
|
|
390
|
-
window.setTimeout(() => {
|
|
391
|
-
void runManualAction(selectorDef.afterAction, !isSidebarOnly ? resolveElements() : []);
|
|
392
|
-
}, HIGHLIGHT_DURATION_MS);
|
|
252
|
+
highlightElement(selectorDef.selector);
|
|
393
253
|
}
|
|
394
|
-
}, disabled: !isActionable, className: cn("inline-flex
|
|
254
|
+
}, disabled: !isActionable, className: cn("inline-flex items-center rounded border px-1.5 py-0.5 text-xs font-medium transition-colors", isActionable
|
|
395
255
|
? "cursor-pointer border-blue-200 bg-blue-50 text-blue-700 hover:bg-blue-100"
|
|
396
|
-
: "cursor-not-allowed border-gray-200 bg-gray-100 text-gray-400"), children:
|
|
256
|
+
: "cursor-not-allowed border-gray-200 bg-gray-100 text-gray-400"), children: "Show me" }, keyProp) }), _jsx(TooltipContent, { children: tooltipText })] }));
|
|
257
|
+
}
|
|
258
|
+
// Check if a line is a markdown table row (starts and ends with |)
|
|
259
|
+
function isTableRow(line) {
|
|
260
|
+
const trimmed = line.trim();
|
|
261
|
+
return trimmed.startsWith("|") && trimmed.endsWith("|");
|
|
262
|
+
}
|
|
263
|
+
// Check if a line is a table separator row (contains only |, -, :, and spaces)
|
|
264
|
+
function isTableSeparator(line) {
|
|
265
|
+
const trimmed = line.trim();
|
|
266
|
+
return isTableRow(line) && /^\|[\s\-:|]+\|$/.test(trimmed);
|
|
267
|
+
}
|
|
268
|
+
// Parse table cells from a row, handling the | delimiters
|
|
269
|
+
function parseTableCells(line) {
|
|
270
|
+
const trimmed = line.trim();
|
|
271
|
+
// Remove leading and trailing |, then split by |
|
|
272
|
+
const inner = trimmed.slice(1, -1);
|
|
273
|
+
return inner.split("|").map((cell) => cell.trim());
|
|
274
|
+
}
|
|
275
|
+
// Parse column alignments from separator row
|
|
276
|
+
function parseTableAlignments(separatorLine) {
|
|
277
|
+
const cells = parseTableCells(separatorLine);
|
|
278
|
+
return cells.map((cell) => {
|
|
279
|
+
const trimmed = cell.trim();
|
|
280
|
+
const startsWithColon = trimmed.startsWith(":");
|
|
281
|
+
const endsWithColon = trimmed.endsWith(":");
|
|
282
|
+
if (startsWithColon && endsWithColon)
|
|
283
|
+
return "center";
|
|
284
|
+
if (endsWithColon)
|
|
285
|
+
return "right";
|
|
286
|
+
return "left";
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
// Render a markdown table
|
|
290
|
+
function renderTable(headerCells, alignments, bodyRows, uiSelectors, keyPrefix) {
|
|
291
|
+
const alignClasses = {
|
|
292
|
+
left: "text-left",
|
|
293
|
+
center: "text-center",
|
|
294
|
+
right: "text-right",
|
|
295
|
+
};
|
|
296
|
+
return (_jsx("div", { className: "my-3 overflow-x-auto", children: _jsxs("table", { className: "min-w-full border-collapse rounded-md border border-gray-200 text-sm", children: [_jsx("thead", { className: "bg-gray-50", children: _jsx("tr", { children: headerCells.map((cell, cellIndex) => (_jsx("th", { className: cn("border border-gray-200 px-3 py-2 font-semibold text-gray-700", alignClasses[alignments[cellIndex] || "left"]), children: renderLineWithSelectors(cell, uiSelectors) }, cellIndex))) }) }), _jsx("tbody", { children: bodyRows.map((row, rowIndex) => (_jsx("tr", { className: rowIndex % 2 === 0 ? "bg-white" : "bg-gray-50", children: row.map((cell, cellIndex) => (_jsx("td", { className: cn("border border-gray-200 px-3 py-2 text-gray-600", alignClasses[alignments[cellIndex] || "left"]), children: renderLineWithSelectors(cell, uiSelectors) }, cellIndex))) }, rowIndex))) })] }) }, keyPrefix));
|
|
397
297
|
}
|
|
398
298
|
// Render markdown content with clickable selectors
|
|
399
299
|
// Supports both {{selectorName}} syntax (looks up in uiSelectors) and legacy @selector syntax
|
|
400
|
-
function renderMarkdownWithSelectors(content, uiSelectors
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
300
|
+
function renderMarkdownWithSelectors(content, uiSelectors) {
|
|
301
|
+
// Simple markdown rendering with selector support
|
|
302
|
+
// Normalize line endings (handle \r\n and \r)
|
|
303
|
+
const normalizedContent = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
304
|
+
const lines = normalizedContent.split("\n");
|
|
305
|
+
const elements = [];
|
|
306
|
+
let lineIndex = 0;
|
|
307
|
+
while (lineIndex < lines.length) {
|
|
308
|
+
const line = lines[lineIndex] || "";
|
|
309
|
+
// Check if this is the start of a table
|
|
310
|
+
if (isTableRow(line) && !isTableSeparator(line)) {
|
|
311
|
+
// Look ahead for separator row to confirm this is a table
|
|
312
|
+
const nextLine = lines[lineIndex + 1];
|
|
313
|
+
if (nextLine && isTableSeparator(nextLine)) {
|
|
314
|
+
// This is a table! Parse it
|
|
315
|
+
const headerCells = parseTableCells(line);
|
|
316
|
+
const alignments = parseTableAlignments(nextLine);
|
|
317
|
+
const bodyRows = [];
|
|
318
|
+
// Skip header and separator
|
|
319
|
+
let tableLineIndex = lineIndex + 2;
|
|
320
|
+
// Collect body rows
|
|
321
|
+
while (tableLineIndex < lines.length &&
|
|
322
|
+
isTableRow(lines[tableLineIndex] || "") &&
|
|
323
|
+
!isTableSeparator(lines[tableLineIndex] || "")) {
|
|
324
|
+
bodyRows.push(parseTableCells(lines[tableLineIndex] || ""));
|
|
325
|
+
tableLineIndex++;
|
|
326
|
+
}
|
|
327
|
+
elements.push(renderTable(headerCells, alignments, bodyRows, uiSelectors, lineIndex));
|
|
328
|
+
lineIndex = tableLineIndex;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// Handle headings
|
|
333
|
+
if (line.startsWith("# ")) {
|
|
334
|
+
elements.push(_jsx("h1", { className: "mt-4 mb-2 text-xl font-bold text-gray-900", children: renderLineWithSelectors(line.substring(2), uiSelectors) }, lineIndex));
|
|
335
|
+
lineIndex++;
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
if (line.startsWith("## ")) {
|
|
339
|
+
elements.push(_jsx("h2", { className: "mt-3 mb-2 text-lg font-semibold text-gray-800", children: renderLineWithSelectors(line.substring(3), uiSelectors) }, lineIndex));
|
|
340
|
+
lineIndex++;
|
|
341
|
+
continue;
|
|
420
342
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
343
|
+
if (line.startsWith("### ")) {
|
|
344
|
+
elements.push(_jsx("h3", { className: "mt-2 mb-1 text-base font-semibold text-gray-700", children: renderLineWithSelectors(line.substring(4), uiSelectors) }, lineIndex));
|
|
345
|
+
lineIndex++;
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
// Handle unordered list items - collect consecutive items and wrap in <ul>
|
|
349
|
+
if (line.match(/^[-*] /)) {
|
|
350
|
+
const listItems = [];
|
|
351
|
+
const startIndex = lineIndex;
|
|
352
|
+
while (lineIndex < lines.length &&
|
|
353
|
+
(lines[lineIndex] || "").match(/^[-*] /)) {
|
|
354
|
+
const itemLine = lines[lineIndex] || "";
|
|
355
|
+
listItems.push(_jsx("li", { className: "text-sm text-gray-600", children: renderLineWithSelectors(itemLine.substring(2), uiSelectors) }, lineIndex));
|
|
356
|
+
lineIndex++;
|
|
357
|
+
}
|
|
358
|
+
elements.push(_jsx("ul", { className: "my-2 ml-6 space-y-1", style: { listStyleType: "disc", paddingLeft: "1rem" }, children: listItems }, `ul-${startIndex}`));
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
// Handle ordered list items - collect consecutive items and wrap in <ol>
|
|
362
|
+
if (line.match(/^\d+\.\s/)) {
|
|
363
|
+
const listItems = [];
|
|
364
|
+
const startIndex = lineIndex;
|
|
365
|
+
while (lineIndex < lines.length &&
|
|
366
|
+
(lines[lineIndex] || "").match(/^\d+\.\s/)) {
|
|
367
|
+
const itemLine = lines[lineIndex] || "";
|
|
368
|
+
// Extract content after "N. " - use substring to get everything after the number and dot
|
|
369
|
+
const dotIndex = itemLine.indexOf(".");
|
|
370
|
+
const itemContent = dotIndex >= 0
|
|
371
|
+
? itemLine.substring(dotIndex + 1).trimStart()
|
|
372
|
+
: itemLine;
|
|
373
|
+
listItems.push(_jsx("li", { className: "text-sm text-gray-600", children: renderLineWithSelectors(itemContent, uiSelectors) }, lineIndex));
|
|
374
|
+
lineIndex++;
|
|
375
|
+
}
|
|
376
|
+
elements.push(_jsx("ol", { className: "my-2 ml-6 space-y-1", style: { listStyleType: "decimal", paddingLeft: "1rem" }, children: listItems }, `ol-${startIndex}`));
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
// Handle horizontal rules (---, ***, ___)
|
|
380
|
+
if (line.match(/^[-*_]{3,}\s*$/)) {
|
|
381
|
+
elements.push(_jsx("hr", { className: "my-4 border-t border-gray-200" }, lineIndex));
|
|
382
|
+
lineIndex++;
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
// Regular paragraph
|
|
386
|
+
if (line.trim()) {
|
|
387
|
+
elements.push(_jsx("p", { className: "my-1 text-sm text-gray-600", children: renderLineWithSelectors(line, uiSelectors) }, lineIndex));
|
|
424
388
|
}
|
|
425
389
|
else {
|
|
426
|
-
|
|
390
|
+
elements.push(_jsx("div", { className: "h-2" }, lineIndex));
|
|
427
391
|
}
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
if (lastIndex < text.length) {
|
|
431
|
-
const suffix = text.substring(lastIndex);
|
|
432
|
-
parts.push(_jsx(React.Fragment, { children: renderInlineSelectorsAndFormatting(suffix, uiSelectors) }, `suffix-${lastIndex}`));
|
|
392
|
+
lineIndex++;
|
|
433
393
|
}
|
|
434
|
-
return _jsx(
|
|
394
|
+
return _jsx("div", { className: "space-y-1", children: elements });
|
|
435
395
|
}
|
|
436
|
-
|
|
396
|
+
// Render a line with clickable selectors and basic formatting
|
|
397
|
+
// Supports: {{selectorName}} for named selectors, @selector for legacy direct selectors, **bold** text
|
|
398
|
+
// Parentheses around selectors (e.g., ({{name}})) are automatically hidden
|
|
399
|
+
function renderLineWithSelectors(text, uiSelectors) {
|
|
437
400
|
const parts = [];
|
|
438
401
|
let lastIndex = 0;
|
|
439
402
|
// Combined regex for {{namedSelector}}, @selector, and **bold**
|
|
440
403
|
// Note: @selector can include -sidebar suffix for sidebar-only selectors
|
|
441
404
|
// Also supports @iframe:selector syntax (iframe: is special and allowed)
|
|
442
405
|
// Now also matches optional parentheses around selectors: ({{name}}) or (@selector)
|
|
443
|
-
const regex = /(\()?(\{\{([\w\-]+)\}\})|(\()?(@(?:iframe:[\w\-\.#\[\]=]
|
|
406
|
+
const regex = /(\()?(\{\{([\w\-]+)\}\})|(\()?(@(?:iframe:[\w\-\.#\[\]=]+|[\w\-\.#\[\]=]+))|(\*\*(.+?)\*\*)/g;
|
|
444
407
|
let match;
|
|
445
408
|
while ((match = regex.exec(text)) !== null) {
|
|
446
409
|
// Check if there's an opening parenthesis before the selector
|
|
@@ -477,9 +440,7 @@ function renderInlineSelectorsAndFormatting(text, uiSelectors) {
|
|
|
477
440
|
// @selector match (legacy direct selector syntax) - create ad-hoc selector def
|
|
478
441
|
const selectorToken = match[5];
|
|
479
442
|
const parsed = parseSelectorToken(selectorToken);
|
|
480
|
-
const
|
|
481
|
-
const registeredSelectorDef = uiSelectors.get(selectorName);
|
|
482
|
-
const effectiveSelectorDef = registeredSelectorDef ?? {
|
|
443
|
+
const adHocSelectorDef = {
|
|
483
444
|
name: selectorToken,
|
|
484
445
|
selector: parsed.selector,
|
|
485
446
|
description: parsed.isSidebarOnly
|
|
@@ -491,7 +452,7 @@ function renderInlineSelectorsAndFormatting(text, uiSelectors) {
|
|
|
491
452
|
// Check if there's a closing paren after this selector
|
|
492
453
|
const afterMatch = match.index + match[0].length;
|
|
493
454
|
const hasCloseParen = text[afterMatch] === ")";
|
|
494
|
-
parts.push(_jsx(SelectorButton, { selectorDef:
|
|
455
|
+
parts.push(_jsx(SelectorButton, { selectorDef: adHocSelectorDef, keyProp: match.index }, match.index));
|
|
495
456
|
// Skip the closing paren if present
|
|
496
457
|
if (hasCloseParen && hasOpenParen) {
|
|
497
458
|
lastIndex = afterMatch + 1;
|
|
@@ -511,6 +472,21 @@ function renderInlineSelectorsAndFormatting(text, uiSelectors) {
|
|
|
511
472
|
}
|
|
512
473
|
return _jsx(_Fragment, { children: parts });
|
|
513
474
|
}
|
|
475
|
+
// Flatten TOC tree into options with indentation for hierarchy
|
|
476
|
+
function flattenTocToOptions(sections, depth = 0) {
|
|
477
|
+
const options = [];
|
|
478
|
+
for (const section of sections) {
|
|
479
|
+
const indent = "\u00A0\u00A0".repeat(depth); // Non-breaking spaces for indentation
|
|
480
|
+
options.push({
|
|
481
|
+
value: section.id,
|
|
482
|
+
label: `${indent}${section.title || "Untitled"}`,
|
|
483
|
+
});
|
|
484
|
+
if (section.children && section.children.length > 0) {
|
|
485
|
+
options.push(...flattenTocToOptions(section.children, depth + 1));
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return options;
|
|
489
|
+
}
|
|
514
490
|
function findTocPath(sections, targetId, ancestors = []) {
|
|
515
491
|
for (const section of sections) {
|
|
516
492
|
const nextAncestors = [...ancestors, section];
|
|
@@ -524,278 +500,36 @@ function findTocPath(sections, targetId, ancestors = []) {
|
|
|
524
500
|
}
|
|
525
501
|
return null;
|
|
526
502
|
}
|
|
527
|
-
function
|
|
528
|
-
return !!section.hasContent || section.children.length === 0;
|
|
529
|
-
}
|
|
530
|
-
function resolveFirstNavigableSection(section) {
|
|
531
|
-
if (isDirectlyNavigableSection(section) || section.children.length === 0) {
|
|
532
|
-
return section;
|
|
533
|
-
}
|
|
534
|
-
return resolveFirstNavigableSection(section.children[0]);
|
|
535
|
-
}
|
|
536
|
-
function resolveSelectedSectionId(sections, targetId) {
|
|
537
|
-
const path = findTocPath(sections, targetId);
|
|
538
|
-
const targetSection = path?.[path.length - 1];
|
|
539
|
-
if (!targetSection)
|
|
540
|
-
return targetId;
|
|
541
|
-
return resolveFirstNavigableSection(targetSection).id;
|
|
542
|
-
}
|
|
543
|
-
function findNearestNavigableAncestor(path) {
|
|
544
|
-
if (!path || path.length < 2)
|
|
545
|
-
return null;
|
|
546
|
-
for (let i = path.length - 2; i >= 0; i -= 1) {
|
|
547
|
-
const section = path[i];
|
|
548
|
-
if (section && isDirectlyNavigableSection(section)) {
|
|
549
|
-
return section;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
return null;
|
|
553
|
-
}
|
|
554
|
-
const SECTION_THEMES = {
|
|
555
|
-
"getting started": {
|
|
556
|
-
icon: Rocket,
|
|
557
|
-
color: "text-emerald-600",
|
|
558
|
-
bg: "bg-emerald-50",
|
|
559
|
-
border: "border-emerald-100",
|
|
560
|
-
accent: "bg-emerald-500",
|
|
561
|
-
},
|
|
562
|
-
"page editing": {
|
|
563
|
-
icon: FileEdit,
|
|
564
|
-
color: "text-blue-600",
|
|
565
|
-
bg: "bg-blue-50",
|
|
566
|
-
border: "border-blue-100",
|
|
567
|
-
accent: "bg-blue-500",
|
|
568
|
-
},
|
|
569
|
-
"managing content": {
|
|
570
|
-
icon: BookOpen,
|
|
571
|
-
color: "text-amber-600",
|
|
572
|
-
bg: "bg-amber-50",
|
|
573
|
-
border: "border-amber-100",
|
|
574
|
-
accent: "bg-amber-500",
|
|
575
|
-
},
|
|
576
|
-
"ai assistant": {
|
|
577
|
-
icon: BookOpen,
|
|
578
|
-
color: "text-violet-600",
|
|
579
|
-
bg: "bg-violet-50",
|
|
580
|
-
border: "border-violet-100",
|
|
581
|
-
accent: "bg-violet-500",
|
|
582
|
-
},
|
|
583
|
-
};
|
|
584
|
-
const DEFAULT_THEME = {
|
|
585
|
-
icon: BookOpen,
|
|
586
|
-
color: "text-violet-600",
|
|
587
|
-
bg: "bg-violet-50",
|
|
588
|
-
border: "border-violet-100",
|
|
589
|
-
accent: "bg-violet-500",
|
|
590
|
-
};
|
|
591
|
-
function getSectionTheme(title) {
|
|
592
|
-
if (!title)
|
|
593
|
-
return DEFAULT_THEME;
|
|
594
|
-
return SECTION_THEMES[title.toLowerCase()] ?? DEFAULT_THEME;
|
|
595
|
-
}
|
|
596
|
-
function TocSectionCard({ section, onSelect, onToggleCollapse, isCollapsed, }) {
|
|
597
|
-
const theme = getSectionTheme(section.title);
|
|
598
|
-
const Icon = theme.icon;
|
|
599
|
-
const hasChildren = !!(section.children && section.children.length > 0);
|
|
600
|
-
return (_jsxs("div", { className: "group", children: [_jsx("button", { type: "button", onClick: () => onSelect(section.id), className: cn("w-full rounded-lg p-3 text-left transition-all", "bg-white hover:bg-gray-50/50"), children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: cn("flex h-9 w-9 shrink-0 items-center justify-center rounded-lg", theme.bg), children: section.svgIcon ? (_jsx(SvgIcon, { svg: section.svgIcon, size: 24, className: theme.color })) : (_jsx(Icon, { className: cn("h-[18px] w-[18px]", theme.color), strokeWidth: 1.75 })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "flex items-center gap-2", children: _jsx("span", { className: "text-sm font-semibold text-gray-900", children: section.title || "Untitled" }) }), section.summary && (_jsx("p", { className: "mt-0.5 line-clamp-2 text-xs leading-relaxed text-gray-500", children: section.summary }))] })] }) }), hasChildren && (_jsxs("div", { className: "mt-1", children: [_jsxs("button", { type: "button", onClick: () => onToggleCollapse(section.id), className: "ml-[60px] flex w-fit items-center gap-1.5 rounded-md py-1 text-xs text-gray-400 transition-colors hover:text-gray-600", children: [_jsx(ChevronRight, { className: cn("h-3 w-3 shrink-0 transition-transform", !isCollapsed && "rotate-90") }), _jsx("span", { children: isCollapsed ? "Show articles" : "Hide articles" })] }), !isCollapsed && (_jsx("div", { className: "mt-0.5 ml-[60px] space-y-px border-l-2 border-gray-100 pl-3", children: section.children.map((child) => (_jsxs("button", { type: "button", onClick: () => onSelect(child.id), className: "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-gray-600 transition-colors hover:bg-gray-50 hover:text-gray-900", children: [_jsx("span", { className: cn("h-1.5 w-1.5 shrink-0 rounded-full", theme.accent, "opacity-40 transition-opacity group-hover:opacity-70") }), _jsx("span", { className: "truncate", children: child.title || "Untitled" })] }, child.id))) }))] }))] }));
|
|
601
|
-
}
|
|
602
|
-
function renderTocTree(sections, onSelect, onToggleCollapse, collapsedSectionIds, depth = 0) {
|
|
603
|
-
if (depth === 0) {
|
|
604
|
-
return (_jsx("div", { className: "space-y-3", children: sections.map((section) => {
|
|
605
|
-
const isCollapsed = collapsedSectionIds.has(section.id);
|
|
606
|
-
return (_jsx(TocSectionCard, { section: section, onSelect: onSelect, onToggleCollapse: onToggleCollapse, isCollapsed: isCollapsed }, section.id));
|
|
607
|
-
}) }));
|
|
608
|
-
}
|
|
609
|
-
return (_jsx("div", { className: cn(depth > 0 && "ml-3 border-l border-gray-100 pl-2"), children: sections.map((section) => {
|
|
610
|
-
const hasChildren = !!(section.children && section.children.length > 0);
|
|
611
|
-
const isCollapsed = hasChildren && collapsedSectionIds.has(section.id);
|
|
612
|
-
return (_jsxs("div", { className: "my-0.5", children: [_jsxs("div", { className: cn("group flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 transition-colors hover:bg-gray-50", "text-sm text-gray-500 hover:text-gray-700"), children: [hasChildren ? (_jsx("button", { type: "button", onClick: () => onToggleCollapse(section.id), className: "rounded p-0.5 text-gray-300 transition-colors hover:bg-gray-100 hover:text-gray-500", "aria-label": isCollapsed
|
|
613
|
-
? `Expand ${section.title || "section"}`
|
|
614
|
-
: `Collapse ${section.title || "section"}`, title: isCollapsed ? "Expand section" : "Collapse section", children: _jsx(ChevronRight, { className: cn("h-3.5 w-3.5 shrink-0 transition-transform", !isCollapsed && "rotate-90") }) })) : (_jsx("span", { className: "h-3.5 w-3.5 shrink-0" })), _jsx("button", { type: "button", onClick: () => onSelect(section.id), className: "flex-1 text-left", children: section.title || "Untitled" })] }), hasChildren &&
|
|
615
|
-
!isCollapsed &&
|
|
616
|
-
renderTocTree(section.children, onSelect, onToggleCollapse, collapsedSectionIds, depth + 1)] }, section.id));
|
|
617
|
-
}) }));
|
|
618
|
-
}
|
|
619
|
-
function buildChapterOptions(chapter) {
|
|
620
|
-
const result = [];
|
|
621
|
-
const walk = (sections, depth) => {
|
|
622
|
-
for (const section of sections) {
|
|
623
|
-
result.push({ section, depth });
|
|
624
|
-
if (section.children.length > 0) {
|
|
625
|
-
walk(section.children, depth + 1);
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
};
|
|
629
|
-
// Include the chapter itself if it has content, then its children
|
|
630
|
-
if (isDirectlyNavigableSection(chapter)) {
|
|
631
|
-
result.push({ section: chapter, depth: 0 });
|
|
632
|
-
}
|
|
633
|
-
walk(chapter.children, isDirectlyNavigableSection(chapter) ? 1 : 0);
|
|
634
|
-
return result;
|
|
635
|
-
}
|
|
636
|
-
function InChapterDropdown({ toc, currentTocPath, selectedSectionId, onSelect, }) {
|
|
637
|
-
const chapter = currentTocPath?.[0] ?? null;
|
|
638
|
-
const chapterOptions = useMemo(() => (chapter ? buildChapterOptions(chapter) : []), [chapter]);
|
|
639
|
-
const allChapters = useMemo(() => toc, [toc]);
|
|
640
|
-
// Don't render if there's no chapter or only one page in it
|
|
641
|
-
if (!chapter || chapterOptions.length <= 1)
|
|
642
|
-
return null;
|
|
643
|
-
const selectedTitle = chapterOptions.find((o) => o.section.id === selectedSectionId)?.section.title;
|
|
644
|
-
return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "inline-flex w-full items-center justify-between gap-2 rounded-md border border-gray-200 bg-white px-2.5 py-1.5 text-xs transition-colors hover:bg-gray-50", children: [_jsxs("span", { className: "truncate text-gray-500", children: [_jsx("span", { className: "font-medium text-gray-700", children: selectedTitle ?? chapter.title }), " ", _jsxs("span", { className: "text-gray-400", children: ["\u2014 in ", chapter.title] })] }), _jsx(ChevronDown, { className: "h-3.5 w-3.5 shrink-0 text-gray-400" })] }) }), _jsxs(DropdownMenuContent, { align: "start", className: "max-h-80 w-[--radix-dropdown-menu-trigger-width] overflow-y-auto", children: [allChapters.length > 0 && (_jsxs(_Fragment, { children: [_jsx(DropdownMenuLabel, { className: "text-[11px] font-semibold tracking-wide text-gray-400 uppercase", children: "Chapters" }), allChapters.map((c) => {
|
|
645
|
-
const isCurrent = c.id === chapter?.id;
|
|
646
|
-
const theme = getSectionTheme(c.title);
|
|
647
|
-
const Icon = theme.icon;
|
|
648
|
-
return (_jsxs(DropdownMenuItem, { onClick: () => !isCurrent && onSelect(c.id), className: cn(isCurrent && "bg-blue-50 font-medium"), children: [c.svgIcon ? (_jsx(SvgIcon, { svg: c.svgIcon, size: 14, className: cn("mr-1.5 shrink-0", theme.color) })) : (_jsx(Icon, { className: cn("mr-1.5 h-3.5 w-3.5 shrink-0", theme.color), strokeWidth: 1.75 })), _jsx("span", { className: "truncate", children: c.title })] }, c.id));
|
|
649
|
-
}), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuLabel, { className: "text-[11px] font-semibold tracking-wide text-gray-400 uppercase", children: ["In ", chapter.title] })] })), chapterOptions.map(({ section, depth }) => {
|
|
650
|
-
const isActive = section.id === selectedSectionId;
|
|
651
|
-
const navigable = isDirectlyNavigableSection(section);
|
|
652
|
-
return (_jsx(DropdownMenuItem, { disabled: !navigable, onClick: () => navigable && onSelect(section.id), className: cn(isActive && "bg-blue-50 font-medium", !navigable && "pointer-events-none opacity-60"), style: { paddingLeft: `${8 + depth * 16}px` }, children: _jsx("span", { className: "truncate", children: section.title || "Untitled" }) }, section.id));
|
|
653
|
-
})] })] }));
|
|
654
|
-
}
|
|
655
|
-
function flattenSections(sections) {
|
|
656
|
-
const flattened = [];
|
|
657
|
-
for (const section of sections) {
|
|
658
|
-
flattened.push(section);
|
|
659
|
-
if (section.children && section.children.length > 0) {
|
|
660
|
-
flattened.push(...flattenSections(section.children));
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
return flattened;
|
|
664
|
-
}
|
|
665
|
-
function flattenNavigableSections(sections) {
|
|
666
|
-
const flattened = [];
|
|
667
|
-
for (const section of sections) {
|
|
668
|
-
if (isDirectlyNavigableSection(section)) {
|
|
669
|
-
flattened.push(section);
|
|
670
|
-
}
|
|
671
|
-
if (section.children.length > 0) {
|
|
672
|
-
flattened.push(...flattenNavigableSections(section.children));
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
return flattened;
|
|
676
|
-
}
|
|
677
|
-
const MANUAL_SECTION_TEMPLATE_ID = "c5f1e8a2-9b50-4fe2-9b6d-3db00c3b3b8a";
|
|
678
|
-
export function ManualBrowser({ onClose }) {
|
|
503
|
+
export function ManualBrowser() {
|
|
679
504
|
const editContext = useEditContext();
|
|
680
505
|
const [toc, setToc] = useState([]);
|
|
681
|
-
const selectedSectionId =
|
|
506
|
+
const [selectedSectionId, setSelectedSectionId] = useState(null);
|
|
682
507
|
const [currentSection, setCurrentSection] = useState(null);
|
|
683
|
-
const currentSectionRef = useRef(null);
|
|
684
508
|
const [loadingToc, setLoadingToc] = useState(false);
|
|
685
509
|
const [loadingSection, setLoadingSection] = useState(false);
|
|
686
510
|
const [error, setError] = useState(null);
|
|
687
|
-
const [searchQuery, setSearchQuery] = useState("");
|
|
688
|
-
const [searchResults, setSearchResults] = useState([]);
|
|
689
|
-
const [searching, setSearching] = useState(false);
|
|
690
|
-
const [collapsedTocSectionIds, setCollapsedTocSectionIds] = useState(() => new Set());
|
|
691
|
-
const [manualBackHistory, setManualBackHistory] = useState([]);
|
|
692
511
|
// Track revision to force re-fetch (incremented when websocket notifies of changes)
|
|
693
512
|
const [sectionRevision, setSectionRevision] = useState(0);
|
|
694
513
|
// Keep a ref to all TOC item IDs for checking if changed item is in the manual
|
|
695
514
|
const tocItemIdsRef = useRef(new Set());
|
|
696
|
-
const manualBackHistoryRef = useRef([]);
|
|
697
|
-
const historyNavigationModeRef = useRef(null);
|
|
698
|
-
const lastObservedSelectedSectionIdRef = useRef(undefined);
|
|
699
515
|
// Keep a ref to selectedSectionId to avoid stale closures in websocket callback
|
|
700
516
|
const selectedSectionIdRef = useRef(null);
|
|
517
|
+
// Flatten TOC into select options
|
|
518
|
+
const sectionOptions = useMemo(() => flattenTocToOptions(toc), [toc]);
|
|
701
519
|
const currentTocPath = useMemo(() => {
|
|
702
520
|
if (!selectedSectionId)
|
|
703
521
|
return null;
|
|
704
522
|
return findTocPath(toc, selectedSectionId);
|
|
705
523
|
}, [toc, selectedSectionId]);
|
|
706
524
|
const parentTocSection = useMemo(() => {
|
|
707
|
-
|
|
708
|
-
}, [currentTocPath]);
|
|
709
|
-
const chapterNavigation = useMemo(() => {
|
|
710
|
-
if (!selectedSectionId)
|
|
711
|
-
return { previous: null, next: null };
|
|
712
|
-
const flatSections = flattenNavigableSections(toc);
|
|
713
|
-
const currentIndex = flatSections.findIndex((section) => section.id === selectedSectionId);
|
|
714
|
-
if (currentIndex < 0)
|
|
715
|
-
return { previous: null, next: null };
|
|
716
|
-
return {
|
|
717
|
-
previous: currentIndex > 0 ? flatSections[currentIndex - 1] : null,
|
|
718
|
-
next: currentIndex < flatSections.length - 1
|
|
719
|
-
? flatSections[currentIndex + 1]
|
|
720
|
-
: null,
|
|
721
|
-
};
|
|
722
|
-
}, [toc, selectedSectionId]);
|
|
723
|
-
const manualLinkTargets = useMemo(() => {
|
|
724
|
-
const lookup = new Map();
|
|
725
|
-
const sections = flattenSections(toc);
|
|
726
|
-
for (const section of sections) {
|
|
727
|
-
const key = section.title?.trim().toLowerCase();
|
|
728
|
-
if (key && !lookup.has(key)) {
|
|
729
|
-
lookup.set(key, resolveFirstNavigableSection(section).id);
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
return lookup;
|
|
733
|
-
}, [toc]);
|
|
734
|
-
const manualSectionsById = useMemo(() => {
|
|
735
|
-
const map = new Map();
|
|
736
|
-
const sections = flattenSections(toc);
|
|
737
|
-
for (const section of sections) {
|
|
738
|
-
map.set(section.id.toLowerCase(), section);
|
|
739
|
-
}
|
|
740
|
-
return map;
|
|
741
|
-
}, [toc]);
|
|
742
|
-
const backTargetSectionId = manualBackHistory.length > 0
|
|
743
|
-
? manualBackHistory[manualBackHistory.length - 1]
|
|
744
|
-
: null;
|
|
745
|
-
const backTargetSection = useMemo(() => {
|
|
746
|
-
if (!backTargetSectionId)
|
|
525
|
+
if (!currentTocPath || currentTocPath.length < 2)
|
|
747
526
|
return null;
|
|
748
|
-
return
|
|
749
|
-
}, [
|
|
750
|
-
const backButtonLabel = backTargetSection?.title
|
|
751
|
-
? `Back to ${backTargetSection.title}`
|
|
752
|
-
: "Back to contents";
|
|
753
|
-
const backButtonText = backTargetSectionId === null ? "Contents" : "Back";
|
|
527
|
+
return currentTocPath[currentTocPath.length - 2] || null;
|
|
528
|
+
}, [currentTocPath]);
|
|
754
529
|
// Keep selectedSectionId ref in sync
|
|
755
530
|
useEffect(() => {
|
|
756
531
|
selectedSectionIdRef.current = selectedSectionId;
|
|
757
532
|
}, [selectedSectionId]);
|
|
758
|
-
useEffect(() => {
|
|
759
|
-
currentSectionRef.current = currentSection;
|
|
760
|
-
}, [currentSection]);
|
|
761
|
-
useEffect(() => {
|
|
762
|
-
manualBackHistoryRef.current = manualBackHistory;
|
|
763
|
-
}, [manualBackHistory]);
|
|
764
|
-
useEffect(() => {
|
|
765
|
-
const previousSelectedSectionId = lastObservedSelectedSectionIdRef.current;
|
|
766
|
-
if (previousSelectedSectionId === undefined) {
|
|
767
|
-
lastObservedSelectedSectionIdRef.current = selectedSectionId;
|
|
768
|
-
return;
|
|
769
|
-
}
|
|
770
|
-
const normalizedPreviousSelectedSectionId = previousSelectedSectionId && toc.length > 0
|
|
771
|
-
? resolveSelectedSectionId(toc, previousSelectedSectionId)
|
|
772
|
-
: previousSelectedSectionId;
|
|
773
|
-
const normalizedSelectedSectionId = selectedSectionId && toc.length > 0
|
|
774
|
-
? resolveSelectedSectionId(toc, selectedSectionId)
|
|
775
|
-
: selectedSectionId;
|
|
776
|
-
if (normalizedPreviousSelectedSectionId === normalizedSelectedSectionId) {
|
|
777
|
-
lastObservedSelectedSectionIdRef.current = selectedSectionId;
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
if (historyNavigationModeRef.current === "back") {
|
|
781
|
-
historyNavigationModeRef.current = null;
|
|
782
|
-
}
|
|
783
|
-
else {
|
|
784
|
-
setManualBackHistory((prev) => [
|
|
785
|
-
...prev,
|
|
786
|
-
normalizedPreviousSelectedSectionId,
|
|
787
|
-
]);
|
|
788
|
-
}
|
|
789
|
-
lastObservedSelectedSectionIdRef.current = selectedSectionId;
|
|
790
|
-
}, [selectedSectionId, toc]);
|
|
791
|
-
useEffect(() => {
|
|
792
|
-
if (!selectedSectionId || !editContext || toc.length === 0)
|
|
793
|
-
return;
|
|
794
|
-
const resolvedSectionId = resolveSelectedSectionId(toc, selectedSectionId);
|
|
795
|
-
if (resolvedSectionId !== selectedSectionId) {
|
|
796
|
-
editContext.setSelectedHelpSectionId(resolvedSectionId);
|
|
797
|
-
}
|
|
798
|
-
}, [editContext, selectedSectionId, toc]);
|
|
799
533
|
// Build set of all TOC item IDs (for websocket matching)
|
|
800
534
|
useEffect(() => {
|
|
801
535
|
const collectIds = (sections) => {
|
|
@@ -817,6 +551,10 @@ export function ManualBrowser({ onClose }) {
|
|
|
817
551
|
loadManualToc()
|
|
818
552
|
.then((data) => {
|
|
819
553
|
setToc(data);
|
|
554
|
+
// Auto-select first section if available
|
|
555
|
+
if (data.length > 0 && data[0]) {
|
|
556
|
+
setSelectedSectionId(data[0].id);
|
|
557
|
+
}
|
|
820
558
|
})
|
|
821
559
|
.catch((err) => {
|
|
822
560
|
console.error("Failed to load manual TOC:", err);
|
|
@@ -828,96 +566,28 @@ export function ManualBrowser({ onClose }) {
|
|
|
828
566
|
}, []);
|
|
829
567
|
// Load section content when selection changes or revision changes
|
|
830
568
|
useEffect(() => {
|
|
831
|
-
let cancelled = false;
|
|
832
569
|
if (!selectedSectionId) {
|
|
833
570
|
setCurrentSection(null);
|
|
834
571
|
setLoadingSection(false);
|
|
835
572
|
return;
|
|
836
573
|
}
|
|
837
|
-
const resolvedSectionId = toc.length > 0
|
|
838
|
-
? resolveSelectedSectionId(toc, selectedSectionId)
|
|
839
|
-
: selectedSectionId;
|
|
840
|
-
if (resolvedSectionId !== selectedSectionId) {
|
|
841
|
-
return () => {
|
|
842
|
-
cancelled = true;
|
|
843
|
-
};
|
|
844
|
-
}
|
|
845
574
|
// Only show loading spinner if we don't have current section (initial load)
|
|
846
575
|
// For refreshes, keep showing the old content to avoid flicker
|
|
847
|
-
const isInitialLoad = !
|
|
848
|
-
currentSectionRef.current.id !== selectedSectionId;
|
|
576
|
+
const isInitialLoad = !currentSection || currentSection.id !== selectedSectionId;
|
|
849
577
|
if (isInitialLoad) {
|
|
850
578
|
setLoadingSection(true);
|
|
851
579
|
}
|
|
852
|
-
loadManualSection(
|
|
580
|
+
loadManualSection(selectedSectionId)
|
|
853
581
|
.then((data) => {
|
|
854
|
-
if (cancelled)
|
|
855
|
-
return;
|
|
856
582
|
setCurrentSection(data);
|
|
857
583
|
setLoadingSection(false);
|
|
858
584
|
})
|
|
859
585
|
.catch((err) => {
|
|
860
|
-
if (cancelled)
|
|
861
|
-
return;
|
|
862
586
|
console.error("Failed to load section:", err);
|
|
863
587
|
setCurrentSection(null);
|
|
864
588
|
setLoadingSection(false);
|
|
865
589
|
});
|
|
866
|
-
|
|
867
|
-
cancelled = true;
|
|
868
|
-
};
|
|
869
|
-
}, [sectionRevision, selectedSectionId, toc]);
|
|
870
|
-
// Search manual sections using internal search (SQL + AI providers).
|
|
871
|
-
useEffect(() => {
|
|
872
|
-
let cancelled = false;
|
|
873
|
-
const trimmedQuery = searchQuery.trim();
|
|
874
|
-
if (!trimmedQuery || !editContext) {
|
|
875
|
-
setSearching(false);
|
|
876
|
-
setSearchResults([]);
|
|
877
|
-
return;
|
|
878
|
-
}
|
|
879
|
-
const timeoutId = window.setTimeout(async () => {
|
|
880
|
-
setSearching(true);
|
|
881
|
-
try {
|
|
882
|
-
const result = await executeSearch({
|
|
883
|
-
query: `${trimmedQuery}|template:${MANUAL_SECTION_TEMPLATE_ID}`,
|
|
884
|
-
editContext,
|
|
885
|
-
maxResults: 20,
|
|
886
|
-
index: "master",
|
|
887
|
-
skipValidation: true,
|
|
888
|
-
});
|
|
889
|
-
if (cancelled)
|
|
890
|
-
return;
|
|
891
|
-
if (result.type === "success") {
|
|
892
|
-
const items = result.data || [];
|
|
893
|
-
const mapped = items
|
|
894
|
-
.map((item) => manualSectionsById.get(String(item.id || "").toLowerCase()))
|
|
895
|
-
.filter((section) => !!section);
|
|
896
|
-
const unique = Array.from(new Map(mapped.map((section) => [section.id, section])).values());
|
|
897
|
-
setSearchResults(unique);
|
|
898
|
-
}
|
|
899
|
-
else {
|
|
900
|
-
console.error("Failed to search manual", result.response.statusText);
|
|
901
|
-
setSearchResults([]);
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
catch (err) {
|
|
905
|
-
if (!cancelled) {
|
|
906
|
-
console.error("Manual search failed", err);
|
|
907
|
-
setSearchResults([]);
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
finally {
|
|
911
|
-
if (!cancelled) {
|
|
912
|
-
setSearching(false);
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
}, 300);
|
|
916
|
-
return () => {
|
|
917
|
-
cancelled = true;
|
|
918
|
-
window.clearTimeout(timeoutId);
|
|
919
|
-
};
|
|
920
|
-
}, [searchQuery, editContext, manualSectionsById]);
|
|
590
|
+
}, [selectedSectionId, sectionRevision]);
|
|
921
591
|
// Listen for websocket messages to auto-refresh when manual items change
|
|
922
592
|
// Use ref for selectedSectionId to avoid stale closures and only re-register when selection actually changes
|
|
923
593
|
useEffect(() => {
|
|
@@ -951,43 +621,8 @@ export function ManualBrowser({ onClose }) {
|
|
|
951
621
|
return removeListener;
|
|
952
622
|
}, [selectedSectionId]); // Only re-register when selectedSectionId changes, not when editContext object changes
|
|
953
623
|
const handleSelectSection = useCallback((id) => {
|
|
954
|
-
|
|
955
|
-
return;
|
|
956
|
-
editContext.setSelectedHelpSectionId(resolveSelectedSectionId(toc, id));
|
|
957
|
-
}, [editContext, toc]);
|
|
958
|
-
const handleSelectSearchResult = useCallback((id) => {
|
|
959
|
-
if (!editContext)
|
|
960
|
-
return;
|
|
961
|
-
editContext.setSelectedHelpSectionId(resolveSelectedSectionId(toc, id));
|
|
962
|
-
setSearchQuery("");
|
|
963
|
-
setSearchResults([]);
|
|
964
|
-
}, [editContext, toc]);
|
|
965
|
-
const handleToggleTocSection = useCallback((id) => {
|
|
966
|
-
setCollapsedTocSectionIds((prev) => {
|
|
967
|
-
const next = new Set(prev);
|
|
968
|
-
if (next.has(id)) {
|
|
969
|
-
next.delete(id);
|
|
970
|
-
}
|
|
971
|
-
else {
|
|
972
|
-
next.add(id);
|
|
973
|
-
}
|
|
974
|
-
return next;
|
|
975
|
-
});
|
|
624
|
+
setSelectedSectionId(id);
|
|
976
625
|
}, []);
|
|
977
|
-
const normalizeHistorySectionId = useCallback((id) => {
|
|
978
|
-
if (!id || toc.length === 0)
|
|
979
|
-
return id;
|
|
980
|
-
return resolveSelectedSectionId(toc, id);
|
|
981
|
-
}, [toc]);
|
|
982
|
-
const handleGoBack = useCallback(() => {
|
|
983
|
-
if (!editContext || !selectedSectionId)
|
|
984
|
-
return;
|
|
985
|
-
const history = manualBackHistoryRef.current;
|
|
986
|
-
const previousSectionId = history.length > 0 ? history[history.length - 1] : null;
|
|
987
|
-
historyNavigationModeRef.current = "back";
|
|
988
|
-
setManualBackHistory((prev) => prev.length > 0 ? prev.slice(0, -1) : prev);
|
|
989
|
-
editContext.setSelectedHelpSectionId(normalizeHistorySectionId(previousSectionId));
|
|
990
|
-
}, [editContext, normalizeHistorySectionId, selectedSectionId]);
|
|
991
626
|
if (loadingToc) {
|
|
992
627
|
return (_jsx("div", { className: "flex items-center justify-center py-8", children: _jsx(Loader2, { className: "h-5 w-5 animate-spin text-gray-400" }) }));
|
|
993
628
|
}
|
|
@@ -997,7 +632,7 @@ export function ManualBrowser({ onClose }) {
|
|
|
997
632
|
if (toc.length === 0) {
|
|
998
633
|
return (_jsxs("div", { className: "px-4 py-8 text-center text-sm text-gray-500", children: [_jsx(Book, { className: "mx-auto mb-2 h-8 w-8 text-gray-300" }), _jsx("p", { children: "No manual content available yet." })] }));
|
|
999
634
|
}
|
|
1000
|
-
return (_jsxs("div", { className: "flex h-full flex-col", children: [
|
|
635
|
+
return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsx("div", { className: "shrink-0 border-b border-gray-100 px-3 py-2", children: _jsx(Select, { value: selectedSectionId || undefined, onValueChange: handleSelectSection, options: sectionOptions, placeholder: "Select a section...", size: "sm", className: "w-full rounded-md", searchable: sectionOptions.length > 10, searchPlaceholder: "Search sections..." }) }), _jsx("div", { className: "flex-1 overflow-y-auto p-4 select-text", children: loadingSection ? (_jsx("div", { className: "flex items-center justify-center py-8", children: _jsx(Loader2, { className: "h-5 w-5 animate-spin text-gray-400" }) })) : currentSection ? (_jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-start justify-between gap-2", children: [_jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-2", children: [parentTocSection && (_jsxs("button", { type: "button", onClick: () => handleSelectSection(parentTocSection.id), className: "inline-flex shrink-0 items-center gap-1 rounded px-2 py-1 text-sm text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900", "aria-label": `Back to ${parentTocSection.title}`, title: `Back to ${parentTocSection.title}`, children: [_jsx(ArrowLeft, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "Back" })] })), _jsx("h2", { className: "min-w-0 flex-1 text-xl font-bold text-gray-900", children: currentSection.title })] }), editContext?.user?.isAdministrator && editContext?.loadItem && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: async (e) => {
|
|
1001
636
|
e.preventDefault();
|
|
1002
637
|
e.stopPropagation();
|
|
1003
638
|
if (!editContext?.loadItem) {
|
|
@@ -1005,6 +640,7 @@ export function ManualBrowser({ onClose }) {
|
|
|
1005
640
|
return;
|
|
1006
641
|
}
|
|
1007
642
|
try {
|
|
643
|
+
// Load the manual section item in the editor
|
|
1008
644
|
const language = editContext?.currentItemDescriptor?.language ||
|
|
1009
645
|
editContext?.item?.language ||
|
|
1010
646
|
"en";
|
|
@@ -1019,20 +655,7 @@ export function ManualBrowser({ onClose }) {
|
|
|
1019
655
|
catch (error) {
|
|
1020
656
|
console.error("Failed to load manual section:", error);
|
|
1021
657
|
}
|
|
1022
|
-
}, className: "shrink-0 rounded p-1.5 text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700", "aria-label": "Edit item", title: "Edit item", children: _jsx(Edit, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: "Edit item" })] }))] }),
|
|
1023
|
-
(() => {
|
|
1024
|
-
const theme = parentTocSection
|
|
1025
|
-
? getSectionTheme(parentTocSection.title)
|
|
1026
|
-
: getSectionTheme(currentSection.title);
|
|
1027
|
-
return (_jsx("p", { className: cn("my-4 mb-8 border-l-2 pl-3 text-sm text-gray-500 italic", theme.border), children: currentSection.summary }));
|
|
1028
|
-
})(), _jsx("div", { className: "prose prose-sm max-w-none select-text", children: renderMarkdownWithSelectors(currentSection.content || "", parseUiSelectors(currentSection.uiSelectors), manualLinkTargets, handleSelectSection) }), currentSection.subsections &&
|
|
1029
|
-
currentSection.subsections.length > 0 && (_jsxs("div", { className: "mt-8 border-t border-gray-100 pt-4", children: [_jsx("h3", { className: "mb-3 text-[11px] font-bold tracking-widest text-gray-400 uppercase", children: "In this section" }), _jsx("div", { className: "space-y-0.5", children: currentSection.subsections.map((subsection) => {
|
|
1030
|
-
const theme = getSectionTheme(currentSection.title);
|
|
1031
|
-
return (_jsxs("button", { onClick: () => handleSelectSection(subsection.id), className: "group flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-left text-sm text-gray-600 transition-all hover:bg-gray-50 hover:text-gray-900", children: [_jsx("span", { className: cn("h-1.5 w-1.5 shrink-0 rounded-full transition-transform group-hover:scale-125", theme.accent, "opacity-50 group-hover:opacity-80") }), _jsx("span", { className: "flex-1 truncate font-medium", children: subsection.title }), _jsx(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 text-gray-300 transition-colors group-hover:text-gray-500" })] }, subsection.id));
|
|
1032
|
-
}) })] }))] })) : (_jsx("div", { className: "py-8 text-center text-sm text-gray-500", children: "Select a section to view its content" })) }), selectedSectionId &&
|
|
1033
|
-
currentSection &&
|
|
1034
|
-
(chapterNavigation.previous || chapterNavigation.next) && (_jsx("div", { className: "shrink-0 border-t border-gray-200/60 bg-white px-4 py-3", children: _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [chapterNavigation.previous ? (_jsxs("button", { type: "button", onClick: () => chapterNavigation.previous &&
|
|
1035
|
-
handleSelectSection(chapterNavigation.previous.id), className: "group rounded-lg border border-gray-200 px-3 py-2 text-left transition-all hover:border-blue-200 hover:bg-blue-50/30", children: [_jsxs("span", { className: "mb-0.5 inline-flex items-center gap-1 text-xs font-medium text-gray-400 transition-colors group-hover:text-blue-500", children: [_jsx(ArrowLeft, { className: "h-3 w-3" }), "Previous"] }), _jsx("span", { className: "block truncate text-sm font-medium text-gray-700 transition-colors group-hover:text-gray-900", children: chapterNavigation.previous.title })] })) : (_jsx("div", {})), chapterNavigation.next ? (_jsxs("button", { type: "button", onClick: () => chapterNavigation.next &&
|
|
1036
|
-
handleSelectSection(chapterNavigation.next.id), className: "group rounded-lg border border-gray-200 px-3 py-2 text-right transition-all hover:border-blue-200 hover:bg-blue-50/30", children: [_jsxs("span", { className: "mb-0.5 inline-flex items-center justify-end gap-1 text-xs font-medium text-gray-400 transition-colors group-hover:text-blue-500", children: ["Next", _jsx(ArrowRight, { className: "h-3 w-3" })] }), _jsx("span", { className: "block truncate text-sm font-medium text-gray-700 transition-colors group-hover:text-gray-900", children: chapterNavigation.next.title })] })) : (_jsx("div", {}))] }) }))] }));
|
|
658
|
+
}, className: "shrink-0 rounded p-1.5 text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700", "aria-label": "Edit item", title: "Edit item", children: _jsx(Edit, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: "Edit item" })] }))] }), currentSection.summary && (_jsx("p", { className: "mb-3 text-sm text-gray-500", children: currentSection.summary })), _jsx("div", { className: "prose prose-sm max-w-none select-text", children: renderMarkdownWithSelectors(currentSection.content || "", parseUiSelectors(currentSection.uiSelectors)) }), currentSection.subsections &&
|
|
659
|
+
currentSection.subsections.length > 0 && (_jsxs("div", { className: "mt-6 border-t border-gray-200 pt-4", children: [_jsx("h3", { className: "mb-3 text-sm font-semibold text-gray-700", children: "Subsections" }), _jsx("ul", { className: "space-y-2", children: currentSection.subsections.map((subsection) => (_jsx("li", { children: _jsx("button", { onClick: () => handleSelectSection(subsection.id), className: "text-left text-sm text-blue-600 hover:text-blue-800 hover:underline", children: subsection.title }) }, subsection.id))) })] }))] })) : (_jsx("div", { className: "py-8 text-center text-sm text-gray-500", children: "Select a section to view its content" })) })] }));
|
|
1037
660
|
}
|
|
1038
661
|
//# sourceMappingURL=ManualBrowser.js.map
|