@parhelia/core 0.1.12881 → 0.1.12882
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/components/ui/card.d.ts +1 -3
- package/dist/components/ui/card.js +2 -2
- package/dist/components/ui/card.js.map +1 -1
- package/dist/components/ui/context-menu.js +2 -2
- package/dist/config/config.js +7 -8
- package/dist/config/config.js.map +1 -1
- package/dist/config/types.d.ts +7 -0
- package/dist/config/types.js.map +1 -1
- package/dist/editor/FieldActionsOverlay.d.ts +1 -0
- package/dist/editor/FieldActionsOverlay.js +45 -1
- package/dist/editor/FieldActionsOverlay.js.map +1 -1
- package/dist/editor/FieldListField.d.ts +1 -1
- package/dist/editor/FieldListField.js +18 -20
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/ImageEditor.d.ts +1 -6
- package/dist/editor/ImageEditor.js +3 -19
- package/dist/editor/ImageEditor.js.map +1 -1
- package/dist/editor/PictureEditor.d.ts +1 -2
- package/dist/editor/PictureEditor.js +14 -5
- package/dist/editor/PictureEditor.js.map +1 -1
- package/dist/editor/ai/Agents.js +2 -2
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/GuidanceOverlay.js +11 -1
- package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
- package/dist/editor/ai/InlineAiDialog.js +11 -22
- package/dist/editor/ai/InlineAiDialog.js.map +1 -1
- package/dist/editor/ai/InlineAiTrigger.js +57 -17
- package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
- package/dist/editor/ai/dialogs/capturePageDom.js +36 -66
- package/dist/editor/ai/dialogs/capturePageDom.js.map +1 -1
- package/dist/editor/ai/dialogs/capturePageScreenshot.js +162 -281
- package/dist/editor/ai/dialogs/capturePageScreenshot.js.map +1 -1
- package/dist/editor/ai/terminal/agentSessionState.d.ts +0 -3
- package/dist/editor/ai/terminal/agentSessionState.js +1 -3
- package/dist/editor/ai/terminal/agentSessionState.js.map +1 -1
- package/dist/editor/ai/terminal/agentStartRequest.d.ts +1 -2
- package/dist/editor/ai/terminal/agentStartRequest.js +1 -2
- package/dist/editor/ai/terminal/agentStartRequest.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentCostDisplay.js +1 -1
- package/dist/editor/ai/terminal/components/AgentCostDisplay.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentDocumentList.d.ts +0 -7
- package/dist/editor/ai/terminal/components/AgentDocumentList.js +13 -55
- package/dist/editor/ai/terminal/components/AgentDocumentList.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentFullPromptControls.d.ts +1 -3
- package/dist/editor/ai/terminal/components/AgentFullPromptControls.js +14 -22
- package/dist/editor/ai/terminal/components/AgentFullPromptControls.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentModeSelector.js +4 -4
- package/dist/editor/ai/terminal/components/AgentModeSelector.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentPromptActionButtons.js +4 -4
- package/dist/editor/ai/terminal/components/AgentPromptActionButtons.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentPromptComposer.js +1 -1
- package/dist/editor/ai/terminal/components/AgentPromptComposer.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentPromptInputArea.d.ts +1 -2
- package/dist/editor/ai/terminal/components/AgentPromptInputArea.js +11 -8
- package/dist/editor/ai/terminal/components/AgentPromptInputArea.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.d.ts +4 -1
- package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js +14 -31
- package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentSettingsPopover.js +1 -1
- package/dist/editor/ai/terminal/components/AgentSettingsPopover.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.d.ts +1 -2
- package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.js +4 -2
- package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalView.js +2 -13
- package/dist/editor/ai/terminal/components/AgentTerminalView.js.map +1 -1
- package/dist/editor/ai/terminal/components/AiResponseMessage.js +14 -16
- package/dist/editor/ai/terminal/components/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/terminal/components/ContextInfoBar.js +2 -22
- package/dist/editor/ai/terminal/components/ContextInfoBar.js.map +1 -1
- package/dist/editor/ai/terminal/components/QueuedPromptsPanel.js +26 -37
- package/dist/editor/ai/terminal/components/QueuedPromptsPanel.js.map +1 -1
- package/dist/editor/ai/terminal/components/UserMessage.d.ts +1 -2
- package/dist/editor/ai/terminal/components/UserMessage.js +8 -144
- package/dist/editor/ai/terminal/components/UserMessage.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentPromptComposerHandlers.js +1 -1
- package/dist/editor/ai/terminal/useAgentPromptComposerHandlers.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentSessionSync.d.ts +0 -1
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.d.ts +1 -3
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.js +3 -9
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentTerminalController.js +0 -7
- package/dist/editor/ai/terminal/useAgentTerminalController.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentTerminalUiState.js +1 -1
- package/dist/editor/ai/terminal/useAgentTerminalUiState.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentUserMessageSocketHandler.js +1 -3
- package/dist/editor/ai/terminal/useAgentUserMessageSocketHandler.js.map +1 -1
- package/dist/editor/ai/useInlineAiPosition.d.ts +1 -1
- package/dist/editor/ai/useInlineAiPosition.js +52 -22
- package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
- package/dist/editor/ai-image-editor/AiImageResultOverlay.js +62 -30
- package/dist/editor/ai-image-editor/AiImageResultOverlay.js.map +1 -1
- package/dist/editor/client/EditorShell.d.ts +1 -5
- package/dist/editor/client/EditorShell.js +136 -285
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +5 -33
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js +17 -14
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/itemsRepository.d.ts +0 -2
- package/dist/editor/client/itemsRepository.js +8 -15
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/client/operations.d.ts +1 -1
- package/dist/editor/client/operations.js +17 -41
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/client/pageModelBuilder.js +7 -24
- package/dist/editor/client/pageModelBuilder.js.map +1 -1
- package/dist/editor/commands/handlers/uiActionHandlers.js +5 -1
- package/dist/editor/commands/handlers/uiActionHandlers.js.map +1 -1
- package/dist/editor/editor-warnings/FinalWorkflowStateReadOnly.js +5 -0
- package/dist/editor/editor-warnings/FinalWorkflowStateReadOnly.js.map +1 -1
- package/dist/editor/editor-warnings/ItemLocked.js +6 -3
- package/dist/editor/editor-warnings/ItemLocked.js.map +1 -1
- package/dist/editor/field-types/MultiLineText.js +3 -10
- package/dist/editor/field-types/MultiLineText.js.map +1 -1
- package/dist/editor/field-types/RawEditor.js +1 -8
- package/dist/editor/field-types/RawEditor.js.map +1 -1
- package/dist/editor/field-types/RichTextEditorComponent.js +45 -156
- package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js +3 -10
- package/dist/editor/field-types/SingleLineText.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ReactSlate.js +2 -8
- package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
- package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +2 -1
- package/dist/editor/field-types/richtext/contextMenuFactory.js +303 -100
- 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/media-selector/MediaFolderBrowser.d.ts +2 -1
- package/dist/editor/media-selector/MediaFolderBrowser.js +19 -9
- package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
- package/dist/editor/media-selector/TreeSelector.js +30 -24
- package/dist/editor/media-selector/TreeSelector.js.map +1 -1
- package/dist/editor/media-selector/UploadZone.d.ts +2 -1
- package/dist/editor/media-selector/UploadZone.js +21 -9
- package/dist/editor/media-selector/UploadZone.js.map +1 -1
- package/dist/editor/menubar/PageSelector.js +2 -8
- package/dist/editor/menubar/PageSelector.js.map +1 -1
- package/dist/editor/menubar/VersionPreviewCard.js +249 -4
- package/dist/editor/menubar/VersionPreviewCard.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/EditControls.js +2 -2
- package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.d.ts +10 -0
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +462 -63
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlightings.d.ts +2 -5
- package/dist/editor/page-editor-chrome/CommentHighlightings.js +215 -340
- package/dist/editor/page-editor-chrome/CommentHighlightings.js.map +1 -1
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.d.ts +1 -5
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js +4 -11
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js.map +1 -1
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js +13 -21
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/FieldEditedIndicator.js +29 -23
- package/dist/editor/page-editor-chrome/FieldEditedIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +19 -110
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/InlineEditor.d.ts +7 -0
- package/dist/editor/page-editor-chrome/InlineEditor.js +1719 -0
- package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -0
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.d.ts +2 -3
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.js +45 -148
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/PageEditorChrome.d.ts +0 -2
- package/dist/editor/page-editor-chrome/PageEditorChrome.js +21 -25
- package/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -1
- package/dist/editor/page-editor-chrome/PictureEditorOverlay.js +128 -163
- package/dist/editor/page-editor-chrome/PictureEditorOverlay.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.d.ts +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +3 -6
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.d.ts +2 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +146 -83
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.d.ts +2 -5
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js +63 -144
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js.map +1 -1
- package/dist/editor/page-editor-chrome/VersionDiffHighlightings.d.ts +2 -1
- package/dist/editor/page-editor-chrome/VersionDiffHighlightings.js +30 -101
- package/dist/editor/page-editor-chrome/VersionDiffHighlightings.js.map +1 -1
- package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.d.ts +1 -10
- package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js +122 -105
- package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js.map +1 -1
- package/dist/editor/page-editor-chrome/overlay/geometry.d.ts +4 -11
- package/dist/editor/page-editor-chrome/overlay/geometry.js +36 -139
- package/dist/editor/page-editor-chrome/overlay/geometry.js.map +1 -1
- package/dist/editor/page-editor-chrome/overlay/iframeAccess.d.ts +2 -0
- package/dist/editor/page-editor-chrome/overlay/iframeAccess.js +21 -0
- package/dist/editor/page-editor-chrome/overlay/iframeAccess.js.map +1 -0
- package/dist/editor/page-editor-chrome/useInlineAICompletion.d.ts +7 -0
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js +758 -0
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -0
- package/dist/editor/page-viewer/EditorForm.js +1 -17
- package/dist/editor/page-viewer/EditorForm.js.map +1 -1
- package/dist/editor/page-viewer/MiniMap.d.ts +2 -2
- package/dist/editor/page-viewer/MiniMap.js +364 -176
- package/dist/editor/page-viewer/MiniMap.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js +13 -40
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.d.ts +5 -0
- package/dist/editor/page-viewer/PageViewerFrame.js +1509 -1527
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.d.ts +3 -0
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +796 -0
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -0
- package/dist/editor/page-viewer/pageViewContext.d.ts +0 -32
- package/dist/editor/page-viewer/pageViewContext.js +6 -37
- package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
- package/dist/editor/reviews/Comment.d.ts +1 -2
- package/dist/editor/reviews/Comment.js +4 -9
- package/dist/editor/reviews/Comment.js.map +1 -1
- package/dist/editor/reviews/CommentEditor.js +1 -1
- package/dist/editor/reviews/CommentEditor.js.map +1 -1
- package/dist/editor/reviews/CommentPopover.js +9 -68
- package/dist/editor/reviews/CommentPopover.js.map +1 -1
- package/dist/editor/reviews/CommentView.js +4 -24
- package/dist/editor/reviews/CommentView.js.map +1 -1
- package/dist/editor/reviews/Comments.d.ts +2 -0
- package/dist/editor/reviews/Comments.js +30 -29
- package/dist/editor/reviews/Comments.js.map +1 -1
- package/dist/editor/reviews/FeedbackCard.d.ts +2 -4
- package/dist/editor/reviews/FeedbackCard.js +5 -5
- package/dist/editor/reviews/FeedbackCard.js.map +1 -1
- package/dist/editor/reviews/SuggestedEdit.js +6 -4
- package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
- package/dist/editor/reviews/SuggestionDisplayPopover.js +2 -3
- package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/commentAi.js +27 -96
- package/dist/editor/reviews/commentAi.js.map +1 -1
- package/dist/editor/reviews/feedbackSelection.js +4 -32
- package/dist/editor/reviews/feedbackSelection.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +0 -15
- package/dist/editor/services/agentService.js +1 -11
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/contentService.d.ts +1 -0
- package/dist/editor/services/contentService.js.map +1 -1
- package/dist/editor/services/reviewsService.d.ts +2 -2
- package/dist/editor/services/reviewsService.js.map +1 -1
- package/dist/editor/settings/SettingsView.js +2 -2
- package/dist/editor/settings/SettingsView.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js +1 -1
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProvidersPanel.js +3 -2
- package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
- package/dist/editor/sidebar/MorePanelsButton.js +1 -1
- package/dist/editor/sidebar/MorePanelsButton.js.map +1 -1
- package/dist/editor/sidebar/Workbox.js +1 -1
- package/dist/editor/sidebar/Workbox.js.map +1 -1
- package/dist/editor/ui/IconSelectorDialog.js +1 -1
- package/dist/editor/ui/IconSelectorDialog.js.map +1 -1
- package/dist/editor/ui/SimpleIconButton.d.ts +2 -2
- package/dist/editor/ui/SimpleIconButton.js +1 -1
- package/dist/editor/ui/SimpleIconButton.js.map +1 -1
- package/dist/editor/utils.d.ts +17 -1
- package/dist/editor/utils.js +143 -0
- package/dist/editor/utils.js.map +1 -1
- package/dist/editor/version-diff/versionDiffTargets.d.ts +8 -3
- package/dist/editor/version-diff/versionDiffTargets.js +94 -37
- package/dist/editor/version-diff/versionDiffTargets.js.map +1 -1
- package/dist/editor/views/MediaFolderEditView.js +1 -1
- package/dist/editor/views/MediaFolderEditView.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/DialogWrappers.js +2 -2
- package/dist/splash-screen/DialogWrappers.js.map +1 -1
- package/dist/splash-screen/ModernSplashScreen.js +3 -11
- package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
- package/dist/splash-screen/NewPage.js +5 -7
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/OpenPage.js +3 -5
- package/dist/splash-screen/OpenPage.js.map +1 -1
- package/dist/splash-screen/RecentPages.js +3 -3
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/package.json +1 -2
- package/styles.css +0 -49
- package/dist/editor/ai/terminal/components/AgentEditHistoryButton.d.ts +0 -5
- package/dist/editor/ai/terminal/components/AgentEditHistoryButton.js +0 -12
- package/dist/editor/ai/terminal/components/AgentEditHistoryButton.js.map +0 -1
- package/dist/editor/bridge/BridgeClient.d.ts +0 -80
- package/dist/editor/bridge/BridgeClient.js +0 -417
- package/dist/editor/bridge/BridgeClient.js.map +0 -1
- package/dist/editor/field-types/useFormFieldCaretPresence.d.ts +0 -13
- package/dist/editor/field-types/useFormFieldCaretPresence.js +0 -92
- package/dist/editor/field-types/useFormFieldCaretPresence.js.map +0 -1
- package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.d.ts +0 -6
- package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js +0 -123
- package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js.map +0 -1
- package/dist/editor/page-editor-chrome/useBridgeInlineEditing.d.ts +0 -26
- package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js +0 -222
- package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js.map +0 -1
- package/dist/editor/page-viewer/bridgeFieldPatch.d.ts +0 -20
- package/dist/editor/page-viewer/bridgeFieldPatch.js +0 -33
- package/dist/editor/page-viewer/bridgeFieldPatch.js.map +0 -1
- package/dist/editor/reviews/commentTransientSelection.d.ts +0 -23
- package/dist/editor/reviews/commentTransientSelection.js +0 -7
- package/dist/editor/reviews/commentTransientSelection.js.map +0 -1
- package/dist/editor/reviews/feedbackOrdering.d.ts +0 -5
- package/dist/editor/reviews/feedbackOrdering.js +0 -27
- package/dist/editor/reviews/feedbackOrdering.js.map +0 -1
- package/dist/editor/reviews/suggestedEditState.d.ts +0 -12
- package/dist/editor/reviews/suggestedEditState.js +0 -90
- package/dist/editor/reviews/suggestedEditState.js.map +0 -1
- package/dist/editor/reviews/suggestionDisplayValue.d.ts +0 -43
- package/dist/editor/reviews/suggestionDisplayValue.js +0 -93
- package/dist/editor/reviews/suggestionDisplayValue.js.map +0 -1
|
@@ -17,6 +17,60 @@ function SvgIcon({ svg, size, className, }) {
|
|
|
17
17
|
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 } }));
|
|
18
18
|
}
|
|
19
19
|
const HIGHLIGHT_DURATION_MS = 2000;
|
|
20
|
+
const EDITOR_FORM_SLIDER_SELECTOR = '[data-testid="editor-form-slider"]';
|
|
21
|
+
const EDITOR_FORM_HIDDEN_ATTRIBUTE = "aria-hidden";
|
|
22
|
+
const CLOSE_PANE_LABEL = "Close pane";
|
|
23
|
+
function waitForDelay(delayMs) {
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
window.setTimeout(resolve, delayMs);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function getEditorFormSlider(elements = []) {
|
|
29
|
+
for (const element of elements) {
|
|
30
|
+
const slider = element.closest(EDITOR_FORM_SLIDER_SELECTOR);
|
|
31
|
+
if (slider) {
|
|
32
|
+
return slider;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return document.querySelector(EDITOR_FORM_SLIDER_SELECTOR);
|
|
36
|
+
}
|
|
37
|
+
function isEditorFormSliderHidden(slider) {
|
|
38
|
+
return slider?.getAttribute(EDITOR_FORM_HIDDEN_ATTRIBUTE) === "true";
|
|
39
|
+
}
|
|
40
|
+
async function waitForEditorFormSliderOpen(slider, timeoutMs = 1000) {
|
|
41
|
+
const startedAt = Date.now();
|
|
42
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
43
|
+
if (!isEditorFormSliderHidden(slider ?? getEditorFormSlider())) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
await waitForDelay(50);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function waitForResolvedElements(resolveElements, selector, timeoutMs = 1000) {
|
|
50
|
+
const startedAt = Date.now();
|
|
51
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
52
|
+
const elements = resolveElements(selector);
|
|
53
|
+
if (elements.length > 0) {
|
|
54
|
+
return elements;
|
|
55
|
+
}
|
|
56
|
+
await waitForDelay(50);
|
|
57
|
+
}
|
|
58
|
+
return resolveElements(selector);
|
|
59
|
+
}
|
|
60
|
+
// Wait until at least one element for the selector is actually VISIBLE (not just
|
|
61
|
+
// present). After a reveal/animation a target can be in the DOM but not yet laid
|
|
62
|
+
// out, which would otherwise cause highlightElement to skip it.
|
|
63
|
+
async function waitForVisibleElements(selector, timeoutMs = 1000) {
|
|
64
|
+
const startedAt = Date.now();
|
|
65
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
66
|
+
const elements = getVisibleElementsForSelector(selector);
|
|
67
|
+
if (elements.length > 0) {
|
|
68
|
+
return elements;
|
|
69
|
+
}
|
|
70
|
+
await waitForDelay(50);
|
|
71
|
+
}
|
|
72
|
+
return getVisibleElementsForSelector(selector);
|
|
73
|
+
}
|
|
20
74
|
const manualMarkdownComponents = {
|
|
21
75
|
h1: ({ children }) => (_jsx("h1", { className: "text-neutral-grey-100 mt-4 mb-0 text-xl font-bold", children: children })),
|
|
22
76
|
h2: ({ children }) => (_jsx("h2", { className: "text-neutral-grey-100 mt-3 mb-0 text-lg font-semibold", children: children })),
|
|
@@ -52,7 +106,15 @@ export function parseUiSelectors(uiSelectors) {
|
|
|
52
106
|
let beforeAction;
|
|
53
107
|
let afterAction;
|
|
54
108
|
let availabilitySelector;
|
|
109
|
+
let selectorOverride;
|
|
110
|
+
let tab;
|
|
111
|
+
let closeMode;
|
|
55
112
|
for (const segment of segments) {
|
|
113
|
+
if (segment.startsWith("close=")) {
|
|
114
|
+
const value = segment.substring("close=".length).trim();
|
|
115
|
+
closeMode = value === "auto" ? "auto" : "click";
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
56
118
|
if (segment.startsWith("beforeAction=")) {
|
|
57
119
|
beforeAction = segment.substring("beforeAction=".length).trim();
|
|
58
120
|
continue;
|
|
@@ -67,6 +129,14 @@ export function parseUiSelectors(uiSelectors) {
|
|
|
67
129
|
.trim();
|
|
68
130
|
continue;
|
|
69
131
|
}
|
|
132
|
+
if (segment.startsWith("selector=")) {
|
|
133
|
+
selectorOverride = segment.substring("selector=".length).trim();
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (segment.startsWith("tab=")) {
|
|
137
|
+
tab = segment.substring("tab=".length).trim();
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
70
140
|
if (!notFoundMessage) {
|
|
71
141
|
notFoundMessage = segment;
|
|
72
142
|
}
|
|
@@ -80,14 +150,16 @@ export function parseUiSelectors(uiSelectors) {
|
|
|
80
150
|
: undefined;
|
|
81
151
|
const parsed = {
|
|
82
152
|
name,
|
|
83
|
-
selector: isSidebarOnly ? "" : `@${name}`,
|
|
153
|
+
selector: isSidebarOnly ? "" : selectorOverride || `@${name}`,
|
|
84
154
|
availabilitySelector,
|
|
155
|
+
tab,
|
|
85
156
|
description,
|
|
86
157
|
notFoundMessage: notFoundMessage || undefined,
|
|
87
158
|
location: isSidebarOnly ? sidebarId : undefined, // Use actual sidebar ID (without -sidebar suffix) for sidebar-only
|
|
88
159
|
isSidebarOnly,
|
|
89
160
|
beforeAction,
|
|
90
161
|
afterAction,
|
|
162
|
+
closeMode,
|
|
91
163
|
};
|
|
92
164
|
// Primary key remains the selector name
|
|
93
165
|
map.set(name, parsed);
|
|
@@ -99,8 +171,7 @@ function parseSelectorToken(selectorToken) {
|
|
|
99
171
|
if (!selectorToken.startsWith("@"))
|
|
100
172
|
return { selector: selectorToken };
|
|
101
173
|
const raw = selectorToken.slice(1);
|
|
102
|
-
// Preserve iframe: selectors
|
|
103
|
-
// goes through the editing bridge instead of same-origin iframe probing.
|
|
174
|
+
// Preserve iframe: selectors (handled specially by expandSelector/highlightElement)
|
|
104
175
|
if (raw.startsWith("iframe:"))
|
|
105
176
|
return { selector: selectorToken };
|
|
106
177
|
// Check for sidebar-only syntax: @sidebar-id-sidebar (e.g., @reviews-sidebar)
|
|
@@ -136,6 +207,7 @@ export function expandSelector(selectorShorthand) {
|
|
|
136
207
|
return selector;
|
|
137
208
|
}
|
|
138
209
|
if (selector.startsWith("iframe:")) {
|
|
210
|
+
// Iframe selector: @iframe:selector → iframe:selector (handled by GuidanceOverlay)
|
|
139
211
|
return selector;
|
|
140
212
|
}
|
|
141
213
|
// Default: data-testid selector: @name → [data-testid="name"]
|
|
@@ -144,10 +216,55 @@ export function expandSelector(selectorShorthand) {
|
|
|
144
216
|
function getElementsForSelector(selector) {
|
|
145
217
|
const cssSelector = expandSelector(selector);
|
|
146
218
|
if (cssSelector.startsWith("iframe:")) {
|
|
147
|
-
|
|
219
|
+
const iframeSelector = cssSelector.substring(7);
|
|
220
|
+
const iframe = document.querySelector("iframe.page-iframe");
|
|
221
|
+
if (!iframe?.contentDocument) {
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
return Array.from(iframe.contentDocument.querySelectorAll(iframeSelector));
|
|
148
225
|
}
|
|
149
226
|
return Array.from(document.querySelectorAll(cssSelector));
|
|
150
227
|
}
|
|
228
|
+
// Determine whether an element is genuinely visible to the user, not merely
|
|
229
|
+
// present in the DOM. A target sitting inside a collapsed panel, a hidden
|
|
230
|
+
// sidebar (aria-hidden), or with `display:none` / `visibility:hidden` / zero
|
|
231
|
+
// size counts as NOT visible.
|
|
232
|
+
function isElementVisible(element) {
|
|
233
|
+
// Treat anything inside an explicitly aria-hidden container (e.g. a collapsed
|
|
234
|
+
// editor form slider) as not visible.
|
|
235
|
+
if (element.closest('[aria-hidden="true"]')) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
const candidate = element;
|
|
239
|
+
if (typeof candidate.checkVisibility === "function") {
|
|
240
|
+
if (!candidate.checkVisibility({
|
|
241
|
+
checkOpacity: true,
|
|
242
|
+
checkVisibilityCSS: true,
|
|
243
|
+
})) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
// Fallback for environments without Element.checkVisibility (e.g. jsdom).
|
|
249
|
+
const style = window.getComputedStyle(element);
|
|
250
|
+
if (style.display === "none" ||
|
|
251
|
+
style.visibility === "hidden" ||
|
|
252
|
+
style.visibility === "collapse") {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
// position:fixed elements have a null offsetParent but can still be visible.
|
|
256
|
+
if (element.offsetParent === null && style.position !== "fixed") {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Reject zero-area elements (e.g. a width:0 collapsed panel).
|
|
261
|
+
const rect = element.getBoundingClientRect();
|
|
262
|
+
return rect.width > 0 && rect.height > 0;
|
|
263
|
+
}
|
|
264
|
+
// Return only the elements matching a selector that are currently visible.
|
|
265
|
+
function getVisibleElementsForSelector(selector) {
|
|
266
|
+
return getElementsForSelector(selector).filter(isElementVisible);
|
|
267
|
+
}
|
|
151
268
|
function shouldSkipHighlightScroll(element) {
|
|
152
269
|
const rect = element.getBoundingClientRect();
|
|
153
270
|
const computedStyle = window.getComputedStyle(element);
|
|
@@ -185,6 +302,32 @@ async function waitForScrollToFinish(element) {
|
|
|
185
302
|
previousRect = currentRect;
|
|
186
303
|
}
|
|
187
304
|
}
|
|
305
|
+
// Wait until an element's box (position and size) stops changing. This avoids
|
|
306
|
+
// drawing the highlight overlay mid-animation (e.g. while a sidebar panel is
|
|
307
|
+
// still expanding from its collapsed width).
|
|
308
|
+
async function waitForStableRect(element, timeoutMs = 1000) {
|
|
309
|
+
let previousRect = element.getBoundingClientRect();
|
|
310
|
+
let stableFrames = 0;
|
|
311
|
+
const startedAt = Date.now();
|
|
312
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
313
|
+
await waitForNextFrame();
|
|
314
|
+
const currentRect = element.getBoundingClientRect();
|
|
315
|
+
const changed = Math.abs(currentRect.width - previousRect.width) > 0.5 ||
|
|
316
|
+
Math.abs(currentRect.height - previousRect.height) > 0.5 ||
|
|
317
|
+
Math.abs(currentRect.top - previousRect.top) > 0.5 ||
|
|
318
|
+
Math.abs(currentRect.left - previousRect.left) > 0.5;
|
|
319
|
+
if (changed) {
|
|
320
|
+
stableFrames = 0;
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
stableFrames += 1;
|
|
324
|
+
if (stableFrames >= 2) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
previousRect = currentRect;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
188
331
|
async function scrollElementForHighlight(element) {
|
|
189
332
|
if (shouldSkipHighlightScroll(element)) {
|
|
190
333
|
return;
|
|
@@ -199,21 +342,57 @@ async function scrollElementForHighlight(element) {
|
|
|
199
342
|
// Highlight an element temporarily
|
|
200
343
|
export async function highlightElement(selector, duration = HIGHLIGHT_DURATION_MS) {
|
|
201
344
|
const cssSelector = expandSelector(selector);
|
|
202
|
-
|
|
345
|
+
// Only ever highlight elements that are actually visible. A target inside a
|
|
346
|
+
// collapsed panel or hidden sidebar must not receive a stray overlay.
|
|
347
|
+
const elements = getElementsForSelector(selector).filter(isElementVisible);
|
|
203
348
|
if (elements.length === 0)
|
|
204
349
|
return;
|
|
350
|
+
if (cssSelector.startsWith("iframe:")) {
|
|
351
|
+
const iframe = document.querySelector("iframe.page-iframe");
|
|
352
|
+
const iframeRect = iframe?.getBoundingClientRect();
|
|
353
|
+
if (elements[0]) {
|
|
354
|
+
await scrollElementForHighlight(elements[0]);
|
|
355
|
+
await waitForStableRect(elements[0]);
|
|
356
|
+
}
|
|
357
|
+
elements.forEach((element) => {
|
|
358
|
+
const elementRect = element.getBoundingClientRect();
|
|
359
|
+
showHighlightOverlay(elementRect.left + (iframeRect?.left ?? 0), elementRect.top + (iframeRect?.top ?? 0), elementRect.width, elementRect.height, duration);
|
|
360
|
+
});
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
205
363
|
if (elements[0]) {
|
|
206
364
|
await scrollElementForHighlight(elements[0]);
|
|
365
|
+
await waitForStableRect(elements[0]);
|
|
207
366
|
}
|
|
208
367
|
elements.forEach((element) => {
|
|
209
368
|
const rect = element.getBoundingClientRect();
|
|
210
369
|
showHighlightOverlay(rect.left, rect.top, rect.width, rect.height, duration);
|
|
211
370
|
});
|
|
212
371
|
}
|
|
213
|
-
// Check if an element is currently
|
|
214
|
-
function
|
|
372
|
+
// Check if an element is currently present in the DOM (regardless of visibility)
|
|
373
|
+
function isElementPresent(selector) {
|
|
215
374
|
return getElementsForSelector(selector).length > 0;
|
|
216
375
|
}
|
|
376
|
+
// Check if an element matching the selector is currently visible to the user
|
|
377
|
+
function isElementVisibleBySelector(selector) {
|
|
378
|
+
return getVisibleElementsForSelector(selector).length > 0;
|
|
379
|
+
}
|
|
380
|
+
export function deriveSelectorState(params) {
|
|
381
|
+
if (!params.isAnchorReachable) {
|
|
382
|
+
return "disabled";
|
|
383
|
+
}
|
|
384
|
+
// Sidebar-only selectors have no element to "see"; opening the sidebar is the action.
|
|
385
|
+
if (params.isSidebarOnly) {
|
|
386
|
+
return "show-action";
|
|
387
|
+
}
|
|
388
|
+
if (params.isTargetVisible) {
|
|
389
|
+
return "show";
|
|
390
|
+
}
|
|
391
|
+
if (params.hasRevealPath) {
|
|
392
|
+
return "show-action";
|
|
393
|
+
}
|
|
394
|
+
return "disabled";
|
|
395
|
+
}
|
|
217
396
|
// Create a temporary highlight overlay
|
|
218
397
|
function showHighlightOverlay(x, y, width, height, duration) {
|
|
219
398
|
const padding = 4;
|
|
@@ -265,59 +444,187 @@ function showHighlightOverlay(x, y, width, height, duration) {
|
|
|
265
444
|
overlay.remove();
|
|
266
445
|
}, duration);
|
|
267
446
|
}
|
|
447
|
+
let activeRevealController = null;
|
|
448
|
+
let revealControllerSeq = 0;
|
|
449
|
+
function registerActiveReveal(controller) {
|
|
450
|
+
const previous = activeRevealController;
|
|
451
|
+
activeRevealController = controller;
|
|
452
|
+
if (previous && previous.id !== controller.id) {
|
|
453
|
+
previous.close();
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
function clearActiveReveal(id) {
|
|
457
|
+
if (activeRevealController?.id === id) {
|
|
458
|
+
activeRevealController = null;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
// Close the More-panels flyout if it is currently open (inverse of open-more-sidebars).
|
|
462
|
+
function closeMorePanelsIfOpen() {
|
|
463
|
+
if (!isElementPresent("@more-sidebars-panel"))
|
|
464
|
+
return;
|
|
465
|
+
const trigger = document.querySelector('[data-testid="more-sidebars-button"]');
|
|
466
|
+
trigger?.click();
|
|
467
|
+
}
|
|
268
468
|
// Button component for "Show me" functionality with availability detection
|
|
269
469
|
function SelectorButton({ selectorDef, keyProp, }) {
|
|
270
470
|
const editContext = useEditContext();
|
|
271
471
|
const manualActions = editContext?.configuration.editor.manualActions;
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
//
|
|
279
|
-
const
|
|
472
|
+
const isSidebarOnly = !!selectorDef.isSidebarOnly;
|
|
473
|
+
const targetSelector = selectorDef.selector;
|
|
474
|
+
// Anchor = explicit availabilitySelector only. It gates the disabled state.
|
|
475
|
+
const anchorSelector = selectorDef.availabilitySelector;
|
|
476
|
+
const hasAvailabilitySelector = Boolean(anchorSelector);
|
|
477
|
+
const closeMode = selectorDef.closeMode ?? "click";
|
|
478
|
+
// Keep a fresh reference to editContext for use inside reveal/restore closures.
|
|
479
|
+
const editContextRef = useRef(editContext);
|
|
480
|
+
editContextRef.current = editContext;
|
|
280
481
|
const hasBeforeAction = Boolean(selectorDef.beforeAction &&
|
|
281
482
|
manualActions?.[selectorDef.beforeAction] &&
|
|
282
483
|
editContext);
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
484
|
+
// A sidebar-only selector is reachable only when the current workspace
|
|
485
|
+
// supports sidebars and offers this specific sidebar (both are workspace-scoped).
|
|
486
|
+
const canAutoOpenSidebar = Boolean(isSidebarOnly &&
|
|
487
|
+
selectorDef.location &&
|
|
488
|
+
editContext?.openSidebar &&
|
|
489
|
+
editContext.workspace?.supportsSidebars &&
|
|
490
|
+
editContext.availableSidebars?.some((s) => s.id === selectorDef.location));
|
|
491
|
+
// Presence/visibility probes, kept up to date by the effect below.
|
|
492
|
+
// The anchor gates "is this relevant in the current context", so it checks
|
|
493
|
+
// presence (it may itself be a currently-collapsed container). The target
|
|
494
|
+
// checks visibility to distinguish "show" from "show-action".
|
|
495
|
+
const [isTargetPresent, setIsTargetPresent] = useState(false);
|
|
496
|
+
const [isTargetVisible, setIsTargetVisible] = useState(false);
|
|
497
|
+
const [isAnchorPresent, setIsAnchorPresent] = useState(false);
|
|
498
|
+
// True while THIS button has revealed a container (State 3 active -> green).
|
|
499
|
+
const [isActiveReveal, setIsActiveReveal] = useState(false);
|
|
500
|
+
const controllerIdRef = useRef(0);
|
|
501
|
+
const revealRef = useRef(null);
|
|
502
|
+
const isAnchorReachable = hasAvailabilitySelector
|
|
503
|
+
? isAnchorPresent
|
|
504
|
+
: isSidebarOnly
|
|
505
|
+
? canAutoOpenSidebar
|
|
506
|
+
: isTargetPresent || hasBeforeAction;
|
|
507
|
+
const hasRevealPath = isSidebarOnly || hasBeforeAction || canAutoOpenSidebar || isTargetPresent;
|
|
508
|
+
const state = deriveSelectorState({
|
|
509
|
+
isSidebarOnly,
|
|
510
|
+
isAnchorReachable,
|
|
511
|
+
isTargetVisible,
|
|
512
|
+
hasRevealPath,
|
|
513
|
+
});
|
|
514
|
+
const isDisabled = state === "disabled";
|
|
515
|
+
// Reset active (green) state WITHOUT running the undo steps. Used when the
|
|
516
|
+
// revealed container was closed by some other means.
|
|
517
|
+
const resetActiveState = useCallback(() => {
|
|
518
|
+
clearActiveReveal(controllerIdRef.current);
|
|
519
|
+
revealRef.current = null;
|
|
520
|
+
setIsActiveReveal(false);
|
|
521
|
+
}, []);
|
|
522
|
+
// Run the undo steps and reset. Used for explicit close (2nd click, auto
|
|
523
|
+
// timer, or being superseded by another reveal via mutual exclusion).
|
|
524
|
+
const runRestore = useCallback(() => {
|
|
525
|
+
const reveal = revealRef.current;
|
|
526
|
+
if (reveal) {
|
|
527
|
+
try {
|
|
528
|
+
reveal.restore();
|
|
529
|
+
}
|
|
530
|
+
catch {
|
|
531
|
+
// ignore restore failures
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
clearActiveReveal(reveal?.id ?? controllerIdRef.current);
|
|
535
|
+
revealRef.current = null;
|
|
536
|
+
setIsActiveReveal(false);
|
|
537
|
+
}, []);
|
|
538
|
+
const runRestoreRef = useRef(runRestore);
|
|
539
|
+
runRestoreRef.current = runRestore;
|
|
540
|
+
// Keep the presence/visibility probes fresh.
|
|
287
541
|
useEffect(() => {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
542
|
+
const check = () => {
|
|
543
|
+
setIsTargetPresent(targetSelector ? isElementPresent(targetSelector) : false);
|
|
544
|
+
setIsTargetVisible(targetSelector ? isElementVisibleBySelector(targetSelector) : false);
|
|
545
|
+
setIsAnchorPresent(anchorSelector ? isElementPresent(anchorSelector) : false);
|
|
546
|
+
};
|
|
547
|
+
check();
|
|
548
|
+
const attributeFilter = [
|
|
549
|
+
"data-testid",
|
|
550
|
+
"class",
|
|
551
|
+
"id",
|
|
552
|
+
"style",
|
|
553
|
+
"hidden",
|
|
554
|
+
"aria-hidden",
|
|
555
|
+
];
|
|
556
|
+
const observer = new MutationObserver(check);
|
|
557
|
+
observer.observe(document.body, {
|
|
558
|
+
childList: true,
|
|
559
|
+
subtree: true,
|
|
560
|
+
attributes: true,
|
|
561
|
+
attributeFilter,
|
|
562
|
+
});
|
|
563
|
+
let iframeObserver = null;
|
|
564
|
+
const iframe = document.querySelector("iframe.page-iframe");
|
|
565
|
+
if (iframe?.contentDocument?.body) {
|
|
566
|
+
iframeObserver = new MutationObserver(check);
|
|
567
|
+
iframeObserver.observe(iframe.contentDocument.body, {
|
|
568
|
+
childList: true,
|
|
569
|
+
subtree: true,
|
|
570
|
+
attributes: true,
|
|
571
|
+
attributeFilter,
|
|
572
|
+
});
|
|
292
573
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const available = isElementAvailable(availabilitySelector);
|
|
299
|
-
setIsAvailable(available);
|
|
574
|
+
const intervalId = setInterval(check, 1000);
|
|
575
|
+
return () => {
|
|
576
|
+
observer.disconnect();
|
|
577
|
+
iframeObserver?.disconnect();
|
|
578
|
+
clearInterval(intervalId);
|
|
300
579
|
};
|
|
301
|
-
|
|
302
|
-
|
|
580
|
+
}, [targetSelector, anchorSelector]);
|
|
581
|
+
// While active, detect if the revealed container was closed externally and
|
|
582
|
+
// reset the button's active (green) state accordingly.
|
|
583
|
+
useEffect(() => {
|
|
584
|
+
if (!isActiveReveal)
|
|
585
|
+
return;
|
|
586
|
+
const check = () => {
|
|
587
|
+
const reveal = revealRef.current;
|
|
588
|
+
if (!reveal || !reveal.isStillOpen()) {
|
|
589
|
+
resetActiveState();
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
const observer = new MutationObserver(check);
|
|
303
593
|
observer.observe(document.body, {
|
|
304
594
|
childList: true,
|
|
305
595
|
subtree: true,
|
|
306
596
|
attributes: true,
|
|
307
|
-
attributeFilter: [
|
|
597
|
+
attributeFilter: [
|
|
598
|
+
EDITOR_FORM_HIDDEN_ATTRIBUTE,
|
|
599
|
+
"class",
|
|
600
|
+
"style",
|
|
601
|
+
"data-testid",
|
|
602
|
+
],
|
|
308
603
|
});
|
|
309
|
-
|
|
310
|
-
const intervalId = setInterval(checkAvailability, 1000);
|
|
604
|
+
const intervalId = setInterval(check, 500);
|
|
311
605
|
return () => {
|
|
312
606
|
observer.disconnect();
|
|
313
607
|
clearInterval(intervalId);
|
|
314
608
|
};
|
|
315
|
-
}, [
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
609
|
+
}, [isActiveReveal, resetActiveState]);
|
|
610
|
+
// Clear the global active controller if this button unmounts while active.
|
|
611
|
+
useEffect(() => {
|
|
612
|
+
return () => {
|
|
613
|
+
clearActiveReveal(controllerIdRef.current);
|
|
614
|
+
};
|
|
615
|
+
}, []);
|
|
616
|
+
const tooltipText = isActiveReveal
|
|
617
|
+
? CLOSE_PANE_LABEL
|
|
618
|
+
: isDisabled
|
|
619
|
+
? selectorDef.notFoundMessage || selectorDef.description
|
|
620
|
+
: selectorDef.description;
|
|
621
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { "aria-label": isActiveReveal ? CLOSE_PANE_LABEL : "Show me", onClick: async () => {
|
|
622
|
+
// Second click while active -> restore (close=click behaviour).
|
|
623
|
+
if (isActiveReveal) {
|
|
624
|
+
runRestore();
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
if (isDisabled)
|
|
321
628
|
return;
|
|
322
629
|
const runId = globalThis.crypto?.randomUUID?.() ??
|
|
323
630
|
`manual-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
@@ -337,34 +644,126 @@ function SelectorButton({ selectorDef, keyProp, }) {
|
|
|
337
644
|
};
|
|
338
645
|
await action(actionProps);
|
|
339
646
|
};
|
|
340
|
-
//
|
|
341
|
-
//
|
|
342
|
-
|
|
647
|
+
// Undo steps captured as we reveal, plus predicates telling whether
|
|
648
|
+
// the revealed container is still open.
|
|
649
|
+
const undoSteps = [];
|
|
650
|
+
const openPredicates = [];
|
|
651
|
+
// 1. Sidebar-only: open the sidebar.
|
|
652
|
+
if (isSidebarOnly &&
|
|
343
653
|
editContext?.openSidebar &&
|
|
344
654
|
selectorDef.location) {
|
|
345
655
|
const sidebarId = selectorDef.location;
|
|
346
|
-
const
|
|
347
|
-
if (!
|
|
656
|
+
const wasOpen = !!editContext.openSidebars?.includes(sidebarId);
|
|
657
|
+
if (!wasOpen) {
|
|
348
658
|
editContext.openSidebar(sidebarId);
|
|
349
|
-
|
|
659
|
+
undoSteps.push(() => editContextRef.current?.toggleSidebar?.(sidebarId, {
|
|
660
|
+
forceClose: true,
|
|
661
|
+
}));
|
|
662
|
+
// Give the sidebar a moment to render before querying.
|
|
350
663
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
351
664
|
}
|
|
665
|
+
openPredicates.push(() => !!editContextRef.current?.openSidebars?.includes(sidebarId));
|
|
666
|
+
}
|
|
667
|
+
const availabilityElements = anchorSelector
|
|
668
|
+
? resolveElements(anchorSelector)
|
|
669
|
+
: [];
|
|
670
|
+
const relevantElements = !isSidebarOnly
|
|
671
|
+
? [...resolveElements(), ...availabilityElements]
|
|
672
|
+
: availabilityElements;
|
|
673
|
+
const formSlider = getEditorFormSlider(relevantElements);
|
|
674
|
+
const shouldOpenEditorForm = !isSidebarOnly &&
|
|
675
|
+
!!formSlider &&
|
|
676
|
+
isEditorFormSliderHidden(formSlider);
|
|
677
|
+
if (selectorDef.tab) {
|
|
678
|
+
editContext?.setActiveEditorTab(selectorDef.tab);
|
|
679
|
+
}
|
|
680
|
+
// 2. Editor form slider.
|
|
681
|
+
if (shouldOpenEditorForm && editContext) {
|
|
682
|
+
const slotId = editContext.getActiveSlotId();
|
|
683
|
+
editContext.setEditorFormHiddenForSlot(slotId, false);
|
|
684
|
+
undoSteps.push(() => editContextRef.current?.setEditorFormHiddenForSlot(slotId, true));
|
|
685
|
+
openPredicates.push(() => !isEditorFormSliderHidden(getEditorFormSlider()));
|
|
686
|
+
await waitForEditorFormSliderOpen(formSlider);
|
|
687
|
+
}
|
|
688
|
+
else if (selectorDef.tab) {
|
|
689
|
+
await waitForNextFrame();
|
|
352
690
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
691
|
+
// 3. beforeAction (may open the More-panels flyout, reveal fields, etc.).
|
|
692
|
+
const resolvedElements = !isSidebarOnly
|
|
693
|
+
? await waitForResolvedElements(resolveElements, selectorDef.selector)
|
|
694
|
+
: [];
|
|
695
|
+
const actionElements = resolvedElements.length > 0
|
|
696
|
+
? resolvedElements
|
|
697
|
+
: availabilityElements;
|
|
698
|
+
const morePanelsWasOpen = isElementPresent("@more-sidebars-panel");
|
|
699
|
+
await runManualAction(selectorDef.beforeAction, actionElements);
|
|
700
|
+
if (selectorDef.beforeAction === "open-more-sidebars") {
|
|
701
|
+
const morePanelsNowOpen = isElementPresent("@more-sidebars-panel");
|
|
702
|
+
if (!morePanelsWasOpen && morePanelsNowOpen) {
|
|
703
|
+
undoSteps.push(() => closeMorePanelsIfOpen());
|
|
704
|
+
openPredicates.push(() => isElementPresent("@more-sidebars-panel"));
|
|
705
|
+
}
|
|
359
706
|
}
|
|
707
|
+
// afterAction is the declared inverse for custom reveals (e.g. field actions).
|
|
360
708
|
if (selectorDef.afterAction) {
|
|
361
|
-
|
|
362
|
-
void runManualAction(selectorDef.afterAction, !isSidebarOnly ? resolveElements() :
|
|
363
|
-
}
|
|
709
|
+
undoSteps.push(() => {
|
|
710
|
+
void runManualAction(selectorDef.afterAction, !isSidebarOnly ? resolveElements() : availabilityElements);
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
// Highlight the target. For sidebar-only selectors there is no inner
|
|
714
|
+
// target, so we highlight the opened sidebar panel itself. Wait for
|
|
715
|
+
// it to become visible first, since a just-revealed element may be
|
|
716
|
+
// present but not yet laid out (highlightElement skips invisible ones).
|
|
717
|
+
const highlightSelector = isSidebarOnly
|
|
718
|
+
? selectorDef.location
|
|
719
|
+
? `@sidebar-panel-${selectorDef.location}`
|
|
720
|
+
: ""
|
|
721
|
+
: selectorDef.selector;
|
|
722
|
+
if (highlightSelector) {
|
|
723
|
+
const highlightTargets = await waitForVisibleElements(highlightSelector, 1500);
|
|
724
|
+
if (highlightTargets.length > 0) {
|
|
725
|
+
await highlightElement(highlightSelector, HIGHLIGHT_DURATION_MS);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
// If we opened/undid anything, this was a State-3 reveal: keep the
|
|
729
|
+
// button active (green) and register it for mutual exclusion.
|
|
730
|
+
if (undoSteps.length > 0) {
|
|
731
|
+
const id = ++revealControllerSeq;
|
|
732
|
+
controllerIdRef.current = id;
|
|
733
|
+
revealRef.current = {
|
|
734
|
+
id,
|
|
735
|
+
restore: () => {
|
|
736
|
+
for (let i = undoSteps.length - 1; i >= 0; i -= 1) {
|
|
737
|
+
try {
|
|
738
|
+
undoSteps[i]?.();
|
|
739
|
+
}
|
|
740
|
+
catch {
|
|
741
|
+
// ignore individual undo failures
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
isStillOpen: () => openPredicates.length === 0
|
|
746
|
+
? true
|
|
747
|
+
: openPredicates.some((predicate) => predicate()),
|
|
748
|
+
};
|
|
749
|
+
registerActiveReveal({
|
|
750
|
+
id,
|
|
751
|
+
close: () => runRestoreRef.current(),
|
|
752
|
+
});
|
|
753
|
+
setIsActiveReveal(true);
|
|
754
|
+
if (closeMode === "auto") {
|
|
755
|
+
window.setTimeout(() => {
|
|
756
|
+
if (controllerIdRef.current === id) {
|
|
757
|
+
runRestoreRef.current();
|
|
758
|
+
}
|
|
759
|
+
}, HIGHLIGHT_DURATION_MS);
|
|
760
|
+
}
|
|
364
761
|
}
|
|
365
|
-
}, disabled: !
|
|
366
|
-
? "border-feedback-
|
|
367
|
-
:
|
|
762
|
+
}, disabled: isDisabled && !isActiveReveal, className: cn("inline-flex h-5 w-5 items-center justify-center rounded border transition-colors", isActiveReveal
|
|
763
|
+
? "border-feedback-green bg-feedback-green-light text-feedback-green hover:bg-feedback-green-light cursor-pointer"
|
|
764
|
+
: !isDisabled
|
|
765
|
+
? "border-feedback-blue bg-feedback-blue-light text-feedback-blue hover:bg-feedback-blue-light cursor-pointer"
|
|
766
|
+
: "border-border-default bg-neutral-grey-5 text-neutral-grey-50 cursor-not-allowed"), children: [_jsx(LocateFixed, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }), _jsx("span", { className: "sr-only", children: "Show me" })] }, keyProp) }), _jsx(TooltipContent, { children: tooltipText })] }));
|
|
368
767
|
}
|
|
369
768
|
// Render markdown content with clickable selectors
|
|
370
769
|
// Supports both {{selectorName}} syntax (looks up in uiSelectors) and legacy @selector syntax
|
|
@@ -407,10 +806,10 @@ function renderLineWithSelectors(text, uiSelectors, manualLinkTargets, onManualL
|
|
|
407
806
|
function renderInlineSelectorsAndFormatting(text, uiSelectors) {
|
|
408
807
|
const parts = [];
|
|
409
808
|
let lastIndex = 0;
|
|
410
|
-
// Combined regex for {{namedSelector}}, @selector, and **bold
|
|
411
|
-
// @selector can include -sidebar suffix for sidebar-only selectors
|
|
412
|
-
//
|
|
413
|
-
//
|
|
809
|
+
// Combined regex for {{namedSelector}}, @selector, and **bold**
|
|
810
|
+
// Note: @selector can include -sidebar suffix for sidebar-only selectors
|
|
811
|
+
// Also supports @iframe:selector syntax (iframe: is special and allowed)
|
|
812
|
+
// Now also matches optional parentheses around selectors: ({{name}}) or (@selector)
|
|
414
813
|
const regex = /(\()?(\{\{([\w\-]+)\}\})|(\()?(@(?:iframe:[\w\-\.#\[\]=]*[\w\-#\[\]=]|[\w\-\.#\[\]=]*[\w\-#\[\]=]))|(\*\*(.+?)\*\*)/g;
|
|
415
814
|
let match;
|
|
416
815
|
while ((match = regex.exec(text)) !== null) {
|