@replohq/sandbox-runtime 1.19.5 → 1.21.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.
Files changed (52) hide show
  1. package/PagePreviewHeightResponder.d.ts +1 -0
  2. package/PagePreviewHeightResponder.js +159 -0
  3. package/_vendor/schemas/comments.d.ts +898 -0
  4. package/_vendor/schemas/commentsOverlayRpc.d.ts +348 -0
  5. package/_vendor/schemas/commentsOverlayRpc.mjs +92 -0
  6. package/_vendor/schemas/generated/comments.d.ts +237 -0
  7. package/_vendor/schemas/generated/commentsOverlayRpc.d.ts +18 -0
  8. package/_vendor/schemas/generated/selectMode.d.ts +3 -1
  9. package/_vendor/schemas/pagePreviewHeight.d.ts +14 -0
  10. package/_vendor/schemas/pagePreviewHeight.mjs +18 -0
  11. package/_vendor/schemas/selectMode.d.ts +113 -0
  12. package/_vendor/schemas/selectMode.mjs +1 -1
  13. package/_vendor/schemas/selectModeIframeRpc.d.ts +226 -0
  14. package/_vendor/schemas/selectModeIframeRpc.mjs +1 -1
  15. package/buildMetadata.js +3 -3
  16. package/chunk-NVOBD46N.mjs +541 -0
  17. package/comments-overlay/CommentsOverlayMount.d.ts +1 -0
  18. package/comments-overlay/CommentsOverlayMount.js +44 -0
  19. package/comments-overlay/LICENSE-THIRD-PARTY.md +45 -0
  20. package/comments-overlay/bridge.d.ts +11 -0
  21. package/comments-overlay/bridge.js +136 -0
  22. package/comments-overlay/capture.d.ts +55 -0
  23. package/comments-overlay/capture.js +250 -0
  24. package/comments-overlay/originGate.d.ts +1 -0
  25. package/comments-overlay/originGate.js +11 -0
  26. package/comments-overlay/overlay.d.ts +52 -0
  27. package/comments-overlay/overlay.js +781 -0
  28. package/comments-overlay/resolve.d.ts +27 -0
  29. package/comments-overlay/resolve.js +201 -0
  30. package/comments-overlay/sourceLookup.d.ts +11 -0
  31. package/comments-overlay/sourceLookup.js +63 -0
  32. package/comments-overlay/textQuote.d.ts +17 -0
  33. package/comments-overlay/textQuote.js +87 -0
  34. package/comments-overlay/vendor/bippy.d.ts +53 -0
  35. package/comments-overlay/vendor/bippy.js +402 -0
  36. package/comments-overlay/vendor/elementAnchors.d.ts +9 -0
  37. package/comments-overlay/vendor/elementAnchors.js +144 -0
  38. package/comments-overlay/vendor/fiberElement.d.ts +21 -0
  39. package/comments-overlay/vendor/fiberElement.js +251 -0
  40. package/comments-overlay/vendor/htmlPreview.d.ts +13 -0
  41. package/comments-overlay/vendor/htmlPreview.js +179 -0
  42. package/comments-overlay/vendor/selector.d.ts +38 -0
  43. package/comments-overlay/vendor/selector.js +372 -0
  44. package/package.json +5 -4
  45. package/pinPreviewViewportUnits.d.ts +4 -0
  46. package/pinPreviewViewportUnits.js +76 -0
  47. package/sandbox-runtime.js +4 -0
  48. package/select-mode/descriptor/elementDescriptor.d.ts +4 -3
  49. package/select-mode/descriptor/elementDescriptor.js +20 -30
  50. package/select-mode/iframeRpcChannel.d.ts +84 -0
  51. package/select-mode/symbolicate.js +25 -7
  52. package/chunk-QTGDSYSU.mjs +0 -249
