@replohq/sandbox-runtime 1.1.0 → 1.3.0

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.
@@ -42,6 +42,24 @@ function LinkInterceptor() {
42
42
  const originalPushState = history.pushState;
43
43
  const originalReplaceState = history.replaceState;
44
44
  const navigation = getWindowNavigation();
45
+ const reportNavigated = (rawUrl) => {
46
+ let route;
47
+ try {
48
+ route = new URL(
49
+ typeof rawUrl === "string" ? rawUrl : rawUrl.href,
50
+ window.location.href
51
+ ).pathname;
52
+ } catch {
53
+ route = String(rawUrl);
54
+ }
55
+ window.parent.postMessage(
56
+ {
57
+ type: "replo:navigated",
58
+ route
59
+ },
60
+ "*"
61
+ );
62
+ };
45
63
  window.open = function(url, target, features) {
46
64
  if (url !== void 0 && url !== "" && urlLeavesSandbox(url) === true) {
47
65
  return null;
@@ -52,13 +70,21 @@ function LinkInterceptor() {
52
70
  if (url && urlLeavesSandbox(url) === true) {
53
71
  return;
54
72
  }
55
- return originalPushState.call(history, state, unused, url);
73
+ const result = originalPushState.call(history, state, unused, url);
74
+ if (url) {
75
+ reportNavigated(url);
76
+ }
77
+ return result;
56
78
  };
57
79
  history.replaceState = function(state, unused, url) {
58
80
  if (url && urlLeavesSandbox(url) === true) {
59
81
  return;
60
82
  }
61
- return originalReplaceState.call(history, state, unused, url);
83
+ const result = originalReplaceState.call(history, state, unused, url);
84
+ if (url) {
85
+ reportNavigated(url);
86
+ }
87
+ return result;
62
88
  };
63
89
  const handleNavigate = (event) => {
64
90
  const destinationUrl = event.destination?.url;
@@ -95,20 +121,18 @@ function LinkInterceptor() {
95
121
  blockNavigation(event);
96
122
  return;
97
123
  }
98
- event.preventDefault();
99
- let route;
100
- try {
101
- route = new URL(href, window.location.href).pathname;
102
- } catch {
103
- route = href;
124
+ if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
125
+ return;
104
126
  }
105
- window.parent.postMessage(
106
- {
107
- type: "replo:navigate",
108
- route
109
- },
110
- "*"
111
- );
127
+ if (link.hasAttribute("download")) {
128
+ return;
129
+ }
130
+ queueMicrotask(() => {
131
+ if (event.defaultPrevented) {
132
+ return;
133
+ }
134
+ reportNavigated(href);
135
+ });
112
136
  };
113
137
  navigation?.addEventListener("navigate", handleNavigate);
114
138
  document.addEventListener("click", handleClick, true);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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\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 urlLeavesSandbox(rawUrl: string | URL): boolean | null {\n try {\n const resolved =\n typeof rawUrl === \"string\"\n ? new URL(rawUrl, window.location.href)\n : new URL(rawUrl.href, window.location.href);\n return resolved.origin !== window.location.origin;\n } catch {\n return null;\n }\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 window.open = function (\n url?: string | URL,\n target?: string,\n features?: string,\n ) {\n if (url !== undefined && url !== \"\" && urlLeavesSandbox(url) === true) {\n return null;\n }\n\n return originalWindowOpen.call(window, url, target, features);\n };\n\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 return originalPushState.call(history, state, unused, url);\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 return originalReplaceState.call(history, state, unused, url);\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 };\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 return;\n }\n\n if (urlLeavesSandbox(href) === true) {\n blockNavigation(event);\n return;\n }\n\n event.preventDefault();\n\n let route: string;\n try {\n route = new URL(href, window.location.href).pathname;\n } catch {\n route = href;\n }\n\n window.parent.postMessage(\n {\n type: \"replo:navigate\",\n route,\n },\n \"*\",\n );\n };\n\n navigation?.addEventListener(\"navigate\", handleNavigate);\n document.addEventListener(\"click\", handleClick, true);\n\n return () => {\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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",
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\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 urlLeavesSandbox(rawUrl: string | URL): boolean | null {\n try {\n const resolved =\n typeof rawUrl === \"string\"\n ? new URL(rawUrl, window.location.href)\n : new URL(rawUrl.href, window.location.href);\n return resolved.origin !== window.location.origin;\n } catch {\n return null;\n }\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 let route: string;\n try {\n route = new URL(\n typeof rawUrl === \"string\" ? rawUrl : rawUrl.href,\n window.location.href,\n ).pathname;\n } catch {\n route = String(rawUrl);\n }\n window.parent.postMessage(\n {\n type: \"replo:navigated\",\n route,\n },\n \"*\",\n );\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 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 };\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 return;\n }\n\n if (urlLeavesSandbox(href) === true) {\n blockNavigation(event);\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 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
6
  "names": []
7
7
  }
@@ -0,0 +1 @@
1
+ export declare function NavigationReceiver(): null;
@@ -0,0 +1,25 @@
1
+ "use client";
2
+ import { useEffect, useMemo } from "react";
3
+ import { useRouter } from "next/navigation";
4
+ import { useIframeRpcChannel } from "./_vendor/replo-utils/react/use-iframe-rpc-channel.mjs";
5
+ import {
6
+ getSelectModeIframeRpcChannel,
7
+ setNavigateToRouteHandler
8
+ } from "./select-mode/iframeRpcChannel";
9
+ function NavigationReceiver() {
10
+ const router = useRouter();
11
+ useIframeRpcChannel(useMemo(() => getSelectModeIframeRpcChannel(), []));
12
+ useEffect(() => {
13
+ setNavigateToRouteHandler(({ pathname }) => {
14
+ router.push(pathname);
15
+ });
16
+ return () => {
17
+ setNavigateToRouteHandler(null);
18
+ };
19
+ }, [router]);
20
+ return null;
21
+ }
22
+ export {
23
+ NavigationReceiver
24
+ };
25
+ //# sourceMappingURL=NavigationReceiver.js.map
@@ -0,0 +1,7 @@
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
+ }
@@ -87,13 +87,15 @@ export type RectOffset = {
87
87
  left: number;
88
88
  top: number;
89
89
  };
90
- export declare function transformRect({ rect, offset, }: {
90
+ export declare function transformRect({ rect, offset, scale, }: {
91
91
  rect: SelectModeBoundingRect;
92
92
  offset: RectOffset;
93
+ scale?: number;
93
94
  }): SelectModeBoundingRect;
94
- export declare function transformPoint({ point, offset, }: {
95
+ export declare function transformPoint({ point, offset, scale, }: {
95
96
  point: SelectModeClickPosition;
96
97
  offset: RectOffset;
98
+ scale?: number;
97
99
  }): SelectModeClickPosition;
98
100
  export declare function getIframeOffset(iframe: HTMLIFrameElement | null): RectOffset;
99
101
  export declare const selectedElementSchema: z.ZodObject<{
@@ -257,6 +259,11 @@ export type SelectModeBoundingRect = z.infer<typeof selectModeBoundingRectSchema
257
259
  export type SelectModeClickPosition = z.infer<typeof selectModeClickPositionSchema>;
258
260
  export type SelectableData = z.infer<typeof selectableDataSchema>;
259
261
  export type SelectableDataPayload = z.infer<typeof selectableDataPayloadSchema>;
262
+ export declare function transformSelectedElement({ element, offset, scale, }: {
263
+ element: z.infer<typeof selectedElementSchema>;
264
+ offset: RectOffset;
265
+ scale?: number;
266
+ }): z.infer<typeof selectedElementSchema>;
260
267
  export declare function transformSelectableData({ data, offset, }: {
261
268
  data: SelectableData;
262
269
  offset: RectOffset;
@@ -1,3 +1,3 @@
1
- export { SELECT_MODE_SELECTABLE_ATTRIBUTE, SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE, displayModeSchema, getIframeOffset, readSelectablePayload, selectModeBoundingRectSchema, selectModeClickPositionSchema, selectModeDefinedStyleSchema, selectModeFiberChainEntrySchema, selectModeFormatCommandSchema, selectModeInlineTextStatusSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionRectSchema, selectModeSelectionSchema, selectModeSelectionTypeSchema, selectModeSourceLocationSchema, selectModeStyleAtRuleSchema, selectModeStyleVariantSchema, selectModeTextMetricsSchema, selectModeTiptapActiveMarksSchema, selectableDataPayloadSchema, selectableDataSchema, selectablePlanDataSchema, selectablePlanPayloadSchema, selectedElementSchema, transformPoint, transformRect, transformSelectableData } from '../../chunk-P5NWJM64.mjs';
1
+ export { SELECT_MODE_SELECTABLE_ATTRIBUTE, SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE, displayModeSchema, getIframeOffset, readSelectablePayload, selectModeBoundingRectSchema, selectModeClickPositionSchema, selectModeDefinedStyleSchema, selectModeFiberChainEntrySchema, selectModeFormatCommandSchema, selectModeInlineTextStatusSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionRectSchema, selectModeSelectionSchema, selectModeSelectionTypeSchema, selectModeSourceLocationSchema, selectModeStyleAtRuleSchema, selectModeStyleVariantSchema, selectModeTextMetricsSchema, selectModeTiptapActiveMarksSchema, selectableDataPayloadSchema, selectableDataSchema, selectablePlanDataSchema, selectablePlanPayloadSchema, selectedElementSchema, transformPoint, transformRect, transformSelectableData, transformSelectedElement } from '../../chunk-2455EG5R.mjs';
2
2
  import '../../chunk-N5EI2MOZ.mjs';
3
3
  import '../../chunk-FNTGY7I5.mjs';
@@ -131,6 +131,12 @@ export declare const websiteBuilderToCanopyMethodConfig: {
131
131
  }, z.core.$strip>;
132
132
  timeoutMs: number;
133
133
  };
134
+ navigateToRoute: {
135
+ inputSchema: z.ZodObject<{
136
+ pathname: z.ZodString;
137
+ }, z.core.$strip>;
138
+ outputSchema: z.ZodVoid;
139
+ };
134
140
  setDisplayMode: {
135
141
  inputSchema: z.ZodObject<{
136
142
  displayMode: z.ZodEnum<{
@@ -1,4 +1,4 @@
1
- import { selectModeFormatCommandSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionTypeSchema, displayModeSchema, selectModeTiptapActiveMarksSchema, selectModeBoundingRectSchema, selectableDataSchema, selectModeSelectionRectSchema, selectModeClickPositionSchema, selectedElementSchema } from '../../chunk-P5NWJM64.mjs';
1
+ import { selectModeFormatCommandSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionTypeSchema, displayModeSchema, selectModeTiptapActiveMarksSchema, selectModeBoundingRectSchema, selectableDataSchema, selectModeSelectionRectSchema, selectModeClickPositionSchema, selectedElementSchema } from '../../chunk-2455EG5R.mjs';
2
2
  import '../../chunk-N5EI2MOZ.mjs';
3
3
  import '../../chunk-FNTGY7I5.mjs';
4
4
  import { z } from 'zod';
@@ -18,6 +18,11 @@ var websiteBuilderToCanopyMethodConfig = {
18
18
  outputSchema: selectedElementSchema,
19
19
  timeoutMs: 1500
20
20
  },
21
+ // Client-side transition command; fire-and-forget because success is observed as the `replo:navigated` echo.
22
+ navigateToRoute: {
23
+ inputSchema: z.object({ pathname: z.string() }),
24
+ outputSchema: z.void()
25
+ },
21
26
  setDisplayMode: {
22
27
  inputSchema: z.object({ displayMode: displayModeSchema }),
23
28
  outputSchema: z.void()
package/buildMetadata.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export const BUILD_METADATA = {
2
2
  "packageName": "@replohq/sandbox-runtime",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "branch": "HEAD",
5
- "commit": "9293953aa1a314e9bbfd7b614cfdd11181138f00",
6
- "builtAt": "2026-08-20T04:27:18.976Z"
5
+ "commit": "544d5eef4f0142da5e8569baa4832a525d11fc06",
6
+ "builtAt": "2026-08-26T18:10:31.971Z"
7
7
  };
@@ -71,26 +71,28 @@ var selectModeDefinedStyleSchema = z.object({
71
71
  }).describe("SelectModeDefinedStyle");
72
72
  function transformRect({
73
73
  rect,
74
- offset
74
+ offset,
75
+ scale = 1
75
76
  }) {
76
77
  return {
77
- x: rect.x + offset.left,
78
- y: rect.y + offset.top,
79
- left: rect.left + offset.left,
80
- right: rect.right + offset.left,
81
- top: rect.top + offset.top,
82
- bottom: rect.bottom + offset.top,
83
- width: rect.width,
84
- height: rect.height
78
+ x: rect.x * scale + offset.left,
79
+ y: rect.y * scale + offset.top,
80
+ left: rect.left * scale + offset.left,
81
+ right: rect.right * scale + offset.left,
82
+ top: rect.top * scale + offset.top,
83
+ bottom: rect.bottom * scale + offset.top,
84
+ width: rect.width * scale,
85
+ height: rect.height * scale
85
86
  };
86
87
  }
87
88
  function transformPoint({
88
89
  point,
89
- offset
90
+ offset,
91
+ scale = 1
90
92
  }) {
91
93
  return {
92
- x: point.x + offset.left,
93
- y: point.y + offset.top
94
+ x: point.x * scale + offset.left,
95
+ y: point.y * scale + offset.top
94
96
  };
95
97
  }
96
98
  function getIframeOffset(iframe) {
@@ -125,6 +127,21 @@ var selectablePlanDataSchema = z.object({
125
127
  var selectablePlanPayloadSchema = selectablePlanDataSchema.omit({ rect: true }).describe("SelectablePlanPayload");
126
128
  var selectableDataPayloadSchema = z.discriminatedUnion("kind", [selectablePlanPayloadSchema]).describe("SelectableDataPayload");
127
129
  var selectableDataSchema = z.discriminatedUnion("kind", [selectedElementSchema, selectablePlanDataSchema]).describe("SelectableData");
130
+ function transformSelectedElement({
131
+ element,
132
+ offset,
133
+ scale = 1
134
+ }) {
135
+ return {
136
+ ...element,
137
+ rect: transformRect({ rect: element.rect, offset, scale }),
138
+ clickPosition: transformPoint({
139
+ point: element.clickPosition,
140
+ offset,
141
+ scale
142
+ })
143
+ };
144
+ }
128
145
  function transformSelectableData({
129
146
  data,
130
147
  offset
@@ -133,14 +150,7 @@ function transformSelectableData({
133
150
  data,
134
151
  "kind"
135
152
  )({
136
- "react-element": (element) => ({
137
- ...element,
138
- rect: transformRect({ rect: element.rect, offset }),
139
- clickPosition: transformPoint({
140
- point: element.clickPosition,
141
- offset
142
- })
143
- }),
153
+ "react-element": (element) => transformSelectedElement({ element, offset }),
144
154
  plan: (plan) => ({
145
155
  ...plan,
146
156
  rect: transformRect({ rect: plan.rect, offset })
@@ -202,4 +212,4 @@ var selectModeSelectionSchema = z.discriminatedUnion("type", [
202
212
  })
203
213
  ]).describe("SelectModeSelection");
204
214
 
205
- export { SELECT_MODE_SELECTABLE_ATTRIBUTE, SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE, displayModeSchema, getIframeOffset, readSelectablePayload, selectModeBoundingRectSchema, selectModeClickPositionSchema, selectModeDefinedStyleSchema, selectModeFiberChainEntrySchema, selectModeFormatCommandSchema, selectModeInlineTextStatusSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionRectSchema, selectModeSelectionSchema, selectModeSelectionTypeSchema, selectModeSourceLocationSchema, selectModeStyleAtRuleSchema, selectModeStyleVariantSchema, selectModeTextMetricsSchema, selectModeTiptapActiveMarksSchema, selectableDataPayloadSchema, selectableDataSchema, selectablePlanDataSchema, selectablePlanPayloadSchema, selectedElementSchema, transformPoint, transformRect, transformSelectableData };
215
+ export { SELECT_MODE_SELECTABLE_ATTRIBUTE, SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE, displayModeSchema, getIframeOffset, readSelectablePayload, selectModeBoundingRectSchema, selectModeClickPositionSchema, selectModeDefinedStyleSchema, selectModeFiberChainEntrySchema, selectModeFormatCommandSchema, selectModeInlineTextStatusSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionRectSchema, selectModeSelectionSchema, selectModeSelectionTypeSchema, selectModeSourceLocationSchema, selectModeStyleAtRuleSchema, selectModeStyleVariantSchema, selectModeTextMetricsSchema, selectModeTiptapActiveMarksSchema, selectableDataPayloadSchema, selectableDataSchema, selectablePlanDataSchema, selectablePlanPayloadSchema, selectedElementSchema, transformPoint, transformRect, transformSelectableData, transformSelectedElement };
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@replohq/sandbox-runtime",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "reploBuild": {
5
5
  "packageName": "@replohq/sandbox-runtime",
6
- "version": "1.1.0",
6
+ "version": "1.3.0",
7
7
  "branch": "HEAD",
8
- "commit": "9293953aa1a314e9bbfd7b614cfdd11181138f00",
9
- "builtAt": "2026-08-20T04:27:18.976Z"
8
+ "commit": "544d5eef4f0142da5e8569baa4832a525d11fc06",
9
+ "builtAt": "2026-08-26T18:10:31.971Z"
10
10
  },
11
11
  "description": "Replo sandbox runtime — editor integration for agent-built Next.js sites.",
12
12
  "license": "SEE LICENSE IN LICENSE",
@@ -5,6 +5,7 @@ import { ClientErrorBoundary } from "./ClientErrorBoundary";
5
5
  import { DesignLibraryPreview } from "./design-library-preview/DesignLibraryPreview";
6
6
  import { DocumentReadyBeacon } from "./DocumentReadyBeacon";
7
7
  import LinkInterceptor from "./LinkInterceptor";
8
+ import { NavigationReceiver } from "./NavigationReceiver";
8
9
  import { NextErrorReporter } from "./NextErrorReporter";
9
10
  import PostHogRelay from "./posthog-relay";
10
11
  import { EditorSelection } from "./select-mode/EditorSelection";
@@ -15,6 +16,7 @@ function SandboxRuntime({ children }) {
15
16
  /* @__PURE__ */ jsx(NextErrorReporter, {}),
16
17
  /* @__PURE__ */ jsxs(ClientErrorBoundary, { children: [
17
18
  /* @__PURE__ */ jsx(LinkInterceptor, {}),
19
+ /* @__PURE__ */ jsx(NavigationReceiver, {}),
18
20
  /* @__PURE__ */ jsx(PostHogRelay, {}),
19
21
  /* @__PURE__ */ jsx(EditorSelection, {}),
20
22
  /* @__PURE__ */ jsx(AnnotationLayerMount, {}),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../sandbox-runtime.tsx"],
4
- "sourcesContent": ["\"use client\";\n\nimport { AnnotationLayerMount } from \"./annotations/AnnotationLayerMount\";\nimport { ClientErrorBoundary } from \"./ClientErrorBoundary\";\nimport { DesignLibraryPreview } from \"./design-library-preview/DesignLibraryPreview\";\nimport { DocumentReadyBeacon } from \"./DocumentReadyBeacon\";\nimport LinkInterceptor from \"./LinkInterceptor\";\nimport { NextErrorReporter } from \"./NextErrorReporter\";\nimport PostHogRelay from \"./posthog-relay\";\nimport { EditorSelection } from \"./select-mode/EditorSelection\";\n\nexport function SandboxRuntime({ children }: React.PropsWithChildren) {\n // The editor only embeds dev servers (`next dev`), so editor-integration components render there only \u2014 production builds ship none of them and behave like plain Next apps.\n const isDevServer = process.env.NODE_ENV === \"development\";\n\n return isDevServer ? (\n <>\n <DocumentReadyBeacon />\n {/* NOTE (Max, 2026-06-08): Outside ClientErrorBoundary on purpose \u2014 when\n the boundary catches a runtime error it swaps its children for a\n neutral cover, which would unmount the reporter and freeze it in the\n error state. It must stay mounted to observe Next's overlay across\n error <-> recover. */}\n <NextErrorReporter />\n <ClientErrorBoundary>\n <LinkInterceptor />\n <PostHogRelay />\n <EditorSelection />\n <AnnotationLayerMount />\n <DesignLibraryPreview />\n {children}\n </ClientErrorBoundary>\n </>\n ) : (\n children\n );\n}\n"],
5
- "mappings": ";AAgBI,mBACE,KAOA,YARF;AAdJ,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,OAAO,qBAAqB;AAC5B,SAAS,yBAAyB;AAClC,OAAO,kBAAkB;AACzB,SAAS,uBAAuB;AAEzB,SAAS,eAAe,EAAE,SAAS,GAA4B;AAEpE,QAAM,cAAc,QAAQ,IAAI,aAAa;AAE7C,SAAO,cACL,iCACE;AAAA,wBAAC,uBAAoB;AAAA,IAMrB,oBAAC,qBAAkB;AAAA,IACnB,qBAAC,uBACC;AAAA,0BAAC,mBAAgB;AAAA,MACjB,oBAAC,gBAAa;AAAA,MACd,oBAAC,mBAAgB;AAAA,MACjB,oBAAC,wBAAqB;AAAA,MACtB,oBAAC,wBAAqB;AAAA,MACrB;AAAA,OACH;AAAA,KACF,IAEA;AAEJ;",
4
+ "sourcesContent": ["\"use client\";\n\nimport { AnnotationLayerMount } from \"./annotations/AnnotationLayerMount\";\nimport { ClientErrorBoundary } from \"./ClientErrorBoundary\";\nimport { DesignLibraryPreview } from \"./design-library-preview/DesignLibraryPreview\";\nimport { DocumentReadyBeacon } from \"./DocumentReadyBeacon\";\nimport LinkInterceptor from \"./LinkInterceptor\";\nimport { NavigationReceiver } from \"./NavigationReceiver\";\nimport { NextErrorReporter } from \"./NextErrorReporter\";\nimport PostHogRelay from \"./posthog-relay\";\nimport { EditorSelection } from \"./select-mode/EditorSelection\";\n\nexport function SandboxRuntime({ children }: React.PropsWithChildren) {\n // The editor only embeds dev servers (`next dev`), so editor-integration components render there only \u2014 production builds ship none of them and behave like plain Next apps.\n const isDevServer = process.env.NODE_ENV === \"development\";\n\n return isDevServer ? (\n <>\n <DocumentReadyBeacon />\n {/* NOTE (Max, 2026-06-08): Outside ClientErrorBoundary on purpose \u2014 when\n the boundary catches a runtime error it swaps its children for a\n neutral cover, which would unmount the reporter and freeze it in the\n error state. It must stay mounted to observe Next's overlay across\n error <-> recover. */}\n <NextErrorReporter />\n <ClientErrorBoundary>\n <LinkInterceptor />\n <NavigationReceiver />\n <PostHogRelay />\n <EditorSelection />\n <AnnotationLayerMount />\n <DesignLibraryPreview />\n {children}\n </ClientErrorBoundary>\n </>\n ) : (\n children\n );\n}\n"],
5
+ "mappings": ";AAiBI,mBACE,KAOA,YARF;AAfJ,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,OAAO,qBAAqB;AAC5B,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,OAAO,kBAAkB;AACzB,SAAS,uBAAuB;AAEzB,SAAS,eAAe,EAAE,SAAS,GAA4B;AAEpE,QAAM,cAAc,QAAQ,IAAI,aAAa;AAE7C,SAAO,cACL,iCACE;AAAA,wBAAC,uBAAoB;AAAA,IAMrB,oBAAC,qBAAkB;AAAA,IACnB,qBAAC,uBACC;AAAA,0BAAC,mBAAgB;AAAA,MACjB,oBAAC,sBAAmB;AAAA,MACpB,oBAAC,gBAAa;AAAA,MACd,oBAAC,mBAAgB;AAAA,MACjB,oBAAC,wBAAqB;AAAA,MACtB,oBAAC,wBAAqB;AAAA,MACrB;AAAA,OACH;AAAA,KACF,IAEA;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../select-mode/displayModeStore.ts"],
4
- "sourcesContent": ["\"use client\";\n\nimport type { DisplayMode } from \"schemas/generated/selectMode\";\n\nimport { useSyncExternalStore } from \"react\";\n\n/**\n * Framework-agnostic singleton for the preview iframe's select-mode display\n * mode (\"browse\" vs \"selection\"). It lives as a module singleton so that\n * components that don't share a provider ancestor \u2014 `EditorSelection` (which\n * owns the pointer/selection machinery) and `LinkInterceptor` (a sibling under\n * `ReploProvider`) \u2014 can agree on whether the user is currently selecting.\n *\n * `LinkInterceptor` needs this because in agent-preview mode it turns\n * same-origin link clicks into a `replo:navigate` postMessage (SPA-style\n * navigation of the preview). While select mode is active that navigation must\n * stand down so a link click selects the element instead of leaving the page \u2014\n * the two capture-phase click listeners otherwise race, and `stopPropagation`\n * can't suppress a sibling listener on the same node.\n *\n * @author Noah Gilmore 2026-07-23\n */\n\nconst listeners = new Set<() => void>();\nlet displayMode: DisplayMode = \"browse\";\n\n// select-mode DOM behavior is client-only, so the server snapshot is a stable\n// constant and never causes a hydration mismatch.\nconst SERVER_SNAPSHOT: DisplayMode = \"browse\";\n\nfunction notify() {\n for (const listener of listeners) {\n listener();\n }\n}\n\nexport const displayModeStore = {\n getSnapshot(): DisplayMode {\n return displayMode;\n },\n getServerSnapshot(): DisplayMode {\n return SERVER_SNAPSHOT;\n },\n subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n setDisplayMode(nextDisplayMode: DisplayMode) {\n if (nextDisplayMode === displayMode) {\n return;\n }\n displayMode = nextDisplayMode;\n notify();\n },\n /** Test-only: reset back to the default so specs don't leak state. */\n reset() {\n displayMode = \"browse\";\n },\n};\n\nexport function useDisplayMode(): DisplayMode {\n return useSyncExternalStore(\n displayModeStore.subscribe,\n displayModeStore.getSnapshot,\n displayModeStore.getServerSnapshot,\n );\n}\n"],
4
+ "sourcesContent": ["\"use client\";\n\nimport type { DisplayMode } from \"schemas/generated/selectMode\";\n\nimport { useSyncExternalStore } from \"react\";\n\n/**\n * Framework-agnostic singleton for the preview iframe's select-mode display\n * mode (\"browse\" vs \"selection\"). It lives as a module singleton so that\n * components that don't share a provider ancestor \u2014 `EditorSelection` (which\n * owns the pointer/selection machinery) and `LinkInterceptor` (a sibling under\n * `ReploProvider`) \u2014 can agree on whether the user is currently selecting.\n *\n * `LinkInterceptor` needs this because in agent-preview mode it observes\n * same-origin link clicks and reports the resulting navigation to the parent\n * editor (`replo:navigated`). While select mode is active that must stand\n * down so a link click selects the element instead of leaving the page \u2014\n * the two capture-phase click listeners otherwise race, and `stopPropagation`\n * can't suppress a sibling listener on the same node.\n *\n * @author Noah Gilmore 2026-07-23\n */\n\nconst listeners = new Set<() => void>();\nlet displayMode: DisplayMode = \"browse\";\n\n// select-mode DOM behavior is client-only, so the server snapshot is a stable\n// constant and never causes a hydration mismatch.\nconst SERVER_SNAPSHOT: DisplayMode = \"browse\";\n\nfunction notify() {\n for (const listener of listeners) {\n listener();\n }\n}\n\nexport const displayModeStore = {\n getSnapshot(): DisplayMode {\n return displayMode;\n },\n getServerSnapshot(): DisplayMode {\n return SERVER_SNAPSHOT;\n },\n subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n setDisplayMode(nextDisplayMode: DisplayMode) {\n if (nextDisplayMode === displayMode) {\n return;\n }\n displayMode = nextDisplayMode;\n notify();\n },\n /** Test-only: reset back to the default so specs don't leak state. */\n reset() {\n displayMode = \"browse\";\n },\n};\n\nexport function useDisplayMode(): DisplayMode {\n return useSyncExternalStore(\n displayModeStore.subscribe,\n displayModeStore.getSnapshot,\n displayModeStore.getServerSnapshot,\n );\n}\n"],
5
5
  "mappings": ";AAIA,SAAS,4BAA4B;AAmBrC,MAAM,YAAY,oBAAI,IAAgB;AACtC,IAAI,cAA2B;AAI/B,MAAM,kBAA+B;AAErC,SAAS,SAAS;AAChB,aAAW,YAAY,WAAW;AAChC,aAAS;AAAA,EACX;AACF;AAEO,MAAM,mBAAmB;AAAA,EAC9B,cAA2B;AACzB,WAAO;AAAA,EACT;AAAA,EACA,oBAAiC;AAC/B,WAAO;AAAA,EACT;AAAA,EACA,UAAU,UAAkC;AAC1C,cAAU,IAAI,QAAQ;AACtB,WAAO,MAAM;AACX,gBAAU,OAAO,QAAQ;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,eAAe,iBAA8B;AAC3C,QAAI,oBAAoB,aAAa;AACnC;AAAA,IACF;AACA,kBAAc;AACd,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,QAAQ;AACN,kBAAc;AAAA,EAChB;AACF;AAEO,SAAS,iBAA8B;AAC5C,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACnB;AACF;",
6
6
  "names": []
7
7
  }
@@ -2,7 +2,10 @@ import type { SelectedElement } from "../_vendor/schemas/generated/selectMode";
2
2
  import type { IframeRpcChannelInputHandlers, IframeRpcChannelRemote } from "../_vendor/schemas/iframeRpcChannel";
3
3
  import { canopyToWebsiteBuilderMethodConfig, websiteBuilderToCanopyMethodConfig } from "../_vendor/schemas/selectModeIframeRpc";
4
4
  export type WebsiteBuilderRpcRemote = IframeRpcChannelRemote<typeof canopyToWebsiteBuilderMethodConfig>;
5
- type SelectModeParentMessagingHandlers = Omit<IframeRpcChannelInputHandlers<typeof websiteBuilderToCanopyMethodConfig>, "symbolicateSelectedElement">;
5
+ type SelectModeParentMessagingHandlers = Omit<IframeRpcChannelInputHandlers<typeof websiteBuilderToCanopyMethodConfig>, "symbolicateSelectedElement" | "navigateToRoute">;
6
+ export declare function setNavigateToRouteHandler(handler: ((input: {
7
+ pathname: string;
8
+ }) => void) | null): void;
6
9
  export declare function getSelectModeIframeRpcChannel(): import("../_vendor/schemas/iframeRpcChannel").IframeRpcChannel<{
7
10
  requestInlineTextEdit: {
8
11
  inputSchema: import("zod").ZodObject<{
@@ -10,6 +10,10 @@ import {
10
10
  } from "../_vendor/schemas/selectModeIframeRpc.mjs";
11
11
  import { symbolicateSelectedElement } from "./symbolicate";
12
12
  let messagingHandlers = null;
13
+ let navigateToRouteHandler = null;
14
+ function setNavigateToRouteHandler(handler) {
15
+ navigateToRouteHandler = handler;
16
+ }
13
17
  function createSelectModeIframeRpcChannel() {
14
18
  return createIframeRpcChannel({
15
19
  subscriberWindow: window,
@@ -50,6 +54,9 @@ function createSelectModeIframeRpcChannel() {
50
54
  },
51
55
  symbolicateSelectedElement: (element) => {
52
56
  return symbolicateSelectedElement(element);
57
+ },
58
+ navigateToRoute: (input) => {
59
+ navigateToRouteHandler?.(input);
53
60
  }
54
61
  }
55
62
  });
@@ -87,6 +94,7 @@ export {
87
94
  getSelectModeIframeRpcChannel,
88
95
  getWebsiteBuilderRpc,
89
96
  requestInlineTextEdit,
97
+ setNavigateToRouteHandler,
90
98
  setSelectModeParentHandlers
91
99
  };
92
100
  //# sourceMappingURL=iframeRpcChannel.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../select-mode/iframeRpcChannel.ts"],
4
- "sourcesContent": ["import type { SelectedElement } from \"schemas/generated/selectMode\";\nimport type {\n IframeRpcChannelInputHandlers,\n IframeRpcChannelRemote,\n} from \"schemas/iframeRpcChannel\";\n\nimport {\n createIframeRpcChannel,\n createIframeRpcRemote,\n} from \"schemas/iframeRpcChannel\";\nimport {\n canopyToWebsiteBuilderMethodConfig,\n SELECT_MODE_IFRAME_RPC_CHANNEL_ID,\n SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION,\n websiteBuilderToCanopyMethodConfig,\n} from \"schemas/selectModeIframeRpc\";\n\nimport { symbolicateSelectedElement } from \"./symbolicate\";\n\nexport type WebsiteBuilderRpcRemote = IframeRpcChannelRemote<\n typeof canopyToWebsiteBuilderMethodConfig\n>;\n\ntype SelectModeParentMessagingHandlers = Omit<\n IframeRpcChannelInputHandlers<typeof websiteBuilderToCanopyMethodConfig>,\n \"symbolicateSelectedElement\"\n>;\n\n// Module-level handler pointers; `useParentMessaging` sets these on mount\n// and nulls them on unmount. Inbound void methods are dropped until then.\n// `symbolicateSelectedElement` is wired permanently on the channel.\nlet messagingHandlers: SelectModeParentMessagingHandlers | null = null;\n\nfunction createSelectModeIframeRpcChannel() {\n return createIframeRpcChannel({\n subscriberWindow: window,\n channelIdentifier: SELECT_MODE_IFRAME_RPC_CHANNEL_ID,\n version: SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION,\n getTargetWindow: () => (window.parent === window ? null : window.parent),\n targetOrigin: \"*\",\n isExpectedMessage: (event) => event.source === window.parent,\n outgoingMethods: canopyToWebsiteBuilderMethodConfig,\n incomingMethods: websiteBuilderToCanopyMethodConfig,\n handlers: {\n setDisplayMode: (input) => {\n messagingHandlers?.setDisplayMode(input);\n },\n setSelectionType: (input) => {\n messagingHandlers?.setSelectionType(input);\n },\n applyOptimisticUpdate: (input) => {\n messagingHandlers?.applyOptimisticUpdate(input);\n },\n markCommitted: (input) => {\n messagingHandlers?.markCommitted(input);\n },\n resolveSessionOverrides: (input) => {\n messagingHandlers?.resolveSessionOverrides(input);\n },\n revertOverride: (input) => {\n messagingHandlers?.revertOverride(input);\n },\n enterEditMode: (input) => {\n messagingHandlers?.enterEditMode(input);\n },\n exitEditMode: (input) => {\n messagingHandlers?.exitEditMode(input);\n },\n formatCommand: (input) => {\n messagingHandlers?.formatCommand(input);\n },\n symbolicateSelectedElement: (element) => {\n return symbolicateSelectedElement(element);\n },\n },\n });\n}\n\nlet channel: ReturnType<typeof createSelectModeIframeRpcChannel> | null = null;\nlet websiteBuilderRpc: WebsiteBuilderRpcRemote | null = null;\n\nexport function getSelectModeIframeRpcChannel() {\n if (typeof window === \"undefined\") {\n return null;\n }\n channel ??= createSelectModeIframeRpcChannel();\n return channel;\n}\n\nexport function setSelectModeParentHandlers(\n nextHandlers: SelectModeParentMessagingHandlers | null,\n) {\n messagingHandlers = nextHandlers;\n}\n\nexport function getWebsiteBuilderRpc(): WebsiteBuilderRpcRemote | null {\n const currentChannel = getSelectModeIframeRpcChannel();\n if (!currentChannel) {\n return null;\n }\n websiteBuilderRpc ??= createIframeRpcRemote(currentChannel);\n return websiteBuilderRpc;\n}\n\nexport function requestInlineTextEdit(input: {\n editId: string;\n element: SelectedElement;\n}) {\n const remote = getWebsiteBuilderRpc();\n if (!remote) {\n return Promise.reject(\n new Error(\"Website Builder iframe RPC is unavailable\"),\n );\n }\n return remote.requestInlineTextEdit(input);\n}\n"],
5
- "mappings": "AAMA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,kCAAkC;AAc3C,IAAI,oBAA8D;AAElE,SAAS,mCAAmC;AAC1C,SAAO,uBAAuB;AAAA,IAC5B,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,SAAS;AAAA,IACT,iBAAiB,MAAO,OAAO,WAAW,SAAS,OAAO,OAAO;AAAA,IACjE,cAAc;AAAA,IACd,mBAAmB,CAAC,UAAU,MAAM,WAAW,OAAO;AAAA,IACtD,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,UAAU;AAAA,MACR,gBAAgB,CAAC,UAAU;AACzB,2BAAmB,eAAe,KAAK;AAAA,MACzC;AAAA,MACA,kBAAkB,CAAC,UAAU;AAC3B,2BAAmB,iBAAiB,KAAK;AAAA,MAC3C;AAAA,MACA,uBAAuB,CAAC,UAAU;AAChC,2BAAmB,sBAAsB,KAAK;AAAA,MAChD;AAAA,MACA,eAAe,CAAC,UAAU;AACxB,2BAAmB,cAAc,KAAK;AAAA,MACxC;AAAA,MACA,yBAAyB,CAAC,UAAU;AAClC,2BAAmB,wBAAwB,KAAK;AAAA,MAClD;AAAA,MACA,gBAAgB,CAAC,UAAU;AACzB,2BAAmB,eAAe,KAAK;AAAA,MACzC;AAAA,MACA,eAAe,CAAC,UAAU;AACxB,2BAAmB,cAAc,KAAK;AAAA,MACxC;AAAA,MACA,cAAc,CAAC,UAAU;AACvB,2BAAmB,aAAa,KAAK;AAAA,MACvC;AAAA,MACA,eAAe,CAAC,UAAU;AACxB,2BAAmB,cAAc,KAAK;AAAA,MACxC;AAAA,MACA,4BAA4B,CAAC,YAAY;AACvC,eAAO,2BAA2B,OAAO;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,IAAI,UAAsE;AAC1E,IAAI,oBAAoD;AAEjD,SAAS,gCAAgC;AAC9C,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AACA,cAAY,iCAAiC;AAC7C,SAAO;AACT;AAEO,SAAS,4BACd,cACA;AACA,sBAAoB;AACtB;AAEO,SAAS,uBAAuD;AACrE,QAAM,iBAAiB,8BAA8B;AACrD,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,EACT;AACA,wBAAsB,sBAAsB,cAAc;AAC1D,SAAO;AACT;AAEO,SAAS,sBAAsB,OAGnC;AACD,QAAM,SAAS,qBAAqB;AACpC,MAAI,CAAC,QAAQ;AACX,WAAO,QAAQ;AAAA,MACb,IAAI,MAAM,2CAA2C;AAAA,IACvD;AAAA,EACF;AACA,SAAO,OAAO,sBAAsB,KAAK;AAC3C;",
4
+ "sourcesContent": ["import type { SelectedElement } from \"schemas/generated/selectMode\";\nimport type {\n IframeRpcChannelInputHandlers,\n IframeRpcChannelRemote,\n} from \"schemas/iframeRpcChannel\";\n\nimport {\n createIframeRpcChannel,\n createIframeRpcRemote,\n} from \"schemas/iframeRpcChannel\";\nimport {\n canopyToWebsiteBuilderMethodConfig,\n SELECT_MODE_IFRAME_RPC_CHANNEL_ID,\n SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION,\n websiteBuilderToCanopyMethodConfig,\n} from \"schemas/selectModeIframeRpc\";\n\nimport { symbolicateSelectedElement } from \"./symbolicate\";\n\nexport type WebsiteBuilderRpcRemote = IframeRpcChannelRemote<\n typeof canopyToWebsiteBuilderMethodConfig\n>;\n\ntype SelectModeParentMessagingHandlers = Omit<\n IframeRpcChannelInputHandlers<typeof websiteBuilderToCanopyMethodConfig>,\n \"symbolicateSelectedElement\" | \"navigateToRoute\"\n>;\n\n// Module-level handler pointers; `useParentMessaging` sets these on mount\n// and nulls them on unmount. Inbound void methods are dropped until then.\n// `symbolicateSelectedElement` is wired permanently on the channel.\nlet messagingHandlers: SelectModeParentMessagingHandlers | null = null;\n\n// Set by `NavigationReceiver` while a router is mounted; unhandled commands are dropped.\nlet navigateToRouteHandler: ((input: { pathname: string }) => void) | null =\n null;\n\nexport function setNavigateToRouteHandler(\n handler: ((input: { pathname: string }) => void) | null,\n) {\n navigateToRouteHandler = handler;\n}\n\nfunction createSelectModeIframeRpcChannel() {\n return createIframeRpcChannel({\n subscriberWindow: window,\n channelIdentifier: SELECT_MODE_IFRAME_RPC_CHANNEL_ID,\n version: SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION,\n getTargetWindow: () => (window.parent === window ? null : window.parent),\n targetOrigin: \"*\",\n isExpectedMessage: (event) => event.source === window.parent,\n outgoingMethods: canopyToWebsiteBuilderMethodConfig,\n incomingMethods: websiteBuilderToCanopyMethodConfig,\n handlers: {\n setDisplayMode: (input) => {\n messagingHandlers?.setDisplayMode(input);\n },\n setSelectionType: (input) => {\n messagingHandlers?.setSelectionType(input);\n },\n applyOptimisticUpdate: (input) => {\n messagingHandlers?.applyOptimisticUpdate(input);\n },\n markCommitted: (input) => {\n messagingHandlers?.markCommitted(input);\n },\n resolveSessionOverrides: (input) => {\n messagingHandlers?.resolveSessionOverrides(input);\n },\n revertOverride: (input) => {\n messagingHandlers?.revertOverride(input);\n },\n enterEditMode: (input) => {\n messagingHandlers?.enterEditMode(input);\n },\n exitEditMode: (input) => {\n messagingHandlers?.exitEditMode(input);\n },\n formatCommand: (input) => {\n messagingHandlers?.formatCommand(input);\n },\n symbolicateSelectedElement: (element) => {\n return symbolicateSelectedElement(element);\n },\n navigateToRoute: (input) => {\n navigateToRouteHandler?.(input);\n },\n },\n });\n}\n\nlet channel: ReturnType<typeof createSelectModeIframeRpcChannel> | null = null;\nlet websiteBuilderRpc: WebsiteBuilderRpcRemote | null = null;\n\nexport function getSelectModeIframeRpcChannel() {\n if (typeof window === \"undefined\") {\n return null;\n }\n channel ??= createSelectModeIframeRpcChannel();\n return channel;\n}\n\nexport function setSelectModeParentHandlers(\n nextHandlers: SelectModeParentMessagingHandlers | null,\n) {\n messagingHandlers = nextHandlers;\n}\n\nexport function getWebsiteBuilderRpc(): WebsiteBuilderRpcRemote | null {\n const currentChannel = getSelectModeIframeRpcChannel();\n if (!currentChannel) {\n return null;\n }\n websiteBuilderRpc ??= createIframeRpcRemote(currentChannel);\n return websiteBuilderRpc;\n}\n\nexport function requestInlineTextEdit(input: {\n editId: string;\n element: SelectedElement;\n}) {\n const remote = getWebsiteBuilderRpc();\n if (!remote) {\n return Promise.reject(\n new Error(\"Website Builder iframe RPC is unavailable\"),\n );\n }\n return remote.requestInlineTextEdit(input);\n}\n"],
5
+ "mappings": "AAMA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,kCAAkC;AAc3C,IAAI,oBAA8D;AAGlE,IAAI,yBACF;AAEK,SAAS,0BACd,SACA;AACA,2BAAyB;AAC3B;AAEA,SAAS,mCAAmC;AAC1C,SAAO,uBAAuB;AAAA,IAC5B,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,SAAS;AAAA,IACT,iBAAiB,MAAO,OAAO,WAAW,SAAS,OAAO,OAAO;AAAA,IACjE,cAAc;AAAA,IACd,mBAAmB,CAAC,UAAU,MAAM,WAAW,OAAO;AAAA,IACtD,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,UAAU;AAAA,MACR,gBAAgB,CAAC,UAAU;AACzB,2BAAmB,eAAe,KAAK;AAAA,MACzC;AAAA,MACA,kBAAkB,CAAC,UAAU;AAC3B,2BAAmB,iBAAiB,KAAK;AAAA,MAC3C;AAAA,MACA,uBAAuB,CAAC,UAAU;AAChC,2BAAmB,sBAAsB,KAAK;AAAA,MAChD;AAAA,MACA,eAAe,CAAC,UAAU;AACxB,2BAAmB,cAAc,KAAK;AAAA,MACxC;AAAA,MACA,yBAAyB,CAAC,UAAU;AAClC,2BAAmB,wBAAwB,KAAK;AAAA,MAClD;AAAA,MACA,gBAAgB,CAAC,UAAU;AACzB,2BAAmB,eAAe,KAAK;AAAA,MACzC;AAAA,MACA,eAAe,CAAC,UAAU;AACxB,2BAAmB,cAAc,KAAK;AAAA,MACxC;AAAA,MACA,cAAc,CAAC,UAAU;AACvB,2BAAmB,aAAa,KAAK;AAAA,MACvC;AAAA,MACA,eAAe,CAAC,UAAU;AACxB,2BAAmB,cAAc,KAAK;AAAA,MACxC;AAAA,MACA,4BAA4B,CAAC,YAAY;AACvC,eAAO,2BAA2B,OAAO;AAAA,MAC3C;AAAA,MACA,iBAAiB,CAAC,UAAU;AAC1B,iCAAyB,KAAK;AAAA,MAChC;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,IAAI,UAAsE;AAC1E,IAAI,oBAAoD;AAEjD,SAAS,gCAAgC;AAC9C,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AACA,cAAY,iCAAiC;AAC7C,SAAO;AACT;AAEO,SAAS,4BACd,cACA;AACA,sBAAoB;AACtB;AAEO,SAAS,uBAAuD;AACrE,QAAM,iBAAiB,8BAA8B;AACrD,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,EACT;AACA,wBAAsB,sBAAsB,cAAc;AAC1D,SAAO;AACT;AAEO,SAAS,sBAAsB,OAGnC;AACD,QAAM,SAAS,qBAAqB;AACpC,MAAI,CAAC,QAAQ;AACX,WAAO,QAAQ;AAAA,MACb,IAAI,MAAM,2CAA2C;AAAA,IACvD;AAAA,EACF;AACA,SAAO,OAAO,sBAAsB,KAAK;AAC3C;",
6
6
  "names": []
7
7
  }