@replohq/sandbox-runtime 1.16.2 → 1.17.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.
- package/_vendor/replo-utils/lib/historyKeys.d.ts +2 -0
- package/_vendor/replo-utils/lib/historyKeys.mjs +18 -0
- package/_vendor/schemas/generated/selectModeIframeRpc.d.ts +43 -0
- package/_vendor/schemas/selectModeIframeRpc.d.ts +146 -0
- package/_vendor/schemas/selectModeIframeRpc.mjs +72 -2
- package/buildMetadata.js +3 -3
- package/package.json +4 -4
- package/select-mode/EditorSelection.js +5 -1
- package/select-mode/fast-refresh-relay.js +82 -3
- package/select-mode/fiber.d.ts +6 -0
- package/select-mode/fiber.js +33 -0
- package/select-mode/hooks/useParentMessaging.js +10 -3
- package/select-mode/hooks/useSelectionHover.js +2 -1
- package/select-mode/hooks/useSelectionInteractions.js +10 -0
- package/select-mode/iframeRpcChannel.d.ts +45 -1
- package/select-mode/iframeRpcChannel.js +7 -0
- package/select-mode/section-canvas/SectionCanvas.d.ts +7 -0
- package/select-mode/section-canvas/SectionCanvas.js +599 -0
- package/select-mode/section-canvas/optimisticSectionMove.d.ts +39 -0
- package/select-mode/section-canvas/optimisticSectionMove.js +172 -0
- package/select-mode/section-canvas/sectionCanvasControls.d.ts +3 -0
- package/select-mode/section-canvas/sectionCanvasControls.js +8 -0
- package/select-mode/section-canvas/sectionCanvasStore.d.ts +71 -0
- package/select-mode/section-canvas/sectionCanvasStore.js +275 -0
- package/select-mode/section-canvas/sectionElements.d.ts +16 -0
- package/select-mode/section-canvas/sectionElements.js +94 -0
- package/select-mode/section-canvas/sectionGhost.d.ts +5 -0
- package/select-mode/section-canvas/sectionGhost.js +23 -0
- package/select-mode/symbolicate.d.ts +2 -0
- package/select-mode/symbolicate.js +18 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/** Which undo history step a key press asks for: Cmd/Ctrl+Z, Cmd/Ctrl+Shift+Z or Cmd/Ctrl+Y, never while typing in a field. */
|
|
2
|
+
export declare function historyStepForKey(event: Pick<KeyboardEvent, "key" | "metaKey" | "ctrlKey" | "altKey" | "shiftKey" | "target">): "undo" | "redo" | null;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function isTyping(target) {
|
|
2
|
+
return target instanceof HTMLElement && (target.isContentEditable || target.closest("[contenteditable]:not([contenteditable='false'])") !== null || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName));
|
|
3
|
+
}
|
|
4
|
+
function historyStepForKey(event) {
|
|
5
|
+
if (!(event.metaKey || event.ctrlKey) || event.altKey) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
if (isTyping(event.target)) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const key = event.key.toLowerCase();
|
|
12
|
+
if (key === "y" || key === "z" && event.shiftKey) {
|
|
13
|
+
return "redo";
|
|
14
|
+
}
|
|
15
|
+
return key === "z" ? "undo" : null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { historyStepForKey };
|
|
@@ -9,6 +9,49 @@ export type IframeRuntimeBuildMetadata = {
|
|
|
9
9
|
branch: string | null;
|
|
10
10
|
commit: string | null;
|
|
11
11
|
builtAt: string | null;
|
|
12
|
+
capabilities?: string[];
|
|
13
|
+
};
|
|
14
|
+
export type SectionCanvasSection = {
|
|
15
|
+
index: number;
|
|
16
|
+
startLine: number;
|
|
17
|
+
endLine: number;
|
|
18
|
+
label: string;
|
|
19
|
+
isLocked: boolean;
|
|
20
|
+
};
|
|
21
|
+
export type SectionCanvasState = {
|
|
22
|
+
pageFilePath: string;
|
|
23
|
+
sections: SectionCanvasSection[];
|
|
24
|
+
previewScale: number;
|
|
25
|
+
isDisabled: boolean;
|
|
26
|
+
insertingAt?: number | null;
|
|
27
|
+
occludedInsets?: {
|
|
28
|
+
left: number;
|
|
29
|
+
right: number;
|
|
30
|
+
} | null;
|
|
31
|
+
};
|
|
32
|
+
export type SectionCanvasRequest = {
|
|
33
|
+
type: "insert";
|
|
34
|
+
at: number;
|
|
35
|
+
} | {
|
|
36
|
+
type: "move";
|
|
37
|
+
moveId: string;
|
|
38
|
+
index: number;
|
|
39
|
+
to: number;
|
|
40
|
+
} | {
|
|
41
|
+
type: "remove";
|
|
42
|
+
index: number;
|
|
43
|
+
} | {
|
|
44
|
+
type: "undo";
|
|
45
|
+
} | {
|
|
46
|
+
type: "redo";
|
|
47
|
+
} | {
|
|
48
|
+
type: "cancelInsert";
|
|
49
|
+
};
|
|
50
|
+
export type SectionCanvasLayoutEntry = {
|
|
51
|
+
index: number;
|
|
52
|
+
startLine: number;
|
|
53
|
+
endLine: number;
|
|
54
|
+
rect: SelectModeBoundingRect;
|
|
12
55
|
};
|
|
13
56
|
export type SelectModeParentMessage = {
|
|
14
57
|
method: "expandToSection";
|
|
@@ -25,6 +25,75 @@ export declare const iframeRuntimeBuildMetadataSchema: z.ZodObject<{
|
|
|
25
25
|
branch: z.ZodNullable<z.ZodString>;
|
|
26
26
|
commit: z.ZodNullable<z.ZodString>;
|
|
27
27
|
builtAt: z.ZodNullable<z.ZodString>;
|
|
28
|
+
capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
/** Runtimes listing this draw section insert and drag controls on the canvas and accept `setSectionCanvas`. */
|
|
31
|
+
export declare const SECTION_CANVAS_CAPABILITY = "sectionCanvas";
|
|
32
|
+
export declare const sectionCanvasSectionSchema: z.ZodObject<{
|
|
33
|
+
index: z.ZodNumber;
|
|
34
|
+
startLine: z.ZodNumber;
|
|
35
|
+
endLine: z.ZodNumber;
|
|
36
|
+
label: z.ZodString;
|
|
37
|
+
isLocked: z.ZodBoolean;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
/**
|
|
40
|
+
* Whether a source location's file is the canvas's page file. Locations arrive as `file://` URLs,
|
|
41
|
+
* `./`-relative or absolute paths, and the page file is workspace-relative, so either may be a path
|
|
42
|
+
* suffix of the other. The builder's selection sync and the runtime's section finding both use this.
|
|
43
|
+
*/
|
|
44
|
+
export declare function isSectionCanvasPageFile({ filePath, pageFilePath, }: {
|
|
45
|
+
filePath: string;
|
|
46
|
+
pageFilePath: string;
|
|
47
|
+
}): boolean;
|
|
48
|
+
export declare const sectionCanvasStateSchema: z.ZodObject<{
|
|
49
|
+
pageFilePath: z.ZodString;
|
|
50
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
51
|
+
index: z.ZodNumber;
|
|
52
|
+
startLine: z.ZodNumber;
|
|
53
|
+
endLine: z.ZodNumber;
|
|
54
|
+
label: z.ZodString;
|
|
55
|
+
isLocked: z.ZodBoolean;
|
|
56
|
+
}, z.core.$strip>>;
|
|
57
|
+
previewScale: z.ZodNumber;
|
|
58
|
+
isDisabled: z.ZodBoolean;
|
|
59
|
+
insertingAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
60
|
+
occludedInsets: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
61
|
+
left: z.ZodNumber;
|
|
62
|
+
right: z.ZodNumber;
|
|
63
|
+
}, z.core.$strip>>>;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
export declare const sectionCanvasRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
66
|
+
type: z.ZodLiteral<"insert">;
|
|
67
|
+
at: z.ZodNumber;
|
|
68
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
69
|
+
type: z.ZodLiteral<"move">;
|
|
70
|
+
moveId: z.ZodString;
|
|
71
|
+
index: z.ZodNumber;
|
|
72
|
+
to: z.ZodNumber;
|
|
73
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
74
|
+
type: z.ZodLiteral<"remove">;
|
|
75
|
+
index: z.ZodNumber;
|
|
76
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
77
|
+
type: z.ZodLiteral<"undo">;
|
|
78
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
79
|
+
type: z.ZodLiteral<"redo">;
|
|
80
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
81
|
+
type: z.ZodLiteral<"cancelInsert">;
|
|
82
|
+
}, z.core.$strip>], "type">;
|
|
83
|
+
export declare const sectionCanvasLayoutEntrySchema: z.ZodObject<{
|
|
84
|
+
index: z.ZodNumber;
|
|
85
|
+
startLine: z.ZodNumber;
|
|
86
|
+
endLine: z.ZodNumber;
|
|
87
|
+
rect: z.ZodObject<{
|
|
88
|
+
x: z.ZodNumber;
|
|
89
|
+
y: z.ZodNumber;
|
|
90
|
+
left: z.ZodNumber;
|
|
91
|
+
top: z.ZodNumber;
|
|
92
|
+
right: z.ZodNumber;
|
|
93
|
+
bottom: z.ZodNumber;
|
|
94
|
+
width: z.ZodNumber;
|
|
95
|
+
height: z.ZodNumber;
|
|
96
|
+
}, z.core.$strip>;
|
|
28
97
|
}, z.core.$strip>;
|
|
29
98
|
export declare const selectModeEventInputSchemas: {
|
|
30
99
|
hover: z.ZodObject<{
|
|
@@ -185,6 +254,38 @@ export declare const selectModeEventInputSchemas: {
|
|
|
185
254
|
}, z.core.$strip>;
|
|
186
255
|
};
|
|
187
256
|
export declare const websiteBuilderToPreviewIframeMethodConfig: {
|
|
257
|
+
setSectionCanvas: {
|
|
258
|
+
inputSchema: z.ZodObject<{
|
|
259
|
+
canvas: z.ZodNullable<z.ZodObject<{
|
|
260
|
+
pageFilePath: z.ZodString;
|
|
261
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
262
|
+
index: z.ZodNumber;
|
|
263
|
+
startLine: z.ZodNumber;
|
|
264
|
+
endLine: z.ZodNumber;
|
|
265
|
+
label: z.ZodString;
|
|
266
|
+
isLocked: z.ZodBoolean;
|
|
267
|
+
}, z.core.$strip>>;
|
|
268
|
+
previewScale: z.ZodNumber;
|
|
269
|
+
isDisabled: z.ZodBoolean;
|
|
270
|
+
insertingAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
271
|
+
occludedInsets: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
272
|
+
left: z.ZodNumber;
|
|
273
|
+
right: z.ZodNumber;
|
|
274
|
+
}, z.core.$strip>>>;
|
|
275
|
+
}, z.core.$strip>>;
|
|
276
|
+
}, z.core.$strip>;
|
|
277
|
+
outputSchema: z.ZodVoid;
|
|
278
|
+
};
|
|
279
|
+
settleSectionMove: {
|
|
280
|
+
inputSchema: z.ZodObject<{
|
|
281
|
+
moveId: z.ZodString;
|
|
282
|
+
outcome: z.ZodEnum<{
|
|
283
|
+
failed: "failed";
|
|
284
|
+
persisted: "persisted";
|
|
285
|
+
}>;
|
|
286
|
+
}, z.core.$strip>;
|
|
287
|
+
outputSchema: z.ZodVoid;
|
|
288
|
+
};
|
|
188
289
|
expandToSection: {
|
|
189
290
|
inputSchema: z.ZodObject<{
|
|
190
291
|
targetSelector: z.ZodString;
|
|
@@ -478,6 +579,49 @@ export declare const websiteBuilderToPreviewIframeMethodConfig: {
|
|
|
478
579
|
};
|
|
479
580
|
};
|
|
480
581
|
export declare const previewIframeToWebsiteBuilderMethodConfig: {
|
|
582
|
+
sectionCanvasRequest: {
|
|
583
|
+
inputSchema: z.ZodObject<{
|
|
584
|
+
request: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
585
|
+
type: z.ZodLiteral<"insert">;
|
|
586
|
+
at: z.ZodNumber;
|
|
587
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
588
|
+
type: z.ZodLiteral<"move">;
|
|
589
|
+
moveId: z.ZodString;
|
|
590
|
+
index: z.ZodNumber;
|
|
591
|
+
to: z.ZodNumber;
|
|
592
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
593
|
+
type: z.ZodLiteral<"remove">;
|
|
594
|
+
index: z.ZodNumber;
|
|
595
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
596
|
+
type: z.ZodLiteral<"undo">;
|
|
597
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
598
|
+
type: z.ZodLiteral<"redo">;
|
|
599
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
600
|
+
type: z.ZodLiteral<"cancelInsert">;
|
|
601
|
+
}, z.core.$strip>], "type">;
|
|
602
|
+
}, z.core.$strip>;
|
|
603
|
+
outputSchema: z.ZodVoid;
|
|
604
|
+
};
|
|
605
|
+
sectionCanvasLayoutChanged: {
|
|
606
|
+
inputSchema: z.ZodObject<{
|
|
607
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
608
|
+
index: z.ZodNumber;
|
|
609
|
+
startLine: z.ZodNumber;
|
|
610
|
+
endLine: z.ZodNumber;
|
|
611
|
+
rect: z.ZodObject<{
|
|
612
|
+
x: z.ZodNumber;
|
|
613
|
+
y: z.ZodNumber;
|
|
614
|
+
left: z.ZodNumber;
|
|
615
|
+
top: z.ZodNumber;
|
|
616
|
+
right: z.ZodNumber;
|
|
617
|
+
bottom: z.ZodNumber;
|
|
618
|
+
width: z.ZodNumber;
|
|
619
|
+
height: z.ZodNumber;
|
|
620
|
+
}, z.core.$strip>;
|
|
621
|
+
}, z.core.$strip>>;
|
|
622
|
+
}, z.core.$strip>;
|
|
623
|
+
outputSchema: z.ZodVoid;
|
|
624
|
+
};
|
|
481
625
|
requestInlineTextEdit: {
|
|
482
626
|
inputSchema: z.ZodObject<{
|
|
483
627
|
editId: z.ZodString;
|
|
@@ -576,6 +720,7 @@ export declare const previewIframeToWebsiteBuilderMethodConfig: {
|
|
|
576
720
|
branch: z.ZodNullable<z.ZodString>;
|
|
577
721
|
commit: z.ZodNullable<z.ZodString>;
|
|
578
722
|
builtAt: z.ZodNullable<z.ZodString>;
|
|
723
|
+
capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
579
724
|
}, z.core.$strip>;
|
|
580
725
|
outputSchema: z.ZodVoid;
|
|
581
726
|
};
|
|
@@ -1032,6 +1177,7 @@ export declare const selectModeIframeMessageSchema: z.ZodDiscriminatedUnion<[z.Z
|
|
|
1032
1177
|
branch: z.ZodNullable<z.ZodString>;
|
|
1033
1178
|
commit: z.ZodNullable<z.ZodString>;
|
|
1034
1179
|
builtAt: z.ZodNullable<z.ZodString>;
|
|
1180
|
+
capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1035
1181
|
}, z.core.$strip>;
|
|
1036
1182
|
}, z.core.$strip>, z.ZodObject<{
|
|
1037
1183
|
method: z.ZodLiteral<"elementSelected">;
|
|
@@ -16,8 +16,57 @@ var iframeRuntimeBuildMetadataSchema = z.object({
|
|
|
16
16
|
version: z.string(),
|
|
17
17
|
branch: z.string().nullable(),
|
|
18
18
|
commit: z.string().nullable(),
|
|
19
|
-
builtAt: z.string().nullable()
|
|
19
|
+
builtAt: z.string().nullable(),
|
|
20
|
+
capabilities: z.array(z.string()).optional()
|
|
20
21
|
}).describe("IframeRuntimeBuildMetadata");
|
|
22
|
+
var SECTION_CANVAS_CAPABILITY = "sectionCanvas";
|
|
23
|
+
var sectionCanvasSectionSchema = z.object({
|
|
24
|
+
index: z.number().int().nonnegative(),
|
|
25
|
+
startLine: z.number().int().positive(),
|
|
26
|
+
endLine: z.number().int().positive(),
|
|
27
|
+
label: z.string(),
|
|
28
|
+
isLocked: z.boolean()
|
|
29
|
+
}).describe("SectionCanvasSection");
|
|
30
|
+
function isSectionCanvasPageFile({
|
|
31
|
+
filePath,
|
|
32
|
+
pageFilePath
|
|
33
|
+
}) {
|
|
34
|
+
const normalized = filePath.replace(/^file:\/\//u, "").replace(/^\.\//u, "");
|
|
35
|
+
return normalized === pageFilePath || normalized.endsWith(`/${pageFilePath}`) || pageFilePath.endsWith(`/${normalized}`);
|
|
36
|
+
}
|
|
37
|
+
var sectionCanvasStateSchema = z.object({
|
|
38
|
+
pageFilePath: z.string(),
|
|
39
|
+
sections: z.array(sectionCanvasSectionSchema),
|
|
40
|
+
previewScale: z.number().positive(),
|
|
41
|
+
isDisabled: z.boolean(),
|
|
42
|
+
insertingAt: z.number().int().nonnegative().nullish(),
|
|
43
|
+
occludedInsets: z.object({
|
|
44
|
+
left: z.number().nonnegative(),
|
|
45
|
+
right: z.number().nonnegative()
|
|
46
|
+
}).nullish()
|
|
47
|
+
}).describe("SectionCanvasState");
|
|
48
|
+
var sectionCanvasRequestSchema = z.discriminatedUnion("type", [
|
|
49
|
+
z.object({ type: z.literal("insert"), at: z.number().int().nonnegative() }),
|
|
50
|
+
z.object({
|
|
51
|
+
type: z.literal("move"),
|
|
52
|
+
moveId: z.string(),
|
|
53
|
+
index: z.number().int().nonnegative(),
|
|
54
|
+
to: z.number().int().nonnegative()
|
|
55
|
+
}),
|
|
56
|
+
z.object({
|
|
57
|
+
type: z.literal("remove"),
|
|
58
|
+
index: z.number().int().nonnegative()
|
|
59
|
+
}),
|
|
60
|
+
z.object({ type: z.literal("undo") }),
|
|
61
|
+
z.object({ type: z.literal("redo") }),
|
|
62
|
+
z.object({ type: z.literal("cancelInsert") })
|
|
63
|
+
]).describe("SectionCanvasRequest");
|
|
64
|
+
var sectionCanvasLayoutEntrySchema = z.object({
|
|
65
|
+
index: z.number().int().nonnegative(),
|
|
66
|
+
startLine: z.number().int().positive(),
|
|
67
|
+
endLine: z.number().int().positive(),
|
|
68
|
+
rect: selectModeBoundingRectSchema
|
|
69
|
+
}).describe("SectionCanvasLayoutEntry");
|
|
21
70
|
var selectModeEventInputSchemas = {
|
|
22
71
|
hover: z.object({
|
|
23
72
|
rect: selectModeHoverRectSchema.nullable()
|
|
@@ -37,6 +86,17 @@ var selectModeEventInputSchemas = {
|
|
|
37
86
|
})
|
|
38
87
|
};
|
|
39
88
|
var websiteBuilderToPreviewIframeMethodConfig = {
|
|
89
|
+
setSectionCanvas: {
|
|
90
|
+
inputSchema: z.object({ canvas: sectionCanvasStateSchema.nullable() }),
|
|
91
|
+
outputSchema: z.void()
|
|
92
|
+
},
|
|
93
|
+
settleSectionMove: {
|
|
94
|
+
inputSchema: z.object({
|
|
95
|
+
moveId: z.string(),
|
|
96
|
+
outcome: z.enum(["persisted", "failed"])
|
|
97
|
+
}),
|
|
98
|
+
outputSchema: z.void()
|
|
99
|
+
},
|
|
40
100
|
expandToSection: {
|
|
41
101
|
inputSchema: z.object({ targetSelector: z.string() }),
|
|
42
102
|
outputSchema: z.void()
|
|
@@ -110,6 +170,16 @@ var websiteBuilderToPreviewIframeMethodConfig = {
|
|
|
110
170
|
}
|
|
111
171
|
};
|
|
112
172
|
var previewIframeToWebsiteBuilderMethodConfig = {
|
|
173
|
+
sectionCanvasRequest: {
|
|
174
|
+
inputSchema: z.object({ request: sectionCanvasRequestSchema }),
|
|
175
|
+
outputSchema: z.void()
|
|
176
|
+
},
|
|
177
|
+
sectionCanvasLayoutChanged: {
|
|
178
|
+
inputSchema: z.object({
|
|
179
|
+
sections: z.array(sectionCanvasLayoutEntrySchema)
|
|
180
|
+
}),
|
|
181
|
+
outputSchema: z.void()
|
|
182
|
+
},
|
|
113
183
|
requestInlineTextEdit: {
|
|
114
184
|
inputSchema: z.object({
|
|
115
185
|
editId: z.string(),
|
|
@@ -265,4 +335,4 @@ var selectModeIframeMessageSchema = z.discriminatedUnion("method", [
|
|
|
265
335
|
})
|
|
266
336
|
]).describe("SelectModeIframeMessage");
|
|
267
337
|
|
|
268
|
-
export { SELECT_MODE_IFRAME_RPC_CHANNEL_ID, SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION, iframeRuntimeBuildMetadataSchema, inlineEditFeedbackSchema, previewIframeToWebsiteBuilderMethodConfig, selectModeEventInputSchemas, selectModeIframeMessageSchema, selectModeParentMessageSchema, websiteBuilderToPreviewIframeMethodConfig };
|
|
338
|
+
export { SECTION_CANVAS_CAPABILITY, SELECT_MODE_IFRAME_RPC_CHANNEL_ID, SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION, iframeRuntimeBuildMetadataSchema, inlineEditFeedbackSchema, isSectionCanvasPageFile, previewIframeToWebsiteBuilderMethodConfig, sectionCanvasLayoutEntrySchema, sectionCanvasRequestSchema, sectionCanvasSectionSchema, sectionCanvasStateSchema, selectModeEventInputSchemas, selectModeIframeMessageSchema, selectModeParentMessageSchema, websiteBuilderToPreviewIframeMethodConfig };
|
package/buildMetadata.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const BUILD_METADATA = {
|
|
2
2
|
"packageName": "@replohq/sandbox-runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"branch": "HEAD",
|
|
5
|
-
"commit": "
|
|
6
|
-
"builtAt": "2026-10-
|
|
5
|
+
"commit": "7d16c9a29182a37625a958569422b94a08b9a627",
|
|
6
|
+
"builtAt": "2026-10-20T04:21:24.844Z"
|
|
7
7
|
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@replohq/sandbox-runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"reploBuild": {
|
|
5
5
|
"packageName": "@replohq/sandbox-runtime",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.17.0",
|
|
7
7
|
"branch": "HEAD",
|
|
8
|
-
"commit": "
|
|
9
|
-
"builtAt": "2026-10-
|
|
8
|
+
"commit": "7d16c9a29182a37625a958569422b94a08b9a627",
|
|
9
|
+
"builtAt": "2026-10-20T04:21:24.844Z"
|
|
10
10
|
},
|
|
11
11
|
"description": "Replo sandbox runtime — editor integration for agent-built Next.js sites.",
|
|
12
12
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -8,6 +8,8 @@ import { useSelectionHover } from "./hooks/useSelectionHover";
|
|
|
8
8
|
import { useSelectionInteractions } from "./hooks/useSelectionInteractions";
|
|
9
9
|
import { useSelectionScrollSync } from "./hooks/useSelectionScrollSync";
|
|
10
10
|
import { PREVIEW_RENDERED_EVENT } from "./previewRendered";
|
|
11
|
+
import { SectionCanvas } from "./section-canvas/SectionCanvas";
|
|
12
|
+
import { sectionCanvasStore } from "./section-canvas/sectionCanvasStore";
|
|
11
13
|
import { SelectionFrames } from "./SelectionFrames";
|
|
12
14
|
import {
|
|
13
15
|
useDisplayMode,
|
|
@@ -90,6 +92,7 @@ function EditorSelection() {
|
|
|
90
92
|
onComplete: () => {
|
|
91
93
|
reapplyOverrides({ skipElement: store.getState().editingElement });
|
|
92
94
|
watchRender();
|
|
95
|
+
sectionCanvasStore.getState().actions.handlePreviewRefresh();
|
|
93
96
|
}
|
|
94
97
|
});
|
|
95
98
|
window.addEventListener(PREVIEW_RENDERED_EVENT, watchRender);
|
|
@@ -151,7 +154,8 @@ function EditorSelection() {
|
|
|
151
154
|
[data-select-mode-inline-editor][contenteditable="true"],
|
|
152
155
|
[data-select-mode-inline-editor][contenteditable="true"] * { cursor: text !important; }
|
|
153
156
|
` }),
|
|
154
|
-
/* @__PURE__ */ jsx(SelectionFrames, {})
|
|
157
|
+
/* @__PURE__ */ jsx(SelectionFrames, {}),
|
|
158
|
+
/* @__PURE__ */ jsx(SectionCanvas, {})
|
|
155
159
|
] });
|
|
156
160
|
}
|
|
157
161
|
export {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { getWebsiteBuilderRpc } from "./iframeRpcChannel";
|
|
2
|
+
import { SECTION_CANVAS_ATTRIBUTE } from "./section-canvas/sectionCanvasControls";
|
|
2
3
|
import { invalidateSymbolicationCache } from "./symbolicate";
|
|
4
|
+
const SERVER_REFRESH_HEADER = "next-hmr-refresh";
|
|
5
|
+
const SERVER_REFRESH_COMMIT_TIMEOUT_MS = 2e3;
|
|
3
6
|
let hasInstalledFastRefreshRelay = false;
|
|
4
7
|
let onFastRefreshComplete = null;
|
|
5
8
|
let lastLatencyMs = null;
|
|
@@ -11,6 +14,7 @@ function installFastRefreshRelay({
|
|
|
11
14
|
return;
|
|
12
15
|
}
|
|
13
16
|
hasInstalledFastRefreshRelay = true;
|
|
17
|
+
installServerRefreshRelay();
|
|
14
18
|
const originalCallback = window.__NEXT_HMR_LATENCY_CB;
|
|
15
19
|
window.__NEXT_HMR_LATENCY_CB = (latencyMs) => {
|
|
16
20
|
const isRepeat = latencyMs === lastLatencyMs;
|
|
@@ -19,12 +23,87 @@ function installFastRefreshRelay({
|
|
|
19
23
|
originalCallback?.(latencyMs);
|
|
20
24
|
return;
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
getWebsiteBuilderRpc()?.fastRefreshComplete(void 0);
|
|
24
|
-
onFastRefreshComplete?.();
|
|
26
|
+
reportRefreshComplete();
|
|
25
27
|
originalCallback?.(latencyMs);
|
|
26
28
|
};
|
|
27
29
|
}
|
|
30
|
+
function reportRefreshComplete() {
|
|
31
|
+
invalidateSymbolicationCache();
|
|
32
|
+
getWebsiteBuilderRpc()?.fastRefreshComplete(void 0);
|
|
33
|
+
onFastRefreshComplete?.();
|
|
34
|
+
}
|
|
35
|
+
function isServerRefreshRequest(input, init) {
|
|
36
|
+
try {
|
|
37
|
+
return new Headers(init?.headers).has(SERVER_REFRESH_HEADER) || input instanceof Request && input.headers.has(SERVER_REFRESH_HEADER);
|
|
38
|
+
} catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function nextReactCommit() {
|
|
43
|
+
const hook = Reflect.get(
|
|
44
|
+
window,
|
|
45
|
+
"__REACT_DEVTOOLS_GLOBAL_HOOK__"
|
|
46
|
+
);
|
|
47
|
+
if (!hook || typeof hook.onCommitFiberRoot !== "function") {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
const original = hook.onCommitFiberRoot;
|
|
52
|
+
hook.onCommitFiberRoot = function relayCommit(...args) {
|
|
53
|
+
hook.onCommitFiberRoot = original;
|
|
54
|
+
resolve();
|
|
55
|
+
return original?.apply(this, args);
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function nextPageMutation() {
|
|
60
|
+
let observer = null;
|
|
61
|
+
const promise = new Promise((resolve) => {
|
|
62
|
+
observer = new MutationObserver((records) => {
|
|
63
|
+
const isPageChange = records.some((record) => {
|
|
64
|
+
const element = record.target instanceof Element ? record.target : record.target.parentElement;
|
|
65
|
+
return element !== null && document.body.contains(element) && !element.closest(`[${SECTION_CANVAS_ATTRIBUTE}]`);
|
|
66
|
+
});
|
|
67
|
+
if (isPageChange) {
|
|
68
|
+
observer?.disconnect();
|
|
69
|
+
resolve();
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
observer.observe(document.documentElement, {
|
|
73
|
+
childList: true,
|
|
74
|
+
subtree: true,
|
|
75
|
+
characterData: true
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
return { promise, cancel: () => observer?.disconnect() };
|
|
79
|
+
}
|
|
80
|
+
function installServerRefreshRelay() {
|
|
81
|
+
const originalFetch = window.fetch;
|
|
82
|
+
window.fetch = function relayServerRefresh(input, init) {
|
|
83
|
+
const response = originalFetch.call(this, input, init);
|
|
84
|
+
if (isServerRefreshRequest(input, init)) {
|
|
85
|
+
void response.then((received) => received.clone().arrayBuffer()).then(
|
|
86
|
+
async () => {
|
|
87
|
+
const commit = nextReactCommit();
|
|
88
|
+
const mutation = commit ? null : nextPageMutation();
|
|
89
|
+
let timeout;
|
|
90
|
+
await Promise.race([
|
|
91
|
+
commit ?? mutation?.promise,
|
|
92
|
+
new Promise((resolve) => {
|
|
93
|
+
timeout = setTimeout(resolve, SERVER_REFRESH_COMMIT_TIMEOUT_MS);
|
|
94
|
+
})
|
|
95
|
+
]);
|
|
96
|
+
mutation?.cancel();
|
|
97
|
+
clearTimeout(timeout);
|
|
98
|
+
reportRefreshComplete();
|
|
99
|
+
},
|
|
100
|
+
() => {
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return response;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
28
107
|
export {
|
|
29
108
|
installFastRefreshRelay
|
|
30
109
|
};
|
package/select-mode/fiber.d.ts
CHANGED
|
@@ -48,4 +48,10 @@ export declare function getFiberChain(element: HTMLElement): {
|
|
|
48
48
|
componentName: string | undefined;
|
|
49
49
|
props: Record<string, unknown> | undefined;
|
|
50
50
|
}[];
|
|
51
|
+
/**
|
|
52
|
+
* JSX call sites from an element outward (its own, then each owner's), still compiled. Skips
|
|
53
|
+
* `resolveCurrentFiber`'s tree scan: a call site is the same in both fiber generations, and this
|
|
54
|
+
* runs for every element near the top of the page.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getElementSourceChain(element: HTMLElement, maxEntries?: number): DebugSource[];
|
|
51
57
|
export {};
|
package/select-mode/fiber.js
CHANGED
|
@@ -493,9 +493,42 @@ function getFiberChain(element) {
|
|
|
493
493
|
}
|
|
494
494
|
return fiberChain;
|
|
495
495
|
}
|
|
496
|
+
function getElementSourceChain(element, maxEntries = 16) {
|
|
497
|
+
const chain = [];
|
|
498
|
+
const seen = /* @__PURE__ */ new Set();
|
|
499
|
+
const seenOwners = /* @__PURE__ */ new Set();
|
|
500
|
+
const push = (source) => {
|
|
501
|
+
if (!source) {
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
const key = `${source.fileName}:${source.lineNumber}:${source.columnNumber ?? ""}`;
|
|
505
|
+
if (!seen.has(key)) {
|
|
506
|
+
seen.add(key);
|
|
507
|
+
chain.push(source);
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
let fiber = getFiberFromElement(element);
|
|
511
|
+
let depth = 0;
|
|
512
|
+
while (fiber && depth < MAX_FIBER_CHAIN_DEPTH && chain.length < maxEntries) {
|
|
513
|
+
push(parseDebugStackSource(fiber._debugStack));
|
|
514
|
+
let owner = fiber._debugOwner;
|
|
515
|
+
while (owner && !seenOwners.has(owner) && chain.length < maxEntries) {
|
|
516
|
+
seenOwners.add(owner);
|
|
517
|
+
if (!("name" in owner)) {
|
|
518
|
+
break;
|
|
519
|
+
}
|
|
520
|
+
push(parseDebugStackSource(owner.debugStack));
|
|
521
|
+
owner = owner.owner;
|
|
522
|
+
}
|
|
523
|
+
fiber = fiber.return;
|
|
524
|
+
depth += 1;
|
|
525
|
+
}
|
|
526
|
+
return chain;
|
|
527
|
+
}
|
|
496
528
|
export {
|
|
497
529
|
findDebugSource,
|
|
498
530
|
getComponentName,
|
|
531
|
+
getElementSourceChain,
|
|
499
532
|
getFiberChain,
|
|
500
533
|
getFiberFromElement,
|
|
501
534
|
getRepetitionHostNodes,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { useEffect, useMemo } from "react";
|
|
2
2
|
import { useIframeRpcChannel } from "../../_vendor/replo-utils/react/use-iframe-rpc-channel.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
iframeRuntimeBuildMetadataSchema,
|
|
5
|
+
SECTION_CANVAS_CAPABILITY
|
|
6
|
+
} from "../../_vendor/schemas/selectModeIframeRpc.mjs";
|
|
4
7
|
import * as z from "zod";
|
|
5
8
|
import { BUILD_METADATA } from "../../buildMetadata";
|
|
6
9
|
import {
|
|
@@ -9,6 +12,7 @@ import {
|
|
|
9
12
|
setSelectModeParentHandlers
|
|
10
13
|
} from "../iframeRpcChannel";
|
|
11
14
|
const SDK_BUILD_METADATA_SPECIFIER = "@replohq/sdk/lib/buildMetadata";
|
|
15
|
+
const RUNTIME_CAPABILITIES = [SECTION_CANVAS_CAPABILITY];
|
|
12
16
|
const sdkBuildMetadataModuleSchema = z.object({
|
|
13
17
|
BUILD_METADATA: iframeRuntimeBuildMetadataSchema
|
|
14
18
|
});
|
|
@@ -18,7 +22,10 @@ async function announceSdkBuildMetadata() {
|
|
|
18
22
|
await import(SDK_BUILD_METADATA_SPECIFIER)
|
|
19
23
|
);
|
|
20
24
|
if (sdkBuildMetadata.success) {
|
|
21
|
-
getWebsiteBuilderRpc()?.iframeReady(
|
|
25
|
+
getWebsiteBuilderRpc()?.iframeReady({
|
|
26
|
+
...sdkBuildMetadata.data.BUILD_METADATA,
|
|
27
|
+
capabilities: RUNTIME_CAPABILITIES
|
|
28
|
+
});
|
|
22
29
|
}
|
|
23
30
|
} catch {
|
|
24
31
|
}
|
|
@@ -78,7 +85,7 @@ function useParentMessaging({
|
|
|
78
85
|
}
|
|
79
86
|
});
|
|
80
87
|
const rpc = getWebsiteBuilderRpc();
|
|
81
|
-
rpc?.iframeReady(BUILD_METADATA);
|
|
88
|
+
rpc?.iframeReady({ ...BUILD_METADATA, capabilities: RUNTIME_CAPABILITIES });
|
|
82
89
|
void announceSdkBuildMetadata();
|
|
83
90
|
return () => {
|
|
84
91
|
setSelectModeParentHandlers(null);
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
findContainingSection
|
|
7
7
|
} from "../interactions/sectionGeometry";
|
|
8
8
|
import { getElementBoundingRect } from "../interactions/selectionGeometry";
|
|
9
|
+
import { isSectionCanvasControl } from "../section-canvas/sectionCanvasControls";
|
|
9
10
|
import { useDisplayMode, useSelectModeStore } from "../selectModeStore";
|
|
10
11
|
function useSelectionHover() {
|
|
11
12
|
const store = useSelectModeStore();
|
|
@@ -54,7 +55,7 @@ function useSelectionHover() {
|
|
|
54
55
|
hoveredElement = hoveredElementStack[hoveredElementStack.length - 1] ?? null;
|
|
55
56
|
}
|
|
56
57
|
postHoveredElement(
|
|
57
|
-
hoveredElement ? getNearestSelectableElement(hoveredElement) : null
|
|
58
|
+
hoveredElement && !isSectionCanvasControl(hoveredElement) ? getNearestSelectableElement(hoveredElement) : null
|
|
58
59
|
);
|
|
59
60
|
};
|
|
60
61
|
const scheduleHoverSync = () => {
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
unionElementPageRects
|
|
21
21
|
} from "../interactions/selectionGeometry";
|
|
22
22
|
import { isTextEditableElement } from "../isTextEditableElement";
|
|
23
|
+
import { isSectionCanvasControl } from "../section-canvas/sectionCanvasControls";
|
|
23
24
|
import { isSelectionStillCurrent } from "../selectionPublish";
|
|
24
25
|
import {
|
|
25
26
|
getConnectedSelectedElement,
|
|
@@ -172,6 +173,9 @@ function useSelectionInteractions() {
|
|
|
172
173
|
);
|
|
173
174
|
};
|
|
174
175
|
const handlePointerDown = (event) => {
|
|
176
|
+
if (isSectionCanvasControl(event.target)) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
175
179
|
if (event.button !== 0) {
|
|
176
180
|
return;
|
|
177
181
|
}
|
|
@@ -362,6 +366,9 @@ function useSelectionInteractions() {
|
|
|
362
366
|
});
|
|
363
367
|
};
|
|
364
368
|
const handlePointerUp = (event) => {
|
|
369
|
+
if (isSectionCanvasControl(event.target)) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
365
372
|
if (event.button !== 0) {
|
|
366
373
|
return;
|
|
367
374
|
}
|
|
@@ -419,6 +426,9 @@ function useSelectionInteractions() {
|
|
|
419
426
|
});
|
|
420
427
|
};
|
|
421
428
|
const handleClick = (event) => {
|
|
429
|
+
if (isSectionCanvasControl(event.target)) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
422
432
|
if (editingElementRef?.current && event.target instanceof Node && editingElementRef.current.contains(event.target)) {
|
|
423
433
|
return;
|
|
424
434
|
}
|