@replohq/sandbox-runtime 1.7.1 → 1.7.3
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/ClientErrorBoundary.d.ts +1 -1
- package/ClientErrorBoundary.js +0 -5
- package/DocumentReadyBeacon.js +0 -1
- package/LinkInterceptor.js +0 -1
- package/NavigationReceiver.js +0 -1
- package/NextErrorReporter.js +0 -1
- package/README.md +48 -0
- package/_vendor/replo-utils/lib/crypto.d.ts +2 -8
- package/_vendor/replo-utils/lib/fonts.d.ts +8 -0
- package/_vendor/replo-utils/lib/fonts.mjs +12 -14
- package/_vendor/replo-utils/lib/geometry.mjs +0 -1
- package/_vendor/replo-utils/lib/math.d.ts +0 -4
- package/_vendor/replo-utils/lib/math.mjs +0 -1
- package/_vendor/replo-utils/lib/posthogReplay.mjs +0 -1
- package/_vendor/replo-utils/react/use-iframe-rpc-channel.mjs +0 -1
- package/_vendor/replo-utils/react/use-viewport-snapshot-responder.mjs +9 -25
- package/_vendor/schemas/componentPreview.mjs +0 -4
- package/_vendor/schemas/designLibrary.mjs +0 -2
- package/_vendor/schemas/errors.d.ts +0 -3
- package/_vendor/schemas/generated/selectModeIframeRpc.d.ts +1 -1
- package/_vendor/schemas/iframeRpcChannel.d.ts +1 -1
- package/_vendor/schemas/iframeRpcChannel.mjs +0 -22
- package/_vendor/schemas/pageAnnotations.mjs +0 -3
- package/_vendor/schemas/selectMode.d.ts +0 -4
- package/_vendor/schemas/selectModeIframeRpc.d.ts +4 -4
- package/_vendor/schemas/selectModeIframeRpc.mjs +2 -12
- package/annotations/AnnotationLayerMount.js +0 -1
- package/annotations/annotationController.js +0 -3
- package/annotations/bridgeGate.js +0 -4
- package/buildMetadata.js +3 -3
- package/chunk-3YA3QXUQ.mjs +1 -4
- package/chunk-FLYEIRFK.mjs +0 -1
- package/chunk-G3S6ZNPF.mjs +0 -7
- package/chunk-JUKCUPQ6.mjs +5 -129
- package/chunk-SGKQ5HGT.mjs +0 -1
- package/chunk-TESFJQID.mjs +0 -1
- package/chunk-UOBGRB5I.mjs +0 -5
- package/design-library-preview/DesignLibraryPreview.js +0 -1
- package/next/component-preview-client.js +0 -1
- package/next/component-preview-href.js +0 -1
- package/next/component-preview-props.js +0 -1
- package/next/component-preview.js +0 -1
- package/next/config.js +0 -1
- package/package.json +4 -4
- package/posthog-relay.js +0 -5
- package/sandbox-runtime.js +0 -1
- package/select-mode/EditorSelection.d.ts +0 -2
- package/select-mode/EditorSelection.js +0 -1
- package/select-mode/annotationFrames.js +0 -1
- package/select-mode/descriptor/elementDescriptor.d.ts +0 -2
- package/select-mode/descriptor/elementDescriptor.js +0 -1
- package/select-mode/descriptor/styleExtraction.js +0 -1
- package/select-mode/displayModeStore.js +0 -2
- package/select-mode/fast-refresh-relay.js +0 -1
- package/select-mode/fiber.js +1 -5
- package/select-mode/hooks/useCrosshairCursor.d.ts +0 -2
- package/select-mode/hooks/useCrosshairCursor.js +0 -1
- package/select-mode/hooks/useEditModeStateMachine.js +0 -1
- package/select-mode/hooks/useOptimisticOverrides.js +0 -1
- package/select-mode/hooks/useParentMessaging.d.ts +0 -2
- package/select-mode/hooks/useParentMessaging.js +0 -1
- package/select-mode/hooks/useSelectModeController.js +0 -1
- package/select-mode/hooks/useSelectionHover.d.ts +0 -2
- package/select-mode/hooks/useSelectionHover.js +0 -1
- package/select-mode/hooks/useSelectionInteractions.d.ts +0 -2
- package/select-mode/hooks/useSelectionInteractions.js +0 -1
- package/select-mode/hooks/useSelectionScrollSync.d.ts +0 -2
- package/select-mode/hooks/useSelectionScrollSync.js +0 -1
- package/select-mode/hooks/useSiblingResolution.js +0 -1
- package/select-mode/iframeRpcChannel.d.ts +2 -2
- package/select-mode/iframeRpcChannel.js +0 -1
- package/select-mode/inlineTextMarks.js +0 -1
- package/select-mode/interactions/selectionGeometry.d.ts +0 -20
- package/select-mode/interactions/selectionGeometry.js +0 -1
- package/select-mode/optimisticOverrideDom.js +0 -1
- package/select-mode/selectModeSession.js +0 -1
- package/select-mode/selectionFrame.d.ts +0 -7
- package/select-mode/selectionFrame.js +0 -1
- package/select-mode/selectionPublish.js +0 -1
- package/select-mode/symbolicate.js +0 -1
- package/select-mode/tiptapInlineEditor.js +0 -5
- package/ClientErrorBoundary.js.map +0 -7
- package/DocumentReadyBeacon.js.map +0 -7
- package/LinkInterceptor.js.map +0 -7
- package/NavigationReceiver.js.map +0 -7
- package/NextErrorReporter.js.map +0 -7
- package/annotations/AnnotationLayerMount.js.map +0 -7
- package/annotations/annotationController.js.map +0 -7
- package/annotations/bridgeGate.js.map +0 -7
- package/buildMetadata.js.map +0 -7
- package/design-library-preview/DesignLibraryPreview.js.map +0 -7
- package/next/component-preview-client.js.map +0 -7
- package/next/component-preview-href.js.map +0 -7
- package/next/component-preview-props.js.map +0 -7
- package/next/component-preview.js.map +0 -7
- package/next/config.js.map +0 -7
- package/posthog-relay.js.map +0 -7
- package/sandbox-runtime.js.map +0 -7
- package/select-mode/EditorSelection.js.map +0 -7
- package/select-mode/annotationFrames.js.map +0 -7
- package/select-mode/descriptor/elementDescriptor.js.map +0 -7
- package/select-mode/descriptor/styleExtraction.js.map +0 -7
- package/select-mode/displayModeStore.js.map +0 -7
- package/select-mode/fast-refresh-relay.js.map +0 -7
- package/select-mode/fiber.js.map +0 -7
- package/select-mode/hooks/useCrosshairCursor.js.map +0 -7
- package/select-mode/hooks/useEditModeStateMachine.js.map +0 -7
- package/select-mode/hooks/useOptimisticOverrides.js.map +0 -7
- package/select-mode/hooks/useParentMessaging.js.map +0 -7
- package/select-mode/hooks/useSelectModeController.js.map +0 -7
- package/select-mode/hooks/useSelectionHover.js.map +0 -7
- package/select-mode/hooks/useSelectionInteractions.js.map +0 -7
- package/select-mode/hooks/useSelectionScrollSync.js.map +0 -7
- package/select-mode/hooks/useSiblingResolution.js.map +0 -7
- package/select-mode/iframeRpcChannel.js.map +0 -7
- package/select-mode/inlineTextMarks.js.map +0 -7
- package/select-mode/interactions/selectionGeometry.js.map +0 -7
- package/select-mode/optimisticOverrideDom.js.map +0 -7
- package/select-mode/selectModeSession.js.map +0 -7
- package/select-mode/selectionFrame.js.map +0 -7
- package/select-mode/selectionPublish.js.map +0 -7
- package/select-mode/symbolicate.js.map +0 -7
- package/select-mode/tiptapInlineEditor.js.map +0 -7
package/chunk-SGKQ5HGT.mjs
CHANGED
package/chunk-TESFJQID.mjs
CHANGED
package/chunk-UOBGRB5I.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { exhaustiveSwitch } from './chunk-JUKCUPQ6.mjs';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
|
-
// ../replo-utils/lib/json.ts
|
|
5
4
|
function parseJsonOrNull(json) {
|
|
6
5
|
try {
|
|
7
6
|
return JSON.parse(json);
|
|
@@ -10,7 +9,6 @@ function parseJsonOrNull(json) {
|
|
|
10
9
|
}
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
// ../replo-utils/lib/parse.ts
|
|
14
12
|
function parseSchemaOrNull(value, schema) {
|
|
15
13
|
const parseResult = schema.safeParse(value);
|
|
16
14
|
return parseResult.success ? parseResult.data : null;
|
|
@@ -205,9 +203,6 @@ var selectModeSelectionSchema = z.discriminatedUnion("type", [
|
|
|
205
203
|
z.object({
|
|
206
204
|
type: z.literal("drag"),
|
|
207
205
|
dragRect: selectModeBoundingRectSchema,
|
|
208
|
-
// Bounding boxes of the selectables the drag currently intersects,
|
|
209
|
-
// rendered as lighter highlights so the user can see what the drag
|
|
210
|
-
// will capture before they release.
|
|
211
206
|
selectionRects: z.array(selectModeSelectionRectSchema)
|
|
212
207
|
})
|
|
213
208
|
]).describe("SelectModeSelection");
|
package/next/config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@replohq/sandbox-runtime",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.3",
|
|
4
4
|
"reploBuild": {
|
|
5
5
|
"packageName": "@replohq/sandbox-runtime",
|
|
6
|
-
"version": "1.7.
|
|
6
|
+
"version": "1.7.3",
|
|
7
7
|
"branch": "HEAD",
|
|
8
|
-
"commit": "
|
|
9
|
-
"builtAt": "2026-09-
|
|
8
|
+
"commit": "769a5347144bb3d6c77b6f06b075c8f6ad45a6b3",
|
|
9
|
+
"builtAt": "2026-09-16T18:01:45.448Z"
|
|
10
10
|
},
|
|
11
11
|
"description": "Replo sandbox runtime — editor integration for agent-built Next.js sites.",
|
|
12
12
|
"license": "SEE LICENSE IN LICENSE",
|
package/posthog-relay.js
CHANGED
|
@@ -39,14 +39,10 @@ function initPostHogRelay() {
|
|
|
39
39
|
api_host: POSTHOG_API_HOST,
|
|
40
40
|
persistence: "localStorage",
|
|
41
41
|
autocapture: false,
|
|
42
|
-
// (Noah, 2026-07-14, REPL-29305): Disable performance capture — its PerformanceObserver
|
|
43
|
-
// relays a non-cloneable PerformanceServerTiming across the iframe boundary via postMessage,
|
|
44
|
-
// throwing a DataCloneError in the preview. Matches the bedrock-sdk relay.
|
|
45
42
|
capture_performance: false,
|
|
46
43
|
capture_pageview: false,
|
|
47
44
|
session_recording: {
|
|
48
45
|
recordCrossOriginIframes: true,
|
|
49
|
-
// NOTE (Nick, 2026-02-02, REPL-23284): Disable canvas recording to prevent SecurityError on tainted canvases
|
|
50
46
|
captureCanvas: { recordCanvas: false }
|
|
51
47
|
}
|
|
52
48
|
});
|
|
@@ -69,4 +65,3 @@ function PostHogRelay() {
|
|
|
69
65
|
export {
|
|
70
66
|
PostHogRelay as default
|
|
71
67
|
};
|
|
72
|
-
//# sourceMappingURL=posthog-relay.js.map
|
package/sandbox-runtime.js
CHANGED
|
@@ -18,7 +18,5 @@
|
|
|
18
18
|
* The `interactionSessionRef` is the single source of truth for the
|
|
19
19
|
* in-progress drag/selection — every hook reads/writes it via ref so we
|
|
20
20
|
* don't trigger React re-renders during interaction-heavy operations.
|
|
21
|
-
*
|
|
22
|
-
* @author Kevin O'Connell 2026-04-17
|
|
23
21
|
*/
|
|
24
22
|
export declare function EditorSelection(): null;
|
|
@@ -16,8 +16,6 @@ export declare function buildSelector(element: Element): string;
|
|
|
16
16
|
* Centralizes everything the parent (and downstream agent) need to know
|
|
17
17
|
* about a selection: identification, geometry, source location, and a
|
|
18
18
|
* style-inlined HTML snippet.
|
|
19
|
-
*
|
|
20
|
-
* @author Kevin O'Connell 2026-04-17
|
|
21
19
|
*/
|
|
22
20
|
export declare function buildElementDescriptor({ element, clickPosition, siblingSelectors, }: {
|
|
23
21
|
element: Element;
|
|
@@ -28,7 +28,6 @@ const displayModeStore = {
|
|
|
28
28
|
displayMode = nextDisplayMode;
|
|
29
29
|
notify();
|
|
30
30
|
},
|
|
31
|
-
/** Test-only: reset back to the default so specs don't leak state. */
|
|
32
31
|
reset() {
|
|
33
32
|
displayMode = "browse";
|
|
34
33
|
}
|
|
@@ -44,4 +43,3 @@ export {
|
|
|
44
43
|
displayModeStore,
|
|
45
44
|
useDisplayMode
|
|
46
45
|
};
|
|
47
|
-
//# sourceMappingURL=displayModeStore.js.map
|
package/select-mode/fiber.js
CHANGED
|
@@ -56,8 +56,7 @@ function parseDebugStackSource(debugStack) {
|
|
|
56
56
|
if (REACT_STACK_BOTTOM_FRAME_PATTERN.test(line)) {
|
|
57
57
|
return null;
|
|
58
58
|
}
|
|
59
|
-
const framedMatch = line.match(/^at\s+(.+?)\s+\((.*):(\d+):(\d+)\)$/) ??
|
|
60
|
-
// segments (`.pnpm/react@19.2.4/…`) from being read as a method.
|
|
59
|
+
const framedMatch = line.match(/^at\s+(.+?)\s+\((.*):(\d+):(\d+)\)$/) ??
|
|
61
60
|
line.match(/^([^@/]*)@(.+):(\d+):(\d+)$/);
|
|
62
61
|
const stackFrameMatch = framedMatch ?? line.match(/^at\s+(?:.*\()?(.*):(\d+):(\d+)\)?$/) ?? line.match(/^(.*):(\d+):(\d+)$/);
|
|
63
62
|
if (!stackFrameMatch) {
|
|
@@ -98,8 +97,6 @@ function getFiberFromElement(element) {
|
|
|
98
97
|
});
|
|
99
98
|
if (fiberSymbolKey) {
|
|
100
99
|
return (
|
|
101
|
-
// Legacy cast - may or may not be necessary
|
|
102
|
-
// eslint-disable-next-line replo/no-as-cast
|
|
103
100
|
element[fiberSymbolKey] ?? null
|
|
104
101
|
);
|
|
105
102
|
}
|
|
@@ -503,4 +500,3 @@ export {
|
|
|
503
500
|
getRepetitionHostNodes,
|
|
504
501
|
getSourceLocation
|
|
505
502
|
};
|
|
506
|
-
//# sourceMappingURL=fiber.js.map
|
|
@@ -4,8 +4,6 @@ import type { DisplayMode } from "../../_vendor/schemas/generated/selectMode";
|
|
|
4
4
|
* is in `selection` mode. We inject a `<style>` tag into the iframe document
|
|
5
5
|
* (rather than toggling a class on `<html>`) so that the `!important` rule
|
|
6
6
|
* wins against any per-element cursor styling on the page being edited.
|
|
7
|
-
*
|
|
8
|
-
* @author Kevin O'Connell 2026-04-17
|
|
9
7
|
*/
|
|
10
8
|
export declare function useCrosshairCursor({ displayMode, }: {
|
|
11
9
|
displayMode: DisplayMode;
|
|
@@ -15,8 +15,6 @@ import type { DisplayMode, SelectModeFormatCommand, SelectModeOptimisticUpdatePa
|
|
|
15
15
|
* Also fires `iframeReady` on mount so the parent knows it's safe to push
|
|
16
16
|
* the initial `setDisplayMode` — without this handshake the parent would
|
|
17
17
|
* race the iframe's mount and the first message could be lost.
|
|
18
|
-
*
|
|
19
|
-
* @author Kevin O'Connell 2026-04-17
|
|
20
18
|
*/
|
|
21
19
|
export declare function useParentMessaging({ applyOptimisticUpdate, markCommitted, resolveSessionOverrides, onEnterEditMode, onExitEditMode, onFormatCommand, revertOverride, setDisplayMode, setSelectionType, }: {
|
|
22
20
|
applyOptimisticUpdate?: (input: {
|
|
@@ -12,8 +12,6 @@ export declare function resetHoverRectDedup(): void;
|
|
|
12
12
|
* the only highlight we want visible.
|
|
13
13
|
* - Unchanged rectangles do not cross the iframe bridge. Viewport updates
|
|
14
14
|
* are coalesced because scroll and wheel can fire in the same frame.
|
|
15
|
-
*
|
|
16
|
-
* @author Noah Gilmore 2026-07-26
|
|
17
15
|
*/
|
|
18
16
|
export declare function useSelectionHover({ displayMode, interactionSessionRef, }: {
|
|
19
17
|
displayMode: DisplayMode;
|
|
@@ -23,8 +23,6 @@ import type { SelectModeInteractionSession } from "../selectModeSession";
|
|
|
23
23
|
* We capture-listen and `preventDefault`/`stopPropagation` clicks so the
|
|
24
24
|
* underlying page can't navigate or trigger handlers while the user is
|
|
25
25
|
* working in selection mode.
|
|
26
|
-
*
|
|
27
|
-
* @author Kevin O'Connell 2026-04-17
|
|
28
26
|
*/
|
|
29
27
|
export declare function useSelectionInteractions({ displayMode, editingElementRef, interactionSessionRef, onBeginEditing, }: {
|
|
30
28
|
displayMode: DisplayMode;
|
|
@@ -18,8 +18,6 @@ import type { SelectModeInteractionSession } from "../selectModeSession";
|
|
|
18
18
|
* - For an `area` session we keep the original *page* rect (which doesn't
|
|
19
19
|
* move) and convert it to viewport coordinates using the latest scroll
|
|
20
20
|
* offset before sending.
|
|
21
|
-
*
|
|
22
|
-
* @author Noah Gilmore 2026-07-26
|
|
23
21
|
*/
|
|
24
22
|
export declare function useSelectionScrollSync({ displayMode, interactionSessionRef, }: {
|
|
25
23
|
displayMode: DisplayMode;
|
|
@@ -76,13 +76,13 @@ export declare function getSelectModeIframeRpcChannel(): import("../_vendor/sche
|
|
|
76
76
|
timeoutMs: number;
|
|
77
77
|
};
|
|
78
78
|
iframeReady: {
|
|
79
|
-
inputSchema: import("zod").
|
|
79
|
+
inputSchema: import("zod").ZodObject<{
|
|
80
80
|
packageName: import("zod").ZodString;
|
|
81
81
|
version: import("zod").ZodString;
|
|
82
82
|
branch: import("zod").ZodNullable<import("zod").ZodString>;
|
|
83
83
|
commit: import("zod").ZodNullable<import("zod").ZodString>;
|
|
84
84
|
builtAt: import("zod").ZodNullable<import("zod").ZodString>;
|
|
85
|
-
}, import("zod/v4/core").$strip
|
|
85
|
+
}, import("zod/v4/core").$strip>;
|
|
86
86
|
outputSchema: import("zod").ZodVoid;
|
|
87
87
|
};
|
|
88
88
|
elementSelected: {
|
|
@@ -12,36 +12,21 @@ export type ScrollOffset = {
|
|
|
12
12
|
export type SelectedAreaState = {
|
|
13
13
|
pageRect: SelectModeBoundingRect;
|
|
14
14
|
};
|
|
15
|
-
/**
|
|
16
|
-
* @author Kevin O'Connell 2026-04-17
|
|
17
|
-
*/
|
|
18
15
|
export declare function getDragPositionFromClient({ clientX, clientY, scrollOffset, }: {
|
|
19
16
|
clientX: number;
|
|
20
17
|
clientY: number;
|
|
21
18
|
scrollOffset: ScrollOffset;
|
|
22
19
|
}): DragPosition;
|
|
23
|
-
/**
|
|
24
|
-
* @author Kevin O'Connell 2026-04-17
|
|
25
|
-
*/
|
|
26
20
|
export declare function getDocumentScrollOffset(): ScrollOffset;
|
|
27
|
-
/**
|
|
28
|
-
* @author Kevin O'Connell 2026-04-17
|
|
29
|
-
*/
|
|
30
21
|
export declare function getViewportSelectionRect({ dragStart, dragCurrent, scrollOffset, }: {
|
|
31
22
|
dragStart: DragPosition;
|
|
32
23
|
dragCurrent: DragPosition;
|
|
33
24
|
scrollOffset: ScrollOffset;
|
|
34
25
|
}): SelectModeBoundingRect;
|
|
35
|
-
/**
|
|
36
|
-
* @author Kevin O'Connell 2026-04-17
|
|
37
|
-
*/
|
|
38
26
|
export declare function getPageRectFromViewportRect({ rect, scrollOffset, }: {
|
|
39
27
|
rect: SelectModeBoundingRect;
|
|
40
28
|
scrollOffset: ScrollOffset;
|
|
41
29
|
}): SelectModeBoundingRect;
|
|
42
|
-
/**
|
|
43
|
-
* @author Kevin O'Connell 2026-04-17
|
|
44
|
-
*/
|
|
45
30
|
export declare function getViewportRectFromPageRect({ rect, scrollOffset, }: {
|
|
46
31
|
rect: SelectModeBoundingRect;
|
|
47
32
|
scrollOffset: ScrollOffset;
|
|
@@ -117,14 +102,9 @@ export declare function unionElementPageRects({ elements, scrollOffset, }: {
|
|
|
117
102
|
* selection rect, clamped to the element's own bounds. This anchor is what
|
|
118
103
|
* lets the selected-element overlay continue to track the element when the
|
|
119
104
|
* user scrolls (`useSelectionScrollSync` re-projects relative to it).
|
|
120
|
-
*
|
|
121
|
-
* @author Kevin O'Connell 2026-04-17
|
|
122
105
|
*/
|
|
123
106
|
export declare function getElementAnchor({ element, selectionRect, }: {
|
|
124
107
|
element: Element;
|
|
125
108
|
selectionRect: SelectModeBoundingRect;
|
|
126
109
|
}): SelectModeClickPosition;
|
|
127
|
-
/**
|
|
128
|
-
* @author Kevin O'Connell 2026-04-17
|
|
129
|
-
*/
|
|
130
110
|
export declare function getElementBoundingRect(element: Element): SelectModeBoundingRect;
|
|
@@ -23,8 +23,6 @@
|
|
|
23
23
|
* The canopy iframe loads a customer page and doesn't include lattice /
|
|
24
24
|
* tailwind, so styling is intentionally vanilla inline CSS rather than
|
|
25
25
|
* Tailwind classes.
|
|
26
|
-
*
|
|
27
|
-
* @author Noah Gilmore 2026-07-26
|
|
28
26
|
*/
|
|
29
27
|
type SelectionFrameVariant = "element" | "area";
|
|
30
28
|
type SelectionFramePageRect = {
|
|
@@ -57,8 +55,6 @@ export declare function getOrCreateFramesLayerContainer({ id, zIndex, }: {
|
|
|
57
55
|
* call this once at commit time and let the browser handle the rest of the
|
|
58
56
|
* scroll lifetime. Reconciles the node pool against `frames.length` so group
|
|
59
57
|
* updates reuse the existing nodes when the repetition count stays stable.
|
|
60
|
-
*
|
|
61
|
-
* @author Noah Gilmore 2026-07-26
|
|
62
58
|
*/
|
|
63
59
|
export declare function showSelectionFrames({ frames, }: {
|
|
64
60
|
frames: SelectionFrameSpec[];
|
|
@@ -77,8 +73,5 @@ export declare function showAreaSelectionFrames({ elements, scrollOffset, }: {
|
|
|
77
73
|
top: number;
|
|
78
74
|
};
|
|
79
75
|
}): void;
|
|
80
|
-
/**
|
|
81
|
-
* @author Kevin O'Connell 2026-05-26
|
|
82
|
-
*/
|
|
83
76
|
export declare function hideSelectionFrame(): void;
|
|
84
77
|
export {};
|
|
@@ -58,8 +58,6 @@ function createInlineTiptapEditor({
|
|
|
58
58
|
InlineLink
|
|
59
59
|
],
|
|
60
60
|
editorProps: {
|
|
61
|
-
// Drop the browser's default focus ring on the contenteditable — the
|
|
62
|
-
// select-mode selection frame already indicates the edit target.
|
|
63
61
|
attributes: {
|
|
64
62
|
"data-select-mode-inline-editor": "",
|
|
65
63
|
style: "outline: none;"
|
|
@@ -92,8 +90,6 @@ function createInlineTiptapEditor({
|
|
|
92
90
|
});
|
|
93
91
|
return {
|
|
94
92
|
focus: () => editor.commands.focus(),
|
|
95
|
-
// Focus the editor with the full text block selected so the user can type
|
|
96
|
-
// to replace it immediately (or arrow/click to drop the selection).
|
|
97
93
|
focusAndSelectAll: () => editor.chain().focus().selectAll().run(),
|
|
98
94
|
destroy: () => {
|
|
99
95
|
editor.destroy();
|
|
@@ -120,4 +116,3 @@ function createInlineTiptapEditor({
|
|
|
120
116
|
export {
|
|
121
117
|
createInlineTiptapEditor
|
|
122
118
|
};
|
|
123
|
-
//# sourceMappingURL=tiptapInlineEditor.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../ClientErrorBoundary.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\n\nimport * as React from \"react\";\n\ninterface ErrorBoundaryState {\n didCatch: boolean;\n}\n\ntype ErrorBoundaryProps = React.PropsWithChildren<{\n onError?: (error: unknown, info: React.ErrorInfo) => void;\n}>;\n\nclass ErrorBoundary extends React.Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n state: ErrorBoundaryState = {\n didCatch: false,\n };\n\n static getDerivedStateFromError(): ErrorBoundaryState {\n return { didCatch: true };\n }\n\n componentDidCatch(error: unknown, info: React.ErrorInfo) {\n this.props.onError?.(error, info);\n }\n\n render() {\n if (this.state.didCatch) {\n /**\n * NOTE (Max, 2026-06-10): When there's any error that hits this Error boundary,\n * we render this neutral cover.\n * getDerivedStateFromError() runs in the render phase, before commit, so this cover\n * is what hits the DOM immediately when the error is caught.\n * The editor lays its own loading / error UI on top (driven by NextErrorReporter's\n * status postMessage).\n * This div has a plain light neutral color, close enough to the editor's\n * loading animation. If we returned null, it'd show a cover with the site's default color (e.g. black),\n * which makes the transition less smooth between the sandbox runtime showing this cover, and the iframe embedder\n * receiving the post message telling it to show some loading animation.\n *\n * I'm really unsatisfied with this approach: there's no apparent flicker only because the editor's loading animation\n * when receiving the post message has the same color as this neutral cover... Alternative would be for\n * this error boundary to show the loading animation itself (instead of the embedder) but that's even more weird...\n */\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483646,\n background: \"#ffffff\",\n }}\n />\n );\n }\n return this.props.children;\n }\n}\n\n/**\n * NOTE (Max, 2026-06-10): Client-side error boundary. On a caught render error it\n * (1) reports the error to the parent editor via postMessage (so it can get reported to Sentry)\n * and (2) renders a neutral cover instead of going blank, so the preview never flashes the broken\n * page while the agent fixes it. The editor decides what to show on top (loading\n * vs. an actionable error screen); the embedder reloads the iframe once the error\n * clears.\n */\nexport function ClientErrorBoundary({ children }: React.PropsWithChildren) {\n const handleError = React.useCallback(\n (error: unknown, errorInfo: React.ErrorInfo) => {\n const errorObj =\n error instanceof Error ? error : new Error(String(error));\n window.parent.postMessage(\n {\n // TODO (Max, 2026-06-11, REPL-27851): When adding Sentry to miniapps, I'll ensure we listen to this message\n // and send it to Sentry. I'm not a fan of having 2 separate post messages for reporting errors (the 'error' post message in NextErrorReporter, and this one).\n // But there's no way for the NextErrorReporter to get the actual error object, so we'll\n // need a separate postMessage (this one, with an updated name).\n type: \"replo-editor:client-error\",\n payload: {\n pageRoute: window.location.pathname,\n error: {\n message: errorObj.message,\n stack: errorObj.stack,\n componentStack: errorInfo.componentStack,\n },\n },\n },\n \"*\",\n );\n },\n [],\n );\n\n return <ErrorBoundary onError={handleError}>{children}</ErrorBoundary>;\n}\n"],
|
|
5
|
-
"mappings": ";AA+CQ;AA7CR,YAAY,WAAW;AAUvB,MAAM,sBAAsB,MAAM,UAGhC;AAAA,EACA,QAA4B;AAAA,IAC1B,UAAU;AAAA,EACZ;AAAA,EAEA,OAAO,2BAA+C;AACpD,WAAO,EAAE,UAAU,KAAK;AAAA,EAC1B;AAAA,EAEA,kBAAkB,OAAgB,MAAuB;AACvD,SAAK,MAAM,UAAU,OAAO,IAAI;AAAA,EAClC;AAAA,EAEA,SAAS;AACP,QAAI,KAAK,MAAM,UAAU;AAiBvB,aACE;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,YAAY;AAAA,UACd;AAAA;AAAA,MACF;AAAA,IAEJ;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AAUO,SAAS,oBAAoB,EAAE,SAAS,GAA4B;AACzE,QAAM,cAAc,MAAM;AAAA,IACxB,CAAC,OAAgB,cAA+B;AAC9C,YAAM,WACJ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAC1D,aAAO,OAAO;AAAA,QACZ;AAAA;AAAA;AAAA;AAAA;AAAA,UAKE,MAAM;AAAA,UACN,SAAS;AAAA,YACP,WAAW,OAAO,SAAS;AAAA,YAC3B,OAAO;AAAA,cACL,SAAS,SAAS;AAAA,cAClB,OAAO,SAAS;AAAA,cAChB,gBAAgB,UAAU;AAAA,YAC5B;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,SAAO,oBAAC,iBAAc,SAAS,aAAc,UAAS;AACxD;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../DocumentReadyBeacon.tsx"],
|
|
4
|
-
"sourcesContent": ["// Posts at HTML parse time, pre-hydration; error shells and retry pages are different documents without this script, so receiving it proves the real site's document arrived.\n// phase: \"document\" lets the editor distinguish this from the hydration-time reporter \u2014 document arrival must not disarm its JS-boot watchdog.\nconst BEACON_SCRIPT = `if (window.parent !== window) { window.parent.postMessage({ type: \"replo:preview:status\", status: \"ok\", phase: \"document\", route: window.location.pathname }, \"*\"); }`;\n\nexport function DocumentReadyBeacon() {\n return <script dangerouslySetInnerHTML={{ __html: BEACON_SCRIPT }} />;\n}\n"],
|
|
5
|
-
"mappings": "AAKS;AAHT,MAAM,gBAAgB;AAEf,SAAS,sBAAsB;AACpC,SAAO,oBAAC,YAAO,yBAAyB,EAAE,QAAQ,cAAc,GAAG;AACrE;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/LinkInterceptor.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../LinkInterceptor.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\n\nimport { useEffect } from \"react\";\n\nimport { displayModeStore } from \"./select-mode/displayModeStore\";\n\ntype NavigationNavigateEvent = {\n destination?: { url?: string };\n preventDefault?: () => void;\n};\n\ntype NavigationLike = {\n addEventListener: (\n type: \"navigate\",\n listener: (event: NavigationNavigateEvent) => void,\n ) => void;\n removeEventListener: (\n type: \"navigate\",\n listener: (event: NavigationNavigateEvent) => void,\n ) => void;\n};\n\n// NOTE (Max, 2026-08-26): Shared by name with @replohq/sdk's `navigateExternal`\n// (packages/sdk/lib/external-navigation.ts) rather than by import \u2014 the two\n// packages publish independently and must not depend on each other.\nconst EXTERNAL_NAVIGATION_HANDLER_KEY = \"__reploExternalNavigationHandler\";\n\nfunction blockNavigation(event: MouseEvent) {\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n}\n\nfunction isNavigationLike(value: unknown): value is NavigationLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n return (\n typeof Reflect.get(value, \"addEventListener\") === \"function\" &&\n typeof Reflect.get(value, \"removeEventListener\") === \"function\"\n );\n}\n\nfunction getWindowNavigation() {\n const navigation = Reflect.get(window, \"navigation\");\n return isNavigationLike(navigation) ? navigation : null;\n}\n\nfunction shouldInterceptNavigationForAgentPreview() {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n if (window.parent === window) {\n return false;\n }\n\n return (\n new URLSearchParams(window.location.search).get(\"__reploAgentPreview\") ===\n \"1\"\n );\n}\n\nfunction resolveUrl(rawUrl: string | URL): URL | null {\n try {\n return new URL(\n typeof rawUrl === \"string\" ? rawUrl : rawUrl.href,\n window.location.href,\n );\n } catch {\n return null;\n }\n}\n\nfunction urlLeavesSandbox(rawUrl: string | URL): boolean | null {\n const resolved = resolveUrl(rawUrl);\n return resolved === null ? null : resolved.origin !== window.location.origin;\n}\n\nexport default function LinkInterceptor() {\n // eslint-disable-next-line replo/no-use-effect -- Browser navigation APIs must be patched at client runtime and restored when the interceptor unmounts.\n useEffect(() => {\n if (!shouldInterceptNavigationForAgentPreview()) {\n return;\n }\n\n const originalWindowOpen = window.open;\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n const navigation = getWindowNavigation();\n\n // Tell the parent editor where the site's own navigation went so it can\n // keep its URL, page list, and select-mode in sync without reloading the\n // iframe. A fact, not a request: it is only sent once a navigation is\n // actually happening.\n const reportNavigated = (rawUrl: string | URL) => {\n window.parent.postMessage(\n {\n type: \"replo:navigated\",\n route: resolveUrl(rawUrl)?.pathname ?? String(rawUrl),\n },\n \"*\",\n );\n };\n\n // A navigation that leaves the sandbox cannot happen in place: checkout\n // providers refuse to be framed and the iframe has no `allow-popups`. Hand\n // the destination to the editor, which opens it in a real browser tab.\n const openInParent = (rawUrl: string | URL) => {\n const resolved = resolveUrl(rawUrl);\n if (!resolved) {\n return;\n }\n window.parent.postMessage(\n {\n type: \"replo:open-external\",\n url: resolved.toString(),\n },\n \"*\",\n );\n };\n\n Reflect.set(window, EXTERNAL_NAVIGATION_HANDLER_KEY, (url: string) => {\n openInParent(url);\n return true;\n });\n\n window.open = function (\n url?: string | URL,\n target?: string,\n features?: string,\n ) {\n if (url !== undefined && url !== \"\" && urlLeavesSandbox(url) === true) {\n openInParent(url);\n return null;\n }\n\n return originalWindowOpen.call(window, url, target, features);\n };\n\n // The history patches are where client-side navigations are reported:\n // next/link cancels its click and routes through pushState, so the click\n // handler below cannot know whether the site actually navigated \u2014 these\n // patches fire exactly when it did (link clicks and programmatic\n // router.push/redirects alike).\n history.pushState = function (\n state: Parameters<History[\"pushState\"]>[0],\n unused: string,\n url?: string | URL | null,\n ) {\n if (url && urlLeavesSandbox(url) === true) {\n return;\n }\n\n const result = originalPushState.call(history, state, unused, url);\n if (url) {\n reportNavigated(url);\n }\n return result;\n };\n\n history.replaceState = function (\n state: Parameters<History[\"replaceState\"]>[0],\n unused: string,\n url?: string | URL | null,\n ) {\n if (url && urlLeavesSandbox(url) === true) {\n return;\n }\n\n const result = originalReplaceState.call(history, state, unused, url);\n if (url) {\n reportNavigated(url);\n }\n return result;\n };\n\n const handleNavigate = (event: NavigationNavigateEvent) => {\n const destinationUrl = event.destination?.url;\n if (\n destinationUrl === undefined ||\n destinationUrl === \"\" ||\n urlLeavesSandbox(destinationUrl) !== true\n ) {\n return;\n }\n\n event.preventDefault?.();\n openInParent(destinationUrl);\n };\n\n const handleClick = (event: MouseEvent) => {\n // While select mode is active a link click must select the element, not\n // navigate. `useSelectionInteractions` prevents the default nav, but this\n // sibling capture listener would still post `replo:navigate` and move the\n // preview off the page \u2014 `stopPropagation` there can't suppress a\n // listener on the same node, so we bail out here explicitly.\n if (displayModeStore.getSnapshot() === \"selection\") {\n return;\n }\n\n const target = event.target;\n\n if (!(target instanceof Element)) {\n return;\n }\n\n const link = target.closest(\"a[href]\");\n\n if (!(link instanceof HTMLAnchorElement)) {\n return;\n }\n\n const href = link.getAttribute(\"href\");\n if (!href) {\n return;\n }\n\n if (href.startsWith(\"#\")) {\n return;\n }\n\n const linkTarget = link.getAttribute(\"target\");\n if (linkTarget && linkTarget !== \"_self\") {\n blockNavigation(event);\n openInParent(href);\n return;\n }\n\n if (urlLeavesSandbox(href) === true) {\n blockNavigation(event);\n openInParent(href);\n return;\n }\n\n // A modified click (new tab / etc.) is the browser's to handle \u2014 the\n // iframe sandbox has no `allow-popups`, so it can't escape anyway.\n // Don't hijack it or tell the parent we navigated.\n if (\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n ) {\n return;\n }\n\n // A download link never navigates, so there is nothing to report.\n if (link.hasAttribute(\"download\")) {\n return;\n }\n\n // Let the site navigate itself \u2014 next/link does an instant client-side\n // transition, exactly like a normal Next.js app \u2014 instead of cancelling\n // the click and making the parent editor tear down and reload the whole\n // preview iframe. next/link navigations are reported by the pushState\n // patch above; this deferred report covers plain anchors the browser\n // itself navigates (a full document load inside the iframe). Deferred a\n // microtask because this capture listener runs before the site's own\n // handlers: a cancelled click (next/link included) navigates nothing.\n queueMicrotask(() => {\n if (event.defaultPrevented) {\n return;\n }\n reportNavigated(href);\n });\n };\n\n navigation?.addEventListener(\"navigate\", handleNavigate);\n document.addEventListener(\"click\", handleClick, true);\n\n return () => {\n Reflect.deleteProperty(window, EXTERNAL_NAVIGATION_HANDLER_KEY);\n window.open = originalWindowOpen;\n history.pushState = originalPushState;\n history.replaceState = originalReplaceState;\n navigation?.removeEventListener(\"navigate\", handleNavigate);\n document.removeEventListener(\"click\", handleClick, true);\n };\n }, []);\n\n return null;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../NavigationReceiver.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\n\nimport { useEffect, useMemo } from \"react\";\n\nimport { useRouter } from \"next/navigation\";\n\nimport { useIframeRpcChannel } from \"replo-utils/react/use-iframe-rpc-channel\";\n\nimport {\n getSelectModeIframeRpcChannel,\n setNavigateToRouteHandler,\n} from \"./select-mode/iframeRpcChannel\";\n\n// Hands the editor's `navigateToRoute` commands to the app router; `LinkInterceptor` reports the resulting navigation up.\nexport function NavigationReceiver() {\n const router = useRouter();\n useIframeRpcChannel(useMemo(() => getSelectModeIframeRpcChannel(), []));\n\n // eslint-disable-next-line replo/no-use-effect -- RPC handler registration tied to the router's lifetime.\n useEffect(() => {\n setNavigateToRouteHandler(({ pathname }) => {\n router.push(pathname);\n });\n return () => {\n setNavigateToRouteHandler(null);\n };\n }, [router]);\n\n return null;\n}\n"],
|
|
5
|
-
"mappings": ";AAEA,SAAS,WAAW,eAAe;AAEnC,SAAS,iBAAiB;AAE1B,SAAS,2BAA2B;AAEpC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAGA,SAAS,qBAAqB;AACnC,QAAM,SAAS,UAAU;AACzB,sBAAoB,QAAQ,MAAM,8BAA8B,GAAG,CAAC,CAAC,CAAC;AAGtE,YAAU,MAAM;AACd,8BAA0B,CAAC,EAAE,SAAS,MAAM;AAC1C,aAAO,KAAK,QAAQ;AAAA,IACtB,CAAC;AACD,WAAO,MAAM;AACX,gCAA0B,IAAI;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO;AACT;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/NextErrorReporter.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../NextErrorReporter.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n isAllowedEditorMessage,\n isAllowedEditorOrigin,\n} from \"./annotations/bridgeGate\";\n\n/**\n * NOTE (Max, 2026-06-10): This component sends post messages to its embedder (website-builder miniapp)\n * so that it can render a loading / error UI if there's an error on this page.\n *\n * Ideally, we wouldn't need any update to the sandbox runtime to achieve this: the miniapp would just read the\n * iframe's content and detect whenever there's a nextjs error overlay.\n * But the preview runs cross-origin from the editor, so the editor can't read the iframe's\n * DOM (browser security).\n *\n * This component has observers that detect when the nextjs error overlay appears or\n * disappears, and sends a post message with a status:\n * - `status`: \"error\" while Next's dev overlay opens its blocking error dialog\n * (a real page break \u2014 see the selectors below for why the badge's issue\n * count is deliberately NOT used: it also counts recovered loader misses)\n * - `status`: \"ok\" otherwise. Cleared by Fast Refresh on a fix, so it's also the\n * recovery signal (agent fixed the error, so it's the error -> ok transition)\n *\n * It also hides Next's dev error overlay (`<nextjs-portal>`) at the source the\n * instant an error appears, so the red bubble never paints \u2014 the MutationObserver\n * callback runs as a microtask before paint. `data-error` stays queryable while\n * hidden, so detection is unaffected;\n *\n * The overlay lives in `<nextjs-portal>`'s shadow root, which Next can recreate,\n * so we re-attach the shadow observer whenever it hands us a new root. No polling.\n *\n * This must be mounted OUTSIDE the error boundary (see ReploProvider) so it keeps\n * reporting while the boundary is caught (and showing its neutral cover).\n *\n * I'm unsatisfied with this approach: observing for the nextjs-portal is brittle and ugly.\n * Ideally, the ClientErrorBoundary, which hooks into the render cycle, in componentDidCatch, would\n * just report a post message to the miniapp. I prototyped that, the error detection works\n * great (ok -> error transition).\n * But the error -> ok transition doesn't work for Server components (it only does for Client\n * components). Here's a slack thread with me <> Gabe on it:\n * https://replohq.slack.com/archives/C03AACVP08Y/p1781154057832689?thread_ts=1781029224.564489&cid=C03AACVP08Y.\n */\n// NOTE (Max, 2026-08-04; Nick, 2026-09-11): Two independent things have to be\n// read off <nextjs-portal>: *what* Next collected, and whether it considers that\n// blocking.\n// - `[data-nextjs-dialog]` holds the text of the collected issue and is\n// present for recoverable issues too, so it is the only description of the\n// problem available. It is NOT evidence the page broke.\n// - the surrounding `[data-nextjs-dialog-overlay]` says whether Next opened\n// the overlay, which it auto-does only for a genuinely blocking error: the\n// app shell's error boundary catching an uncaught render crash, an\n// unrecoverable SSR error (missing root tags), or a build error. Verified\n// against next@16.1.7 and next@15.3.8: the sole auto-open is\n// AppDevOverlayErrorBoundary's componentDidCatch -> openErrorOverlay, which\n// a nested LoaderErrorBoundary never reaches.\n// So an *open* overlay is the fatal-vs-recoverable discriminator. The badge's\n// issue count is not: it lights for every collected issue, including a\n// server-side loader error React already recovered from by streaming the\n// LoaderErrorBoundary fallback (product unpublished, deleted collection, \u2026).\n// Keying off the badge reported those as full-page errors, blanking a preview\n// that had rendered its fallback.\n//\n// Reading \"open\" is version-dependent. next@16.3 keeps the dialog mounted for\n// recoverable issues, parked inside a wrapper it marks `data-rendered=\"false\"`\n// and hides with `display: none !important`; opening flips that to `\"true\"`.\n// Earlier versions mount the dialog only when it is open, so \"has no explicitly\n// closed ancestor\" reads correctly on both.\n//\n// We still *hide* the whole portal whenever Next paints red chrome (the errored\n// badge OR the dialog) so no dev overlay bleeds into the preview \u2014 a recovered\n// loader miss shouldn't flash a red dot either.\nconst ERRORED_BADGE_SELECTOR = '[data-next-badge][data-error=\"true\"]';\nconst COLLECTED_ISSUE_SELECTOR = \"[data-nextjs-dialog]\";\nconst CLOSED_DIALOG_OVERLAY_SELECTOR =\n '[data-nextjs-dialog-overlay][data-rendered=\"false\"]';\nconst RED_CHROME_SELECTOR = `${ERRORED_BADGE_SELECTOR}, ${COLLECTED_ISSUE_SELECTOR}`;\n\n// HMR portal churn flips the overlay for milliseconds in both directions; only a state that persists this long is real.\nconst STATUS_LATCH_MS = 500;\n\ntype PreviewStatus = \"ok\" | \"error\";\n\n// The embedder's origin as the browser reports it, trusted only if it is an allowed editor. `ancestorOrigins` names the actual parent and survives referrer policies and in-frame navigations, but Firefox lacks it; the referrer covers Firefox, the same way the annotation layer announces itself.\nfunction findInitialEditorOrigin(): string | null {\n // A top-level page has no editor to report to.\n if (window.self === window.top) {\n return null;\n }\n const ancestorOrigin =\n \"ancestorOrigins\" in window.location\n ? window.location.ancestorOrigins.item(0)\n : null;\n return (\n [ancestorOrigin, getOriginOrNull(document.referrer)].find((origin) => {\n return origin !== null && isAllowedEditorOrigin(origin);\n }) ?? null\n );\n}\n\nfunction getOriginOrNull(url: string): string | null {\n try {\n return new URL(url).origin;\n } catch {\n return null;\n }\n}\n\nexport function NextErrorReporter() {\n // eslint-disable-next-line replo/no-use-effect -- Observes Next's dev error overlay (a shadow-DOM node outside React's tree) and relays its state to the cross-origin embedder. No React alternative applies.\n React.useEffect(() => {\n let editorOrigin = findInitialEditorOrigin();\n let lastStatus: PreviewStatus | null = null;\n let shadowObserver: MutationObserver | null = null;\n let observedRoot: ShadowRoot | null = null;\n let pendingPost: { status: PreviewStatus; timeoutId: number } | null = null;\n\n // Status and route are only for the editor, so they never go out with a wildcard target; without a trusted origin the status is kept and delivered once one is learned.\n const deliver = () => {\n if (editorOrigin === null || lastStatus === null) {\n return;\n }\n window.parent.postMessage(\n {\n type: \"replo:preview:status\",\n route: window.location.pathname,\n status: lastStatus,\n },\n editorOrigin,\n );\n };\n\n const postNow = (status: PreviewStatus) => {\n if (lastStatus === status) {\n return;\n }\n lastStatus = status;\n deliver();\n };\n\n // Covers a missing or stale referrer (Firefox after an in-frame navigation): a message from the parent window at an allowed origin proves where the editor lives, the same capture the annotation layer uses for its replies.\n const handleParentMessage = (event: MessageEvent) => {\n if (event.source !== window.parent || !isAllowedEditorMessage(event)) {\n return;\n }\n if (event.origin === editorOrigin) {\n return;\n }\n editorOrigin = event.origin;\n deliver();\n };\n window.addEventListener(\"message\", handleParentMessage);\n\n // Latch every transition (the opposite observation cancels a pending one) \u2014 a false error <-> ok flip makes the editor reload the preview. Only the initial \"ok\" posts immediately, as the readiness signal.\n const post = (status: PreviewStatus) => {\n if (pendingPost) {\n if (pendingPost.status === status) {\n return;\n }\n window.clearTimeout(pendingPost.timeoutId);\n pendingPost = null;\n }\n if (lastStatus === status) {\n return;\n }\n if (lastStatus === null && status === \"ok\") {\n postNow(status);\n return;\n }\n const timeoutId = window.setTimeout(() => {\n pendingPost = null;\n postNow(status);\n }, STATUS_LATCH_MS);\n pendingPost = { status, timeoutId };\n };\n\n // NOTE (Max, 2026-06-10): Reads the dev overlay's current error state and\n // propagates it \u2014 re-attach the shadow observer to the live root, hide the\n // portal while erroring, and post ok/error up to the editor. Runs on init and\n // on every observed DOM mutation.\n const syncOverlayState = () => {\n const portal = document.getElementsByTagName(\"nextjs-portal\")[0];\n if (!(portal instanceof HTMLElement)) {\n post(\"ok\");\n return;\n }\n // NOTE (Max, 2026-06-10): Re-attach whenever Next hands us a fresh shadow\n // root, else we'd keep watching a detached one after the overlay is\n // recreated.\n const root = portal.shadowRoot;\n if (root && root !== observedRoot) {\n shadowObserver?.disconnect();\n shadowObserver = new MutationObserver(syncOverlayState);\n shadowObserver.observe(root, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: [\"data-error\", \"data-rendered\"],\n });\n observedRoot = root;\n }\n // NOTE (Max, 2026-06-10): Hide the dev overlay at the source so the red\n // bubble never paints \u2014 for any red chrome, including a recovered miss's\n // errored badge.\n portal.style.display = root?.querySelector(RED_CHROME_SELECTOR)\n ? \"none\"\n : \"\";\n const dialog = root?.querySelector(COLLECTED_ISSUE_SELECTOR) ?? null;\n post(\n dialog && !dialog.closest(CLOSED_DIALOG_OVERLAY_SELECTOR)\n ? \"error\"\n : \"ok\",\n );\n };\n\n // NOTE (Max, 2026-06-10): Catches the portal being added/removed in the light\n // DOM; the re-attached shadow observer catches in-overlay changes.\n const lightObserver = new MutationObserver(syncOverlayState);\n lightObserver.observe(document.documentElement, {\n childList: true,\n subtree: true,\n });\n\n syncOverlayState();\n\n return () => {\n window.removeEventListener(\"message\", handleParentMessage);\n lightObserver.disconnect();\n shadowObserver?.disconnect();\n if (pendingPost) {\n window.clearTimeout(pendingPost.timeoutId);\n }\n };\n }, []);\n\n return null;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../annotations/AnnotationLayerMount.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\n\n/**\n * Boots the vanilla annotation controller inside preview iframes. The chunk\n * loads (and this module-scope boot runs) only when the provider actually\n * renders the element, which it folds away on a NODE_ENV literal \u2014 so\n * annotation code never ships to published storefronts.\n */\nif (typeof window !== \"undefined\") {\n void import(\"./annotationController\").then((module) => {\n module.initAnnotationLayer();\n });\n}\n\nexport function AnnotationLayerMount() {\n return null;\n}\n"],
|
|
5
|
-
"mappings": ";AAQA,IAAI,OAAO,WAAW,aAAa;AACjC,OAAK,OAAO,wBAAwB,EAAE,KAAK,CAAC,WAAW;AACrD,WAAO,oBAAoB;AAAA,EAC7B,CAAC;AACH;AAEO,SAAS,uBAAuB;AACrC,SAAO;AACT;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|