@parhelia/core 0.1.12927 → 0.1.12928
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/client-components/index.d.ts +1 -1
- package/dist/client-components/index.js +1 -1
- package/dist/client-components/index.js.map +1 -1
- package/dist/editor/FieldListField.js +8 -0
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/MainLayout.js +2 -1
- package/dist/editor/MainLayout.js.map +1 -1
- package/dist/editor/PerfProfiler.d.ts +11 -0
- package/dist/editor/PerfProfiler.js +29 -0
- package/dist/editor/PerfProfiler.js.map +1 -0
- package/dist/editor/ai/GuidanceOverlay.js +4 -9
- package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
- package/dist/editor/ai/InlineAiDialog.js +2 -2
- package/dist/editor/ai/InlineAiDialog.js.map +1 -1
- package/dist/editor/ai/dialogs/capturePageScreenshot.js +1 -1
- package/dist/editor/ai/dialogs/capturePageScreenshot.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentSettingsContent.d.ts +2 -1
- package/dist/editor/ai/terminal/components/AgentSettingsContent.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentSettingsSections.d.ts +2 -1
- package/dist/editor/ai/terminal/components/AgentSettingsSections.js +9 -2
- package/dist/editor/ai/terminal/components/AgentSettingsSections.js.map +1 -1
- package/dist/editor/ai/terminal/components/ContextInfoBar.js +4 -3
- package/dist/editor/ai/terminal/components/ContextInfoBar.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentSettingsData.d.ts +8 -1
- package/dist/editor/ai/terminal/useAgentSettingsData.js +42 -3
- package/dist/editor/ai/terminal/useAgentSettingsData.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentSettingsPanel.d.ts +1 -1
- package/dist/editor/bridge/BridgeClient.js +9 -1
- package/dist/editor/bridge/BridgeClient.js.map +1 -1
- package/dist/editor/bridge/protocol.d.ts +19 -0
- package/dist/editor/bridge/protocol.js +1 -1
- package/dist/editor/bridge/protocol.js.map +1 -1
- package/dist/editor/client/EditorShell.js +156 -20
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +32 -1
- package/dist/editor/client/editContext.js +8 -0
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/fieldModificationStore.js +64 -0
- package/dist/editor/client/fieldModificationStore.js.map +1 -1
- package/dist/editor/client/itemsRepository.js +95 -3
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/client/operations.d.ts +1 -0
- package/dist/editor/client/operations.js +147 -13
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/client/ui/EditorChrome.js +6 -5
- package/dist/editor/client/ui/EditorChrome.js.map +1 -1
- package/dist/editor/commands/keyboardCommands.js +1 -1
- package/dist/editor/commands/keyboardCommands.js.map +1 -1
- package/dist/editor/componentTreeHelper.js +15 -5
- package/dist/editor/componentTreeHelper.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js +79 -9
- package/dist/editor/field-types/SingleLineText.js.map +1 -1
- package/dist/editor/fieldValueDiagnostics.d.ts +79 -0
- package/dist/editor/fieldValueDiagnostics.js +133 -0
- package/dist/editor/fieldValueDiagnostics.js.map +1 -0
- package/dist/editor/page-editor-chrome/DragInsertionOverlay.js +51 -19
- package/dist/editor/page-editor-chrome/DragInsertionOverlay.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.d.ts +2 -0
- package/dist/editor/page-editor-chrome/FrameMenu.js +8 -6
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenus.d.ts +3 -1
- package/dist/editor/page-editor-chrome/FrameMenus.js +4 -4
- package/dist/editor/page-editor-chrome/FrameMenus.js.map +1 -1
- package/dist/editor/page-editor-chrome/PageEditorChrome.js +17 -4
- package/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -1
- package/dist/editor/page-editor-chrome/PictureEditorOverlay.js +4 -7
- package/dist/editor/page-editor-chrome/PictureEditorOverlay.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.d.ts +8 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +14 -3
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.d.ts +3 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +2 -2
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/overlay/placeholderZones.js +43 -1
- package/dist/editor/page-editor-chrome/overlay/placeholderZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js +121 -48
- package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js.map +1 -1
- package/dist/editor/page-viewer/EditorForm.js +54 -5
- package/dist/editor/page-viewer/EditorForm.js.map +1 -1
- package/dist/editor/page-viewer/MiniMap.js +4 -4
- package/dist/editor/page-viewer/MiniMap.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js +9 -7
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +267 -25
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/bridgeFieldPatch.js +49 -2
- package/dist/editor/page-viewer/bridgeFieldPatch.js.map +1 -1
- package/dist/editor/page-viewer/pageViewContext.d.ts +1 -0
- package/dist/editor/page-viewer/pageViewContext.js +7 -0
- package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
- package/dist/editor/perfTrace.d.ts +46 -0
- package/dist/editor/perfTrace.js +213 -0
- package/dist/editor/perfTrace.js.map +1 -0
- package/dist/editor/reviews/CommentPopover.js +2 -3
- package/dist/editor/reviews/CommentPopover.js.map +1 -1
- package/dist/editor/reviews/commentAi.js +1 -1
- package/dist/editor/reviews/commentAi.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +2 -0
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +1 -0
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.js +10 -9
- package/dist/editor/sidebar/ComponentTree.js.map +1 -1
- package/dist/editor/sidebar/ContentTreePanel.d.ts +2 -2
- package/dist/editor/sidebar/ContentTreePanel.js +6 -2
- package/dist/editor/sidebar/ContentTreePanel.js.map +1 -1
- package/dist/editor/sidebar/MainContentTree.js +3 -2
- package/dist/editor/sidebar/MainContentTree.js.map +1 -1
- package/dist/editor/utils/keyboardNavigation.js +2 -2
- package/dist/editor/utils/keyboardNavigation.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/package.json +1 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
3
|
import { BRIDGE_DOM_UPDATED_EVENT, MiniMap } from "./MiniMap";
|
|
4
|
-
import { useEditContext, useEditContextRef, useFieldsEditContext, useFieldsEditContextRef, } from "../client/editContext";
|
|
4
|
+
import { useCanvasSelection, useEditContext, useEditContextRef, useFieldsEditContext, useFieldsEditContextRef, } from "../client/editContext";
|
|
5
5
|
import { useSlotContext } from "../views/editorSlotContext";
|
|
6
6
|
import { useDebouncedCallback, useThrottledCallback } from "use-debounce";
|
|
7
7
|
import { PageEditorChrome } from "../page-editor-chrome/PageEditorChrome";
|
|
8
8
|
import { useBridgeInlineEditing, } from "../page-editor-chrome/useBridgeInlineEditing";
|
|
9
9
|
import { getInlineAiAnchorFromBridgeToolbar, getVisibleBridgeToolbarRect, waitForVisibleBridgeToolbarRect, } from "../page-editor-chrome/bridgeInlineFormatToolbarLayout";
|
|
10
10
|
import { IFRAME_OVERLAY_BRIDGE_DRAG_GESTURE_EVENT, IFRAME_OVERLAY_BRIDGE_GEOMETRY_EVENT, IFRAME_OVERLAY_BRIDGE_SCROLL_EVENT, IframeOverlayProvider, } from "../page-editor-chrome/overlay/IframeOverlayProvider";
|
|
11
|
-
import { DEVICE_CHANGE_EVENT, useViewportChangeSignal, } from "./pageViewContext";
|
|
11
|
+
import { CANVAS_REFRESH_COMPLETED_EVENT, DEVICE_CHANGE_EVENT, useViewportChangeSignal, } from "./pageViewContext";
|
|
12
12
|
import uuid from "react-uuid";
|
|
13
13
|
import { cn } from "../../lib/utils";
|
|
14
14
|
import { normalizeMarkerId } from "../utils";
|
|
@@ -26,8 +26,10 @@ import { DeviceToolbar } from "./DeviceToolbar";
|
|
|
26
26
|
import { FullscreenControls } from "../client/ui/FullscreenControls";
|
|
27
27
|
import { toSitecoreDate } from "../utils/sitecoreDate";
|
|
28
28
|
import { BridgeClient } from "../bridge/BridgeClient";
|
|
29
|
+
import { beginPerfTrace, isPerfTraceActive, isPerfTraceEnabled, perfTraceStep, } from "../perfTrace";
|
|
29
30
|
import { getSuggestionDisplayValue } from "../reviews/suggestionDisplayValue";
|
|
30
31
|
import { buildBridgeFieldPatchPayload, getBridgeFieldPatchValue, isBridgePatchableTextField, } from "./bridgeFieldPatch";
|
|
32
|
+
import { logFieldValueDiagnostic, summarizeField, summarizeFieldDescriptor, summarizeFieldValue, } from "../fieldValueDiagnostics";
|
|
31
33
|
import { createKeyboardEventFromBridgeInteraction } from "./bridgeKeyboardShortcuts";
|
|
32
34
|
import { formatParentBridgeInjectionDiagnostic, injectParheliaBridgeFromParent, } from "./parentBridgeInjection";
|
|
33
35
|
import { getTextCompletion, normalizeTextCompletion, } from "../services/textCompletionService";
|
|
@@ -39,6 +41,9 @@ const BRIDGE_INLINE_EDIT_RELEASE_EVENT = "parhelia:bridge-inline-edit-release";
|
|
|
39
41
|
const INLINE_AI_CLOSE_EVENT = "inline-ai-close";
|
|
40
42
|
const BRIDGE_INLINE_LINK_OPEN_EVENT = "bridge-inline-link-open";
|
|
41
43
|
const SCROLL_INTO_VIEW_BRIDGE_SOURCE = "scroll-into-view";
|
|
44
|
+
// How long a requested canvas refresh may suppress viewport reactions
|
|
45
|
+
// (selection auto-scroll, scrollIntoView) before it is presumed lost.
|
|
46
|
+
const CANVAS_REFRESH_IN_FLIGHT_MAX_MS = 15000;
|
|
42
47
|
// Suggestions-mode cursor: a text I-beam (the click insertion point) badged with
|
|
43
48
|
// the lucide PenLine icon from the "Suggestions mode" toolbar button. A white
|
|
44
49
|
// halo keeps it visible on any page background; the hotspot is the I-beam centre.
|
|
@@ -602,6 +607,7 @@ export function PageViewerFrame(props) {
|
|
|
602
607
|
function PageViewerFrameContent({ compareView, pageViewContext, editContext, className, slotCloseButton, }) {
|
|
603
608
|
const fieldsContext = useFieldsEditContext();
|
|
604
609
|
const slotContext = useSlotContext();
|
|
610
|
+
const canvasSelection = useCanvasSelection();
|
|
605
611
|
const pathname = usePathname();
|
|
606
612
|
const pageViewContextRef = useRef(undefined);
|
|
607
613
|
useEffect(() => {
|
|
@@ -636,6 +642,27 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
636
642
|
const directOverlayScrollSyncRef = useRef(false);
|
|
637
643
|
const lastBridgeHoverInteractionRef = useRef(undefined);
|
|
638
644
|
const pendingRefreshScrollRef = useRef(undefined);
|
|
645
|
+
// Set when a canvas refresh (bridge patch or full reload) has been requested
|
|
646
|
+
// and its result has not landed yet. While in flight, bridgeGeometry still
|
|
647
|
+
// describes the PRE-refresh DOM — a moved component is still measured at its
|
|
648
|
+
// old position — so viewport-affecting reactions (selection auto-scroll,
|
|
649
|
+
// scrollIntoView) must wait for the refreshed geometry instead of scrolling
|
|
650
|
+
// toward stale rects. Timestamped so a refresh that never completes cannot
|
|
651
|
+
// suppress scrolling forever.
|
|
652
|
+
const canvasRefreshInFlightSinceRef = useRef(null);
|
|
653
|
+
// Set when refreshCompleted arrived with applied:"host-app": the page's own
|
|
654
|
+
// app accepted the refresh but its re-render lands later as DOM mutations.
|
|
655
|
+
// The in-flight window then stays open until the next structureUpdated.
|
|
656
|
+
const awaitingHostAppRefreshRenderRef = useRef(false);
|
|
657
|
+
const isCanvasRefreshInFlight = useCallback(() => {
|
|
658
|
+
const since = canvasRefreshInFlightSinceRef.current;
|
|
659
|
+
return (since !== null && Date.now() - since < CANVAS_REFRESH_IN_FLIGHT_MAX_MS);
|
|
660
|
+
}, []);
|
|
661
|
+
const completeCanvasRefresh = useCallback(() => {
|
|
662
|
+
awaitingHostAppRefreshRenderRef.current = false;
|
|
663
|
+
canvasRefreshInFlightSinceRef.current = null;
|
|
664
|
+
window.dispatchEvent(new CustomEvent(CANVAS_REFRESH_COMPLETED_EVENT));
|
|
665
|
+
}, []);
|
|
639
666
|
const restorePendingRefreshScroll = useCallback((iframe, targetScroll, observedScroll) => {
|
|
640
667
|
if (!targetScroll)
|
|
641
668
|
return;
|
|
@@ -775,16 +802,34 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
775
802
|
// Iframe blur is handled by the bridge inline-edit lifecycle now.
|
|
776
803
|
}, []);
|
|
777
804
|
const sendBeginInlineEdit = useCallback((payload) => {
|
|
778
|
-
|
|
779
|
-
false
|
|
805
|
+
const sent = bridgeClientRef.current?.sendCommand("beginInlineEdit", payload) ??
|
|
806
|
+
false;
|
|
807
|
+
logFieldValueDiagnostic("bridge-frame", "beginInlineEdit command", {
|
|
808
|
+
sent,
|
|
809
|
+
payload,
|
|
810
|
+
});
|
|
811
|
+
return sent;
|
|
780
812
|
}, []);
|
|
781
813
|
const sendCancelInlineEdit = useCallback((payload) => {
|
|
782
|
-
|
|
783
|
-
false
|
|
814
|
+
const sent = bridgeClientRef.current?.sendCommand("cancelInlineEdit", payload) ??
|
|
815
|
+
false;
|
|
816
|
+
logFieldValueDiagnostic("bridge-frame", "cancelInlineEdit command", {
|
|
817
|
+
sent,
|
|
818
|
+
payload,
|
|
819
|
+
});
|
|
820
|
+
return sent;
|
|
784
821
|
}, []);
|
|
785
822
|
const sendApplyFieldPatchCommand = useCallback((payload) => {
|
|
786
|
-
|
|
787
|
-
false
|
|
823
|
+
const sent = bridgeClientRef.current?.sendCommand("applyFieldPatch", payload) ??
|
|
824
|
+
false;
|
|
825
|
+
logFieldValueDiagnostic("bridge-frame", "applyFieldPatch command", {
|
|
826
|
+
sent,
|
|
827
|
+
payload: {
|
|
828
|
+
...payload,
|
|
829
|
+
value: summarizeFieldValue(payload.value),
|
|
830
|
+
},
|
|
831
|
+
});
|
|
832
|
+
return sent;
|
|
788
833
|
}, []);
|
|
789
834
|
const sendApplyRichTextCommand = useCallback((payload) => {
|
|
790
835
|
return (bridgeClientRef.current?.sendCommand("applyRichTextCommand", payload) ??
|
|
@@ -833,6 +878,18 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
833
878
|
sendApplyFieldPatch: sendApplyFieldPatchCommand,
|
|
834
879
|
});
|
|
835
880
|
const beginTrackedBridgeInlineEdit = useCallback(async (interaction) => {
|
|
881
|
+
logFieldValueDiagnostic("bridge-frame", "begin tracked inline edit", {
|
|
882
|
+
previousActiveInlineEdit: activeBridgeInlineEditRef.current,
|
|
883
|
+
interaction: {
|
|
884
|
+
kind: interaction.kind,
|
|
885
|
+
elementKey: interaction.elementKey,
|
|
886
|
+
fieldId: interaction.fieldId,
|
|
887
|
+
item: interaction.item,
|
|
888
|
+
selectedText: summarizeFieldValue(interaction.selectedText),
|
|
889
|
+
selectionStartOffset: interaction.selectionStartOffset,
|
|
890
|
+
selectionEndOffset: interaction.selectionEndOffset,
|
|
891
|
+
},
|
|
892
|
+
});
|
|
836
893
|
clearActiveBridgeInlineEdit();
|
|
837
894
|
const started = await beginBridgeInlineEdit(interaction);
|
|
838
895
|
if (started && interaction.elementKey && interaction.fieldId) {
|
|
@@ -857,6 +914,10 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
857
914
|
};
|
|
858
915
|
setIsBridgeInlineEditing(true);
|
|
859
916
|
}
|
|
917
|
+
logFieldValueDiagnostic("bridge-frame", "tracked inline edit result", {
|
|
918
|
+
started,
|
|
919
|
+
nextActiveInlineEdit: activeBridgeInlineEditRef.current,
|
|
920
|
+
});
|
|
860
921
|
return started;
|
|
861
922
|
}, [
|
|
862
923
|
beginBridgeInlineEdit,
|
|
@@ -865,9 +926,17 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
865
926
|
editContextRef,
|
|
866
927
|
]);
|
|
867
928
|
const endTrackedBridgeFieldFocus = useCallback(() => {
|
|
929
|
+
logFieldValueDiagnostic("bridge-frame", "ending tracked field focus", {
|
|
930
|
+
activeInlineEdit: activeBridgeInlineEditRef.current,
|
|
931
|
+
});
|
|
868
932
|
clearActiveBridgeInlineEdit();
|
|
869
933
|
endBridgeFieldFocus();
|
|
870
934
|
}, [clearActiveBridgeInlineEdit, endBridgeFieldFocus]);
|
|
935
|
+
const beginTrackedBridgeInlineEditAfterSelection = useCallback((interaction) => {
|
|
936
|
+
window.setTimeout(() => {
|
|
937
|
+
void beginTrackedBridgeInlineEdit(interaction);
|
|
938
|
+
}, 0);
|
|
939
|
+
}, [beginTrackedBridgeInlineEdit]);
|
|
871
940
|
useEffect(() => {
|
|
872
941
|
const handleBridgeInlineEditRelease = (event) => {
|
|
873
942
|
const detail = event
|
|
@@ -881,6 +950,10 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
881
950
|
if (activeEdit.item && !bridgeItemMatches(activeEdit.item, field.item)) {
|
|
882
951
|
return;
|
|
883
952
|
}
|
|
953
|
+
logFieldValueDiagnostic("bridge-frame", "inline edit released by form", {
|
|
954
|
+
activeInlineEdit: activeEdit,
|
|
955
|
+
field: summarizeFieldDescriptor(field),
|
|
956
|
+
});
|
|
884
957
|
clearActiveBridgeInlineEdit();
|
|
885
958
|
bridgePatchSignatureRef.current.delete(`${activeEdit.elementKey}:${activeEdit.fieldId}`);
|
|
886
959
|
};
|
|
@@ -932,12 +1005,33 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
932
1005
|
},
|
|
933
1006
|
mode: showSuggestions ? "suggestions" : "baseline",
|
|
934
1007
|
});
|
|
935
|
-
|
|
1008
|
+
const result = {
|
|
936
1009
|
value: showSuggestions ? display.mergedValue : display.baselineValue,
|
|
937
1010
|
source: showSuggestions && display.hasSuggestions
|
|
938
1011
|
? "suggestion-preview"
|
|
939
1012
|
: "real",
|
|
940
1013
|
};
|
|
1014
|
+
logFieldValueDiagnostic("bridge-patch", "display value resolved", {
|
|
1015
|
+
showSuggestions,
|
|
1016
|
+
preferRepositoryValue,
|
|
1017
|
+
field: summarizeField(field),
|
|
1018
|
+
structureField: {
|
|
1019
|
+
elementKey: structureField.elementKey,
|
|
1020
|
+
fieldId: structureField.fieldId,
|
|
1021
|
+
item: structureField.item,
|
|
1022
|
+
textContent: summarizeFieldValue(structureField.textContent),
|
|
1023
|
+
isRichText: structureField.isRichText,
|
|
1024
|
+
},
|
|
1025
|
+
itemDescriptor,
|
|
1026
|
+
repositoryValue: summarizeFieldValue(repositoryValue),
|
|
1027
|
+
result: {
|
|
1028
|
+
...result,
|
|
1029
|
+
value: summarizeFieldValue(result.value),
|
|
1030
|
+
},
|
|
1031
|
+
modifiedFieldCount: fieldsContext?.modifiedFields?.length,
|
|
1032
|
+
suggestedEditCount: editContext.suggestedEdits?.length,
|
|
1033
|
+
});
|
|
1034
|
+
return result;
|
|
941
1035
|
}, [
|
|
942
1036
|
editContext.mode,
|
|
943
1037
|
editContext.showSuggestedEdits,
|
|
@@ -972,10 +1066,28 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
972
1066
|
source: patch.source ?? "",
|
|
973
1067
|
observedTextContent: observedTextContent ?? "",
|
|
974
1068
|
});
|
|
975
|
-
|
|
1069
|
+
const previousSignature = bridgePatchSignatureRef.current.get(cacheKey);
|
|
1070
|
+
if (previousSignature === signature) {
|
|
1071
|
+
logFieldValueDiagnostic("bridge-patch", "skipped duplicate send", {
|
|
1072
|
+
cacheKey,
|
|
1073
|
+
patch: {
|
|
1074
|
+
...patch,
|
|
1075
|
+
value: summarizeFieldValue(patch.value),
|
|
1076
|
+
},
|
|
1077
|
+
observedTextContent: summarizeFieldValue(observedTextContent),
|
|
1078
|
+
});
|
|
976
1079
|
return false;
|
|
977
1080
|
}
|
|
978
1081
|
bridgePatchSignatureRef.current.set(cacheKey, signature);
|
|
1082
|
+
logFieldValueDiagnostic("bridge-patch", "sending patch", {
|
|
1083
|
+
cacheKey,
|
|
1084
|
+
patch: {
|
|
1085
|
+
...patch,
|
|
1086
|
+
value: summarizeFieldValue(patch.value),
|
|
1087
|
+
},
|
|
1088
|
+
observedTextContent: summarizeFieldValue(observedTextContent),
|
|
1089
|
+
previousSignature,
|
|
1090
|
+
});
|
|
979
1091
|
bridge.sendCommand("applyFieldPatch", patch);
|
|
980
1092
|
return true;
|
|
981
1093
|
}, []);
|
|
@@ -1517,9 +1629,11 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1517
1629
|
if (!editor)
|
|
1518
1630
|
return;
|
|
1519
1631
|
const selectFromBridgeInteraction = (ids) => {
|
|
1520
|
-
|
|
1632
|
+
const unchanged = bridgeComponentSelectionsMatch(editor.getSelection(), ids);
|
|
1633
|
+
if (!unchanged) {
|
|
1521
1634
|
suppressNextSelectionScrollRef.current = true;
|
|
1522
1635
|
}
|
|
1636
|
+
perfTraceStep("frame:select-dispatched", { ids, unchanged });
|
|
1523
1637
|
editor.select(ids);
|
|
1524
1638
|
};
|
|
1525
1639
|
let effectiveInteraction = interaction;
|
|
@@ -1581,7 +1695,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1581
1695
|
selectFromBridgeInteraction([]);
|
|
1582
1696
|
if (isEditableFieldClick) {
|
|
1583
1697
|
clearSelectedRangeForEditableClick();
|
|
1584
|
-
|
|
1698
|
+
beginTrackedBridgeInlineEditAfterSelection(effectiveInteraction);
|
|
1585
1699
|
}
|
|
1586
1700
|
else if (interaction.kind === "click") {
|
|
1587
1701
|
closeInlineAiIfOpen();
|
|
@@ -1589,7 +1703,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1589
1703
|
}
|
|
1590
1704
|
return;
|
|
1591
1705
|
}
|
|
1592
|
-
const currentSelection = editor.
|
|
1706
|
+
const currentSelection = editor.getSelection();
|
|
1593
1707
|
if (interaction.kind === "contextMenu") {
|
|
1594
1708
|
if (pageViewContextRef.current) {
|
|
1595
1709
|
pageViewContextRef.current.bridgeInteraction = effectiveInteraction;
|
|
@@ -1719,7 +1833,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1719
1833
|
selectFromBridgeInteraction([componentId]);
|
|
1720
1834
|
if (isEditableFieldClick) {
|
|
1721
1835
|
clearSelectedRangeForEditableClick();
|
|
1722
|
-
|
|
1836
|
+
beginTrackedBridgeInlineEditAfterSelection(effectiveInteraction);
|
|
1723
1837
|
}
|
|
1724
1838
|
else {
|
|
1725
1839
|
closeInlineAiIfOpen();
|
|
@@ -1728,6 +1842,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1728
1842
|
}, [
|
|
1729
1843
|
applyBridgeTextCompletion,
|
|
1730
1844
|
beginTrackedBridgeInlineEdit,
|
|
1845
|
+
beginTrackedBridgeInlineEditAfterSelection,
|
|
1731
1846
|
clearBridgeTextCompletion,
|
|
1732
1847
|
endTrackedBridgeFieldFocus,
|
|
1733
1848
|
requestBridgeTextCompletion,
|
|
@@ -1849,9 +1964,12 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1849
1964
|
suggestionsCursorActive: !activeBridgeInlineEditRef.current &&
|
|
1850
1965
|
(editContextRef.current?.mode === "suggestions" ||
|
|
1851
1966
|
!!editContextRef.current?.showSuggestedEdits),
|
|
1852
|
-
selectedComponentIds: editContextRef.current?.
|
|
1967
|
+
selectedComponentIds: editContextRef.current?.getSelection() ?? [],
|
|
1853
1968
|
featureFlags: {
|
|
1854
1969
|
crossOriginBridge: true,
|
|
1970
|
+
// Lets the host emit its own perf logs + interaction perf
|
|
1971
|
+
// timestamps without needing a flag in the iframe's origin.
|
|
1972
|
+
perfTrace: isPerfTraceEnabled(),
|
|
1855
1973
|
},
|
|
1856
1974
|
version: bridge.getDiagnostics().editorVersion,
|
|
1857
1975
|
acknowledgedCapabilities: bridge.getAcknowledgedCapabilities(),
|
|
@@ -1864,12 +1982,31 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1864
1982
|
}
|
|
1865
1983
|
break;
|
|
1866
1984
|
case "structureUpdated":
|
|
1985
|
+
if (isPerfTraceActive()) {
|
|
1986
|
+
perfTraceStep("frame:structure-updated-received", {
|
|
1987
|
+
components: event.payload.structure.components.length,
|
|
1988
|
+
fields: event.payload.structure.fields.length,
|
|
1989
|
+
transportMs: Date.now() - event.timestamp,
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1867
1992
|
pageViewContext.setBridgeStructure(event.payload.structure);
|
|
1993
|
+
if (awaitingHostAppRefreshRenderRef.current) {
|
|
1994
|
+
// First structure change after a host-app refresh: the page's
|
|
1995
|
+
// own re-render has reached the DOM — the refresh is now truly
|
|
1996
|
+
// complete.
|
|
1997
|
+
completeCanvasRefresh();
|
|
1998
|
+
}
|
|
1868
1999
|
break;
|
|
1869
2000
|
case "pageSkeletonUpdated":
|
|
1870
2001
|
pageViewContext.setPageSkeleton(event.payload.pageSkeleton);
|
|
1871
2002
|
break;
|
|
1872
2003
|
case "geometryUpdated": {
|
|
2004
|
+
if (isPerfTraceActive()) {
|
|
2005
|
+
perfTraceStep("frame:geometry-updated-received", {
|
|
2006
|
+
targets: event.payload.geometry.targets.length,
|
|
2007
|
+
transportMs: Date.now() - event.timestamp,
|
|
2008
|
+
});
|
|
2009
|
+
}
|
|
1873
2010
|
latestBridgeScrollRef.current = event.payload.geometry.scroll;
|
|
1874
2011
|
pageViewContext.bridgeGeometry = event.payload.geometry;
|
|
1875
2012
|
pageViewContext.setBridgeGeometry(event.payload.geometry);
|
|
@@ -1893,11 +2030,22 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1893
2030
|
window.dispatchEvent(new CustomEvent(BRIDGE_DOM_UPDATED_EVENT));
|
|
1894
2031
|
break;
|
|
1895
2032
|
case "refreshStarted":
|
|
2033
|
+
logFieldValueDiagnostic("bridge-frame", "refresh started", {
|
|
2034
|
+
revision: event.payload.revision,
|
|
2035
|
+
activeInlineEdit: activeBridgeInlineEditRef.current,
|
|
2036
|
+
patchSignatureCount: bridgePatchSignatureRef.current.size,
|
|
2037
|
+
});
|
|
1896
2038
|
clearBridgeTextCompletion();
|
|
1897
2039
|
clearBridgePatchSignatures();
|
|
1898
2040
|
clearActiveBridgeInlineEdit();
|
|
1899
2041
|
break;
|
|
1900
2042
|
case "refreshCompleted":
|
|
2043
|
+
logFieldValueDiagnostic("bridge-frame", "refresh completed", {
|
|
2044
|
+
activeInlineEdit: activeBridgeInlineEditRef.current,
|
|
2045
|
+
hasStructure: !!event.payload.structure,
|
|
2046
|
+
hasGeometry: !!event.payload.geometry,
|
|
2047
|
+
structureFieldCount: event.payload.structure?.fields.length,
|
|
2048
|
+
});
|
|
1901
2049
|
// Runtime refresh replaces host DOM without a new bridge ready event.
|
|
1902
2050
|
// Field patches sent during the refresh window may have been cached
|
|
1903
2051
|
// against the previous DOM generation, so force the refreshed host to
|
|
@@ -1934,6 +2082,18 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1934
2082
|
};
|
|
1935
2083
|
restorePendingRefreshScroll(iframe, targetScroll, observedScroll);
|
|
1936
2084
|
}
|
|
2085
|
+
if (event.payload.applied === "host-app") {
|
|
2086
|
+
// The page's own app (e.g. a Next.js rendering host) accepted
|
|
2087
|
+
// the refresh, but its re-render lands later as ordinary DOM
|
|
2088
|
+
// mutations. Completing now would reopen viewport reactions
|
|
2089
|
+
// (selection auto-scroll, scrollIntoView, the inserting
|
|
2090
|
+
// indicator) while geometry still describes the pre-edit DOM —
|
|
2091
|
+
// wait for the mutation-driven structureUpdated instead.
|
|
2092
|
+
awaitingHostAppRefreshRenderRef.current = true;
|
|
2093
|
+
}
|
|
2094
|
+
else {
|
|
2095
|
+
completeCanvasRefresh();
|
|
2096
|
+
}
|
|
1937
2097
|
setShowSpinner(false);
|
|
1938
2098
|
break;
|
|
1939
2099
|
case "selectionChanged":
|
|
@@ -1944,11 +2104,32 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1944
2104
|
if (event.payload.elementKey && event.payload.fieldId) {
|
|
1945
2105
|
setIsBridgeInlineEditing(true);
|
|
1946
2106
|
}
|
|
2107
|
+
logFieldValueDiagnostic("bridge-frame", "fieldValueChanged event", {
|
|
2108
|
+
elementKey: event.payload.elementKey,
|
|
2109
|
+
fieldId: event.payload.fieldId,
|
|
2110
|
+
item: event.payload.item,
|
|
2111
|
+
isRichText: event.payload.isRichText,
|
|
2112
|
+
value: summarizeFieldValue(event.payload.value),
|
|
2113
|
+
activeInlineEdit: activeBridgeInlineEditRef.current,
|
|
2114
|
+
});
|
|
1947
2115
|
handleBridgeFieldValueChanged(event.payload);
|
|
1948
2116
|
break;
|
|
1949
2117
|
case "inlineEditEnded":
|
|
2118
|
+
logFieldValueDiagnostic("bridge-frame", "inlineEditEnded event", {
|
|
2119
|
+
reason: event.payload.reason,
|
|
2120
|
+
elementKey: event.payload.elementKey,
|
|
2121
|
+
fieldId: event.payload.fieldId,
|
|
2122
|
+
item: event.payload.item,
|
|
2123
|
+
isRichText: event.payload.isRichText,
|
|
2124
|
+
value: summarizeFieldValue(event.payload.value),
|
|
2125
|
+
activeInlineEdit: activeBridgeInlineEditRef.current,
|
|
2126
|
+
});
|
|
1950
2127
|
handleBridgeInlineEditEnded(event.payload);
|
|
1951
2128
|
clearActiveBridgeInlineEdit();
|
|
2129
|
+
logFieldValueDiagnostic("bridge-frame", "active inline edit cleared after end", {
|
|
2130
|
+
fieldId: event.payload.fieldId,
|
|
2131
|
+
reason: event.payload.reason,
|
|
2132
|
+
});
|
|
1952
2133
|
break;
|
|
1953
2134
|
case "interaction":
|
|
1954
2135
|
if (event.payload.kind === "hover") {
|
|
@@ -1960,6 +2141,24 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
1960
2141
|
else {
|
|
1961
2142
|
lastBridgeHoverInteractionRef.current = undefined;
|
|
1962
2143
|
}
|
|
2144
|
+
if (isPerfTraceEnabled() &&
|
|
2145
|
+
(event.payload.kind === "click" ||
|
|
2146
|
+
event.payload.kind === "doubleClick" ||
|
|
2147
|
+
event.payload.kind === "contextMenu")) {
|
|
2148
|
+
// Backdate to the host's DOM-event timestamp when available so
|
|
2149
|
+
// host-side dispatch (hit-test + deferred-click debounce) is
|
|
2150
|
+
// part of the waterfall; the envelope timestamp is when the
|
|
2151
|
+
// host posted the message.
|
|
2152
|
+
const eventAt = event.payload.perf?.eventAt;
|
|
2153
|
+
beginPerfTrace(`select-${event.payload.kind}`, {
|
|
2154
|
+
componentId: event.payload.componentId,
|
|
2155
|
+
fieldId: event.payload.fieldId,
|
|
2156
|
+
hostDispatchMs: eventAt !== undefined
|
|
2157
|
+
? event.timestamp - eventAt
|
|
2158
|
+
: "n/a (host without perf tracing)",
|
|
2159
|
+
transportMs: Date.now() - event.timestamp,
|
|
2160
|
+
}, eventAt ?? event.timestamp);
|
|
2161
|
+
}
|
|
1963
2162
|
pageViewContext.setBridgeInteraction(event.payload);
|
|
1964
2163
|
void handleBridgeInteraction(event.payload, iframe);
|
|
1965
2164
|
break;
|
|
@@ -2032,6 +2231,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2032
2231
|
scheduleBridgeGeometryRevision,
|
|
2033
2232
|
shouldTrackMinimapScroll,
|
|
2034
2233
|
restorePendingRefreshScroll,
|
|
2234
|
+
completeCanvasRefresh,
|
|
2035
2235
|
]);
|
|
2036
2236
|
useEffect(() => {
|
|
2037
2237
|
const repository = editContext.itemsRepository;
|
|
@@ -2421,6 +2621,8 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2421
2621
|
pendingRefreshScrollRef.current ??=
|
|
2422
2622
|
getIframeWindowScroll(iframeRef.current) ??
|
|
2423
2623
|
latestBridgeScrollRef.current;
|
|
2624
|
+
canvasRefreshInFlightSinceRef.current = Date.now();
|
|
2625
|
+
awaitingHostAppRefreshRenderRef.current = false;
|
|
2424
2626
|
setShowSpinner(true);
|
|
2425
2627
|
console.log(initialLoad
|
|
2426
2628
|
? "Initial load - setting iframe src"
|
|
@@ -2443,6 +2645,8 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2443
2645
|
}
|
|
2444
2646
|
console.log("Bridge - requesting iframe refresh");
|
|
2445
2647
|
pageViewContext.setIframeSupportsRefresh(true);
|
|
2648
|
+
canvasRefreshInFlightSinceRef.current = Date.now();
|
|
2649
|
+
awaitingHostAppRefreshRenderRef.current = false;
|
|
2446
2650
|
const accepted = bridge.sendCommand("refresh", {
|
|
2447
2651
|
url: renderUrl.toString(),
|
|
2448
2652
|
revision: editContext.revision,
|
|
@@ -2450,6 +2654,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2450
2654
|
});
|
|
2451
2655
|
if (!accepted) {
|
|
2452
2656
|
pendingRefreshScrollRef.current = undefined;
|
|
2657
|
+
canvasRefreshInFlightSinceRef.current = null;
|
|
2453
2658
|
pageViewContext.setIframeSupportsRefresh(false);
|
|
2454
2659
|
runFallbackRefresh();
|
|
2455
2660
|
}
|
|
@@ -2486,8 +2691,18 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2486
2691
|
]);
|
|
2487
2692
|
useEffect(() => {
|
|
2488
2693
|
if (fieldsContext?.focusedField) {
|
|
2489
|
-
|
|
2490
|
-
|
|
2694
|
+
// A refresh is being applied: the field's rect still describes the
|
|
2695
|
+
// pre-edit DOM (after a move, its old position — where the drag
|
|
2696
|
+
// started), so scrolling now would yank the canvas to a stale spot.
|
|
2697
|
+
// This fires on the post-operation auto-focus of the moved/added
|
|
2698
|
+
// component; a genuine user focus during a refresh loses one
|
|
2699
|
+
// auto-scroll, which is the lesser evil.
|
|
2700
|
+
if (isCanvasRefreshInFlight())
|
|
2701
|
+
return;
|
|
2702
|
+
// Event-time read: this effect is keyed on focusedField, not selection.
|
|
2703
|
+
const currentSelection = editContext.getSelection();
|
|
2704
|
+
if (currentSelection.length > 0 &&
|
|
2705
|
+
fieldsContext.focusedField.item.id !== currentSelection[0])
|
|
2491
2706
|
return;
|
|
2492
2707
|
const bounds = findBridgeFieldDocumentBounds(pageViewContextRef.current?.bridgeGeometry, fieldsContext.focusedField);
|
|
2493
2708
|
const activePageViewContext = pageViewContextRef.current;
|
|
@@ -2495,7 +2710,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2495
2710
|
scrollBridgeBoundsIntoView(activePageViewContext, bounds, latestBridgeScrollRef.current);
|
|
2496
2711
|
}
|
|
2497
2712
|
}
|
|
2498
|
-
}, [fieldsContext?.focusedField]);
|
|
2713
|
+
}, [fieldsContext?.focusedField, isCanvasRefreshInFlight]);
|
|
2499
2714
|
// Drive the selection-scroll suppression window from the drag lifecycle.
|
|
2500
2715
|
// Declared BEFORE the selection-scroll effect so it runs first in the same
|
|
2501
2716
|
// commit (when a drop changes both dragObject and selection at once).
|
|
@@ -2512,7 +2727,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2512
2727
|
}
|
|
2513
2728
|
}, [editContext.dragObject]);
|
|
2514
2729
|
useEffect(() => {
|
|
2515
|
-
const selectionKey =
|
|
2730
|
+
const selectionKey = canvasSelection.join("|");
|
|
2516
2731
|
const selectionChanged = selectionKey !== lastScrolledSelectionKeyRef.current;
|
|
2517
2732
|
lastScrolledSelectionKeyRef.current = selectionKey;
|
|
2518
2733
|
// The effect also re-runs when focusedField changes (e.g. a field blurs
|
|
@@ -2525,24 +2740,43 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2525
2740
|
suppressNextSelectionScrollRef.current = false;
|
|
2526
2741
|
return;
|
|
2527
2742
|
}
|
|
2743
|
+
// Programmatic selections (the drop target's parent, the post-operation
|
|
2744
|
+
// focus of a moved/added component) arm this suppression at their source:
|
|
2745
|
+
// their targets may still measure at pre-edit geometry, and unlike user
|
|
2746
|
+
// clicks they carry no intent to see the component. Deterministic — no
|
|
2747
|
+
// time window to lose against a slow operation or frozen host.
|
|
2748
|
+
if (editContext.consumeNextSelectionAutoScrollSuppression?.())
|
|
2749
|
+
return;
|
|
2528
2750
|
// Suppressed during a drag and briefly after it ends. The drag owns
|
|
2529
2751
|
// scrolling, and the drop's re-selection must not jump the page away from
|
|
2530
2752
|
// where the user dropped (toward stale pre-move geometry).
|
|
2531
2753
|
if (Date.now() < suppressSelectionScrollUntilRef.current)
|
|
2532
2754
|
return;
|
|
2533
|
-
|
|
2534
|
-
|
|
2755
|
+
// Suppressed while a refresh is applying: geometry still measures the
|
|
2756
|
+
// pre-refresh DOM (a just-moved component still sits at its old rect), so
|
|
2757
|
+
// scrolling now would target a stale position. The refresh restore owns
|
|
2758
|
+
// the viewport until the refreshed geometry lands.
|
|
2759
|
+
if (isCanvasRefreshInFlight())
|
|
2760
|
+
return;
|
|
2761
|
+
if (!fieldsContext?.focusedField && canvasSelection.length > 0) {
|
|
2762
|
+
const lastSelectedComponent = getComponentById(canvasSelection[canvasSelection.length - 1], pageViewContextRef.current.page);
|
|
2535
2763
|
if (lastSelectedComponent) {
|
|
2536
2764
|
editContext.setScrollIntoView(lastSelectedComponent.id);
|
|
2537
2765
|
}
|
|
2538
2766
|
}
|
|
2539
|
-
}, [
|
|
2767
|
+
}, [canvasSelection, fieldsContext?.focusedField, isCanvasRefreshInFlight]);
|
|
2540
2768
|
useEffect(() => {
|
|
2541
2769
|
if (!editContext.scrollIntoView)
|
|
2542
2770
|
return;
|
|
2543
2771
|
const activePageViewContext = pageViewContextRef.current;
|
|
2544
2772
|
if (!activePageViewContext)
|
|
2545
2773
|
return;
|
|
2774
|
+
// Defer (without consuming the request) while a refresh is applying:
|
|
2775
|
+
// resolving now would measure the target against pre-refresh geometry and
|
|
2776
|
+
// scroll to a stale rect. The effect re-runs when the refreshed geometry
|
|
2777
|
+
// arrives (bridgeGeometry dependency) and resolves against fresh bounds.
|
|
2778
|
+
if (isCanvasRefreshInFlight())
|
|
2779
|
+
return;
|
|
2546
2780
|
const scrollTarget = editContext.scrollIntoView;
|
|
2547
2781
|
const requestState = scrollIntoViewRequestRef.current;
|
|
2548
2782
|
const signature = getScrollIntoViewSignature(scrollTarget);
|
|
@@ -2577,6 +2811,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2577
2811
|
editContext.scrollIntoView,
|
|
2578
2812
|
pageViewContext.page,
|
|
2579
2813
|
pageViewContext.bridgeGeometry,
|
|
2814
|
+
isCanvasRefreshInFlight,
|
|
2580
2815
|
]);
|
|
2581
2816
|
useEffect(() => {
|
|
2582
2817
|
const handleMessage = (message) => {
|
|
@@ -2651,10 +2886,16 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2651
2886
|
};
|
|
2652
2887
|
}, [iframeElement]);
|
|
2653
2888
|
useEffect(() => {
|
|
2654
|
-
bridgeClientRef.current?.sendCommand("setSelection", {
|
|
2655
|
-
componentIds:
|
|
2889
|
+
const sent = bridgeClientRef.current?.sendCommand("setSelection", {
|
|
2890
|
+
componentIds: canvasSelection,
|
|
2656
2891
|
});
|
|
2657
|
-
|
|
2892
|
+
if (isPerfTraceActive()) {
|
|
2893
|
+
perfTraceStep("frame:setSelection-command-sent", {
|
|
2894
|
+
ids: canvasSelection,
|
|
2895
|
+
sent: sent ?? false,
|
|
2896
|
+
});
|
|
2897
|
+
}
|
|
2898
|
+
}, [canvasSelection]);
|
|
2658
2899
|
useEffect(() => {
|
|
2659
2900
|
const bridge = bridgeClientRef.current;
|
|
2660
2901
|
bridge?.sendCommand("setPreviewMode", {
|
|
@@ -2787,6 +3028,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
|
|
|
2787
3028
|
if (pendingRefreshScrollRef.current) {
|
|
2788
3029
|
restorePendingRefreshScroll(iframeRef.current, pendingRefreshScrollRef.current);
|
|
2789
3030
|
}
|
|
3031
|
+
completeCanvasRefresh();
|
|
2790
3032
|
}
|
|
2791
3033
|
} }), iframeElement && (_jsx(IframeOverlayProvider, { iframe: iframeElement, mode: "scrolling", scrollScale: 1, visualScale: 1, invalidationKey: `${zoom}:${bridgeGeometryRevision}`, deferredInvalidationMs: ZOOM_TRANSITION_MS + 50, bleed: { top: 2, bottom: 2, left: 2 }, children: _jsx(PageEditorChrome, { iframe: iframeElement, compareView: compareView, pageViewContext: pageViewContext, onBridgeRichTextCommand: sendApplyRichTextCommand }) })), pageViewContext.deviceHeight && pageViewContext.device && (_jsx("div", { className: "bg-neutral-grey-5 relative z-40 h-full w-full" }))] }), shouldRenderMiniMap && (_jsx(MiniMap, { compareView: compareView, scroll: scroll, mainViewIframeRef: iframeRef, pageViewContext: pageViewContext })), showSpinner && (_jsxs(_Fragment, { children: [_jsx("div", { className: "bg-neutral-grey-5/50 absolute top-0 left-0 h-full w-full" }), _jsx("div", { className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 transform", children: _jsx(Spinner, {}) })] }))] }), _jsx(FieldActionsOverlay, { ref: fieldActionsOverlay, generatorButtons: contextMenuFieldButtons, onActionClick: handleActionClick, onParameterizedActionExecute: handleParameterizedActionExecute, currentOverlay: editContext?.currentOverlay, fieldId: contextMenuField?.fieldId || "", setCurrentOverlay: editContext?.setCurrentOverlay || (() => { }), preSelectedAction: preSelectedAction })] }));
|
|
2792
3034
|
}
|