@replohq/sandbox-runtime 0.1.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/ClientErrorBoundary.d.ts +10 -0
- package/ClientErrorBoundary.js +61 -0
- package/ClientErrorBoundary.js.map +7 -0
- package/DocumentReadyBeacon.d.ts +1 -0
- package/DocumentReadyBeacon.js +9 -0
- package/DocumentReadyBeacon.js.map +7 -0
- package/LICENSE +11 -0
- package/LinkInterceptor.d.ts +1 -0
- package/LinkInterceptor.js +128 -0
- package/LinkInterceptor.js.map +7 -0
- package/NextErrorReporter.d.ts +1 -0
- package/NextErrorReporter.js +92 -0
- package/NextErrorReporter.js.map +7 -0
- package/_vendor/replo-utils/lib/crypto.d.ts +30 -0
- package/_vendor/replo-utils/lib/errors.d.ts +83 -0
- package/_vendor/replo-utils/lib/fonts.d.ts +49 -0
- package/_vendor/replo-utils/lib/fonts.mjs +221 -0
- package/_vendor/replo-utils/lib/geometry.d.ts +18 -0
- package/_vendor/replo-utils/lib/geometry.mjs +9 -0
- package/_vendor/replo-utils/lib/json.d.ts +6 -0
- package/_vendor/replo-utils/lib/log.d.ts +11 -0
- package/_vendor/replo-utils/lib/misc.d.ts +145 -0
- package/_vendor/replo-utils/lib/misc.mjs +2 -0
- package/_vendor/replo-utils/lib/object.d.ts +31 -0
- package/_vendor/replo-utils/lib/parse.d.ts +15 -0
- package/_vendor/replo-utils/lib/posthogReplay.d.ts +43 -0
- package/_vendor/replo-utils/lib/posthogReplay.mjs +121 -0
- package/_vendor/replo-utils/react/use-iframe-rpc-channel.d.ts +14 -0
- package/_vendor/replo-utils/react/use-iframe-rpc-channel.mjs +14 -0
- package/_vendor/schemas/designLibrary.d.ts +361 -0
- package/_vendor/schemas/designLibrary.mjs +126 -0
- package/_vendor/schemas/errors.d.ts +459 -0
- package/_vendor/schemas/generated/errors.d.ts +61 -0
- package/_vendor/schemas/generated/pageAnnotations.d.ts +48 -0
- package/_vendor/schemas/generated/pageAnnotations.mjs +1 -0
- package/_vendor/schemas/generated/selectMode.d.ts +119 -0
- package/_vendor/schemas/generated/selectMode.mjs +1 -0
- package/_vendor/schemas/generated/selectModeIframeRpc.d.ts +100 -0
- package/_vendor/schemas/generated/selectModeIframeRpc.mjs +1 -0
- package/_vendor/schemas/iframeRpcChannel.d.ts +82 -0
- package/_vendor/schemas/iframeRpcChannel.mjs +520 -0
- package/_vendor/schemas/pageAnnotations.d.ts +134 -0
- package/_vendor/schemas/pageAnnotations.mjs +61 -0
- package/_vendor/schemas/savedStyles.d.ts +140 -0
- package/_vendor/schemas/selectMode.d.ts +522 -0
- package/_vendor/schemas/selectMode.mjs +3 -0
- package/_vendor/schemas/selectModeIframeRpc.d.ts +900 -0
- package/_vendor/schemas/selectModeIframeRpc.mjs +223 -0
- package/annotations/AnnotationLayerMount.d.ts +1 -0
- package/annotations/AnnotationLayerMount.js +13 -0
- package/annotations/AnnotationLayerMount.js.map +7 -0
- package/annotations/annotationController.d.ts +1 -0
- package/annotations/annotationController.js +384 -0
- package/annotations/annotationController.js.map +7 -0
- package/annotations/bridgeGate.d.ts +7 -0
- package/annotations/bridgeGate.js +22 -0
- package/annotations/bridgeGate.js.map +7 -0
- package/chunk-3UFG7XTQ.mjs +205 -0
- package/chunk-FNTGY7I5.mjs +68 -0
- package/chunk-N5EI2MOZ.mjs +1535 -0
- package/design-library-preview/DesignLibraryPreview.d.ts +1 -0
- package/design-library-preview/DesignLibraryPreview.js +93 -0
- package/design-library-preview/DesignLibraryPreview.js.map +7 -0
- package/package.json +41 -0
- package/posthog-relay.d.ts +11 -0
- package/posthog-relay.js +72 -0
- package/posthog-relay.js.map +7 -0
- package/sandbox-runtime.d.ts +1 -0
- package/sandbox-runtime.js +29 -0
- package/sandbox-runtime.js.map +7 -0
- package/select-mode/EditorSelection.d.ts +24 -0
- package/select-mode/EditorSelection.js +95 -0
- package/select-mode/EditorSelection.js.map +7 -0
- package/select-mode/annotationFrames.d.ts +33 -0
- package/select-mode/annotationFrames.js +119 -0
- package/select-mode/annotationFrames.js.map +7 -0
- package/select-mode/descriptor/elementDescriptor.d.ts +26 -0
- package/select-mode/descriptor/elementDescriptor.js +201 -0
- package/select-mode/descriptor/elementDescriptor.js.map +7 -0
- package/select-mode/descriptor/styleExtraction.d.ts +3 -0
- package/select-mode/descriptor/styleExtraction.js +271 -0
- package/select-mode/descriptor/styleExtraction.js.map +7 -0
- package/select-mode/displayModeStore.d.ts +10 -0
- package/select-mode/displayModeStore.js +47 -0
- package/select-mode/displayModeStore.js.map +7 -0
- package/select-mode/fast-refresh-relay.d.ts +3 -0
- package/select-mode/fast-refresh-relay.js +33 -0
- package/select-mode/fast-refresh-relay.js.map +7 -0
- package/select-mode/fiber.d.ts +49 -0
- package/select-mode/fiber.js +306 -0
- package/select-mode/fiber.js.map +7 -0
- package/select-mode/hooks/useCrosshairCursor.d.ts +12 -0
- package/select-mode/hooks/useCrosshairCursor.js +20 -0
- package/select-mode/hooks/useCrosshairCursor.js.map +7 -0
- package/select-mode/hooks/useEditModeStateMachine.d.ts +16 -0
- package/select-mode/hooks/useEditModeStateMachine.js +235 -0
- package/select-mode/hooks/useEditModeStateMachine.js.map +7 -0
- package/select-mode/hooks/useOptimisticOverrides.d.ts +17 -0
- package/select-mode/hooks/useOptimisticOverrides.js +283 -0
- package/select-mode/hooks/useOptimisticOverrides.js.map +7 -0
- package/select-mode/hooks/useParentMessaging.d.ts +36 -0
- package/select-mode/hooks/useParentMessaging.js +74 -0
- package/select-mode/hooks/useParentMessaging.js.map +7 -0
- package/select-mode/hooks/useSelectModeController.d.ts +8 -0
- package/select-mode/hooks/useSelectModeController.js +46 -0
- package/select-mode/hooks/useSelectModeController.js.map +7 -0
- package/select-mode/hooks/useSelectionHover.d.ts +22 -0
- package/select-mode/hooks/useSelectionHover.js +110 -0
- package/select-mode/hooks/useSelectionHover.js.map +7 -0
- package/select-mode/hooks/useSelectionInteractions.d.ts +37 -0
- package/select-mode/hooks/useSelectionInteractions.js +353 -0
- package/select-mode/hooks/useSelectionInteractions.js.map +7 -0
- package/select-mode/hooks/useSelectionScrollSync.d.ts +28 -0
- package/select-mode/hooks/useSelectionScrollSync.js +70 -0
- package/select-mode/hooks/useSelectionScrollSync.js.map +7 -0
- package/select-mode/hooks/useSiblingResolution.d.ts +6 -0
- package/select-mode/hooks/useSiblingResolution.js +59 -0
- package/select-mode/hooks/useSiblingResolution.js.map +7 -0
- package/select-mode/iframeRpcChannel.d.ts +356 -0
- package/select-mode/iframeRpcChannel.js +92 -0
- package/select-mode/iframeRpcChannel.js.map +7 -0
- package/select-mode/inlineTextMarks.d.ts +6 -0
- package/select-mode/inlineTextMarks.js +25 -0
- package/select-mode/inlineTextMarks.js.map +7 -0
- package/select-mode/interactions/selectionGeometry.d.ts +105 -0
- package/select-mode/interactions/selectionGeometry.js +192 -0
- package/select-mode/interactions/selectionGeometry.js.map +7 -0
- package/select-mode/selectModeSession.d.ts +21 -0
- package/select-mode/selectModeSession.js +7 -0
- package/select-mode/selectModeSession.js.map +7 -0
- package/select-mode/selectionFrame.d.ts +81 -0
- package/select-mode/selectionFrame.js +132 -0
- package/select-mode/selectionFrame.js.map +7 -0
- package/select-mode/symbolicate.d.ts +2 -0
- package/select-mode/symbolicate.js +200 -0
- package/select-mode/symbolicate.js.map +7 -0
- package/select-mode/tiptapInlineEditor.d.ts +23 -0
- package/select-mode/tiptapInlineEditor.js +120 -0
- package/select-mode/tiptapInlineEditor.js.map +7 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { selectModeFormatCommandSchema, selectModeOptimisticUpdatePayloadSchema, selectModeSelectionTypeSchema, displayModeSchema, selectModeTiptapActiveMarksSchema, selectModeBoundingRectSchema, selectableDataSchema, selectModeSelectionRectSchema, selectModeClickPositionSchema, selectedElementSchema } from '../../chunk-3UFG7XTQ.mjs';
|
|
2
|
+
import '../../chunk-N5EI2MOZ.mjs';
|
|
3
|
+
import '../../chunk-FNTGY7I5.mjs';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
var SELECT_MODE_IFRAME_RPC_CHANNEL_ID = "replo:select-mode-iframe-rpc";
|
|
7
|
+
var SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION = 1;
|
|
8
|
+
var websiteBuilderToCanopyMethodConfig = {
|
|
9
|
+
symbolicateSelectedElement: {
|
|
10
|
+
inputSchema: selectedElementSchema,
|
|
11
|
+
outputSchema: selectedElementSchema,
|
|
12
|
+
timeoutMs: 1500
|
|
13
|
+
},
|
|
14
|
+
setDisplayMode: {
|
|
15
|
+
inputSchema: z.object({ displayMode: displayModeSchema }),
|
|
16
|
+
outputSchema: z.void()
|
|
17
|
+
},
|
|
18
|
+
// Declarative push of the parent's current selection type into the
|
|
19
|
+
// canopy iframe. Transitioning to `none` is canopy's signal to hide
|
|
20
|
+
// its in-iframe selection frame and drop any in-progress drag —
|
|
21
|
+
// there's no separate "clear" message because selection state always
|
|
22
|
+
// flows through agentUiState.
|
|
23
|
+
setSelectionType: {
|
|
24
|
+
inputSchema: z.object({ selectionType: selectModeSelectionTypeSchema }),
|
|
25
|
+
outputSchema: z.void()
|
|
26
|
+
},
|
|
27
|
+
applyOptimisticUpdate: {
|
|
28
|
+
inputSchema: z.object({
|
|
29
|
+
editId: z.string(),
|
|
30
|
+
payload: selectModeOptimisticUpdatePayloadSchema,
|
|
31
|
+
targetSelector: z.string(),
|
|
32
|
+
targetMode: z.enum(["primary", "group"])
|
|
33
|
+
}),
|
|
34
|
+
outputSchema: z.void()
|
|
35
|
+
},
|
|
36
|
+
markCommitted: {
|
|
37
|
+
inputSchema: z.object({
|
|
38
|
+
editId: z.string(),
|
|
39
|
+
sessionId: z.string()
|
|
40
|
+
}),
|
|
41
|
+
outputSchema: z.void()
|
|
42
|
+
},
|
|
43
|
+
resolveSessionOverrides: {
|
|
44
|
+
inputSchema: z.object({
|
|
45
|
+
sessionId: z.string(),
|
|
46
|
+
outcome: z.enum(["persisted", "failed"])
|
|
47
|
+
}),
|
|
48
|
+
outputSchema: z.void()
|
|
49
|
+
},
|
|
50
|
+
revertOverride: {
|
|
51
|
+
inputSchema: z.object({
|
|
52
|
+
editId: z.string()
|
|
53
|
+
}),
|
|
54
|
+
outputSchema: z.void()
|
|
55
|
+
},
|
|
56
|
+
enterEditMode: {
|
|
57
|
+
inputSchema: z.undefined(),
|
|
58
|
+
outputSchema: z.void()
|
|
59
|
+
},
|
|
60
|
+
exitEditMode: {
|
|
61
|
+
inputSchema: z.undefined(),
|
|
62
|
+
outputSchema: z.void()
|
|
63
|
+
},
|
|
64
|
+
formatCommand: {
|
|
65
|
+
inputSchema: z.object({
|
|
66
|
+
command: selectModeFormatCommandSchema
|
|
67
|
+
}),
|
|
68
|
+
outputSchema: z.void()
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var canopyToWebsiteBuilderMethodConfig = {
|
|
72
|
+
requestInlineTextEdit: {
|
|
73
|
+
inputSchema: z.object({
|
|
74
|
+
editId: z.string(),
|
|
75
|
+
element: selectedElementSchema
|
|
76
|
+
}),
|
|
77
|
+
outputSchema: z.object({ allowed: z.boolean() }),
|
|
78
|
+
timeoutMs: 5e3
|
|
79
|
+
},
|
|
80
|
+
iframeReady: {
|
|
81
|
+
inputSchema: z.undefined(),
|
|
82
|
+
outputSchema: z.void()
|
|
83
|
+
},
|
|
84
|
+
elementSelected: {
|
|
85
|
+
inputSchema: z.object({
|
|
86
|
+
data: selectableDataSchema
|
|
87
|
+
}),
|
|
88
|
+
outputSchema: z.void()
|
|
89
|
+
},
|
|
90
|
+
hoverElement: {
|
|
91
|
+
inputSchema: z.object({
|
|
92
|
+
rect: selectModeBoundingRectSchema.nullable()
|
|
93
|
+
}),
|
|
94
|
+
outputSchema: z.void()
|
|
95
|
+
},
|
|
96
|
+
selectedElementRectUpdate: {
|
|
97
|
+
inputSchema: z.object({
|
|
98
|
+
rect: selectModeBoundingRectSchema,
|
|
99
|
+
clickPosition: selectModeClickPositionSchema
|
|
100
|
+
}),
|
|
101
|
+
outputSchema: z.void()
|
|
102
|
+
},
|
|
103
|
+
selectedAreaRectUpdate: {
|
|
104
|
+
inputSchema: z.object({
|
|
105
|
+
rect: selectModeBoundingRectSchema
|
|
106
|
+
}),
|
|
107
|
+
outputSchema: z.void()
|
|
108
|
+
},
|
|
109
|
+
dragRectUpdated: {
|
|
110
|
+
inputSchema: z.object({
|
|
111
|
+
dragRect: selectModeBoundingRectSchema.nullable(),
|
|
112
|
+
selectionRects: z.array(selectModeSelectionRectSchema)
|
|
113
|
+
}),
|
|
114
|
+
outputSchema: z.void()
|
|
115
|
+
},
|
|
116
|
+
areaSelected: {
|
|
117
|
+
inputSchema: z.object({
|
|
118
|
+
rect: selectModeBoundingRectSchema,
|
|
119
|
+
items: z.array(selectableDataSchema)
|
|
120
|
+
}),
|
|
121
|
+
outputSchema: z.void()
|
|
122
|
+
},
|
|
123
|
+
textCommitted: {
|
|
124
|
+
inputSchema: z.object({
|
|
125
|
+
editId: z.string(),
|
|
126
|
+
html: z.string(),
|
|
127
|
+
json: z.record(z.string(), z.unknown()),
|
|
128
|
+
originalInnerHTML: z.string()
|
|
129
|
+
}),
|
|
130
|
+
outputSchema: z.void()
|
|
131
|
+
},
|
|
132
|
+
editorStateUpdate: {
|
|
133
|
+
inputSchema: z.object({
|
|
134
|
+
activeMarks: selectModeTiptapActiveMarksSchema,
|
|
135
|
+
// Whether an inline text edit is currently open. Lets the parent show the
|
|
136
|
+
// inline formatting controls (and live mark state) only while editing.
|
|
137
|
+
isEditing: z.boolean()
|
|
138
|
+
}),
|
|
139
|
+
outputSchema: z.void()
|
|
140
|
+
},
|
|
141
|
+
fastRefreshComplete: {
|
|
142
|
+
inputSchema: z.undefined(),
|
|
143
|
+
outputSchema: z.void()
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
var selectModeParentMessageSchema = z.discriminatedUnion("method", [
|
|
147
|
+
z.object({
|
|
148
|
+
method: z.literal("setDisplayMode"),
|
|
149
|
+
data: websiteBuilderToCanopyMethodConfig.setDisplayMode.inputSchema
|
|
150
|
+
}),
|
|
151
|
+
z.object({
|
|
152
|
+
method: z.literal("setSelectionType"),
|
|
153
|
+
data: websiteBuilderToCanopyMethodConfig.setSelectionType.inputSchema
|
|
154
|
+
}),
|
|
155
|
+
z.object({
|
|
156
|
+
method: z.literal("applyOptimisticUpdate"),
|
|
157
|
+
data: websiteBuilderToCanopyMethodConfig.applyOptimisticUpdate.inputSchema
|
|
158
|
+
}),
|
|
159
|
+
z.object({
|
|
160
|
+
method: z.literal("markCommitted"),
|
|
161
|
+
data: websiteBuilderToCanopyMethodConfig.markCommitted.inputSchema
|
|
162
|
+
}),
|
|
163
|
+
z.object({
|
|
164
|
+
method: z.literal("resolveSessionOverrides"),
|
|
165
|
+
data: websiteBuilderToCanopyMethodConfig.resolveSessionOverrides.inputSchema
|
|
166
|
+
}),
|
|
167
|
+
z.object({
|
|
168
|
+
method: z.literal("revertOverride"),
|
|
169
|
+
data: websiteBuilderToCanopyMethodConfig.revertOverride.inputSchema
|
|
170
|
+
}),
|
|
171
|
+
z.object({
|
|
172
|
+
method: z.literal("enterEditMode")
|
|
173
|
+
}),
|
|
174
|
+
z.object({
|
|
175
|
+
method: z.literal("exitEditMode")
|
|
176
|
+
}),
|
|
177
|
+
z.object({
|
|
178
|
+
method: z.literal("formatCommand"),
|
|
179
|
+
data: websiteBuilderToCanopyMethodConfig.formatCommand.inputSchema
|
|
180
|
+
})
|
|
181
|
+
]).describe("SelectModeParentMessage");
|
|
182
|
+
var selectModeIframeMessageSchema = z.discriminatedUnion("method", [
|
|
183
|
+
z.object({
|
|
184
|
+
method: z.literal("iframeReady")
|
|
185
|
+
}),
|
|
186
|
+
z.object({
|
|
187
|
+
method: z.literal("elementSelected"),
|
|
188
|
+
data: canopyToWebsiteBuilderMethodConfig.elementSelected.inputSchema
|
|
189
|
+
}),
|
|
190
|
+
z.object({
|
|
191
|
+
method: z.literal("hoverElement"),
|
|
192
|
+
data: canopyToWebsiteBuilderMethodConfig.hoverElement.inputSchema
|
|
193
|
+
}),
|
|
194
|
+
z.object({
|
|
195
|
+
method: z.literal("selectedElementRectUpdate"),
|
|
196
|
+
data: canopyToWebsiteBuilderMethodConfig.selectedElementRectUpdate.inputSchema
|
|
197
|
+
}),
|
|
198
|
+
z.object({
|
|
199
|
+
method: z.literal("selectedAreaRectUpdate"),
|
|
200
|
+
data: canopyToWebsiteBuilderMethodConfig.selectedAreaRectUpdate.inputSchema
|
|
201
|
+
}),
|
|
202
|
+
z.object({
|
|
203
|
+
method: z.literal("dragRectUpdated"),
|
|
204
|
+
data: canopyToWebsiteBuilderMethodConfig.dragRectUpdated.inputSchema
|
|
205
|
+
}),
|
|
206
|
+
z.object({
|
|
207
|
+
method: z.literal("areaSelected"),
|
|
208
|
+
data: canopyToWebsiteBuilderMethodConfig.areaSelected.inputSchema
|
|
209
|
+
}),
|
|
210
|
+
z.object({
|
|
211
|
+
method: z.literal("textCommitted"),
|
|
212
|
+
data: canopyToWebsiteBuilderMethodConfig.textCommitted.inputSchema
|
|
213
|
+
}),
|
|
214
|
+
z.object({
|
|
215
|
+
method: z.literal("editorStateUpdate"),
|
|
216
|
+
data: canopyToWebsiteBuilderMethodConfig.editorStateUpdate.inputSchema
|
|
217
|
+
}),
|
|
218
|
+
z.object({
|
|
219
|
+
method: z.literal("fastRefreshComplete")
|
|
220
|
+
})
|
|
221
|
+
]).describe("SelectModeIframeMessage");
|
|
222
|
+
|
|
223
|
+
export { SELECT_MODE_IFRAME_RPC_CHANNEL_ID, SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION, canopyToWebsiteBuilderMethodConfig, selectModeIframeMessageSchema, selectModeParentMessageSchema, websiteBuilderToCanopyMethodConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function AnnotationLayerMount(): null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
if (typeof window !== "undefined") {
|
|
3
|
+
void import("./annotationController").then((module) => {
|
|
4
|
+
module.initAnnotationLayer();
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
function AnnotationLayerMount() {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
AnnotationLayerMount
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=AnnotationLayerMount.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../annotations/AnnotationLayerMount.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\n\n/**\n * Boots the vanilla annotation controller inside preview iframes. The chunk\n * loads (and this module-scope boot runs) only when the provider actually\n * renders the element, which it folds away on a NODE_ENV literal \u2014 so\n * annotation code never ships to published storefronts.\n */\nif (typeof window !== \"undefined\") {\n void import(\"./annotationController\").then((module) => {\n module.initAnnotationLayer();\n });\n}\n\nexport function AnnotationLayerMount() {\n return null;\n}\n"],
|
|
5
|
+
"mappings": ";AAQA,IAAI,OAAO,WAAW,aAAa;AACjC,OAAK,OAAO,wBAAwB,EAAE,KAAK,CAAC,WAAW;AACrD,WAAO,oBAAoB;AAAA,EAC7B,CAAC;AACH;AAEO,SAAS,uBAAuB;AACrC,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initAnnotationLayer(): void;
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { exhaustiveSwitch } from "../_vendor/replo-utils/lib/misc.mjs";
|
|
2
|
+
import {
|
|
3
|
+
PAGE_ANNOTATIONS_PROTOCOL_VERSION,
|
|
4
|
+
pageAnnotationsParentMessageSchema
|
|
5
|
+
} from "../_vendor/schemas/pageAnnotations.mjs";
|
|
6
|
+
import {
|
|
7
|
+
ANNOTATION_CONTAINER_ID,
|
|
8
|
+
clearAnnotationFrames,
|
|
9
|
+
getAnnotationBadgeViewportRect,
|
|
10
|
+
setActiveAnnotationBadge,
|
|
11
|
+
showAnnotationFrames
|
|
12
|
+
} from "../select-mode/annotationFrames";
|
|
13
|
+
import { getDocumentScrollOffset } from "../select-mode/interactions/selectionGeometry";
|
|
14
|
+
import { isAllowedEditorMessage, isAllowedEditorOrigin } from "./bridgeGate";
|
|
15
|
+
const CLUSTER_DISTANCE_PX = 24;
|
|
16
|
+
const CLUSTER_FAN_RADIUS_PX = 30;
|
|
17
|
+
const REMEASURE_DEBOUNCE_MS = 250;
|
|
18
|
+
const PAGE_TOP_STACK_X_PX = 20;
|
|
19
|
+
const PAGE_TOP_STACK_Y_PX = 20;
|
|
20
|
+
const PAGE_TOP_STACK_GAP_PX = 36;
|
|
21
|
+
const COLOR_HEX = {
|
|
22
|
+
red: "#ef196e",
|
|
23
|
+
purple: "#8b32a8",
|
|
24
|
+
amber: "#274ae2"
|
|
25
|
+
};
|
|
26
|
+
const COLOR_SEVERITY = [
|
|
27
|
+
"red",
|
|
28
|
+
"purple",
|
|
29
|
+
"amber"
|
|
30
|
+
];
|
|
31
|
+
let isInitialized = false;
|
|
32
|
+
let editorOrigin = null;
|
|
33
|
+
let markers = [];
|
|
34
|
+
let setId = null;
|
|
35
|
+
let expandedClusterId = null;
|
|
36
|
+
let activeMarkerId = null;
|
|
37
|
+
let remeasureFrameId = null;
|
|
38
|
+
let remeasureDebounceId = null;
|
|
39
|
+
let activeRectFrameId = null;
|
|
40
|
+
let observersActive = false;
|
|
41
|
+
let lastRenderSignature = null;
|
|
42
|
+
let resizeObserver = null;
|
|
43
|
+
let mutationObserver = null;
|
|
44
|
+
function postToEditor(message) {
|
|
45
|
+
if (editorOrigin === null) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
window.parent.postMessage(message, editorOrigin);
|
|
49
|
+
}
|
|
50
|
+
function hasFixedAncestor(element) {
|
|
51
|
+
let current = element;
|
|
52
|
+
while (current !== null && current !== document.documentElement) {
|
|
53
|
+
const position = getComputedStyle(current).position;
|
|
54
|
+
if (position === "fixed" || position === "sticky") {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
current = current.parentElement;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
function resolveMarkers() {
|
|
62
|
+
const resolved = [];
|
|
63
|
+
const unresolvedIds = [];
|
|
64
|
+
let pageTopSlot = 0;
|
|
65
|
+
for (const marker of markers) {
|
|
66
|
+
if (marker.placement === "pageTop") {
|
|
67
|
+
resolved.push({
|
|
68
|
+
marker,
|
|
69
|
+
element: null,
|
|
70
|
+
isFixed: false,
|
|
71
|
+
rect: {
|
|
72
|
+
x: PAGE_TOP_STACK_X_PX + pageTopSlot * PAGE_TOP_STACK_GAP_PX,
|
|
73
|
+
y: PAGE_TOP_STACK_Y_PX,
|
|
74
|
+
width: 0,
|
|
75
|
+
height: 0
|
|
76
|
+
},
|
|
77
|
+
// The editor owns numbering; rendering the wire number keeps dots in sync with the panel.
|
|
78
|
+
displayNumber: marker.number
|
|
79
|
+
});
|
|
80
|
+
pageTopSlot += 1;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
let element = null;
|
|
84
|
+
try {
|
|
85
|
+
element = document.querySelector(marker.selector);
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
88
|
+
const domRect = element?.getBoundingClientRect();
|
|
89
|
+
if (!element || !domRect || domRect.width === 0 && domRect.height === 0) {
|
|
90
|
+
unresolvedIds.push(marker.id);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const isFixed = hasFixedAncestor(element);
|
|
94
|
+
const scrollOffset = getDocumentScrollOffset();
|
|
95
|
+
resolved.push({
|
|
96
|
+
marker,
|
|
97
|
+
element,
|
|
98
|
+
isFixed,
|
|
99
|
+
// Fixed frames use viewport coords; absolute frames use page coords.
|
|
100
|
+
rect: {
|
|
101
|
+
x: domRect.x + (isFixed ? 0 : scrollOffset.left),
|
|
102
|
+
y: domRect.y + (isFixed ? 0 : scrollOffset.top),
|
|
103
|
+
width: domRect.width,
|
|
104
|
+
height: domRect.height
|
|
105
|
+
},
|
|
106
|
+
displayNumber: marker.number
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return { resolved, unresolvedIds };
|
|
110
|
+
}
|
|
111
|
+
function clusterResolvedMarkers(resolved) {
|
|
112
|
+
const clusters = [];
|
|
113
|
+
for (const entry of resolved) {
|
|
114
|
+
const centerX = entry.rect.x + entry.rect.width / 2;
|
|
115
|
+
const centerY = entry.rect.y;
|
|
116
|
+
const host = clusters.find((cluster) => {
|
|
117
|
+
return cluster.isFixed === entry.isFixed && Math.hypot(cluster.centerX - centerX, cluster.centerY - centerY) < CLUSTER_DISTANCE_PX;
|
|
118
|
+
});
|
|
119
|
+
if (host) {
|
|
120
|
+
host.members.push(entry);
|
|
121
|
+
} else {
|
|
122
|
+
clusters.push({
|
|
123
|
+
id: entry.marker.id,
|
|
124
|
+
centerX,
|
|
125
|
+
centerY,
|
|
126
|
+
isFixed: entry.isFixed,
|
|
127
|
+
members: [entry]
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return clusters;
|
|
132
|
+
}
|
|
133
|
+
function getMostSevereColorHex(members) {
|
|
134
|
+
const color = COLOR_SEVERITY.find((candidate) => {
|
|
135
|
+
return members.some((member) => member.marker.color === candidate);
|
|
136
|
+
}) ?? "amber";
|
|
137
|
+
return COLOR_HEX[color];
|
|
138
|
+
}
|
|
139
|
+
function activateMarker(id) {
|
|
140
|
+
activeMarkerId = id;
|
|
141
|
+
const viewportRect = getAnnotationBadgeViewportRect(id);
|
|
142
|
+
if (viewportRect) {
|
|
143
|
+
postToEditor({ type: "replo:annotations:clicked", id, viewportRect });
|
|
144
|
+
}
|
|
145
|
+
setActiveAnnotationBadge(id);
|
|
146
|
+
}
|
|
147
|
+
function buildMemberSpec({
|
|
148
|
+
member,
|
|
149
|
+
badgeCenter
|
|
150
|
+
}) {
|
|
151
|
+
const marker = member.marker;
|
|
152
|
+
return {
|
|
153
|
+
id: marker.id,
|
|
154
|
+
pageRect: member.rect,
|
|
155
|
+
badgeCenter,
|
|
156
|
+
positioning: member.isFixed ? "fixed" : "absolute",
|
|
157
|
+
colorHex: COLOR_HEX[marker.color],
|
|
158
|
+
badgeLabel: String(member.displayNumber),
|
|
159
|
+
badgeAriaLabel: `Page issue ${member.displayNumber}`,
|
|
160
|
+
isActive: activeMarkerId === marker.id,
|
|
161
|
+
onBadgeClick: () => activateMarker(marker.id)
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function buildClusterSpecs(cluster) {
|
|
165
|
+
const [only] = cluster.members;
|
|
166
|
+
if (cluster.members.length === 1 && only) {
|
|
167
|
+
return [
|
|
168
|
+
buildMemberSpec({
|
|
169
|
+
member: only,
|
|
170
|
+
badgeCenter: { x: cluster.centerX, y: cluster.centerY }
|
|
171
|
+
})
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
const hub = {
|
|
175
|
+
x: cluster.centerX,
|
|
176
|
+
y: cluster.centerY,
|
|
177
|
+
width: 0,
|
|
178
|
+
height: 0
|
|
179
|
+
};
|
|
180
|
+
if (expandedClusterId !== cluster.id) {
|
|
181
|
+
return [
|
|
182
|
+
{
|
|
183
|
+
id: `cluster:${cluster.id}`,
|
|
184
|
+
pageRect: hub,
|
|
185
|
+
badgeCenter: { x: cluster.centerX, y: cluster.centerY },
|
|
186
|
+
positioning: cluster.isFixed ? "fixed" : "absolute",
|
|
187
|
+
colorHex: getMostSevereColorHex(cluster.members),
|
|
188
|
+
badgeLabel: String(cluster.members.length),
|
|
189
|
+
badgeAriaLabel: `${cluster.members.length} page issues near this element`,
|
|
190
|
+
isActive: false,
|
|
191
|
+
onBadgeClick: () => {
|
|
192
|
+
expandedClusterId = cluster.id;
|
|
193
|
+
render();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
];
|
|
197
|
+
}
|
|
198
|
+
const memberSpecs = cluster.members.map((member, index) => {
|
|
199
|
+
const angle = index / cluster.members.length * 2 * Math.PI - Math.PI / 2;
|
|
200
|
+
return buildMemberSpec({
|
|
201
|
+
member,
|
|
202
|
+
badgeCenter: {
|
|
203
|
+
x: cluster.centerX + Math.cos(angle) * CLUSTER_FAN_RADIUS_PX,
|
|
204
|
+
y: cluster.centerY + Math.sin(angle) * CLUSTER_FAN_RADIUS_PX
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
return [
|
|
209
|
+
{
|
|
210
|
+
id: `cluster:${cluster.id}`,
|
|
211
|
+
pageRect: hub,
|
|
212
|
+
badgeCenter: { x: cluster.centerX, y: cluster.centerY },
|
|
213
|
+
positioning: cluster.isFixed ? "fixed" : "absolute",
|
|
214
|
+
colorHex: "#94a3b8",
|
|
215
|
+
badgeLabel: "\xD7",
|
|
216
|
+
badgeAriaLabel: "Collapse issue cluster",
|
|
217
|
+
isActive: false,
|
|
218
|
+
onBadgeClick: () => {
|
|
219
|
+
expandedClusterId = null;
|
|
220
|
+
render();
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
...memberSpecs
|
|
224
|
+
];
|
|
225
|
+
}
|
|
226
|
+
function render() {
|
|
227
|
+
if (markers.length === 0) {
|
|
228
|
+
lastRenderSignature = null;
|
|
229
|
+
clearAnnotationFrames();
|
|
230
|
+
syncObservers();
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const { resolved, unresolvedIds } = resolveMarkers();
|
|
234
|
+
if (activeMarkerId !== null && unresolvedIds.includes(activeMarkerId)) {
|
|
235
|
+
activeMarkerId = null;
|
|
236
|
+
}
|
|
237
|
+
const signature = [
|
|
238
|
+
resolved.map((entry) => {
|
|
239
|
+
return `${entry.marker.id}:${Math.round(entry.rect.x)},${Math.round(entry.rect.y)}`;
|
|
240
|
+
}).join("|"),
|
|
241
|
+
`active:${activeMarkerId ?? ""}`,
|
|
242
|
+
`expanded:${expandedClusterId ?? ""}`,
|
|
243
|
+
`unresolved:${unresolvedIds.join(",")}`
|
|
244
|
+
].join("#");
|
|
245
|
+
if (signature === lastRenderSignature) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
lastRenderSignature = signature;
|
|
249
|
+
const frames = clusterResolvedMarkers(resolved).flatMap((cluster) => {
|
|
250
|
+
return buildClusterSpecs(cluster);
|
|
251
|
+
});
|
|
252
|
+
showAnnotationFrames({ frames });
|
|
253
|
+
if (setId !== null) {
|
|
254
|
+
postToEditor({
|
|
255
|
+
type: "replo:annotations:unresolved",
|
|
256
|
+
setId,
|
|
257
|
+
ids: unresolvedIds
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
syncObservers();
|
|
261
|
+
}
|
|
262
|
+
function scheduleRemeasure() {
|
|
263
|
+
remeasureFrameId ??= requestAnimationFrame(() => {
|
|
264
|
+
remeasureFrameId = null;
|
|
265
|
+
render();
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function scheduleDebouncedRemeasure() {
|
|
269
|
+
if (remeasureDebounceId !== null) {
|
|
270
|
+
clearTimeout(remeasureDebounceId);
|
|
271
|
+
}
|
|
272
|
+
remeasureDebounceId = setTimeout(scheduleRemeasure, REMEASURE_DEBOUNCE_MS);
|
|
273
|
+
}
|
|
274
|
+
function handleScroll(event) {
|
|
275
|
+
if (event.target !== document) {
|
|
276
|
+
scheduleRemeasure();
|
|
277
|
+
}
|
|
278
|
+
if (activeMarkerId !== null) {
|
|
279
|
+
const id = activeMarkerId;
|
|
280
|
+
activeRectFrameId ??= requestAnimationFrame(() => {
|
|
281
|
+
activeRectFrameId = null;
|
|
282
|
+
const viewportRect = getAnnotationBadgeViewportRect(id);
|
|
283
|
+
if (viewportRect) {
|
|
284
|
+
postToEditor({
|
|
285
|
+
type: "replo:annotations:activeRect",
|
|
286
|
+
id,
|
|
287
|
+
viewportRect
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function syncObservers() {
|
|
294
|
+
const shouldObserve = markers.length > 0;
|
|
295
|
+
if (shouldObserve === observersActive) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
observersActive = shouldObserve;
|
|
299
|
+
if (shouldObserve) {
|
|
300
|
+
window.addEventListener("resize", scheduleRemeasure);
|
|
301
|
+
window.addEventListener("scroll", handleScroll, { capture: true });
|
|
302
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
303
|
+
resizeObserver = new ResizeObserver(scheduleRemeasure);
|
|
304
|
+
resizeObserver.observe(document.body);
|
|
305
|
+
}
|
|
306
|
+
mutationObserver = new MutationObserver((records) => {
|
|
307
|
+
const container = document.getElementById(ANNOTATION_CONTAINER_ID);
|
|
308
|
+
const hasForeignMutation = records.some((record) => {
|
|
309
|
+
return !container || !container.contains(record.target);
|
|
310
|
+
});
|
|
311
|
+
if (hasForeignMutation) {
|
|
312
|
+
scheduleDebouncedRemeasure();
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
mutationObserver.observe(document.body, { childList: true, subtree: true });
|
|
316
|
+
} else {
|
|
317
|
+
window.removeEventListener("resize", scheduleRemeasure);
|
|
318
|
+
window.removeEventListener("scroll", handleScroll, { capture: true });
|
|
319
|
+
resizeObserver?.disconnect();
|
|
320
|
+
resizeObserver = null;
|
|
321
|
+
mutationObserver?.disconnect();
|
|
322
|
+
mutationObserver = null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function handleMessage(event) {
|
|
326
|
+
if (!isAllowedEditorMessage(event)) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const parsed = pageAnnotationsParentMessageSchema.safeParse(event.data);
|
|
330
|
+
if (!parsed.success) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
editorOrigin = event.origin;
|
|
334
|
+
exhaustiveSwitch(parsed.data)({
|
|
335
|
+
"replo:annotations:set": (message) => {
|
|
336
|
+
markers = message.markers;
|
|
337
|
+
setId = message.setId;
|
|
338
|
+
expandedClusterId = null;
|
|
339
|
+
activeMarkerId = null;
|
|
340
|
+
lastRenderSignature = null;
|
|
341
|
+
render();
|
|
342
|
+
},
|
|
343
|
+
"replo:annotations:clear": () => {
|
|
344
|
+
markers = [];
|
|
345
|
+
setId = null;
|
|
346
|
+
expandedClusterId = null;
|
|
347
|
+
activeMarkerId = null;
|
|
348
|
+
render();
|
|
349
|
+
},
|
|
350
|
+
"replo:annotations:requestReady": () => {
|
|
351
|
+
postToEditor({
|
|
352
|
+
type: "replo:annotations:ready",
|
|
353
|
+
protocolVersion: PAGE_ANNOTATIONS_PROTOCOL_VERSION
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
function initAnnotationLayer() {
|
|
359
|
+
if (isInitialized || typeof window === "undefined") {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (window.self === window.top) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
isInitialized = true;
|
|
366
|
+
window.addEventListener("message", handleMessage);
|
|
367
|
+
try {
|
|
368
|
+
const referrerOrigin = new URL(document.referrer).origin;
|
|
369
|
+
if (isAllowedEditorOrigin(referrerOrigin)) {
|
|
370
|
+
window.parent.postMessage(
|
|
371
|
+
{
|
|
372
|
+
type: "replo:annotations:ready",
|
|
373
|
+
protocolVersion: PAGE_ANNOTATIONS_PROTOCOL_VERSION
|
|
374
|
+
},
|
|
375
|
+
referrerOrigin
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
} catch {
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
export {
|
|
382
|
+
initAnnotationLayer
|
|
383
|
+
};
|
|
384
|
+
//# sourceMappingURL=annotationController.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../annotations/annotationController.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * In-iframe annotation controller: consumes declarative marker sets from the\n * editor bridge, resolves selectors against the live DOM, and drives the\n * shared annotation frame renderer. Scroll costs zero JavaScript (frames use\n * page coordinates); re-measure runs only on resize/mutation/container\n * scroll, batched per animation frame. Data-only protocol \u2014 the editor can\n * describe dots, never execute code.\n */\nimport type {\n PageAnnotationMarker,\n PageAnnotationsIframeMessage,\n} from \"schemas/generated/pageAnnotations\";\nimport type { AnnotationFrameSpec } from \"../select-mode/annotationFrames\";\n\nimport { exhaustiveSwitch } from \"replo-utils/lib/misc\";\nimport {\n PAGE_ANNOTATIONS_PROTOCOL_VERSION,\n pageAnnotationsParentMessageSchema,\n} from \"schemas/pageAnnotations\";\n\nimport {\n ANNOTATION_CONTAINER_ID,\n clearAnnotationFrames,\n getAnnotationBadgeViewportRect,\n setActiveAnnotationBadge,\n showAnnotationFrames,\n} from \"../select-mode/annotationFrames\";\nimport { getDocumentScrollOffset } from \"../select-mode/interactions/selectionGeometry\";\nimport { isAllowedEditorMessage, isAllowedEditorOrigin } from \"./bridgeGate\";\n\nconst CLUSTER_DISTANCE_PX = 24;\nconst CLUSTER_FAN_RADIUS_PX = 30;\nconst REMEASURE_DEBOUNCE_MS = 250;\n// Page-wide findings stack in a row near the top-left of the page and scroll\n// with it like any other annotation.\nconst PAGE_TOP_STACK_X_PX = 20;\nconst PAGE_TOP_STACK_Y_PX = 20;\nconst PAGE_TOP_STACK_GAP_PX = 36;\n\n// Replo brand palette (lattice --color-brand-*): the wire enum names stay\n// red/purple/amber but the rendered hues are brand magenta/purple/blue,\n// matching the editor-side dots and cards.\nconst COLOR_HEX: Record<PageAnnotationMarker[\"color\"], string> = {\n red: \"#ef196e\",\n purple: \"#8b32a8\",\n amber: \"#274ae2\",\n};\nconst COLOR_SEVERITY: PageAnnotationMarker[\"color\"][] = [\n \"red\",\n \"purple\",\n \"amber\",\n];\n\ninterface ResolvedMarker {\n marker: PageAnnotationMarker;\n element: Element | null;\n isFixed: boolean;\n rect: { x: number; y: number; width: number; height: number };\n // The editor-assigned wire number, rendered verbatim.\n displayNumber: number;\n}\n\ninterface MarkerCluster {\n id: string;\n centerX: number;\n centerY: number;\n isFixed: boolean;\n members: ResolvedMarker[];\n}\n\nlet isInitialized = false;\nlet editorOrigin: string | null = null;\nlet markers: PageAnnotationMarker[] = [];\nlet setId: string | null = null;\nlet expandedClusterId: string | null = null;\nlet activeMarkerId: string | null = null;\nlet remeasureFrameId: number | null = null;\nlet remeasureDebounceId: ReturnType<typeof setTimeout> | null = null;\nlet activeRectFrameId: number | null = null;\nlet observersActive = false;\nlet lastRenderSignature: string | null = null;\nlet resizeObserver: ResizeObserver | null = null;\nlet mutationObserver: MutationObserver | null = null;\n\nfunction postToEditor(message: PageAnnotationsIframeMessage) {\n if (editorOrigin === null) {\n return;\n }\n window.parent.postMessage(message, editorOrigin);\n}\n\nfunction hasFixedAncestor(element: Element): boolean {\n let current: Element | null = element;\n while (current !== null && current !== document.documentElement) {\n const position = getComputedStyle(current).position;\n if (position === \"fixed\" || position === \"sticky\") {\n return true;\n }\n current = current.parentElement;\n }\n return false;\n}\n\nfunction resolveMarkers(): {\n resolved: ResolvedMarker[];\n unresolvedIds: string[];\n} {\n const resolved: ResolvedMarker[] = [];\n const unresolvedIds: string[] = [];\n let pageTopSlot = 0;\n for (const marker of markers) {\n if (marker.placement === \"pageTop\") {\n // Page-wide finding: a fixed slot in the top-of-page stack, no selector.\n resolved.push({\n marker,\n element: null,\n isFixed: false,\n rect: {\n x: PAGE_TOP_STACK_X_PX + pageTopSlot * PAGE_TOP_STACK_GAP_PX,\n y: PAGE_TOP_STACK_Y_PX,\n width: 0,\n height: 0,\n },\n // The editor owns numbering; rendering the wire number keeps dots in sync with the panel.\n displayNumber: marker.number,\n });\n pageTopSlot += 1;\n continue;\n }\n let element: Element | null = null;\n try {\n element = document.querySelector(marker.selector);\n } catch {\n // Malformed selector \u2014 unresolved, never a throw.\n }\n const domRect = element?.getBoundingClientRect();\n if (!element || !domRect || (domRect.width === 0 && domRect.height === 0)) {\n unresolvedIds.push(marker.id);\n continue;\n }\n const isFixed = hasFixedAncestor(element);\n const scrollOffset = getDocumentScrollOffset();\n resolved.push({\n marker,\n element,\n isFixed,\n // Fixed frames use viewport coords; absolute frames use page coords.\n rect: {\n x: domRect.x + (isFixed ? 0 : scrollOffset.left),\n y: domRect.y + (isFixed ? 0 : scrollOffset.top),\n width: domRect.width,\n height: domRect.height,\n },\n displayNumber: marker.number,\n });\n }\n return { resolved, unresolvedIds };\n}\n\n// Greedy: a marker joins the first cluster whose badge anchor lies within\n// 24px; fixed and absolute markers never co-cluster (their coordinate spaces\n// diverge as soon as the page scrolls).\nfunction clusterResolvedMarkers(resolved: ResolvedMarker[]): MarkerCluster[] {\n const clusters: MarkerCluster[] = [];\n for (const entry of resolved) {\n const centerX = entry.rect.x + entry.rect.width / 2;\n const centerY = entry.rect.y;\n const host = clusters.find((cluster) => {\n return (\n cluster.isFixed === entry.isFixed &&\n Math.hypot(cluster.centerX - centerX, cluster.centerY - centerY) <\n CLUSTER_DISTANCE_PX\n );\n });\n if (host) {\n host.members.push(entry);\n } else {\n clusters.push({\n id: entry.marker.id,\n centerX,\n centerY,\n isFixed: entry.isFixed,\n members: [entry],\n });\n }\n }\n return clusters;\n}\n\nfunction getMostSevereColorHex(members: ResolvedMarker[]): string {\n const color =\n COLOR_SEVERITY.find((candidate) => {\n return members.some((member) => member.marker.color === candidate);\n }) ?? \"amber\";\n return COLOR_HEX[color];\n}\n\nfunction activateMarker(id: string) {\n activeMarkerId = id;\n const viewportRect = getAnnotationBadgeViewportRect(id);\n if (viewportRect) {\n postToEditor({ type: \"replo:annotations:clicked\", id, viewportRect });\n }\n // Style-only: a rebuild here would race the pointer sequence and swallow\n // the very click being handled.\n setActiveAnnotationBadge(id);\n}\n\nfunction buildMemberSpec({\n member,\n badgeCenter,\n}: {\n member: ResolvedMarker;\n badgeCenter: { x: number; y: number };\n}): AnnotationFrameSpec {\n const marker = member.marker;\n return {\n id: marker.id,\n pageRect: member.rect,\n badgeCenter,\n positioning: member.isFixed ? \"fixed\" : \"absolute\",\n colorHex: COLOR_HEX[marker.color],\n badgeLabel: String(member.displayNumber),\n badgeAriaLabel: `Page issue ${member.displayNumber}`,\n isActive: activeMarkerId === marker.id,\n onBadgeClick: () => activateMarker(marker.id),\n };\n}\n\nfunction buildClusterSpecs(cluster: MarkerCluster): AnnotationFrameSpec[] {\n const [only] = cluster.members;\n if (cluster.members.length === 1 && only) {\n return [\n buildMemberSpec({\n member: only,\n badgeCenter: { x: cluster.centerX, y: cluster.centerY },\n }),\n ];\n }\n const hub = {\n x: cluster.centerX,\n y: cluster.centerY,\n width: 0,\n height: 0,\n };\n if (expandedClusterId !== cluster.id) {\n return [\n {\n id: `cluster:${cluster.id}`,\n pageRect: hub,\n badgeCenter: { x: cluster.centerX, y: cluster.centerY },\n positioning: cluster.isFixed ? \"fixed\" : \"absolute\",\n colorHex: getMostSevereColorHex(cluster.members),\n badgeLabel: String(cluster.members.length),\n badgeAriaLabel: `${cluster.members.length} page issues near this element`,\n isActive: false,\n onBadgeClick: () => {\n expandedClusterId = cluster.id;\n render();\n },\n },\n ];\n }\n const memberSpecs = cluster.members.map((member, index) => {\n const angle = (index / cluster.members.length) * 2 * Math.PI - Math.PI / 2;\n return buildMemberSpec({\n member,\n badgeCenter: {\n x: cluster.centerX + Math.cos(angle) * CLUSTER_FAN_RADIUS_PX,\n y: cluster.centerY + Math.sin(angle) * CLUSTER_FAN_RADIUS_PX,\n },\n });\n });\n return [\n {\n id: `cluster:${cluster.id}`,\n pageRect: hub,\n badgeCenter: { x: cluster.centerX, y: cluster.centerY },\n positioning: cluster.isFixed ? \"fixed\" : \"absolute\",\n colorHex: \"#94a3b8\",\n badgeLabel: \"\u00D7\",\n badgeAriaLabel: \"Collapse issue cluster\",\n isActive: false,\n onBadgeClick: () => {\n expandedClusterId = null;\n render();\n },\n },\n ...memberSpecs,\n ];\n}\n\nfunction render() {\n if (markers.length === 0) {\n lastRenderSignature = null;\n clearAnnotationFrames();\n syncObservers();\n return;\n }\n const { resolved, unresolvedIds } = resolveMarkers();\n if (activeMarkerId !== null && unresolvedIds.includes(activeMarkerId)) {\n activeMarkerId = null;\n }\n // Rebuilding the node pool mid-pointer-sequence swallows clicks, so skip\n // renders whose output would be identical to what is already on screen.\n const signature = [\n resolved\n .map((entry) => {\n return `${entry.marker.id}:${Math.round(entry.rect.x)},${Math.round(entry.rect.y)}`;\n })\n .join(\"|\"),\n `active:${activeMarkerId ?? \"\"}`,\n `expanded:${expandedClusterId ?? \"\"}`,\n `unresolved:${unresolvedIds.join(\",\")}`,\n ].join(\"#\");\n if (signature === lastRenderSignature) {\n return;\n }\n lastRenderSignature = signature;\n const frames = clusterResolvedMarkers(resolved).flatMap((cluster) => {\n return buildClusterSpecs(cluster);\n });\n showAnnotationFrames({ frames });\n if (setId !== null) {\n postToEditor({\n type: \"replo:annotations:unresolved\",\n setId,\n ids: unresolvedIds,\n });\n }\n syncObservers();\n}\n\nfunction scheduleRemeasure() {\n remeasureFrameId ??= requestAnimationFrame(() => {\n remeasureFrameId = null;\n render();\n });\n}\n\nfunction scheduleDebouncedRemeasure() {\n if (remeasureDebounceId !== null) {\n clearTimeout(remeasureDebounceId);\n }\n remeasureDebounceId = setTimeout(scheduleRemeasure, REMEASURE_DEBOUNCE_MS);\n}\n\nfunction handleScroll(event: Event) {\n // Document scroll is free for absolute frames; scrolls of inner overflow\n // containers move elements relative to the page, so re-measure everything.\n if (event.target !== document) {\n scheduleRemeasure();\n }\n if (activeMarkerId !== null) {\n const id = activeMarkerId;\n activeRectFrameId ??= requestAnimationFrame(() => {\n activeRectFrameId = null;\n const viewportRect = getAnnotationBadgeViewportRect(id);\n if (viewportRect) {\n postToEditor({\n type: \"replo:annotations:activeRect\",\n id,\n viewportRect,\n });\n }\n });\n }\n}\n\nfunction syncObservers() {\n const shouldObserve = markers.length > 0;\n if (shouldObserve === observersActive) {\n return;\n }\n observersActive = shouldObserve;\n if (shouldObserve) {\n window.addEventListener(\"resize\", scheduleRemeasure);\n window.addEventListener(\"scroll\", handleScroll, { capture: true });\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver = new ResizeObserver(scheduleRemeasure);\n resizeObserver.observe(document.body);\n }\n mutationObserver = new MutationObserver((records) => {\n // Rendering our own frames mutates body's subtree; reacting to that\n // would re-render forever. Only foreign mutations can move elements.\n const container = document.getElementById(ANNOTATION_CONTAINER_ID);\n const hasForeignMutation = records.some((record) => {\n return !container || !container.contains(record.target);\n });\n if (hasForeignMutation) {\n scheduleDebouncedRemeasure();\n }\n });\n mutationObserver.observe(document.body, { childList: true, subtree: true });\n } else {\n window.removeEventListener(\"resize\", scheduleRemeasure);\n window.removeEventListener(\"scroll\", handleScroll, { capture: true });\n resizeObserver?.disconnect();\n resizeObserver = null;\n mutationObserver?.disconnect();\n mutationObserver = null;\n }\n}\n\nfunction handleMessage(event: MessageEvent) {\n // Origin gate BEFORE any parsing \u2014 hostile embedders never reach the schema.\n if (!isAllowedEditorMessage(event)) {\n return;\n }\n const parsed = pageAnnotationsParentMessageSchema.safeParse(event.data);\n if (!parsed.success) {\n return;\n }\n editorOrigin = event.origin;\n exhaustiveSwitch(parsed.data)({\n \"replo:annotations:set\": (message) => {\n markers = message.markers;\n setId = message.setId;\n expandedClusterId = null;\n activeMarkerId = null;\n // A fresh set always paints (and re-posts unresolved), even if geometry\n // happens to match the previous render.\n lastRenderSignature = null;\n render();\n },\n \"replo:annotations:clear\": () => {\n markers = [];\n setId = null;\n expandedClusterId = null;\n activeMarkerId = null;\n render();\n },\n \"replo:annotations:requestReady\": () => {\n postToEditor({\n type: \"replo:annotations:ready\",\n protocolVersion: PAGE_ANNOTATIONS_PROTOCOL_VERSION,\n });\n },\n });\n}\n\nexport function initAnnotationLayer() {\n if (isInitialized || typeof window === \"undefined\") {\n return;\n }\n if (window.self === window.top) {\n return;\n }\n isInitialized = true;\n window.addEventListener(\"message\", handleMessage);\n // Announce on load for iframe-reload cases where the editor isn't polling;\n // the referrer origin is verified against the same allowlist first.\n try {\n const referrerOrigin = new URL(document.referrer).origin;\n if (isAllowedEditorOrigin(referrerOrigin)) {\n window.parent.postMessage(\n {\n type: \"replo:annotations:ready\",\n protocolVersion: PAGE_ANNOTATIONS_PROTOCOL_VERSION,\n },\n referrerOrigin,\n );\n }\n } catch {\n // No usable referrer \u2014 the editor's requestReady polling covers this.\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|