@replohq/sandbox-runtime 1.22.0 → 1.23.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.
@@ -1,4 +1,4 @@
1
1
  export { coerceNumberToString, deepCloneAndMergeReplacingArrays, errorMessage, exhaustiveSwitch, formatFileSize, getFromRecordOrNull, hasOwnProperty, invariant, isEmpty, isFunction_default as isFunction, isNotNullish, isNullish, isPrimitive, isString_default as isString, mergeReplacingArrays, mergeReplacingObjects, noop, preventDefault, sleep, sleepWithSignal, warning } from '../../../chunk-THOBCJJA.mjs';
2
- import '../../../chunk-4ITJNSXZ.mjs';
3
2
  export { isNumber_default as isNumber } from '../../../chunk-SKVPFN7M.mjs';
3
+ import '../../../chunk-4ITJNSXZ.mjs';
4
4
  import '../../../chunk-XYS6G2ZC.mjs';
@@ -1,7 +1,7 @@
1
1
  import { commentAnchorSchema, displayModeSchema, commentAnchorElementSchema } from '../../chunk-CGRTGQO5.mjs';
2
2
  import '../../chunk-THOBCJJA.mjs';
3
- import '../../chunk-4ITJNSXZ.mjs';
4
3
  import '../../chunk-SKVPFN7M.mjs';
4
+ import '../../chunk-4ITJNSXZ.mjs';
5
5
  import '../../chunk-XYS6G2ZC.mjs';
6
6
  import * as z from 'zod';
7
7
 
@@ -1,8 +1,8 @@
1
1
  import { createIframeRpcChannel } from '../../chunk-6WREP7C2.mjs';
2
2
  import '../../chunk-ZTT7SNYN.mjs';
3
3
  import '../../chunk-THOBCJJA.mjs';
4
- import '../../chunk-4ITJNSXZ.mjs';
5
4
  import '../../chunk-SKVPFN7M.mjs';
5
+ import '../../chunk-4ITJNSXZ.mjs';
6
6
  import '../../chunk-XYS6G2ZC.mjs';
7
7
  import * as z from 'zod';
8
8
 
@@ -1,6 +1,6 @@
1
1
  export { createIframeRpcChannel, createIframeRpcRemote, iframeRpcCallSchema } from '../../chunk-6WREP7C2.mjs';
2
2
  import '../../chunk-ZTT7SNYN.mjs';
3
3
  import '../../chunk-THOBCJJA.mjs';
4
- import '../../chunk-4ITJNSXZ.mjs';
5
4
  import '../../chunk-SKVPFN7M.mjs';
5
+ import '../../chunk-4ITJNSXZ.mjs';
6
6
  import '../../chunk-XYS6G2ZC.mjs';
@@ -0,0 +1,7 @@
1
+ export declare const PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_ID: "replo:placeholder-products-iframe-rpc";
2
+ export declare const PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_VERSION: 3;
3
+ export declare const PLACEHOLDER_HERO_PRODUCT_ID = "f0921037-e530-4e67-a612-d573b7c40b19";
4
+ export declare const PLACEHOLDER_PRODUCT_ID = "c53f98cd-0989-4661-a7c2-a0304d184676";
5
+ export type PlaceholderProductId = typeof PLACEHOLDER_HERO_PRODUCT_ID | typeof PLACEHOLDER_PRODUCT_ID;
6
+ export declare const PLACEHOLDER_PRODUCTS_SOURCE_KEY = "__REPLO_PLACEHOLDER_PRODUCTS__";
7
+ export declare const PLACEHOLDER_PRODUCTS_CHANGE_EVENT = "replo:placeholder-products";
@@ -0,0 +1,8 @@
1
+ var PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_ID = "replo:placeholder-products-iframe-rpc";
2
+ var PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_VERSION = 3;
3
+ var PLACEHOLDER_HERO_PRODUCT_ID = "f0921037-e530-4e67-a612-d573b7c40b19";
4
+ var PLACEHOLDER_PRODUCT_ID = "c53f98cd-0989-4661-a7c2-a0304d184676";
5
+ var PLACEHOLDER_PRODUCTS_SOURCE_KEY = "__REPLO_PLACEHOLDER_PRODUCTS__";
6
+ var PLACEHOLDER_PRODUCTS_CHANGE_EVENT = "replo:placeholder-products";
7
+
8
+ export { PLACEHOLDER_HERO_PRODUCT_ID, PLACEHOLDER_PRODUCTS_CHANGE_EVENT, PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_ID, PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_VERSION, PLACEHOLDER_PRODUCTS_SOURCE_KEY, PLACEHOLDER_PRODUCT_ID };
@@ -1,8 +1,8 @@
1
1
  import { createIframeRpcChannel } from '../../chunk-6WREP7C2.mjs';