@@ -0,0 +1,136 @@
1
+ import {
2
+ COMMENTS_OVERLAY_RPC_CHANNEL_ID,
3
+ COMMENTS_OVERLAY_RPC_CHANNEL_VERSION,
4
+ commentsOverlayToHostMethodConfig,
5
+ hostToCommentsOverlayMethodConfig
6
+ } from "../_vendor/schemas/commentsOverlayRpc.mjs";
7
+ import {
8
+ createIframeRpcChannel,
9
+ createIframeRpcRemote
10
+ } from "../_vendor/schemas/iframeRpcChannel.mjs";
11
+ import { symbolicateAnchor } from "./capture";
12
+ import { isAllowedCommentsOverlayOrigin } from "./originGate";
13
+ import { createCommentsOverlay } from "./overlay";
14
+ import { createSymbolicatedSourceLookup } from "./sourceLookup";
15
+ const LOCATION_POLL_MS = 500;
16
+ let stopActiveOverlay = null;
17
+ function startCommentsOverlay({
18
+ symbolicate
19
+ }) {
20
+ if (stopActiveOverlay) {
21
+ return stopActiveOverlay;
22
+ }
23
+ if (typeof window === "undefined" || window.self === window.top) {
24
+ return () => {
25
+ };
26
+ }
27
+ let hostOrigin = null;
28
+ let isAnnouncing = false;
29
+ let hasAnnouncedToVerifiedHost = false;
30
+ let overlay = null;
31
+ const channel = createIframeRpcChannel({
32
+ subscriberWindow: window,
33
+ channelIdentifier: COMMENTS_OVERLAY_RPC_CHANNEL_ID,
34
+ version: COMMENTS_OVERLAY_RPC_CHANNEL_VERSION,
35
+ getTargetWindow: () => {
36
+ if (!hostOrigin && !isAnnouncing) {
37
+ return null;
38
+ }
39
+ return {
40
+ postMessage: (message) => {
41
+ window.parent.postMessage(message, hostOrigin ?? "*");
42
+ }
43
+ };
44
+ },
45
+ targetOrigin: "*",
46
+ isExpectedMessage: (event) => {
47
+ if (event.source !== window.parent || !isAllowedCommentsOverlayOrigin(event.origin)) {
48
+ return false;
49
+ }
50
+ hostOrigin = event.origin;
51
+ return true;
52
+ },
53
+ outgoingMethods: commentsOverlayToHostMethodConfig,
54
+ incomingMethods: hostToCommentsOverlayMethodConfig,
55
+ handlers: {
56
+ setCommentMode: ({ mode }) => {
57
+ announceToVerifiedHost();
58
+ overlay?.setMode(mode);
59
+ },
60
+ setPins: ({ pins }) => {
61
+ announceToVerifiedHost();
62
+ overlay?.setPins(pins);
63
+ },
64
+ focusThread: ({ threadId }) => {
65
+ overlay?.focusThread(threadId);
66
+ },
67
+ clearDraft: () => {
68
+ overlay?.clearDraft();
69
+ },
70
+ setDraftAnchor: ({ anchor }) => {
71
+ overlay?.setDraftAnchor(anchor);
72
+ }
73
+ }
74
+ });
75
+ const host = createIframeRpcRemote(channel);
76
+ function announceToVerifiedHost() {
77
+ if (!hasAnnouncedToVerifiedHost && hostOrigin) {
78
+ hasAnnouncedToVerifiedHost = true;
79
+ host.overlayReady();
80
+ reportLocation({ force: true });
81
+ }
82
+ }
83
+ let reportedLocation = null;
84
+ function reportLocation({ force }) {
85
+ if (!hostOrigin) {
86
+ return;
87
+ }
88
+ const url = `${window.location.pathname}${window.location.search}`.slice(
89
+ 0,
90
+ 2048
91
+ );
92
+ if (!force && url === reportedLocation) {
93
+ return;
94
+ }
95
+ reportedLocation = url;
96
+ host.locationChanged({ url });
97
+ }
98
+ const handlePopState = () => reportLocation({ force: false });
99
+ window.addEventListener("popstate", handlePopState);
100
+ const locationTimer = window.setInterval(
101
+ () => reportLocation({ force: false }),
102
+ LOCATION_POLL_MS
103
+ );
104
+ overlay = createCommentsOverlay({
105
+ prepareAnchor: (anchor) => symbolicateAnchor(anchor, symbolicate),
106
+ getSource: createSymbolicatedSourceLookup({
107
+ symbolicate,
108
+ onUpdate: () => overlay?.refresh()
109
+ }),
110
+ onAnchorPicked: (input) => host.anchorPicked(input),
111
+ onPinClicked: (input) => host.pinClicked(input),
112
+ onAnchorStatuses: (input) => host.anchorStatuses(input),
113
+ onComposeFromSelection: (input) => host.requestComposeFromSelection(input),
114
+ onPickCancelled: () => host.pickCancelled(),
115
+ onModeShortcut: (input) => host.modeShortcut(input)
116
+ });
117
+ const unsubscribe = channel.subscribe();
118
+ isAnnouncing = true;
119
+ try {
120
+ host.overlayReady();
121
+ } finally {
122
+ isAnnouncing = false;
123
+ }
124
+ stopActiveOverlay = () => {
125
+ window.removeEventListener("popstate", handlePopState);
126
+ window.clearInterval(locationTimer);
127
+ unsubscribe();
128
+ overlay?.destroy();
129
+ overlay = null;
130
+ stopActiveOverlay = null;
131
+ };
132
+ return stopActiveOverlay;
133
+ }
134
+ export {
135
+ startCommentsOverlay
136
+ };
@@ -0,0 +1,55 @@
1
+ import type { CommentAnchorElement } from "../_vendor/schemas/generated/comments";
2
+ export type SourceLocation = {
3
+ filePath: string;
4
+ line?: number;
5
+ col?: number;
6
+ };
7
+ /** Maps compiled locations to original files; returns them unchanged when it can't. */
8
+ export type SourceSymbolicator = (locations: SourceLocation[]) => Promise<SourceLocation[]>;
9
+ export type ElementSource = SourceLocation & {
10
+ componentChain: string[];
11
+ };
12
+ /**
13
+ * Joins an anchor's per-root selector segments for an element inside open
14
+ * shadow roots: the outermost host's selector in the document, then each
15
+ * nested host's (or the element's) selector within the previous shadow root.
16
+ * `>>>` is not valid CSS, so a light-DOM selector never contains it.
17
+ */
18
+ export declare const SHADOW_SELECTOR_DELIMITER = " >>> ";
19
+ /**
20
+ * The structural `tag:nth-of-type` path from the element up to the nearest
21
+ * ancestor with an id (or the root). Select mode uses it as its selector.
22
+ */
23
+ export declare function buildNthOfTypePath(element: Element): string;
24
+ /**
25
+ * Compiled source of the JSX that rendered `element` (its own `_debugStack`,
26
+ * else its owner component's), plus the owner component names. Null outside
27
+ * React dev builds.
28
+ */
29
+ export declare function getElementSource(element: Element): ElementSource | null;
30
+ /**
31
+ * Visible text used for similarity tie-breaks; the HTML preview when there is
32
+ * none. Inside a shadow root it includes nested shadow roots' text.
33
+ */
34
+ export declare function getTextPreview(element: Element): string;
35
+ /** The element an anchor for this click target or selection describes. */
36
+ export declare function getAnchorElement(target: Element | Range): Element | null;
37
+ /**
38
+ * Builds an element anchor (D-13) for a clicked element or a text selection.
39
+ * The selection's quote keeps 80 characters of context on each side within
40
+ * the anchored element; `offset` is `point` as a fraction of its rect.
41
+ */
42
+ export declare function captureAnchor(target: Element | Range, point: {
43
+ x: number;
44
+ y: number;
45
+ }): CommentAnchorElement;
46
+ /** Anchors exactly `element`; select mode has already chosen it. */
47
+ export declare function captureElementAnchor(element: Element, point: {
48
+ x: number;
49
+ y: number;
50
+ }): CommentAnchorElement;
51
+ /**
52
+ * Swaps the anchor's compiled source location for the original file and line
53
+ * through `symbolicate` (Next's dev endpoint in the sandbox runtime).
54
+ */
55
+ export declare function symbolicateAnchor(anchor: CommentAnchorElement, symbolicate: SourceSymbolicator): Promise<CommentAnchorElement>;
@@ -0,0 +1,250 @@
1
+ import { captureQuote } from "./textQuote";
2
+ import { getFiberFromHostInstance, getFiberSource } from "./vendor/bippy";
3
+ import { trackElementAnchor } from "./vendor/elementAnchors";
4
+ import {
5
+ findNearestFiberElement,
6
+ findNearestListItemKey,
7
+ getComponentChain,
8
+ getElementFiber,
9
+ getNearestOwnerFiber,
10
+ normalizeFilePath
11
+ } from "./vendor/fiberElement";
12
+ import { getInlineHTMLPreview } from "./vendor/htmlPreview";
13
+ import {
14
+ buildRelativeNthOfTypePath,
15
+ createNthChildSelector,
16
+ createNearestSemanticSelector,
17
+ createSemanticSelector,
18
+ findUniqueSelector
19
+ } from "./vendor/selector";
20
+ const TEXT_PREVIEW_MAX_CHARS = 200;
21
+ const SHADOW_SELECTOR_DELIMITER = " >>> ";
22
+ const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
23
+ class AnchorTargetError extends Error {
24
+ constructor() {
25
+ super("captureAnchor: the selection is not inside an element");
26
+ }
27
+ }
28
+ function isShadowRoot(node) {
29
+ return typeof ShadowRoot !== "undefined" && node instanceof ShadowRoot;
30
+ }
31
+ function getShadowPath(element) {
32
+ const path = [element];
33
+ for (let root = element.getRootNode(); isShadowRoot(root); root = root.host.getRootNode()) {
34
+ path.unshift(root.host);
35
+ }
36
+ return path;
37
+ }
38
+ function isElement(target) {
39
+ return "tagName" in target;
40
+ }
41
+ function buildNthOfTypePath(element) {
42
+ return getShadowPath(element).map(buildRootNthOfTypePath).join(SHADOW_SELECTOR_DELIMITER);
43
+ }
44
+ function buildRootNthOfTypePath(element) {
45
+ const root = isShadowRoot(element.getRootNode()) ? null : element.ownerDocument.documentElement;
46
+ let idAncestor = element;
47
+ while (idAncestor && idAncestor !== root && !idAncestor.id) {
48
+ idAncestor = idAncestor.parentElement;
49
+ }
50
+ const path = buildRelativeNthOfTypePath(idAncestor ?? root, element);
51
+ if (!idAncestor?.id || idAncestor === root) {
52
+ return path;
53
+ }
54
+ const id = `#${CSS.escape(idAncestor.id)}`;
55
+ return path ? `${id} > ${path}` : id;
56
+ }
57
+ function findFiberElementInRoot(element) {
58
+ for (let current = element; current; current = current.parentElement) {
59
+ if (getFiberFromHostInstance(current)) {
60
+ return current;
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+ function climbOutOfSvg(element) {
66
+ let current = element;
67
+ while (current.namespaceURI === SVG_NAMESPACE) {
68
+ const parentNode = current.parentNode;
69
+ const parent = current.parentElement ?? (parentNode && isShadowRoot(parentNode) ? parentNode.host : null);
70
+ if (!parent) {
71
+ break;
72
+ }
73
+ current = parent;
74
+ }
75
+ return current;
76
+ }
77
+ function snapToAnchorElement(element) {
78
+ let current = element;
79
+ for (let root = current.getRootNode(); isShadowRoot(root); root = current.getRootNode()) {
80
+ current = climbOutOfSvg(current);
81
+ if (current.getRootNode() !== root) {
82
+ continue;
83
+ }
84
+ const fiberElement = findFiberElementInRoot(current);
85
+ if (fiberElement) {
86
+ return fiberElement;
87
+ }
88
+ current = root.host;
89
+ }
90
+ return findNearestFiberElement(current);
91
+ }
92
+ function getElementSource(element) {
93
+ const fiber = getElementFiber(element);
94
+ if (!fiber) {
95
+ return null;
96
+ }
97
+ const owner = getNearestOwnerFiber(fiber);
98
+ const source = getFiberSource(fiber) ?? (owner ? getFiberSource(owner) : null);
99
+ if (!source?.fileName) {
100
+ return null;
101
+ }
102
+ return {
103
+ filePath: source.fileName,
104
+ line: source.lineNumber,
105
+ col: source.columnNumber,
106
+ componentChain: getComponentChain(fiber)
107
+ };
108
+ }
109
+ function collapseWhitespace(text) {
110
+ return text.replace(/\s+/g, " ").trim();
111
+ }
112
+ function getComposedText(node, maxChars) {
113
+ if (node.nodeType === Node.TEXT_NODE) {
114
+ return (node.textContent ?? "").slice(0, maxChars);
115
+ }
116
+ let text = "";
117
+ const shadowRoot = node instanceof Element ? node.shadowRoot : null;
118
+ for (const child of [
119
+ ...shadowRoot ? Array.from(shadowRoot.childNodes) : [],
120
+ ...Array.from(node.childNodes)
121
+ ]) {
122
+ if (text.length >= maxChars) {
123
+ break;
124
+ }
125
+ if (child instanceof Element && child.matches("style, script")) {
126
+ continue;
127
+ }
128
+ text += getComposedText(child, maxChars - text.length);
129
+ }
130
+ return text;
131
+ }
132
+ function getTextPreview(element) {
133
+ const maxChars = TEXT_PREVIEW_MAX_CHARS * 10;
134
+ const text = collapseWhitespace(
135
+ isShadowRoot(element.getRootNode()) ? getComposedText(element, maxChars) : (element.textContent ?? "").slice(0, maxChars)
136
+ );
137
+ return (text || getInlineHTMLPreview(element)).slice(
138
+ 0,
139
+ TEXT_PREVIEW_MAX_CHARS
140
+ );
141
+ }
142
+ function clampUnit(value) {
143
+ return Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : 0.5;
144
+ }
145
+ function rangeContainer(range) {
146
+ const node = range.commonAncestorContainer;
147
+ return node instanceof Element ? node : node.parentElement;
148
+ }
149
+ function createAnchorSelectors(element) {
150
+ const path = getShadowPath(element);
151
+ if (path.length === 1) {
152
+ return createRootAnchorSelectors(element);
153
+ }
154
+ const segments = path.map(createRootAnchorSelectors);
155
+ const target = segments.at(-1);
156
+ const semanticSegments = segments.map((segment) => {
157
+ return segment === target ? segment.semanticSelector : segment.semanticSelector ?? segment.selector;
158
+ });
159
+ return {
160
+ semanticSelector: semanticSegments.every(Boolean) ? semanticSegments.join(SHADOW_SELECTOR_DELIMITER) : null,
161
+ selector: segments.map((segment) => segment.selector).join(SHADOW_SELECTOR_DELIMITER)
162
+ };
163
+ }
164
+ function createRootAnchorSelectors(element) {
165
+ const ownSemanticSelector = createSemanticSelector(element);
166
+ return {
167
+ semanticSelector: ownSemanticSelector ?? createNearestSemanticSelector(element),
168
+ selector: ownSemanticSelector ?? findUniqueSelector(element) ?? createNthChildSelector(element)
169
+ };
170
+ }
171
+ function getAnchorElement(target) {
172
+ const picked = isElement(target) ? target : rangeContainer(target);
173
+ return picked ? snapToAnchorElement(picked) : null;
174
+ }
175
+ function captureAnchor(target, point) {
176
+ const element = getAnchorElement(target);
177
+ if (!element) {
178
+ throw new AnchorTargetError();
179
+ }
180
+ return buildAnchor({ target, element, point });
181
+ }
182
+ function captureElementAnchor(element, point) {
183
+ return buildAnchor({ target: element, element, point });
184
+ }
185
+ function buildAnchor({
186
+ target,
187
+ element,
188
+ point
189
+ }) {
190
+ trackElementAnchor(element);
191
+ const { semanticSelector, selector } = createAnchorSelectors(element);
192
+ const quote = isElement(target) ? null : captureQuote(target, element);
193
+ const source = getElementSource(element);
194
+ const fiber = getElementFiber(element);
195
+ const listKey = fiber ? findNearestListItemKey(fiber) : null;
196
+ const rect = element.getBoundingClientRect();
197
+ return {
198
+ type: "element",
199
+ ...semanticSelector ? { semanticSelector } : {},
200
+ selector,
201
+ nthOfTypePath: buildNthOfTypePath(element),
202
+ ...source ? {
203
+ source: {
204
+ filePath: source.filePath,
205
+ componentChain: source.componentChain,
206
+ ...source.line === void 0 ? {} : { line: source.line },
207
+ ...source.col === void 0 ? {} : { col: source.col }
208
+ }
209
+ } : {},
210
+ ...listKey ? { listKey } : {},
211
+ tagName: element.tagName.toLowerCase(),
212
+ textPreview: getTextPreview(element),
213
+ ...quote ? { quote } : {},
214
+ offset: {
215
+ x: clampUnit((point.x - rect.left) / rect.width),
216
+ y: clampUnit((point.y - rect.top) / rect.height)
217
+ }
218
+ };
219
+ }
220
+ async function symbolicateAnchor(anchor, symbolicate) {
221
+ const source = anchor.source;
222
+ if (!source) {
223
+ return anchor;
224
+ }
225
+ const [resolved] = await symbolicate([
226
+ { filePath: source.filePath, line: source.line, col: source.col }
227
+ ]);
228
+ if (!resolved) {
229
+ return anchor;
230
+ }
231
+ return {
232
+ ...anchor,
233
+ source: {
234
+ filePath: normalizeFilePath(resolved.filePath),
235
+ componentChain: source.componentChain,
236
+ ...resolved.line === void 0 ? {} : { line: resolved.line },
237
+ ...resolved.col === void 0 ? {} : { col: resolved.col }
238
+ }
239
+ };
240
+ }
241
+ export {
242
+ SHADOW_SELECTOR_DELIMITER,
243
+ buildNthOfTypePath,
244
+ captureAnchor,
245
+ captureElementAnchor,
246
+ getAnchorElement,
247
+ getElementSource,
248
+ getTextPreview,
249
+ symbolicateAnchor
250
+ };
@@ -0,0 +1 @@
1
+ export declare function isAllowedCommentsOverlayOrigin(origin: string): boolean;
@@ -0,0 +1,11 @@
1
+ import { isAllowedEditorOrigin } from "../annotations/bridgeGate";
2
+ const ARTIFACT_CONTENT_ORIGIN_PATTERNS = [
3
+ /^https:\/\/[a-z0-9-]+\.artifacts(?:-staging)?\.replousercontent\.com$/u,
4
+ /^http:\/\/[a-z0-9-]+\.artifacts\.localhost(?::\d+)?$/u
5
+ ];
6
+ function isAllowedCommentsOverlayOrigin(origin) {
7
+ return isAllowedEditorOrigin(origin) || ARTIFACT_CONTENT_ORIGIN_PATTERNS.some((pattern) => pattern.test(origin));
8
+ }
9
+ export {
10
+ isAllowedCommentsOverlayOrigin
11
+ };
@@ -0,0 +1,52 @@
1
+ import type { CommentAnchor, CommentAnchorElement } from "../_vendor/schemas/generated/comments";
2
+ import type { CommentOverlayAnchorStatus, CommentOverlayPin, CommentOverlayRect } from "../_vendor/schemas/generated/commentsOverlayRpc";
3
+ import type { DisplayMode } from "../_vendor/schemas/generated/selectMode";
4
+ import type { ElementSource } from "./capture";
5
+ export declare const OVERLAY_Z_INDEX = 2147483645;
6
+ export declare const HIGHLIGHT_BACKGROUND = "rgba(250, 204, 21, 0.28)";
7
+ export declare const BADGE_SIZE_PX = 20;
8
+ export declare const RERESOLVE_DEBOUNCE_MS = 250;
9
+ export type CommentsOverlayCallbacks = {
10
+ onAnchorPicked: (input: {
11
+ anchor: CommentAnchorElement;
12
+ rect: CommentOverlayRect;
13
+ }) => void;
14
+ onPinClicked: (input: {
15
+ threadId: string;
16
+ }) => void;
17
+ onAnchorStatuses: (input: {
18
+ statuses: CommentOverlayAnchorStatus[];
19
+ }) => void;
20
+ onComposeFromSelection: (input: {
21
+ anchor: CommentAnchorElement;
22
+ }) => void;
23
+ onPickCancelled: () => void;
24
+ /** C or Esc pressed in the frame; the host owns the mode. */
25
+ onModeShortcut: (input: {
26
+ mode: "browse" | "comment";
27
+ }) => void;
28
+ };
29
+ type CommentsOverlayOptions = CommentsOverlayCallbacks & {
30
+ /** Async finishing step for a captured anchor, e.g. source symbolication. */
31
+ prepareAnchor: ((anchor: CommentAnchorElement) => Promise<CommentAnchorElement>) | null;
32
+ /** Candidate source lookup for the resolver; null uses the live fiber source. */
33
+ getSource: ((element: Element) => ElementSource | null) | null;
34
+ };
35
+ export type CommentsOverlay = {
36
+ setMode: (mode: DisplayMode) => void;
37
+ setPins: (pins: CommentOverlayPin[]) => void;
38
+ focusThread: (threadId: string) => void;
39
+ clearDraft: () => void;
40
+ setDraftAnchor: (anchor: CommentAnchor | null) => void;
41
+ /** Re-resolves every anchor now, e.g. after symbolication results arrive. */
42
+ refresh: () => void;
43
+ destroy: () => void;
44
+ };
45
+ /**
46
+ * The in-page half of commenting (D-28): resolves anchors, draws highlights
47
+ * and comment markers, outlines and picks elements in comment mode, and offers
48
+ * a "Comment" pill on text selections. It knows thread IDs, anchors and counts
49
+ * only; the host draws every piece of comment content.
50
+ */
51
+ export declare function createCommentsOverlay(options: CommentsOverlayOptions): CommentsOverlay;
52
+ export {};