@parhelia/core 0.1.12868 → 0.1.12875
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 +3 -1
- 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 +22 -2
- package/dist/config/config.js.map +1 -1
- package/dist/config/types.d.ts +0 -1
- package/dist/config/types.js.map +1 -1
- package/dist/editor/FieldActionsOverlay.d.ts +0 -1
- package/dist/editor/FieldActionsOverlay.js +1 -45
- package/dist/editor/FieldActionsOverlay.js.map +1 -1
- package/dist/editor/FieldListField.d.ts +1 -1
- package/dist/editor/FieldListField.js +20 -18
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/ImageEditor.d.ts +6 -1
- package/dist/editor/ImageEditor.js +19 -3
- package/dist/editor/ImageEditor.js.map +1 -1
- package/dist/editor/PictureEditor.d.ts +2 -1
- package/dist/editor/PictureEditor.js +5 -14
- 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 +1 -11
- package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
- package/dist/editor/ai/InlineAiDialog.js +22 -11
- package/dist/editor/ai/InlineAiDialog.js.map +1 -1
- package/dist/editor/ai/InlineAiTrigger.js +15 -15
- package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
- package/dist/editor/ai/dialogs/capturePageDom.js +66 -36
- package/dist/editor/ai/dialogs/capturePageDom.js.map +1 -1
- package/dist/editor/ai/dialogs/capturePageScreenshot.js +281 -162
- package/dist/editor/ai/dialogs/capturePageScreenshot.js.map +1 -1
- package/dist/editor/ai/terminal/agentSessionState.d.ts +3 -0
- package/dist/editor/ai/terminal/agentSessionState.js +3 -1
- package/dist/editor/ai/terminal/agentSessionState.js.map +1 -1
- package/dist/editor/ai/terminal/agentStartRequest.d.ts +2 -1
- package/dist/editor/ai/terminal/agentStartRequest.js +2 -1
- 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 +7 -0
- package/dist/editor/ai/terminal/components/AgentDocumentList.js +55 -13
- package/dist/editor/ai/terminal/components/AgentDocumentList.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentEditHistoryButton.d.ts +5 -0
- package/dist/editor/ai/terminal/components/AgentEditHistoryButton.js +12 -0
- package/dist/editor/ai/terminal/components/AgentEditHistoryButton.js.map +1 -0
- package/dist/editor/ai/terminal/components/AgentFullPromptControls.d.ts +3 -1
- package/dist/editor/ai/terminal/components/AgentFullPromptControls.js +22 -14
- 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 +2 -1
- package/dist/editor/ai/terminal/components/AgentPromptInputArea.js +8 -11
- package/dist/editor/ai/terminal/components/AgentPromptInputArea.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.d.ts +1 -4
- package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js +29 -13
- 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 +2 -1
- package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.js +2 -4
- 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 +13 -2
- package/dist/editor/ai/terminal/components/AgentTerminalView.js.map +1 -1
- package/dist/editor/ai/terminal/components/AiResponseMessage.js +16 -14
- package/dist/editor/ai/terminal/components/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/terminal/components/QueuedPromptsPanel.js +37 -26
- package/dist/editor/ai/terminal/components/QueuedPromptsPanel.js.map +1 -1
- package/dist/editor/ai/terminal/components/UserMessage.d.ts +2 -1
- package/dist/editor/ai/terminal/components/UserMessage.js +130 -8
- 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 +1 -0
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.d.ts +3 -1
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.js +9 -3
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentTerminalController.js +7 -0
- 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 +3 -1
- 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 +22 -52
- package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
- package/dist/editor/ai-image-editor/AiImageResultOverlay.js +30 -62
- package/dist/editor/ai-image-editor/AiImageResultOverlay.js.map +1 -1
- package/dist/editor/bridge/BridgeClient.d.ts +80 -0
- package/dist/editor/bridge/BridgeClient.js +416 -0
- package/dist/editor/bridge/BridgeClient.js.map +1 -0
- package/dist/editor/client/EditorShell.d.ts +5 -1
- package/dist/editor/client/EditorShell.js +286 -126
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +37 -5
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js +14 -17
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/itemsRepository.d.ts +2 -0
- package/dist/editor/client/itemsRepository.js +15 -8
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/client/operations.d.ts +1 -1
- package/dist/editor/client/operations.js +41 -17
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/client/pageModelBuilder.js +24 -7
- package/dist/editor/client/pageModelBuilder.js.map +1 -1
- package/dist/editor/field-types/MultiLineText.js +10 -3
- package/dist/editor/field-types/MultiLineText.js.map +1 -1
- package/dist/editor/field-types/RawEditor.js +8 -1
- package/dist/editor/field-types/RawEditor.js.map +1 -1
- package/dist/editor/field-types/RichTextEditorComponent.js +156 -45
- package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js +10 -3
- package/dist/editor/field-types/SingleLineText.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ReactSlate.js +8 -2
- package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
- package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +1 -2
- package/dist/editor/field-types/richtext/contextMenuFactory.js +100 -303
- package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
- package/dist/editor/field-types/richtext/types.d.ts +2 -0
- package/dist/editor/field-types/richtext/types.js.map +1 -1
- package/dist/editor/field-types/useFormFieldCaretPresence.d.ts +13 -0
- package/dist/editor/field-types/useFormFieldCaretPresence.js +92 -0
- package/dist/editor/field-types/useFormFieldCaretPresence.js.map +1 -0
- package/dist/editor/media-selector/TreeSelector.js +15 -15
- package/dist/editor/media-selector/TreeSelector.js.map +1 -1
- package/dist/editor/menubar/PageSelector.js +8 -2
- package/dist/editor/menubar/PageSelector.js.map +1 -1
- package/dist/editor/menubar/VersionPreviewCard.js +4 -249
- 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 +0 -7
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +23 -198
- 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/BridgeInlineFormatOverlay.d.ts +6 -0
- package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js +123 -0
- package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js.map +1 -0
- package/dist/editor/page-editor-chrome/CommentHighlightings.d.ts +5 -2
- package/dist/editor/page-editor-chrome/CommentHighlightings.js +340 -215
- package/dist/editor/page-editor-chrome/CommentHighlightings.js.map +1 -1
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.d.ts +5 -1
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js +11 -4
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js.map +1 -1
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js +21 -13
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/FieldEditedIndicator.js +23 -29
- package/dist/editor/page-editor-chrome/FieldEditedIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +110 -19
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.d.ts +3 -2
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.js +148 -45
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/PageEditorChrome.d.ts +2 -0
- package/dist/editor/page-editor-chrome/PageEditorChrome.js +25 -21
- package/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -1
- package/dist/editor/page-editor-chrome/PictureEditorOverlay.js +163 -128
- 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 +6 -3
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.d.ts +1 -2
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +83 -146
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.d.ts +5 -2
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js +144 -63
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js.map +1 -1
- package/dist/editor/page-editor-chrome/VersionDiffHighlightings.d.ts +1 -2
- package/dist/editor/page-editor-chrome/VersionDiffHighlightings.js +101 -30
- package/dist/editor/page-editor-chrome/VersionDiffHighlightings.js.map +1 -1
- package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.d.ts +10 -1
- package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js +105 -122
- package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js.map +1 -1
- package/dist/editor/page-editor-chrome/overlay/geometry.d.ts +11 -4
- package/dist/editor/page-editor-chrome/overlay/geometry.js +139 -36
- package/dist/editor/page-editor-chrome/overlay/geometry.js.map +1 -1
- package/dist/editor/page-editor-chrome/useBridgeInlineEditing.d.ts +26 -0
- package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js +222 -0
- package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js.map +1 -0
- package/dist/editor/page-viewer/EditorForm.js +17 -1
- 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 +176 -364
- package/dist/editor/page-viewer/MiniMap.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js +40 -13
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.d.ts +0 -5
- package/dist/editor/page-viewer/PageViewerFrame.js +1525 -1507
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/bridgeFieldPatch.d.ts +20 -0
- package/dist/editor/page-viewer/bridgeFieldPatch.js +33 -0
- package/dist/editor/page-viewer/bridgeFieldPatch.js.map +1 -0
- package/dist/editor/page-viewer/pageViewContext.d.ts +32 -0
- package/dist/editor/page-viewer/pageViewContext.js +37 -6
- package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
- package/dist/editor/reviews/Comment.d.ts +2 -1
- package/dist/editor/reviews/Comment.js +9 -4
- 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 +68 -9
- package/dist/editor/reviews/CommentPopover.js.map +1 -1
- package/dist/editor/reviews/CommentView.js +24 -4
- package/dist/editor/reviews/CommentView.js.map +1 -1
- package/dist/editor/reviews/Comments.d.ts +0 -2
- package/dist/editor/reviews/Comments.js +29 -30
- package/dist/editor/reviews/Comments.js.map +1 -1
- package/dist/editor/reviews/FeedbackCard.d.ts +4 -2
- package/dist/editor/reviews/FeedbackCard.js +5 -5
- package/dist/editor/reviews/FeedbackCard.js.map +1 -1
- package/dist/editor/reviews/SuggestedEdit.js +4 -6
- package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
- package/dist/editor/reviews/SuggestionDisplayPopover.js +3 -2
- package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/commentTransientSelection.d.ts +23 -0
- package/dist/editor/reviews/commentTransientSelection.js +7 -0
- package/dist/editor/reviews/commentTransientSelection.js.map +1 -0
- package/dist/editor/reviews/feedbackOrdering.d.ts +5 -0
- package/dist/editor/reviews/feedbackOrdering.js +27 -0
- package/dist/editor/reviews/feedbackOrdering.js.map +1 -0
- package/dist/editor/reviews/feedbackSelection.js +32 -4
- package/dist/editor/reviews/feedbackSelection.js.map +1 -1
- package/dist/editor/reviews/suggestedEditState.d.ts +12 -0
- package/dist/editor/reviews/suggestedEditState.js +90 -0
- package/dist/editor/reviews/suggestedEditState.js.map +1 -0
- package/dist/editor/reviews/suggestionDisplayValue.d.ts +43 -0
- package/dist/editor/reviews/suggestionDisplayValue.js +93 -0
- package/dist/editor/reviews/suggestionDisplayValue.js.map +1 -0
- package/dist/editor/services/agentService.d.ts +14 -0
- package/dist/editor/services/agentService.js +11 -1
- package/dist/editor/services/agentService.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 +2 -3
- package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
- package/dist/editor/sidebar/BridgeDiagnostics.d.ts +1 -0
- package/dist/editor/sidebar/BridgeDiagnostics.js +41 -0
- package/dist/editor/sidebar/BridgeDiagnostics.js.map +1 -0
- 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 +1 -17
- package/dist/editor/utils.js +0 -143
- package/dist/editor/utils.js.map +1 -1
- package/dist/editor/version-diff/versionDiffTargets.d.ts +3 -8
- package/dist/editor/version-diff/versionDiffTargets.js +37 -94
- package/dist/editor/version-diff/versionDiffTargets.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 +11 -3
- package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
- package/dist/splash-screen/NewPage.js +7 -5
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/OpenPage.js +5 -3
- 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 +2 -1
- package/styles.css +49 -0
- package/dist/editor/page-editor-chrome/InlineEditor.d.ts +0 -7
- package/dist/editor/page-editor-chrome/InlineEditor.js +0 -1719
- package/dist/editor/page-editor-chrome/InlineEditor.js.map +0 -1
- package/dist/editor/page-editor-chrome/overlay/iframeAccess.d.ts +0 -2
- package/dist/editor/page-editor-chrome/overlay/iframeAccess.js +0 -21
- package/dist/editor/page-editor-chrome/overlay/iframeAccess.js.map +0 -1
- package/dist/editor/page-editor-chrome/useInlineAICompletion.d.ts +0 -7
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js +0 -758
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +0 -1
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.d.ts +0 -3
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +0 -796
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +0 -1
|
@@ -46,6 +46,7 @@ import { QuickItemSwitcher } from "../QuickItemSwitcher";
|
|
|
46
46
|
import { useEditorSlotContext, } from "../views/editorSlotContext";
|
|
47
47
|
import { getComments, getAvailableCommentTags, } from "../services/reviewsService";
|
|
48
48
|
import { useReviews } from "../reviews/useReviews";
|
|
49
|
+
import { COMMENT_TRANSIENT_ELEMENT_KEY, COMMENT_TRANSIENT_SELECTION_RECT, } from "../reviews/commentTransientSelection";
|
|
49
50
|
import uuid from "react-uuid";
|
|
50
51
|
import { flushSync } from "react-dom";
|
|
51
52
|
import { getSuggestedEdits } from "../services/suggestedEditsService";
|
|
@@ -67,6 +68,24 @@ import { FeatureGate, LicenseFeatures, LicenseProvider, LicenseOverlay, } from "
|
|
|
67
68
|
// nothing open" (param present with this value) so reload can honor the user's intent.
|
|
68
69
|
const SIDEBAR_NONE_SENTINEL = "none";
|
|
69
70
|
const sidebarUrlValue = (ids) => ids.length ? ids.join(",") : SIDEBAR_NONE_SENTINEL;
|
|
71
|
+
// moved to hooks/useQuota
|
|
72
|
+
function isUsableTextSelectionRange(range) {
|
|
73
|
+
return !!(range &&
|
|
74
|
+
range.text?.trim() &&
|
|
75
|
+
typeof range.startOffset === "number" &&
|
|
76
|
+
typeof range.endOffset === "number" &&
|
|
77
|
+
range.startOffset !== range.endOffset &&
|
|
78
|
+
range.fieldId &&
|
|
79
|
+
range.itemId);
|
|
80
|
+
}
|
|
81
|
+
function selectionRangeMatchesField(range, field) {
|
|
82
|
+
if (!range || !field)
|
|
83
|
+
return false;
|
|
84
|
+
return (cleanId(range.fieldId) === cleanId(field.fieldId) &&
|
|
85
|
+
cleanId(range.itemId) === cleanId(field.item.id) &&
|
|
86
|
+
(!range.language || range.language === field.item.language) &&
|
|
87
|
+
(typeof range.version !== "number" || range.version === field.item.version));
|
|
88
|
+
}
|
|
70
89
|
function reconcileSlotSettingsState(previous, slots, defaults) {
|
|
71
90
|
const next = {};
|
|
72
91
|
let changed = false;
|
|
@@ -134,8 +153,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
134
153
|
const [focusedField, setFocusedField] = useState();
|
|
135
154
|
const focusedFieldRef = useRef(undefined);
|
|
136
155
|
const [selectedRange, setSelectedRange] = useState();
|
|
156
|
+
const lastTextSelectionRangeRef = useRef(undefined);
|
|
137
157
|
const [validating, setValidating] = useState(false);
|
|
138
158
|
const [inserting, setInserting] = useState();
|
|
159
|
+
const insertingSequenceRef = useRef(0);
|
|
139
160
|
const [showFullscreenHint, setShowFullscreenHint] = useState(false);
|
|
140
161
|
// Fullscreen is a shell-level UI mode. Keep it in EditorShell state so the shell can rerender
|
|
141
162
|
// immediately when toggled, while still syncing the active slot's PageViewContext.fullscreen.
|
|
@@ -153,6 +174,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
153
174
|
const [activeFieldActions, setActiveFieldActions] = useState([]);
|
|
154
175
|
const fieldEditorPopupRef = React.useRef(null);
|
|
155
176
|
const [validationResult, setValidationResult] = useState();
|
|
177
|
+
const [bridgeDiagnostics, setBridgeDiagnostics] = useState(undefined);
|
|
156
178
|
const [editHistory, setEditHistory] = useState([]);
|
|
157
179
|
const [historyMode, setHistoryMode] = useState("global");
|
|
158
180
|
const [showOnlyMyChanges, setShowOnlyMyChanges] = useState(true);
|
|
@@ -465,7 +487,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
465
487
|
// The very first URL sync after initial load should replaceState (not pushState)
|
|
466
488
|
// so the initial bare URL isn't left as a dead-end history entry.
|
|
467
489
|
const isFirstUrlSyncRef = useRef(true);
|
|
468
|
-
const [inlineEditingFieldElement, setInlineEditingFieldElement] = useState();
|
|
469
490
|
const [lockedField, setLockedField] = useState();
|
|
470
491
|
const [itemLanguages, setItemLanguages] = useState([]);
|
|
471
492
|
const [itemVersions, setItemVersions] = useState([]);
|
|
@@ -555,9 +576,67 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
555
576
|
const [isTourActive, setIsTourActive] = useState(tourRestoredFromUrl);
|
|
556
577
|
// Track if tour was restored from URL to skip prepareAction on initial render
|
|
557
578
|
const tourRestoredRef = useRef(tourRestoredFromUrl);
|
|
558
|
-
const [mode,
|
|
579
|
+
const [mode, setModeState] = useState("edit");
|
|
580
|
+
const modeRef = useRef("edit");
|
|
581
|
+
modeRef.current = mode;
|
|
582
|
+
const modeChangeParticipantsRef = useRef(new Set());
|
|
583
|
+
const loadSuggestedEditsRef = useRef(async () => { });
|
|
584
|
+
const [modeTransitionRevision, setModeTransitionRevision] = useState(0);
|
|
559
585
|
const [previewDate, setPreviewDate] = useState();
|
|
560
586
|
const [layoutMode, setLayoutMode] = useState("final");
|
|
587
|
+
const registerModeChangeParticipant = useCallback((participant) => {
|
|
588
|
+
modeChangeParticipantsRef.current.add(participant);
|
|
589
|
+
return () => {
|
|
590
|
+
modeChangeParticipantsRef.current.delete(participant);
|
|
591
|
+
};
|
|
592
|
+
}, []);
|
|
593
|
+
const changeMode = useCallback(async (nextMode, options) => {
|
|
594
|
+
const previousMode = modeRef.current;
|
|
595
|
+
if (nextMode === previousMode)
|
|
596
|
+
return;
|
|
597
|
+
const participants = Array.from(modeChangeParticipantsRef.current);
|
|
598
|
+
for (const participant of participants) {
|
|
599
|
+
await participant.beforeModeChange?.(nextMode, previousMode, options);
|
|
600
|
+
}
|
|
601
|
+
for (const participant of participants) {
|
|
602
|
+
participant.clearInlineDedupe?.(nextMode, previousMode, options);
|
|
603
|
+
}
|
|
604
|
+
flushSync(() => {
|
|
605
|
+
modeRef.current = nextMode;
|
|
606
|
+
setModeState(nextMode);
|
|
607
|
+
setModeTransitionRevision((revision) => revision + 1);
|
|
608
|
+
if (nextMode !== "preview") {
|
|
609
|
+
setPreviewDate(undefined);
|
|
610
|
+
}
|
|
611
|
+
if (nextMode === "suggestions") {
|
|
612
|
+
setShowSuggestedEdits(true);
|
|
613
|
+
setWorkspaceId("editor");
|
|
614
|
+
setOpenSidebars((prev) => {
|
|
615
|
+
if (prev.includes("feedback"))
|
|
616
|
+
return prev;
|
|
617
|
+
const next = [...prev, "feedback"];
|
|
618
|
+
openSidebarsRef.current = next;
|
|
619
|
+
return next;
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
setShowSuggestedEdits(false);
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
if (nextMode === "suggestions") {
|
|
627
|
+
void loadSuggestedEditsRef.current();
|
|
628
|
+
}
|
|
629
|
+
}, []);
|
|
630
|
+
const setMode = useCallback((nextMode) => {
|
|
631
|
+
const resolvedMode = typeof nextMode === "function" ? nextMode(modeRef.current) : nextMode;
|
|
632
|
+
void changeMode(resolvedMode);
|
|
633
|
+
}, [changeMode]);
|
|
634
|
+
const workspaceShowsModeControls = !!configuration.editor.workspaces?.find((workspace) => workspace.id === workspaceId)?.toolbarFactory;
|
|
635
|
+
useEffect(() => {
|
|
636
|
+
if (workspaceShowsModeControls || mode !== "suggestions")
|
|
637
|
+
return;
|
|
638
|
+
void changeMode("edit", { reason: "mode-controls-hidden" });
|
|
639
|
+
}, [changeMode, mode, workspaceId, workspaceShowsModeControls]);
|
|
561
640
|
useEffect(() => {
|
|
562
641
|
if (mode !== "preview") {
|
|
563
642
|
setPreviewDate(undefined);
|
|
@@ -663,19 +742,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
663
742
|
setSelectedHelpSectionId(helpParam === "contents" || helpParam === "true" ? null : helpParam);
|
|
664
743
|
}
|
|
665
744
|
}, [searchParams, isInitialLoad]);
|
|
666
|
-
useEffect(() => {
|
|
667
|
-
if (mode === "suggestions") {
|
|
668
|
-
// Ensure we're in the editor workspace and open the feedback sidebar
|
|
669
|
-
setWorkspaceId("editor");
|
|
670
|
-
// Open the feedback sidebar if not already open
|
|
671
|
-
setOpenSidebars((prev) => {
|
|
672
|
-
if (!prev.includes("comments")) {
|
|
673
|
-
return [...prev, "comments"];
|
|
674
|
-
}
|
|
675
|
-
return prev;
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
}, [mode]);
|
|
679
745
|
useEffect(() => {
|
|
680
746
|
if (focusedField &&
|
|
681
747
|
selection.length > 0 &&
|
|
@@ -685,7 +751,19 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
685
751
|
}, [selection]);
|
|
686
752
|
useEffect(() => {
|
|
687
753
|
focusedFieldRef.current = focusedField;
|
|
754
|
+
const lastTextSelection = lastTextSelectionRangeRef.current;
|
|
755
|
+
if (focusedField &&
|
|
756
|
+
lastTextSelection &&
|
|
757
|
+
(focusedField.fieldId !== lastTextSelection.fieldId ||
|
|
758
|
+
focusedField.item.id !== lastTextSelection.itemId)) {
|
|
759
|
+
lastTextSelectionRangeRef.current = undefined;
|
|
760
|
+
}
|
|
688
761
|
}, [focusedField]);
|
|
762
|
+
useEffect(() => {
|
|
763
|
+
if (isUsableTextSelectionRange(selectedRange)) {
|
|
764
|
+
lastTextSelectionRangeRef.current = selectedRange;
|
|
765
|
+
}
|
|
766
|
+
}, [selectedRange]);
|
|
689
767
|
// Track the current page item descriptor for itemsRepository
|
|
690
768
|
const [currentPageItem, setCurrentPageItem] = useState();
|
|
691
769
|
// Create itemsRepository with current page item (will be updated when page loads)
|
|
@@ -1216,7 +1294,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1216
1294
|
const toggleHelpTerminal = useCallback((options) => {
|
|
1217
1295
|
const isCurrentlyOpen = showHelpTerminal;
|
|
1218
1296
|
const requestedTab = options?.activeTab;
|
|
1219
|
-
if (isCurrentlyOpen &&
|
|
1297
|
+
if (isCurrentlyOpen &&
|
|
1298
|
+
(!requestedTab || requestedTab === helpTerminalActiveTab)) {
|
|
1220
1299
|
// Close when toggling the currently active help view.
|
|
1221
1300
|
handleSetShowHelpTerminal(false);
|
|
1222
1301
|
}
|
|
@@ -1419,9 +1498,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1419
1498
|
}
|
|
1420
1499
|
// Handle mode changes — always set to avoid stale-closure mismatch
|
|
1421
1500
|
const urlMode = urlParams.get("mode");
|
|
1422
|
-
|
|
1423
|
-
setMode(urlMode);
|
|
1424
|
-
}
|
|
1501
|
+
setMode(urlMode ?? "edit");
|
|
1425
1502
|
// Handle fullscreen changes (shell-level state)
|
|
1426
1503
|
const isFullscreen = urlParams.get("fullscreen") === "true";
|
|
1427
1504
|
if (configuration.forceFullscreen) {
|
|
@@ -1698,6 +1775,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1698
1775
|
const edits = result.data || [];
|
|
1699
1776
|
setSuggestedEdits(edits);
|
|
1700
1777
|
}, [item, searchParams]);
|
|
1778
|
+
useEffect(() => {
|
|
1779
|
+
loadSuggestedEditsRef.current = loadSuggestedEdits;
|
|
1780
|
+
}, [loadSuggestedEdits]);
|
|
1701
1781
|
const loadFavorites = useCallback(async () => {
|
|
1702
1782
|
try {
|
|
1703
1783
|
const result = await getAllFavorites();
|
|
@@ -1710,6 +1790,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1710
1790
|
setFavorites([]);
|
|
1711
1791
|
}
|
|
1712
1792
|
}, []);
|
|
1793
|
+
const refreshFavorites = useCallback(async (opts) => {
|
|
1794
|
+
await loadFavorites();
|
|
1795
|
+
}, [loadFavorites]);
|
|
1713
1796
|
const page = activePageViewContext.page;
|
|
1714
1797
|
const currentHistoryScope = useMemo(() => {
|
|
1715
1798
|
const currentItem = item?.descriptor;
|
|
@@ -2106,6 +2189,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2106
2189
|
globalThis.editorRefreshTimer = undefined;
|
|
2107
2190
|
};
|
|
2108
2191
|
if (mode === "immediate") {
|
|
2192
|
+
if (refreshTimer) {
|
|
2193
|
+
clearTimeout(refreshTimer);
|
|
2194
|
+
}
|
|
2109
2195
|
doRefresh();
|
|
2110
2196
|
return;
|
|
2111
2197
|
}
|
|
@@ -2299,7 +2385,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2299
2385
|
else {
|
|
2300
2386
|
current.set("compare", "true");
|
|
2301
2387
|
}
|
|
2302
|
-
current.set("mode", mode);
|
|
2388
|
+
current.set("mode", workspaceShowsModeControls ? mode : "edit");
|
|
2303
2389
|
// Handle fullscreen parameter
|
|
2304
2390
|
if (fullscreen) {
|
|
2305
2391
|
current.set("fullscreen", "true");
|
|
@@ -3004,9 +3090,35 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3004
3090
|
};
|
|
3005
3091
|
}, [promptSessionReconnect]);
|
|
3006
3092
|
const sendSocketMessage = useCallback((message) => {
|
|
3093
|
+
if (message.type === "caret-position" &&
|
|
3094
|
+
message.payload?.source === "form-field") {
|
|
3095
|
+
const payload = message.payload;
|
|
3096
|
+
setRemoteCarets((current) => {
|
|
3097
|
+
if (payload.offset == null) {
|
|
3098
|
+
if (!current[sessionId])
|
|
3099
|
+
return current;
|
|
3100
|
+
const next = { ...current };
|
|
3101
|
+
delete next[sessionId];
|
|
3102
|
+
return next;
|
|
3103
|
+
}
|
|
3104
|
+
if (!payload.fieldId || !payload.item) {
|
|
3105
|
+
return current;
|
|
3106
|
+
}
|
|
3107
|
+
return {
|
|
3108
|
+
...current,
|
|
3109
|
+
[sessionId]: {
|
|
3110
|
+
sessionId,
|
|
3111
|
+
fieldId: payload.fieldId,
|
|
3112
|
+
item: payload.item,
|
|
3113
|
+
offset: payload.offset,
|
|
3114
|
+
value: payload.value,
|
|
3115
|
+
},
|
|
3116
|
+
};
|
|
3117
|
+
});
|
|
3118
|
+
}
|
|
3007
3119
|
// Routes over whichever transport is active (WebSocket preferred, SSE fallback).
|
|
3008
3120
|
getEditorRealtime().send(message);
|
|
3009
|
-
}, []);
|
|
3121
|
+
}, [sessionId]);
|
|
3010
3122
|
// URL update helper - defined early so it can be used by workspace/sidebar functions
|
|
3011
3123
|
const updateUrl = useCallback((params) => {
|
|
3012
3124
|
// Use the actual browser pathname (including any basePath like /parhelia)
|
|
@@ -3484,34 +3596,51 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3484
3596
|
operationsContext.context.markOperationComplete;
|
|
3485
3597
|
}, [operationsContext.context.markOperationComplete]);
|
|
3486
3598
|
// Replace selected text with new content (for inline AI editing)
|
|
3487
|
-
const replaceSelectedText = useCallback(async (newText) => {
|
|
3488
|
-
|
|
3489
|
-
return;
|
|
3599
|
+
const replaceSelectedText = useCallback(async (newText, selectionOverride) => {
|
|
3600
|
+
const rangeToReplace = selectionOverride ?? selectedRange ?? lastTextSelectionRangeRef.current;
|
|
3490
3601
|
try {
|
|
3491
3602
|
// If we have selected text and a replaceText callback, use it
|
|
3492
|
-
if (
|
|
3493
|
-
|
|
3603
|
+
if (rangeToReplace?.text && rangeToReplace.replaceText) {
|
|
3604
|
+
rangeToReplace.replaceText(newText);
|
|
3494
3605
|
setSelectedRange(undefined);
|
|
3606
|
+
lastTextSelectionRangeRef.current = undefined;
|
|
3495
3607
|
return;
|
|
3496
3608
|
}
|
|
3497
3609
|
// If no selection but we have a replaceText callback, try to use it for insertion
|
|
3498
3610
|
// (some editors might support insertion via the same callback)
|
|
3499
|
-
if (!
|
|
3500
|
-
|
|
3611
|
+
if (!rangeToReplace?.text && rangeToReplace?.replaceText) {
|
|
3612
|
+
rangeToReplace.replaceText(newText);
|
|
3501
3613
|
setSelectedRange(undefined);
|
|
3614
|
+
lastTextSelectionRangeRef.current = undefined;
|
|
3502
3615
|
return;
|
|
3503
3616
|
}
|
|
3617
|
+
const fieldToReplace = focusedField ??
|
|
3618
|
+
(rangeToReplace?.fieldId &&
|
|
3619
|
+
rangeToReplace.itemId &&
|
|
3620
|
+
rangeToReplace.language &&
|
|
3621
|
+
typeof rangeToReplace.version === "number"
|
|
3622
|
+
? {
|
|
3623
|
+
fieldId: rangeToReplace.fieldId,
|
|
3624
|
+
item: {
|
|
3625
|
+
id: rangeToReplace.itemId,
|
|
3626
|
+
language: rangeToReplace.language,
|
|
3627
|
+
version: rangeToReplace.version,
|
|
3628
|
+
},
|
|
3629
|
+
}
|
|
3630
|
+
: undefined);
|
|
3631
|
+
if (!fieldToReplace)
|
|
3632
|
+
return;
|
|
3504
3633
|
// Fallback: indexOf-based replacement/insertion for plain text fields
|
|
3505
|
-
const { fieldId, item } =
|
|
3634
|
+
const { fieldId, item } = fieldToReplace;
|
|
3506
3635
|
const modifiedField = getActiveSlotContext()?.fieldModificationStore.getField(fieldId, item.id, item.language, item.version);
|
|
3507
3636
|
const currentValue = modifiedField
|
|
3508
3637
|
? modifiedField.value || ""
|
|
3509
|
-
: (await itemsRepository.getField(
|
|
3510
|
-
"";
|
|
3638
|
+
: (await itemsRepository.getField(fieldToReplace))
|
|
3639
|
+
?.value || "";
|
|
3511
3640
|
let newValue;
|
|
3512
|
-
if (
|
|
3641
|
+
if (rangeToReplace?.text) {
|
|
3513
3642
|
// Replace selected text
|
|
3514
|
-
const { text: originalSelectedText } =
|
|
3643
|
+
const { text: originalSelectedText } = rangeToReplace;
|
|
3515
3644
|
const actualPosition = currentValue.indexOf(originalSelectedText);
|
|
3516
3645
|
if (actualPosition === -1) {
|
|
3517
3646
|
console.error("Failed to find selected text in field value");
|
|
@@ -3524,7 +3653,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3524
3653
|
}
|
|
3525
3654
|
else {
|
|
3526
3655
|
// Insert at cursor position (use startOffset if available, otherwise append)
|
|
3527
|
-
const insertPosition =
|
|
3656
|
+
const insertPosition = rangeToReplace?.startOffset ?? currentValue.length;
|
|
3528
3657
|
newValue =
|
|
3529
3658
|
currentValue.slice(0, insertPosition) +
|
|
3530
3659
|
newText +
|
|
@@ -3532,12 +3661,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3532
3661
|
}
|
|
3533
3662
|
// Update the field
|
|
3534
3663
|
await operations.editField({
|
|
3535
|
-
field:
|
|
3664
|
+
field: fieldToReplace,
|
|
3536
3665
|
value: newValue,
|
|
3537
3666
|
refresh: "immediate",
|
|
3538
3667
|
});
|
|
3539
3668
|
// Clear the selection after replacement/insertion
|
|
3540
3669
|
setSelectedRange(undefined);
|
|
3670
|
+
lastTextSelectionRangeRef.current = undefined;
|
|
3541
3671
|
}
|
|
3542
3672
|
catch (error) {
|
|
3543
3673
|
console.error("Failed to replace/insert text:", error);
|
|
@@ -4014,18 +4144,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4014
4144
|
};
|
|
4015
4145
|
}
|
|
4016
4146
|
}, [operations.onFieldBlur]);
|
|
4017
|
-
useEffect(() => {
|
|
4018
|
-
if (mode === "suggestions") {
|
|
4019
|
-
setShowSuggestedEdits(true);
|
|
4020
|
-
// Refresh from the server to recover from any missed
|
|
4021
|
-
// `suggested-edit-updated` WebSocket events (e.g. created by an
|
|
4022
|
-
// agent tool while another tab was focused).
|
|
4023
|
-
loadSuggestedEdits();
|
|
4024
|
-
}
|
|
4025
|
-
else {
|
|
4026
|
-
setShowSuggestedEdits(false);
|
|
4027
|
-
}
|
|
4028
|
-
}, [mode, loadSuggestedEdits]);
|
|
4029
4147
|
const isReadOnly = !item ||
|
|
4030
4148
|
!item.canWriteItem ||
|
|
4031
4149
|
!item.canWriteLanguage ||
|
|
@@ -4044,15 +4162,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4044
4162
|
// Otherwise, only show workspaces that are in the settings
|
|
4045
4163
|
return workspaceIdsFromSettings.includes(w.id) && !w.visible;
|
|
4046
4164
|
});
|
|
4047
|
-
// Handle initial mode setup from URL (only on initial load)
|
|
4048
|
-
useEffect(() => {
|
|
4049
|
-
if (!isInitialLoad)
|
|
4050
|
-
return;
|
|
4051
|
-
const queryMode = searchParams.get("mode");
|
|
4052
|
-
if (queryMode) {
|
|
4053
|
-
setMode(queryMode);
|
|
4054
|
-
}
|
|
4055
|
-
}, [searchParams, isInitialLoad]);
|
|
4056
4165
|
// Add this new effect for initial fullscreen setup
|
|
4057
4166
|
useEffect(() => {
|
|
4058
4167
|
if (!isInitialLoad)
|
|
@@ -4180,16 +4289,11 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4180
4289
|
dragEnd: () => {
|
|
4181
4290
|
setDragObject(undefined);
|
|
4182
4291
|
},
|
|
4183
|
-
droppedInPlaceholder: async (placeholderKey, index, spotPositionElement, spotPositionAnchor, insertOption) => {
|
|
4184
|
-
|
|
4292
|
+
droppedInPlaceholder: async (placeholderKey, index, spotPositionElement, spotPositionAnchor, insertOption, spotPosition) => {
|
|
4293
|
+
const droppedDragObject = dragObject;
|
|
4294
|
+
if ((!droppedDragObject && !insertOption) || !page)
|
|
4185
4295
|
return;
|
|
4186
4296
|
setDragObject(undefined);
|
|
4187
|
-
if (spotPositionElement && spotPositionAnchor) {
|
|
4188
|
-
setInserting({
|
|
4189
|
-
positionElement: spotPositionElement,
|
|
4190
|
-
positionAnchor: spotPositionAnchor,
|
|
4191
|
-
});
|
|
4192
|
-
}
|
|
4193
4297
|
const placeholderKeyComponents = placeholderKey.split("_");
|
|
4194
4298
|
const parentId = placeholderKeyComponents.length === 1
|
|
4195
4299
|
? undefined
|
|
@@ -4199,39 +4303,31 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4199
4303
|
let op;
|
|
4200
4304
|
if (!currentItemDescriptorRef.current)
|
|
4201
4305
|
return;
|
|
4306
|
+
let insertionSequence;
|
|
4307
|
+
if ((spotPosition || spotPositionElement) && spotPositionAnchor) {
|
|
4308
|
+
insertionSequence = ++insertingSequenceRef.current;
|
|
4309
|
+
setInserting({
|
|
4310
|
+
position: spotPosition,
|
|
4311
|
+
positionElement: spotPositionElement,
|
|
4312
|
+
positionAnchor: spotPositionAnchor,
|
|
4313
|
+
});
|
|
4314
|
+
}
|
|
4315
|
+
let operationPromise;
|
|
4202
4316
|
if (insertOption) {
|
|
4203
4317
|
// Clear any selected component type for insertion once the component
|
|
4204
4318
|
// has been dropped into a placeholder. This ensures that insert mode
|
|
4205
4319
|
// can exit cleanly and the editor header updates from "Add Component"
|
|
4206
4320
|
// to the actual component name after the operation completes.
|
|
4207
4321
|
setSelectedForInsertion("");
|
|
4208
|
-
operations
|
|
4209
|
-
.addComponent(insertOption.typeId, placeholderKey, index, currentItemDescriptorRef.current)
|
|
4210
|
-
.then((result) => {
|
|
4211
|
-
setInserting(undefined);
|
|
4212
|
-
})
|
|
4213
|
-
.catch((err) => {
|
|
4214
|
-
setInserting(undefined);
|
|
4215
|
-
});
|
|
4216
|
-
return;
|
|
4322
|
+
operationPromise = operations.addComponent(insertOption.typeId, placeholderKey, index, currentItemDescriptorRef.current);
|
|
4217
4323
|
}
|
|
4218
|
-
if (
|
|
4219
|
-
|
|
4220
|
-
if (dragObject && dragObject.type == "template") {
|
|
4221
|
-
operations
|
|
4222
|
-
.addComponent(dragObject.typeId, placeholderKey, index, currentItemDescriptorRef.current)
|
|
4223
|
-
.then((result) => {
|
|
4224
|
-
setInserting(undefined);
|
|
4225
|
-
})
|
|
4226
|
-
.catch((err) => {
|
|
4227
|
-
setInserting(undefined);
|
|
4228
|
-
});
|
|
4229
|
-
return;
|
|
4324
|
+
else if (droppedDragObject?.type == "template") {
|
|
4325
|
+
operationPromise = operations.addComponent(droppedDragObject.typeId, placeholderKey, index, currentItemDescriptorRef.current);
|
|
4230
4326
|
}
|
|
4231
|
-
if (
|
|
4232
|
-
(
|
|
4327
|
+
else if (droppedDragObject?.type == "component" ||
|
|
4328
|
+
(droppedDragObject?.type == "items" && droppedDragObject.items)) {
|
|
4233
4329
|
const parentComponent = parentId && page ? getComponentById(parentId, page) : null;
|
|
4234
|
-
if (
|
|
4330
|
+
if (droppedDragObject.type == "items" && droppedDragObject.items) {
|
|
4235
4331
|
op = {
|
|
4236
4332
|
type: "link-component",
|
|
4237
4333
|
mainItem: page.item.descriptor,
|
|
@@ -4245,33 +4341,52 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4245
4341
|
placeholderIndex: index,
|
|
4246
4342
|
date: new Date().toISOString(),
|
|
4247
4343
|
id: uuid(),
|
|
4248
|
-
linkedComponentItem:
|
|
4344
|
+
linkedComponentItem: droppedDragObject.items[0],
|
|
4249
4345
|
title: "Link component",
|
|
4250
4346
|
};
|
|
4251
4347
|
}
|
|
4252
4348
|
else {
|
|
4253
|
-
const componentIds =
|
|
4254
|
-
if (componentIds.length
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
}
|
|
4349
|
+
const componentIds = droppedDragObject.components?.map((c) => c.id) ?? [];
|
|
4350
|
+
if (componentIds.length > 0) {
|
|
4351
|
+
op = {
|
|
4352
|
+
type: "move-component",
|
|
4353
|
+
mainItem: page.item.descriptor,
|
|
4354
|
+
parent: parentId && {
|
|
4355
|
+
id: parentId,
|
|
4356
|
+
language: page.item.descriptor.language,
|
|
4357
|
+
version: page.item.descriptor.version,
|
|
4358
|
+
},
|
|
4359
|
+
placeholderKey,
|
|
4360
|
+
placeholderIndex: index,
|
|
4361
|
+
componentIds,
|
|
4362
|
+
date: new Date().toISOString(),
|
|
4363
|
+
id: uuid(),
|
|
4364
|
+
title: "Move component",
|
|
4365
|
+
};
|
|
4366
|
+
}
|
|
4271
4367
|
}
|
|
4272
4368
|
}
|
|
4273
4369
|
if (op)
|
|
4274
|
-
operations.executeEditOperation(op);
|
|
4370
|
+
operationPromise = operations.executeEditOperation(op);
|
|
4371
|
+
if (!operationPromise) {
|
|
4372
|
+
if (insertionSequence !== undefined &&
|
|
4373
|
+
insertingSequenceRef.current === insertionSequence) {
|
|
4374
|
+
setInserting(undefined);
|
|
4375
|
+
}
|
|
4376
|
+
return;
|
|
4377
|
+
}
|
|
4378
|
+
try {
|
|
4379
|
+
await operationPromise;
|
|
4380
|
+
}
|
|
4381
|
+
catch (err) {
|
|
4382
|
+
console.error("Failed to drop component in placeholder", err);
|
|
4383
|
+
}
|
|
4384
|
+
finally {
|
|
4385
|
+
if (insertionSequence !== undefined &&
|
|
4386
|
+
insertingSequenceRef.current === insertionSequence) {
|
|
4387
|
+
setInserting(undefined);
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4275
4390
|
},
|
|
4276
4391
|
page,
|
|
4277
4392
|
triggerFieldAction: async (fieldDescriptor, actionButton, parameters, event) => {
|
|
@@ -4421,6 +4536,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4421
4536
|
inserting,
|
|
4422
4537
|
validating,
|
|
4423
4538
|
validationResult,
|
|
4539
|
+
bridgeDiagnostics,
|
|
4540
|
+
setBridgeDiagnostics,
|
|
4424
4541
|
loadItem,
|
|
4425
4542
|
editHistory: editHistory,
|
|
4426
4543
|
historyMode,
|
|
@@ -4550,27 +4667,50 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4550
4667
|
setShowComments,
|
|
4551
4668
|
showResolvedComments,
|
|
4552
4669
|
setShowResolvedComments,
|
|
4553
|
-
addComment: async () => {
|
|
4670
|
+
addComment: async (options) => {
|
|
4554
4671
|
const descriptor = item?.descriptor;
|
|
4555
4672
|
if (!descriptor)
|
|
4556
4673
|
return;
|
|
4557
4674
|
// Snapshot selection context up-front so switching views doesn't change what we comment on.
|
|
4675
|
+
const hintedFieldSnapshot = options?.field;
|
|
4558
4676
|
const focusedFieldSnapshot = focusedFieldRef.current;
|
|
4559
|
-
const
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4677
|
+
const selectedRangeCandidate = isUsableTextSelectionRange(selectedRange)
|
|
4678
|
+
? selectedRange
|
|
4679
|
+
: lastTextSelectionRangeRef.current;
|
|
4680
|
+
const selectedRangeSnapshot = !hintedFieldSnapshot ||
|
|
4681
|
+
selectionRangeMatchesField(selectedRangeCandidate, hintedFieldSnapshot)
|
|
4682
|
+
? selectedRangeCandidate
|
|
4683
|
+
: undefined;
|
|
4684
|
+
const selectedRangeFieldSnapshot = isUsableTextSelectionRange(selectedRangeSnapshot)
|
|
4685
|
+
? {
|
|
4686
|
+
fieldId: selectedRangeSnapshot.fieldId,
|
|
4687
|
+
item: {
|
|
4688
|
+
id: selectedRangeSnapshot.itemId,
|
|
4689
|
+
language: selectedRangeSnapshot.language || descriptor.language,
|
|
4690
|
+
version: typeof selectedRangeSnapshot.version === "number"
|
|
4691
|
+
? selectedRangeSnapshot.version
|
|
4692
|
+
: descriptor.version,
|
|
4693
|
+
},
|
|
4694
|
+
}
|
|
4695
|
+
: undefined;
|
|
4696
|
+
const commentFieldSnapshot = selectedRangeFieldSnapshot ??
|
|
4697
|
+
hintedFieldSnapshot ??
|
|
4698
|
+
focusedFieldSnapshot;
|
|
4699
|
+
const itemId = commentFieldSnapshot?.item.id ||
|
|
4700
|
+
(selection.length > 0 ? selection[0] : undefined) ||
|
|
4563
4701
|
descriptor.id;
|
|
4564
4702
|
if (!itemId)
|
|
4565
4703
|
return;
|
|
4566
4704
|
// Ensure the feedback sidebar is open when adding a comment (e.g. command palette / toolbar button).
|
|
4567
4705
|
openSidebar("feedback");
|
|
4568
|
-
const language = descriptor.language;
|
|
4569
|
-
const version =
|
|
4706
|
+
const language = commentFieldSnapshot?.item.language || descriptor.language;
|
|
4707
|
+
const version = typeof commentFieldSnapshot?.item.version === "number"
|
|
4708
|
+
? commentFieldSnapshot.item.version
|
|
4709
|
+
: descriptor.version;
|
|
4570
4710
|
const getFieldName = async () => {
|
|
4571
|
-
if (!
|
|
4711
|
+
if (!commentFieldSnapshot)
|
|
4572
4712
|
return "";
|
|
4573
|
-
const field = await itemsRepository.getField(
|
|
4713
|
+
const field = await itemsRepository.getField(commentFieldSnapshot);
|
|
4574
4714
|
return field?.name;
|
|
4575
4715
|
};
|
|
4576
4716
|
const getItemName = async () => {
|
|
@@ -4586,24 +4726,40 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4586
4726
|
isNew: true,
|
|
4587
4727
|
itemId,
|
|
4588
4728
|
itemName: await getItemName(),
|
|
4589
|
-
fieldId:
|
|
4729
|
+
fieldId: commentFieldSnapshot?.fieldId,
|
|
4590
4730
|
fieldName: await getFieldName(),
|
|
4591
4731
|
mainItemId: descriptor.id,
|
|
4592
4732
|
language,
|
|
4593
4733
|
version,
|
|
4594
4734
|
position: 0,
|
|
4595
|
-
rangeStart: selectedRangeSnapshot
|
|
4596
|
-
|
|
4735
|
+
rangeStart: isUsableTextSelectionRange(selectedRangeSnapshot)
|
|
4736
|
+
? selectedRangeSnapshot.startOffset
|
|
4737
|
+
: 0,
|
|
4738
|
+
rangeEnd: isUsableTextSelectionRange(selectedRangeSnapshot)
|
|
4739
|
+
? selectedRangeSnapshot.endOffset
|
|
4740
|
+
: 0,
|
|
4597
4741
|
author: user?.name,
|
|
4598
4742
|
authorDisplayName: user?.fullName,
|
|
4599
|
-
|
|
4743
|
+
created: new Date().toISOString(),
|
|
4600
4744
|
};
|
|
4745
|
+
if (selectedRangeSnapshot?.clientRect) {
|
|
4746
|
+
newComment[COMMENT_TRANSIENT_SELECTION_RECT] =
|
|
4747
|
+
selectedRangeSnapshot.clientRect;
|
|
4748
|
+
}
|
|
4749
|
+
if (selectedRangeSnapshot?.elementKey) {
|
|
4750
|
+
newComment[COMMENT_TRANSIENT_ELEMENT_KEY] =
|
|
4751
|
+
selectedRangeSnapshot.elementKey;
|
|
4752
|
+
}
|
|
4601
4753
|
setComments([newComment, ...comments]);
|
|
4602
4754
|
setSelectedComment(newComment);
|
|
4603
4755
|
setShowComments(true);
|
|
4756
|
+
lastTextSelectionRangeRef.current = undefined;
|
|
4604
4757
|
},
|
|
4605
4758
|
mode,
|
|
4759
|
+
changeMode,
|
|
4606
4760
|
setMode,
|
|
4761
|
+
registerModeChangeParticipant,
|
|
4762
|
+
modeTransitionRevision,
|
|
4607
4763
|
previewDate,
|
|
4608
4764
|
setPreviewDate,
|
|
4609
4765
|
layoutMode,
|
|
@@ -4671,6 +4827,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4671
4827
|
setCurrentWizardId,
|
|
4672
4828
|
favorites,
|
|
4673
4829
|
loadFavorites,
|
|
4830
|
+
refreshFavorites,
|
|
4674
4831
|
isQuickSwitcherVisible: quickSwitcherVisible,
|
|
4675
4832
|
// Context factory registry methods
|
|
4676
4833
|
registerContextFactory: (name, factory) => {
|
|
@@ -4779,6 +4936,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4779
4936
|
isRefreshing,
|
|
4780
4937
|
favorites,
|
|
4781
4938
|
loadFavorites,
|
|
4939
|
+
refreshFavorites,
|
|
4782
4940
|
currentWizardId,
|
|
4783
4941
|
quickSwitcherVisible,
|
|
4784
4942
|
quickSwitcherSelectedIndex,
|
|
@@ -4789,6 +4947,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4789
4947
|
factoriesRef,
|
|
4790
4948
|
user,
|
|
4791
4949
|
statusMessage,
|
|
4950
|
+
changeMode,
|
|
4951
|
+
setMode,
|
|
4952
|
+
registerModeChangeParticipant,
|
|
4953
|
+
modeTransitionRevision,
|
|
4792
4954
|
previewDate,
|
|
4793
4955
|
layoutMode,
|
|
4794
4956
|
enableCompletions,
|
|
@@ -4832,6 +4994,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4832
4994
|
openDialog,
|
|
4833
4995
|
validating,
|
|
4834
4996
|
validationResult,
|
|
4997
|
+
bridgeDiagnostics,
|
|
4835
4998
|
isRefreshing,
|
|
4836
4999
|
executeCommand,
|
|
4837
5000
|
showInfoToast,
|
|
@@ -4854,8 +5017,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4854
5017
|
setLockedField(undefined); // Clear client-side lock state
|
|
4855
5018
|
await releaseFieldLocks(sessionId);
|
|
4856
5019
|
},
|
|
4857
|
-
inlineEditingFieldElement,
|
|
4858
|
-
setInlineEditingFieldElement,
|
|
4859
5020
|
};
|
|
4860
5021
|
// Debug: Track editContext changes
|
|
4861
5022
|
// const prevDependencies = useRef<any[]>([]);
|
|
@@ -4894,7 +5055,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4894
5055
|
// componentDesignerRendering,
|
|
4895
5056
|
// insertMode,
|
|
4896
5057
|
// currentOverlay,
|
|
4897
|
-
// inlineEditingFieldElement,
|
|
4898
5058
|
// lockedField,
|
|
4899
5059
|
// selectedRange,
|
|
4900
5060
|
// pageViewContext,
|
|
@@ -4982,7 +5142,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4982
5142
|
// 'componentDesignerRendering',
|
|
4983
5143
|
// 'insertMode',
|
|
4984
5144
|
// 'currentOverlay',
|
|
4985
|
-
// 'inlineEditingFieldElement',
|
|
4986
5145
|
// 'lockedField',
|
|
4987
5146
|
// 'selectedRange',
|
|
4988
5147
|
// 'pageViewContext',
|
|
@@ -5110,7 +5269,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
5110
5269
|
: window.location.pathname;
|
|
5111
5270
|
window.history.replaceState(getCurrentHistoryState(), "", newUrl);
|
|
5112
5271
|
}, configuration: configuration, restoredFromUrl: tourRestoredRef.current })), _jsx(FeatureGate, { feature: LicenseFeatures.AI, children: _jsx(GuidanceOverlay, {}) }), _jsx(FeatureGate, { feature: LicenseFeatures.AI, children: _jsx(AgentDialogHandler, {}) })] }));
|
|
5113
|
-
|
|
5272
|
+
const showRefreshSpinner = editContext.isRefreshing && !activePageViewContext.iframeSupportsRefresh;
|
|
5273
|
+
return (_jsx(LicenseProvider, { initialLicenseStatus: initialLicenseStatus, initialStatusLoaded: initialLicenseStatusLoaded, children: _jsx("div", { className: `editor h-full w-full`, children: _jsx(OperationsContextProvider, { value: operationsContext.context, children: _jsx(FieldsEditContextProvider, { value: fieldsEditContext, children: _jsx(EditContextProvider, { value: editContext, children: _jsxs(SplashScreenAgentProvider, { children: [_jsx(DevModeIndicator, {}), startupChecks.state === "loading" && _jsx(EditorLoadingOverlay, {}), showRefreshSpinner && (_jsx("div", { className: "text-neutral-grey-50 pointer-events-none fixed right-0 bottom-0 flex h-24 w-24 items-center justify-center opacity-50 select-none", children: _jsx(Spinner, {}) })), (currentWorkspace.id === "agents" ||
|
|
5114
5274
|
currentWorkspace.id === "taskboard" ||
|
|
5115
5275
|
currentWorkspace.id === "translation-management") &&
|
|
5116
5276
|
showAgentsWorkspaceEditor && (_jsx(AgentsSlotContextBridgeHost, { slots: editorSlots })), startupChecks.state !== "loading" && (children || editorUi), startupChecks.state !== "loading" && dialog, _jsx(Toaster, { position: "top-center" }), " ", _jsx(ConfirmationDialog, { ref: confirmationDialogRef }), _jsx(ConcurrentUserLimitDialog, { open: concurrentUserLimitError !== null, onOpenChange: (open) => {
|