2
2
  import '../../chunk-ZTT7SNYN.mjs';
3
3
  import '../../chunk-THOBCJJA.mjs';
4
- import '../../chunk-4ITJNSXZ.mjs';
5
4
  import '../../chunk-SKVPFN7M.mjs';
5
+ import '../../chunk-4ITJNSXZ.mjs';
6
6
  import '../../chunk-XYS6G2ZC.mjs';
7
7
  import * as z from 'zod';
8
8
 
@@ -1,5 +1,5 @@
1
1
  export { SELECT_MODE_SELECTABLE_ATTRIBUTE, SELECT_MODE_SELECTABLE_PAYLOAD_ATTRIBUTE, displayModeSchema, getIframeOffset, isSelectedSection, readSelectablePayload, selectModeBoundingRectSchema, selectModeClickPositionSchema, selectModeDefinedStyleSchema, selectModeFiberChainEntrySchema, selectModeFormatCommandSchema, selectModeHoverRectSchema, selectModeImageSchema, selectModeImageScopeSchema, selectModeImageSourceSchema, selectModeInlineTextStatusSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionRectSchema, selectModeSelectionSchema, selectModeSelectionTypeSchema, selectModeSourceLocationSchema, selectModeStyleAtRuleSchema, selectModeStyleVariantSchema, selectModeTextMetricsSchema, selectModeTiptapActiveMarksSchema, selectModeVideoSchema, selectableDataPayloadSchema, selectableDataSchema, selectablePlanDataSchema, selectablePlanPayloadSchema, selectedElementSchema, transformPoint, transformRect, transformSelectableData, transformSelectedElement } from '../../chunk-CGRTGQO5.mjs';
2
2
  import '../../chunk-THOBCJJA.mjs';
3
- import '../../chunk-4ITJNSXZ.mjs';
4
3
  import '../../chunk-SKVPFN7M.mjs';
4
+ import '../../chunk-4ITJNSXZ.mjs';
5
5
  import '../../chunk-XYS6G2ZC.mjs';
@@ -1,7 +1,7 @@
1
1
  import { selectModeBoundingRectSchema, selectModeTiptapActiveMarksSchema, selectModeSelectionRectSchema, selectableDataSchema, selectModeHoverRectSchema, selectModeFormatCommandSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionTypeSchema, displayModeSchema, selectModeClickPositionSchema, selectedElementSchema } from '../../chunk-CGRTGQO5.mjs';
2
2
  import '../../chunk-THOBCJJA.mjs';
3
- import '../../chunk-4ITJNSXZ.mjs';
4
3
  import '../../chunk-SKVPFN7M.mjs';
4
+ import '../../chunk-4ITJNSXZ.mjs';
5
5
  import '../../chunk-XYS6G2ZC.mjs';
6
6
  import * as z from 'zod';
7
7
 
package/buildMetadata.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export const BUILD_METADATA = {
2
2
  "packageName": "@replohq/sandbox-runtime",
3
- "version": "1.22.0",
3
+ "version": "1.23.0",
4
4
  "branch": "HEAD",
5
- "commit": "06e25b3341d1e79f6171365410c49bee41b1f3e0",
6
- "builtAt": "2026-10-30T20:22:33.673Z"
5
+ "commit": "ace9e163575351a4ad987d0f0427807eaec836ee",
6
+ "builtAt": "2026-10-31T09:51:00.646Z"
7
7
  };
@@ -4,7 +4,7 @@ import type { DisplayMode } from "../_vendor/schemas/generated/selectMode";
4
4
  import type { ElementSource } from "./capture";
5
5
  export declare const OVERLAY_Z_INDEX = 2147483645;
6
6
  export declare const HIGHLIGHT_BACKGROUND = "rgba(250, 204, 21, 0.28)";
7
- export declare const BADGE_SIZE_PX = 20;
7
+ export declare const BADGE_SIZE_PX = 32;
8
8
  export declare const RERESOLVE_DEBOUNCE_MS = 250;
9
9
  export type CommentsOverlayCallbacks = {
10
10
  onAnchorPicked: (input: {
@@ -4,8 +4,9 @@ import { OVERLAY_ROOT_ATTRIBUTE } from "./textQuote";
4
4
  const OVERLAY_Z_INDEX = 2147483645;
5
5
  const HIGHLIGHT_BACKGROUND = "rgba(250, 204, 21, 0.28)";
6
6
  const QUOTE_UNDERLINE = "2px solid rgba(250, 204, 21, 0.9)";
7
- const BADGE_SIZE_PX = 20;
7
+ const BADGE_SIZE_PX = 32;
8
8
  const BADGE_HIT_TARGET_PX = 44;
9
+ const BADGE_HIT_TARGET_WIDTH_PX = 64;
9
10
  const COMPACT_GUTTER_MAX_WIDTH_PX = 600;
10
11
  const RERESOLVE_DEBOUNCE_MS = 250;
11
12
  const SELECTION_PROMPT_DEBOUNCE_MS = 150;
@@ -286,16 +287,17 @@ function createCommentsOverlay(options) {
286
287
  const paintBadges = () => {
287
288
  const isCompact = window.innerWidth <= COMPACT_GUTTER_MAX_WIDTH_PX;
288
289
  const size = BADGE_HIT_TARGET_PX;
289
- const maxLeft = Math.max(0, window.innerWidth - size);
290
+ const width = BADGE_HIT_TARGET_WIDTH_PX;
291
+ const maxLeft = Math.max(0, window.innerWidth - width);
290
292
  const maxTop = Math.max(0, window.innerHeight - size);
291
293
  const placed = [];
292
294
  const place = (rect) => {
293
- const baseLeft = isCompact ? maxLeft : Math.max(0, Math.min(maxLeft, rect.right - size / 2));
295
+ const baseLeft = isCompact ? maxLeft : Math.max(0, Math.min(maxLeft, rect.right - width / 2));
294
296
  const baseTop = Math.max(0, Math.min(maxTop, rect.top - size / 2));
295
- const columns = Math.ceil(maxLeft / size);
297
+ const columns = Math.ceil(maxLeft / width);
296
298
  const rows = Math.ceil(maxTop / size);
297
299
  for (let column = 0; column <= columns * 2; column++) {
298
- const left = baseLeft + (column % 2 ? 1 : -1) * Math.ceil(column / 2) * size;
300
+ const left = baseLeft + (column % 2 ? 1 : -1) * Math.ceil(column / 2) * width;
299
301
  if (left < 0 || left > maxLeft) {
300
302
  continue;
301
303
  }
@@ -305,7 +307,7 @@ function createCommentsOverlay(options) {
305
307
  continue;
306
308
  }
307
309
  const collides = placed.some((slot) => {
308
- return Math.abs(slot.left - left) < size && Math.abs(slot.top - top) < size;
310
+ return Math.abs(slot.left - left) < width && Math.abs(slot.top - top) < size;
309
311
  });
310
312
  if (!collides) {
311
313
  placed.push({ left, top });
@@ -340,7 +342,7 @@ function createCommentsOverlay(options) {
340
342
  "aria-label",
341
343
  pin.count === 1 ? "Open comment" : `Open ${pin.count} comments`
342
344
  );
343
- badge.style.cssText = `position:absolute;pointer-events:auto;display:flex;align-items:center;justify-content:center;width:${size}px;height:${size}px;padding:0;margin:0;border:0;background:transparent;cursor:pointer`;
345
+ badge.style.cssText = `position:absolute;pointer-events:auto;display:flex;align-items:center;justify-content:center;width:${width}px;height:${size}px;padding:0;margin:0;border:0;background:transparent;cursor:pointer;outline-offset:-2px`;
344
346
  if (isCompact) {
345
347
  badge.style.justifyContent = "flex-end";
346
348
  }
@@ -348,25 +350,21 @@ function createCommentsOverlay(options) {
348
350
  badge.style.top = `${position.top}px`;
349
351
  const isActive = isFocused || pin.threadId === hoveredBadgeThreadId;
350
352
  const dot = document.createElement("span");
351
- dot.style.cssText = `display:flex;align-items:center;justify-content:center;gap:3px;box-sizing:border-box;min-width:${BADGE_SIZE_PX}px;height:${BADGE_SIZE_PX}px;padding:0 ${pin.count === 1 ? 0 : 6}px;border-radius:${BADGE_SIZE_PX / 2}px;border:1px solid rgba(17,24,39,.14);background:#fff;color:#6b7280;box-shadow:0 1px 3px rgba(0,0,0,.18);font:600 11px/1 system-ui,-apple-system,sans-serif;font-variant-numeric:tabular-nums;white-space:nowrap`;
353
+ dot.style.cssText = `display:flex;align-items:center;justify-content:center;gap:6px;box-sizing:border-box;min-width:48px;height:${BADGE_SIZE_PX}px;padding:0 6px;border-radius:8px;border:1px solid rgba(0,0,0,.12);background:#ffeb80;color:#171717;box-shadow:0 1px 3px rgba(0,0,0,.12);font:600 14px/1 system-ui,-apple-system,sans-serif;font-variant-numeric:tabular-nums;white-space:nowrap`;
352
354
  if (isCompact) {
353
355
  dot.style.marginRight = "3px";
354
356
  }
355
357
  if (isActive) {
356
- dot.style.borderColor = "#f59e0b";
357
- dot.style.background = "#fef3c7";
358
- dot.style.color = "#b45309";
358
+ dot.style.borderColor = "rgba(0,0,0,.4)";
359
359
  }
360
360
  if (resolution.status === "ambiguous") {
361
361
  dot.style.borderStyle = "dashed";
362
362
  }
363
- const icon = createIcon("12", "M7.9 20A9 9 0 1 0 4 16.1L2 22Z");
363
+ const icon = createIcon("16", "M7.9 20A9 9 0 1 0 4 16.1L2 22Z");
364
364
  icon.setAttribute("stroke-linecap", "round");
365
365
  icon.setAttribute("stroke-linejoin", "round");
366
366
  dot.append(icon);
367
- if (pin.count > 1) {
368
- dot.append(pin.count > 99 ? "99+" : String(pin.count));
369
- }
367
+ dot.append(pin.count > 99 ? "99+" : String(pin.count));
370
368
  badge.append(dot);
371
369
  badge.addEventListener("click", (event) => {
372
370
  event.preventDefault();
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@replohq/sandbox-runtime",
3
- "version": "1.22.0",
3
+ "version": "1.23.0",
4
4
  "reploBuild": {
5
5
  "packageName": "@replohq/sandbox-runtime",
6
- "version": "1.22.0",
6
+ "version": "1.23.0",
7
7
  "branch": "HEAD",
8
- "commit": "06e25b3341d1e79f6171365410c49bee41b1f3e0",
9
- "builtAt": "2026-10-30T20:22:33.673Z"
8
+ "commit": "ace9e163575351a4ad987d0f0427807eaec836ee",
9
+ "builtAt": "2026-10-31T09:51:00.646Z"
10
10
  },
11
11
  "description": "Replo sandbox runtime — editor integration for agent-built Next.js sites.",
12
12
  "license": "SEE LICENSE IN LICENSE",
@@ -0,0 +1,2 @@
1
+ /** Fills a template's placeholder product cards in a template preview; a published site downloads none of that code. */
2
+ export declare function PlaceholderProductReceiver(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,25 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ function startReceiver() {
4
+ const isTemplatePreview = process.env.NODE_ENV === "development" || window.location.hostname.endsWith(".reploregistry.com");
5
+ if (!isTemplatePreview) {
6
+ return;
7
+ }
8
+ let stop = null;
9
+ let isStopped = false;
10
+ void import("./placeholderProductsPreview").then((module) => {
11
+ if (!isStopped) {
12
+ stop = module.startPlaceholderProducts();
13
+ }
14
+ });
15
+ return () => {
16
+ isStopped = true;
17
+ stop?.();
18
+ };
19
+ }
20
+ function PlaceholderProductReceiver() {
21
+ return /* @__PURE__ */ jsx("template", { ref: startReceiver });
22
+ }
23
+ export {
24
+ PlaceholderProductReceiver
25
+ };
@@ -0,0 +1,88 @@
1
+ import type { PlaceholderProductId } from "../_vendor/schemas/placeholderProductsProtocol";
2
+ /** A product as Replo's product loaders return it, as far as the preview touches it. */
3
+ type LoaderProduct = {
4
+ id: string;
5
+ handle: string;
6
+ title: string;
7
+ variants: {
8
+ id: string;
9
+ }[];
10
+ };
11
+ export declare const GRAY_PRODUCT: {
12
+ id: string;
13
+ handle: string;
14
+ title: string;
15
+ description: null;
16
+ descriptionHtml: null;
17
+ availableForSale: boolean;
18
+ featuredImage: {
19
+ url: string;
20
+ altText: string;
21
+ width: null;
22
+ height: null;
23
+ };
24
+ images: {
25
+ url: string;
26
+ altText: string;
27
+ width: null;
28
+ height: null;
29
+ }[];
30
+ media: {
31
+ url: string;
32
+ altText: string;
33
+ width: null;
34
+ height: null;
35
+ type: string;
36
+ alt: string;
37
+ }[];
38
+ options: {
39
+ id: string;
40
+ name: string;
41
+ values: ("Option 1" | "Option 2" | "Option 3")[];
42
+ optionValues: {
43
+ id: string;
44
+ value: "Option 1" | "Option 2" | "Option 3";
45
+ swatch: {
46
+ color: "#d9d9d9" | "#b3b3b3" | "#8c8c8c";
47
+ imageUrl: null;
48
+ };
49
+ }[];
50
+ }[];
51
+ variants: {
52
+ id: string;
53
+ title: "Option 1" | "Option 2" | "Option 3";
54
+ availableForSale: boolean;
55
+ sku: null;
56
+ selectedOptions: {
57
+ name: string;
58
+ value: "Option 1" | "Option 2" | "Option 3";
59
+ }[];
60
+ image: null;
61
+ price: {
62
+ amount: string;
63
+ currencyCode: string;
64
+ };
65
+ compareAtPrice: null;
66
+ sellingPlanIds: never[];
67
+ }[];
68
+ vendor: null;
69
+ productType: null;
70
+ tags: never[];
71
+ sellingPlanGroups: never[];
72
+ requiresSellingPlan: boolean;
73
+ metafields: never[];
74
+ };
75
+ /**
76
+ * The product source @replohq/sdk's loaders read: the hero ID gets the first product, other cards the rest in mount
77
+ * order, cycling. Copies take the card's placeholder ID so the SDK's cart drops their variants.
78
+ */
79
+ export declare function createPlaceholderProductSource({ products, cardNumbers, }: {
80
+ products: readonly LoaderProduct[];
81
+ cardNumbers: Map<string, number>;
82
+ }): ({ productId, cardId, }: {
83
+ productId: PlaceholderProductId;
84
+ cardId: string;
85
+ }) => LoaderProduct | null;
86
+ /** Shows the gray product, then the products the embedding page sends; its two notify messages are spoken by hand. */
87
+ export declare function startPlaceholderProducts(): () => void;
88
+ export {};
@@ -0,0 +1,137 @@
1
+ import {
2
+ PLACEHOLDER_HERO_PRODUCT_ID,
3
+ PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_ID,
4
+ PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_VERSION,
5
+ PLACEHOLDER_PRODUCTS_CHANGE_EVENT,
6
+ PLACEHOLDER_PRODUCTS_SOURCE_KEY
7
+ } from "../_vendor/schemas/placeholderProductsProtocol.mjs";
8
+ const GRAY_IMAGE = {
9
+ url: "https://registry.replocdn.com/placeholder-products/gray.webp",
10
+ altText: "Product name",
11
+ width: null,
12
+ height: null
13
+ };
14
+ const GRAY_VALUES = [
15
+ ["Option 1", "#d9d9d9"],
16
+ ["Option 2", "#b3b3b3"],
17
+ ["Option 3", "#8c8c8c"]
18
+ ];
19
+ const GRAY_PRODUCT = {
20
+ id: "gray",
21
+ handle: "gray",
22
+ title: "Product name",
23
+ description: null,
24
+ descriptionHtml: null,
25
+ availableForSale: true,
26
+ featuredImage: GRAY_IMAGE,
27
+ images: [GRAY_IMAGE],
28
+ media: [{ type: "image", alt: "Product name", ...GRAY_IMAGE }],
29
+ options: [
30
+ {
31
+ id: "gray:option",
32
+ name: "Option",
33
+ values: GRAY_VALUES.map(([value]) => value),
34
+ optionValues: GRAY_VALUES.map(([value, color]) => ({
35
+ id: `gray:${value}`,
36
+ value,
37
+ swatch: { color, imageUrl: null }
38
+ }))
39
+ }
40
+ ],
41
+ variants: GRAY_VALUES.map(([value]) => ({
42
+ id: `gray:${value}`,
43
+ title: value,
44
+ availableForSale: true,
45
+ sku: null,
46
+ selectedOptions: [{ name: "Option", value }],
47
+ image: null,
48
+ price: { amount: "0.00", currencyCode: "USD" },
49
+ compareAtPrice: null,
50
+ sellingPlanIds: []
51
+ })),
52
+ vendor: null,
53
+ productType: null,
54
+ tags: [],
55
+ sellingPlanGroups: [],
56
+ requiresSellingPlan: false,
57
+ metafields: []
58
+ };
59
+ const cardNumbers = /* @__PURE__ */ new Map();
60
+ function createPlaceholderProductSource({
61
+ products,
62
+ cardNumbers: cardNumbers2
63
+ }) {
64
+ const copies = /* @__PURE__ */ new Map();
65
+ const others = products.length > 1 ? products.slice(1) : products;
66
+ return ({
67
+ productId,
68
+ cardId
69
+ }) => {
70
+ const isHero = productId === PLACEHOLDER_HERO_PRODUCT_ID;
71
+ let card = 0;
72
+ if (!isHero) {
73
+ card = cardNumbers2.get(cardId) ?? cardNumbers2.size;
74
+ cardNumbers2.set(cardId, card);
75
+ }
76
+ const product = isHero ? products[0] : others[card % others.length];
77
+ if (!product) {
78
+ return null;
79
+ }
80
+ const id = `${productId}:${card}`;
81
+ const copy = copies.get(id) ?? {
82
+ ...product,
83
+ id,
84
+ handle: isHero ? "sample" : `sample-${card + 1}`,
85
+ variants: product.variants.map((variant) => ({
86
+ ...variant,
87
+ id: `${id}:${variant.id}`
88
+ }))
89
+ };
90
+ copies.set(id, copy);
91
+ return copy;
92
+ };
93
+ }
94
+ function publishSource(products) {
95
+ const source = createPlaceholderProductSource({ products, cardNumbers });
96
+ Object.assign(window, { [PLACEHOLDER_PRODUCTS_SOURCE_KEY]: source });
97
+ window.dispatchEvent(new Event(PLACEHOLDER_PRODUCTS_CHANGE_EVENT));
98
+ }
99
+ function findSentProducts(message) {
100
+ if (typeof message !== "object" || message === null || Reflect.get(message, "channelIdentifier") !== PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_ID || Reflect.get(message, "method") !== "setPlaceholderProducts") {
101
+ return [];
102
+ }
103
+ const data = Reflect.get(message, "data");
104
+ const products = typeof data === "object" && data !== null ? Reflect.get(data, "products") : null;
105
+ return Array.isArray(products) ? (
106
+ products
107
+ ) : [];
108
+ }
109
+ function startPlaceholderProducts() {
110
+ publishSource([GRAY_PRODUCT]);
111
+ if (window.parent === window) {
112
+ return () => {
113
+ };
114
+ }
115
+ const onMessage = (event) => {
116
+ const products = event.source === window.parent ? findSentProducts(event.data) : [];
117
+ if (products.length > 0) {
118
+ publishSource(products);
119
+ }
120
+ };
121
+ window.addEventListener("message", onMessage);
122
+ window.parent.postMessage(
123
+ {
124
+ channelIdentifier: PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_ID,
125
+ version: PLACEHOLDER_PRODUCTS_IFRAME_RPC_CHANNEL_VERSION,
126
+ type: "notify",
127
+ method: "placeholderProductsReady"
128
+ },
129
+ "*"
130
+ );
131
+ return () => window.removeEventListener("message", onMessage);
132
+ }
133
+ export {
134
+ GRAY_PRODUCT,
135
+ createPlaceholderProductSource,
136
+ startPlaceholderProducts
137
+ };
@@ -1 +1 @@
1
- export declare function SandboxRuntime({ children }: React.PropsWithChildren): string | number | bigint | boolean | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
1
+ export declare function SandboxRuntime({ children }: React.PropsWithChildren): import("react/jsx-runtime").JSX.Element;
@@ -11,6 +11,7 @@ import LinkInterceptor from "./LinkInterceptor";
11
11
  import { NavigationReceiver } from "./NavigationReceiver";
12
12
  import { PageCaptureResponder } from "./PageCaptureResponder";
13
13
  import { PagePreviewHeightResponder } from "./PagePreviewHeightResponder";
14
+ import { PlaceholderProductReceiver } from "./placeholder-products/placeholderProducts";
14
15
  import PostHogRelay from "./posthog-relay";
15
16
  import { EditorSelection } from "./select-mode/EditorSelection";
16
17
  function ViewportSnapshotResponder() {
@@ -33,9 +34,13 @@ function SandboxRuntime({ children }) {
33
34
  /* @__PURE__ */ jsx(AnnotationLayerMount, {}),
34
35
  /* @__PURE__ */ jsx(HeatLayerMount, {}),
35
36
  /* @__PURE__ */ jsx(DesignLibraryPreview, {}),
37
+ /* @__PURE__ */ jsx(PlaceholderProductReceiver, {}),
36
38
  children
37
39
  ] })
38
- ] }) : children;
40
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
41
+ children,
42
+ /* @__PURE__ */ jsx(PlaceholderProductReceiver, {})
43
+ ] });
39
44
  }
40
45
  export {
41
46
  SandboxRuntime