@mikuexe/annotator-react 0.1.0 → 0.2.1
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/CHANGELOG.md +25 -0
- package/README.md +69 -27
- package/dist/index.cjs +553 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -6
- package/dist/index.d.ts +18 -6
- package/dist/index.js +551 -110
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/dist/index.js
CHANGED
|
@@ -10,13 +10,18 @@ var MAX_TEXT_LENGTH = 240;
|
|
|
10
10
|
var MAX_HTML_LENGTH = 640;
|
|
11
11
|
var MAX_SELECTOR_DEPTH = 6;
|
|
12
12
|
async function captureElementAnnotation(element, note, id = createAnnotationId()) {
|
|
13
|
+
return {
|
|
14
|
+
id,
|
|
15
|
+
note,
|
|
16
|
+
targets: [await captureAnnotationTarget(element)]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async function captureAnnotationTarget(element) {
|
|
13
20
|
const elementInfo = await safeResolveElementInfo(element);
|
|
14
21
|
const source = normalizeSource(elementInfo?.source, elementInfo?.componentName);
|
|
15
22
|
const sourceStack = normalizeSourceStack(elementInfo?.stack, source);
|
|
16
23
|
const componentPath = getComponentPath(sourceStack, source);
|
|
17
24
|
return {
|
|
18
|
-
id,
|
|
19
|
-
note,
|
|
20
25
|
source,
|
|
21
26
|
sourceStack,
|
|
22
27
|
componentPath,
|
|
@@ -170,10 +175,19 @@ async function copyTextToClipboard(text) {
|
|
|
170
175
|
|
|
171
176
|
// src/format.ts
|
|
172
177
|
var TASK_FRAMING = "Please update the UI based on these source-linked annotations.";
|
|
173
|
-
function createAnnotationCollection(annotations) {
|
|
178
|
+
function createAnnotationCollection(annotations, page = getPageContext()) {
|
|
174
179
|
return {
|
|
175
180
|
annotations,
|
|
176
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
181
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
182
|
+
page
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function getPageContext(targetDocument) {
|
|
186
|
+
const activeDocument = targetDocument ?? (typeof document === "undefined" ? null : document);
|
|
187
|
+
const location = activeDocument?.location;
|
|
188
|
+
return {
|
|
189
|
+
domain: location?.hostname ?? "",
|
|
190
|
+
path: location?.pathname ?? ""
|
|
177
191
|
};
|
|
178
192
|
}
|
|
179
193
|
function formatAnnotationCollection(collection, output = "markdown") {
|
|
@@ -193,43 +207,28 @@ ${formatJson(collection)}
|
|
|
193
207
|
\`\`\``;
|
|
194
208
|
}
|
|
195
209
|
function formatMarkdown(collection) {
|
|
196
|
-
const lines = [
|
|
210
|
+
const lines = [
|
|
211
|
+
TASK_FRAMING,
|
|
212
|
+
"",
|
|
213
|
+
`Collected at: ${collection.createdAt}`,
|
|
214
|
+
`Domain: ${collection.page.domain}`,
|
|
215
|
+
`Path: ${collection.page.path}`,
|
|
216
|
+
""
|
|
217
|
+
];
|
|
197
218
|
if (collection.annotations.length === 0) {
|
|
198
219
|
lines.push("No annotations were collected.");
|
|
199
220
|
return lines.join("\n");
|
|
200
221
|
}
|
|
201
222
|
collection.annotations.forEach((annotation, index) => {
|
|
202
|
-
const source = formatSource(annotation);
|
|
203
|
-
const sourceStack = formatSourceStack(annotation);
|
|
204
|
-
const nearestComponent = annotation.source?.componentName;
|
|
205
|
-
const ownerPath = annotation.componentPath.join(" \u203A ");
|
|
206
223
|
lines.push(`## Annotation ${index + 1}`);
|
|
207
224
|
lines.push("");
|
|
208
225
|
lines.push(`ID: ${annotation.id}`);
|
|
209
226
|
lines.push(`Note: ${annotation.note || "(no note provided)"}`);
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
if (ownerPath && ownerPath !== nearestComponent) {
|
|
217
|
-
lines.push(`React owner path: ${ownerPath}`);
|
|
218
|
-
}
|
|
219
|
-
if (sourceStack.length) {
|
|
220
|
-
lines.push("React source stack:");
|
|
221
|
-
sourceStack.forEach((frame) => lines.push(`- ${frame}`));
|
|
222
|
-
}
|
|
223
|
-
lines.push(`Element tag: ${annotation.element.tagName}`);
|
|
224
|
-
if (annotation.element.html) {
|
|
225
|
-
lines.push(`Element HTML: ${annotation.element.html}`);
|
|
226
|
-
}
|
|
227
|
-
if (annotation.element.text) {
|
|
228
|
-
lines.push(`Element text: ${annotation.element.text}`);
|
|
229
|
-
}
|
|
230
|
-
if (annotation.element.selector) {
|
|
231
|
-
lines.push(`Selector: ${annotation.element.selector}`);
|
|
232
|
-
}
|
|
227
|
+
annotation.targets.forEach((target, targetIndex) => {
|
|
228
|
+
const isSingleTarget = annotation.targets.length === 1;
|
|
229
|
+
const label = isSingleTarget ? "" : `Target ${targetIndex + 1} `;
|
|
230
|
+
appendTargetMarkdown(lines, target, label);
|
|
231
|
+
});
|
|
233
232
|
lines.push("");
|
|
234
233
|
});
|
|
235
234
|
return lines.join("\n").trimEnd();
|
|
@@ -237,8 +236,37 @@ function formatMarkdown(collection) {
|
|
|
237
236
|
function formatJson(collection) {
|
|
238
237
|
return JSON.stringify(collection, null, 2);
|
|
239
238
|
}
|
|
240
|
-
function
|
|
241
|
-
const source =
|
|
239
|
+
function appendTargetMarkdown(lines, target, label) {
|
|
240
|
+
const source = formatSource(target);
|
|
241
|
+
const sourceStack = formatSourceStack(target);
|
|
242
|
+
const nearestComponent = target.source?.componentName;
|
|
243
|
+
const ownerPath = target.componentPath.join(" \u203A ");
|
|
244
|
+
if (source) {
|
|
245
|
+
lines.push(`${label}Source: ${source}`);
|
|
246
|
+
}
|
|
247
|
+
if (nearestComponent) {
|
|
248
|
+
lines.push(`${label}Nearest React component: ${nearestComponent}`);
|
|
249
|
+
}
|
|
250
|
+
if (ownerPath && ownerPath !== nearestComponent) {
|
|
251
|
+
lines.push(`${label}React owner path: ${ownerPath}`);
|
|
252
|
+
}
|
|
253
|
+
if (sourceStack.length) {
|
|
254
|
+
lines.push(`${label}React source stack:`);
|
|
255
|
+
sourceStack.forEach((frame) => lines.push(`- ${frame}`));
|
|
256
|
+
}
|
|
257
|
+
lines.push(`${label}Element tag: ${target.element.tagName}`);
|
|
258
|
+
if (target.element.html) {
|
|
259
|
+
lines.push(`${label}Element HTML: ${target.element.html}`);
|
|
260
|
+
}
|
|
261
|
+
if (target.element.text) {
|
|
262
|
+
lines.push(`${label}Element text: ${target.element.text}`);
|
|
263
|
+
}
|
|
264
|
+
if (target.element.selector) {
|
|
265
|
+
lines.push(`${label}Selector: ${target.element.selector}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function formatSource(target) {
|
|
269
|
+
const source = target.source;
|
|
242
270
|
if (!source?.filePath) {
|
|
243
271
|
return "";
|
|
244
272
|
}
|
|
@@ -246,8 +274,8 @@ function formatSource(annotation) {
|
|
|
246
274
|
const column = source.columnNumber ? `:${source.columnNumber}` : "";
|
|
247
275
|
return `${source.filePath}${line}${column}`;
|
|
248
276
|
}
|
|
249
|
-
function formatSourceStack(
|
|
250
|
-
return
|
|
277
|
+
function formatSourceStack(target) {
|
|
278
|
+
return target.sourceStack.map((frame) => {
|
|
251
279
|
const location = formatSourceFrame(frame);
|
|
252
280
|
const component = frame.componentName ? ` (${frame.componentName})` : "";
|
|
253
281
|
return location ? `${location}${component}` : frame.componentName || "";
|
|
@@ -267,10 +295,22 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
267
295
|
var ROOT_ATTR = "data-mikuexe-annotator-root";
|
|
268
296
|
var DEFAULT_HOTKEY = "alt+a";
|
|
269
297
|
var DEFAULT_OUTPUT = "markdown";
|
|
298
|
+
var BLOCKED_INTERACTION_EVENTS = [
|
|
299
|
+
"pointerdown",
|
|
300
|
+
"pointerup",
|
|
301
|
+
"mousedown",
|
|
302
|
+
"mouseup",
|
|
303
|
+
"dblclick",
|
|
304
|
+
"auxclick",
|
|
305
|
+
"contextmenu",
|
|
306
|
+
"touchstart",
|
|
307
|
+
"touchend"
|
|
308
|
+
];
|
|
270
309
|
function SourceAnnotator({
|
|
271
310
|
enabled = true,
|
|
272
311
|
hotkey = DEFAULT_HOTKEY,
|
|
273
312
|
output = DEFAULT_OUTPUT,
|
|
313
|
+
target,
|
|
274
314
|
onCollect,
|
|
275
315
|
renderToaster = true
|
|
276
316
|
}) {
|
|
@@ -279,17 +319,41 @@ function SourceAnnotator({
|
|
|
279
319
|
const [selected, setSelected] = useState(null);
|
|
280
320
|
const [note, setNote] = useState("");
|
|
281
321
|
const [annotations, setAnnotations] = useState([]);
|
|
322
|
+
const [previewedAnnotation, setPreviewedAnnotation] = useState(null);
|
|
282
323
|
const [status, setStatus] = useState(null);
|
|
324
|
+
const [linkingAnnotationId, setLinkingAnnotationId] = useState(null);
|
|
283
325
|
const selectedRef = useRef(null);
|
|
326
|
+
const resolvedTarget = useResolvedTarget(target);
|
|
284
327
|
selectedRef.current = selected;
|
|
285
|
-
|
|
286
|
-
()
|
|
287
|
-
|
|
288
|
-
|
|
328
|
+
useEffect(() => {
|
|
329
|
+
setHoverRect(null);
|
|
330
|
+
setSelected(null);
|
|
331
|
+
setAnnotations([]);
|
|
332
|
+
setPreviewedAnnotation(null);
|
|
333
|
+
setNote("");
|
|
334
|
+
setStatus(null);
|
|
335
|
+
setLinkingAnnotationId(null);
|
|
336
|
+
}, [resolvedTarget.document, resolvedTarget.frameElement]);
|
|
289
337
|
const refreshTrackedRects = useCallback(() => {
|
|
290
338
|
setHoverRect(null);
|
|
291
|
-
setSelected(
|
|
292
|
-
|
|
339
|
+
setSelected(
|
|
340
|
+
(current) => current ? {
|
|
341
|
+
...current,
|
|
342
|
+
targets: current.targets.map((targetEntry) => ({
|
|
343
|
+
...targetEntry,
|
|
344
|
+
rect: getRect(targetEntry.element, targetEntry.frameElement)
|
|
345
|
+
}))
|
|
346
|
+
} : current
|
|
347
|
+
);
|
|
348
|
+
setAnnotations(
|
|
349
|
+
(existing) => existing.map((annotation) => ({
|
|
350
|
+
...annotation,
|
|
351
|
+
targets: annotation.targets.map((targetEntry) => ({
|
|
352
|
+
...targetEntry,
|
|
353
|
+
rect: getRect(targetEntry.targetElement, targetEntry.frameElement)
|
|
354
|
+
}))
|
|
355
|
+
}))
|
|
356
|
+
);
|
|
293
357
|
}, []);
|
|
294
358
|
useEffect(() => {
|
|
295
359
|
if (!enabled) {
|
|
@@ -304,67 +368,209 @@ function SourceAnnotator({
|
|
|
304
368
|
event.preventDefault();
|
|
305
369
|
setIsAnnotating((current) => enabled && !current);
|
|
306
370
|
};
|
|
371
|
+
if (typeof document === "undefined") {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
307
374
|
document.addEventListener("keydown", onKeyDown);
|
|
308
|
-
|
|
309
|
-
|
|
375
|
+
if (resolvedTarget.document && resolvedTarget.document !== document) {
|
|
376
|
+
resolvedTarget.document.addEventListener("keydown", onKeyDown);
|
|
377
|
+
}
|
|
378
|
+
return () => {
|
|
379
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
380
|
+
if (resolvedTarget.document && resolvedTarget.document !== document) {
|
|
381
|
+
resolvedTarget.document.removeEventListener("keydown", onKeyDown);
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
}, [enabled, hotkey, resolvedTarget.document]);
|
|
385
|
+
const handleElementSelection = useCallback(
|
|
386
|
+
async (eventTarget, frameElement, extendSelection) => {
|
|
387
|
+
if (linkingAnnotationId) {
|
|
388
|
+
const rect2 = getRect(eventTarget, frameElement);
|
|
389
|
+
setStatus("Resolving linked element\u2026");
|
|
390
|
+
try {
|
|
391
|
+
const targetData = await captureAnnotationTarget(eventTarget);
|
|
392
|
+
setAnnotations(
|
|
393
|
+
(existing) => existing.map((annotation) => {
|
|
394
|
+
if (annotation.id !== linkingAnnotationId) {
|
|
395
|
+
return annotation;
|
|
396
|
+
}
|
|
397
|
+
if (annotation.targets.some((targetEntry) => targetEntry.targetElement === eventTarget)) {
|
|
398
|
+
return annotation;
|
|
399
|
+
}
|
|
400
|
+
return {
|
|
401
|
+
...annotation,
|
|
402
|
+
targets: [
|
|
403
|
+
...annotation.targets,
|
|
404
|
+
{
|
|
405
|
+
targetElement: eventTarget,
|
|
406
|
+
rect: rect2,
|
|
407
|
+
frameElement,
|
|
408
|
+
data: targetData
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
};
|
|
412
|
+
})
|
|
413
|
+
);
|
|
414
|
+
setLinkingAnnotationId(null);
|
|
415
|
+
setPreviewedAnnotation(null);
|
|
416
|
+
setStatus("Element linked to annotation.");
|
|
417
|
+
} catch {
|
|
418
|
+
setStatus("Element linked without source info.");
|
|
419
|
+
setAnnotations(
|
|
420
|
+
(existing) => existing.map((annotation) => {
|
|
421
|
+
if (annotation.id !== linkingAnnotationId) {
|
|
422
|
+
return annotation;
|
|
423
|
+
}
|
|
424
|
+
if (annotation.targets.some((targetEntry) => targetEntry.targetElement === eventTarget)) {
|
|
425
|
+
return annotation;
|
|
426
|
+
}
|
|
427
|
+
return {
|
|
428
|
+
...annotation,
|
|
429
|
+
targets: [
|
|
430
|
+
...annotation.targets,
|
|
431
|
+
{
|
|
432
|
+
targetElement: eventTarget,
|
|
433
|
+
rect: rect2,
|
|
434
|
+
frameElement,
|
|
435
|
+
data: {
|
|
436
|
+
source: null,
|
|
437
|
+
sourceStack: [],
|
|
438
|
+
componentPath: [],
|
|
439
|
+
element: {
|
|
440
|
+
tagName: eventTarget.tagName.toLowerCase(),
|
|
441
|
+
text: eventTarget.textContent?.trim() ?? "",
|
|
442
|
+
html: "",
|
|
443
|
+
selector: ""
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
]
|
|
448
|
+
};
|
|
449
|
+
})
|
|
450
|
+
);
|
|
451
|
+
setLinkingAnnotationId(null);
|
|
452
|
+
}
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
const rect = getRect(eventTarget, frameElement);
|
|
456
|
+
const shouldAppend = extendSelection && Boolean(selectedRef.current) && !selectedRef.current?.editingId;
|
|
457
|
+
setSelected((current) => {
|
|
458
|
+
if (shouldAppend && current) {
|
|
459
|
+
if (current.targets.some((targetEntry) => targetEntry.element === eventTarget)) {
|
|
460
|
+
return current;
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
...current,
|
|
464
|
+
targets: [...current.targets, { element: eventTarget, rect, frameElement, target: null, loading: true }]
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
targets: [{ element: eventTarget, rect, frameElement, target: null, loading: true }]
|
|
469
|
+
};
|
|
470
|
+
});
|
|
471
|
+
if (!shouldAppend) {
|
|
472
|
+
setNote("");
|
|
473
|
+
}
|
|
474
|
+
setStatus("Resolving source\u2026");
|
|
475
|
+
try {
|
|
476
|
+
const targetData = await captureAnnotationTarget(eventTarget);
|
|
477
|
+
setSelected((current) => {
|
|
478
|
+
if (!current) {
|
|
479
|
+
return current;
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
...current,
|
|
483
|
+
targets: current.targets.map(
|
|
484
|
+
(targetEntry) => targetEntry.element === eventTarget ? { ...targetEntry, target: targetData, loading: false } : targetEntry
|
|
485
|
+
)
|
|
486
|
+
};
|
|
487
|
+
});
|
|
488
|
+
setStatus(targetData.source ? "Source captured." : "Element captured without source info.");
|
|
489
|
+
} catch {
|
|
490
|
+
setSelected((current) => {
|
|
491
|
+
if (!current) {
|
|
492
|
+
return current;
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
...current,
|
|
496
|
+
targets: current.targets.map(
|
|
497
|
+
(targetEntry) => targetEntry.element === eventTarget ? { ...targetEntry, loading: false } : targetEntry
|
|
498
|
+
)
|
|
499
|
+
};
|
|
500
|
+
});
|
|
501
|
+
setStatus("Element captured without source info.");
|
|
502
|
+
}
|
|
503
|
+
},
|
|
504
|
+
[linkingAnnotationId]
|
|
505
|
+
);
|
|
310
506
|
useEffect(() => {
|
|
311
|
-
if (!enabled || !isAnnotating) {
|
|
507
|
+
if (!enabled || !isAnnotating || !resolvedTarget.document) {
|
|
312
508
|
setHoverRect(null);
|
|
313
509
|
return;
|
|
314
510
|
}
|
|
511
|
+
const activeDocument = resolvedTarget.document;
|
|
315
512
|
const onPointerOver = (event) => {
|
|
316
|
-
const
|
|
317
|
-
if (!
|
|
513
|
+
const eventTarget = getAnnotatableTarget(event.target, activeDocument);
|
|
514
|
+
if (!eventTarget) {
|
|
318
515
|
setHoverRect(null);
|
|
319
516
|
return;
|
|
320
517
|
}
|
|
321
|
-
setHoverRect(getRect(
|
|
518
|
+
setHoverRect(getRect(eventTarget, resolvedTarget.frameElement));
|
|
519
|
+
};
|
|
520
|
+
const suppressInteraction = (event) => {
|
|
521
|
+
const eventTarget = getAnnotatableTarget(event.target, activeDocument);
|
|
522
|
+
if (!eventTarget) {
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
event.preventDefault();
|
|
526
|
+
event.stopPropagation();
|
|
527
|
+
event.stopImmediatePropagation();
|
|
322
528
|
};
|
|
323
529
|
const onClick = (event) => {
|
|
324
|
-
const
|
|
325
|
-
if (!
|
|
530
|
+
const eventTarget = getAnnotatableTarget(event.target, activeDocument);
|
|
531
|
+
if (!eventTarget) {
|
|
326
532
|
return;
|
|
327
533
|
}
|
|
328
534
|
event.preventDefault();
|
|
329
535
|
event.stopPropagation();
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
setNote("");
|
|
333
|
-
setStatus("Resolving source\u2026");
|
|
334
|
-
captureElementAnnotation(target, "").then((annotation) => {
|
|
335
|
-
setSelected((current) => {
|
|
336
|
-
if (current?.element !== target) {
|
|
337
|
-
return current;
|
|
338
|
-
}
|
|
339
|
-
return { ...current, annotation, loading: false };
|
|
340
|
-
});
|
|
341
|
-
setStatus(annotation.source ? "Source captured." : "Element captured without source info.");
|
|
342
|
-
}).catch(() => {
|
|
343
|
-
setSelected((current) => current?.element === target ? { ...current, loading: false } : current);
|
|
344
|
-
setStatus("Element captured without source info.");
|
|
345
|
-
});
|
|
536
|
+
event.stopImmediatePropagation();
|
|
537
|
+
void handleElementSelection(eventTarget, resolvedTarget.frameElement, shouldExtendSelection(event));
|
|
346
538
|
};
|
|
347
|
-
|
|
348
|
-
|
|
539
|
+
const onFramePointerLeave = () => {
|
|
540
|
+
setHoverRect(null);
|
|
541
|
+
};
|
|
542
|
+
activeDocument.addEventListener("pointerover", onPointerOver, true);
|
|
543
|
+
activeDocument.addEventListener("click", onClick, true);
|
|
544
|
+
BLOCKED_INTERACTION_EVENTS.forEach((eventName) => activeDocument.addEventListener(eventName, suppressInteraction, true));
|
|
545
|
+
resolvedTarget.frameElement?.addEventListener("pointerleave", onFramePointerLeave);
|
|
349
546
|
return () => {
|
|
350
|
-
|
|
351
|
-
|
|
547
|
+
activeDocument.removeEventListener("pointerover", onPointerOver, true);
|
|
548
|
+
activeDocument.removeEventListener("click", onClick, true);
|
|
549
|
+
BLOCKED_INTERACTION_EVENTS.forEach((eventName) => activeDocument.removeEventListener(eventName, suppressInteraction, true));
|
|
550
|
+
resolvedTarget.frameElement?.removeEventListener("pointerleave", onFramePointerLeave);
|
|
352
551
|
};
|
|
353
|
-
}, [enabled, isAnnotating]);
|
|
552
|
+
}, [enabled, handleElementSelection, isAnnotating, resolvedTarget]);
|
|
354
553
|
useEffect(() => {
|
|
355
|
-
if (!enabled || !isAnnotating) {
|
|
554
|
+
if (!enabled || !isAnnotating || !resolvedTarget.document) {
|
|
356
555
|
return;
|
|
357
556
|
}
|
|
358
|
-
|
|
557
|
+
const activeDocument = resolvedTarget.document;
|
|
558
|
+
activeDocument.addEventListener("scroll", refreshTrackedRects, true);
|
|
559
|
+
if (typeof document !== "undefined" && activeDocument !== document) {
|
|
560
|
+
document.addEventListener("scroll", refreshTrackedRects, true);
|
|
561
|
+
}
|
|
359
562
|
window.addEventListener("resize", refreshTrackedRects);
|
|
360
563
|
return () => {
|
|
361
|
-
|
|
564
|
+
activeDocument.removeEventListener("scroll", refreshTrackedRects, true);
|
|
565
|
+
if (typeof document !== "undefined" && activeDocument !== document) {
|
|
566
|
+
document.removeEventListener("scroll", refreshTrackedRects, true);
|
|
567
|
+
}
|
|
362
568
|
window.removeEventListener("resize", refreshTrackedRects);
|
|
363
569
|
};
|
|
364
|
-
}, [enabled, isAnnotating, refreshTrackedRects]);
|
|
570
|
+
}, [enabled, isAnnotating, refreshTrackedRects, resolvedTarget.document]);
|
|
365
571
|
const addAnnotation = useCallback(async () => {
|
|
366
572
|
const current = selectedRef.current;
|
|
367
|
-
if (!current || current.loading) {
|
|
573
|
+
if (!current || current.targets.some((targetEntry) => targetEntry.loading)) {
|
|
368
574
|
return;
|
|
369
575
|
}
|
|
370
576
|
const trimmedNote = note.trim();
|
|
@@ -372,14 +578,67 @@ function SourceAnnotator({
|
|
|
372
578
|
setStatus("Add a note before saving this annotation.");
|
|
373
579
|
return;
|
|
374
580
|
}
|
|
375
|
-
const
|
|
376
|
-
|
|
581
|
+
const currentTargets = await Promise.all(
|
|
582
|
+
current.targets.map(async (targetEntry) => {
|
|
583
|
+
if (targetEntry.target) {
|
|
584
|
+
return targetEntry;
|
|
585
|
+
}
|
|
586
|
+
const annotation = await captureElementAnnotation(targetEntry.element, trimmedNote);
|
|
587
|
+
return { ...targetEntry, target: annotation.targets[0], loading: false };
|
|
588
|
+
})
|
|
589
|
+
);
|
|
590
|
+
const storedAnnotation = {
|
|
591
|
+
id: current.editingId ?? createAnnotationId(),
|
|
592
|
+
note: trimmedNote,
|
|
593
|
+
targets: currentTargets.map((targetEntry) => ({
|
|
594
|
+
targetElement: targetEntry.element,
|
|
595
|
+
rect: getRect(targetEntry.element, targetEntry.frameElement),
|
|
596
|
+
frameElement: targetEntry.frameElement,
|
|
597
|
+
data: targetEntry.target
|
|
598
|
+
}))
|
|
599
|
+
};
|
|
600
|
+
setAnnotations((existing) => {
|
|
601
|
+
if (!current.editingId) {
|
|
602
|
+
return [...existing, storedAnnotation];
|
|
603
|
+
}
|
|
604
|
+
return existing.map((item) => item.id === current.editingId ? storedAnnotation : item);
|
|
605
|
+
});
|
|
377
606
|
setSelected(null);
|
|
378
607
|
setNote("");
|
|
379
|
-
|
|
608
|
+
setPreviewedAnnotation(null);
|
|
609
|
+
setStatus(current.editingId ? "Annotation updated." : "Annotation saved.");
|
|
380
610
|
}, [note]);
|
|
611
|
+
const editAnnotation = useCallback((annotation) => {
|
|
612
|
+
setLinkingAnnotationId(null);
|
|
613
|
+
setSelected({
|
|
614
|
+
editingId: annotation.id,
|
|
615
|
+
targets: annotation.targets.map((targetEntry) => ({
|
|
616
|
+
element: targetEntry.targetElement,
|
|
617
|
+
rect: getRect(targetEntry.targetElement, targetEntry.frameElement),
|
|
618
|
+
frameElement: targetEntry.frameElement,
|
|
619
|
+
target: targetEntry.data,
|
|
620
|
+
loading: false
|
|
621
|
+
}))
|
|
622
|
+
});
|
|
623
|
+
setNote(annotation.note);
|
|
624
|
+
setPreviewedAnnotation(null);
|
|
625
|
+
setStatus("Editing annotation.");
|
|
626
|
+
}, []);
|
|
627
|
+
const startLinkingAnnotation = useCallback((annotationId) => {
|
|
628
|
+
setSelected(null);
|
|
629
|
+
setPreviewedAnnotation(null);
|
|
630
|
+
setLinkingAnnotationId(annotationId);
|
|
631
|
+
setStatus("Click another element to link it to this annotation.");
|
|
632
|
+
}, []);
|
|
633
|
+
const deleteAnnotation = useCallback((annotationId) => {
|
|
634
|
+
setAnnotations((existing) => existing.filter((annotation) => annotation.id !== annotationId));
|
|
635
|
+
setSelected((current) => current?.editingId === annotationId ? null : current);
|
|
636
|
+
setPreviewedAnnotation((current) => current?.id === annotationId ? null : current);
|
|
637
|
+
setLinkingAnnotationId((current) => current === annotationId ? null : current);
|
|
638
|
+
setStatus("Annotation deleted.");
|
|
639
|
+
}, []);
|
|
381
640
|
const collect = useCallback(async () => {
|
|
382
|
-
const payload = createAnnotationCollection(annotations
|
|
641
|
+
const payload = createAnnotationCollection(stripStoredAnnotations(annotations), getPageContext(resolvedTarget.document));
|
|
383
642
|
const text = formatAnnotationCollection(payload, output);
|
|
384
643
|
try {
|
|
385
644
|
await copyTextToClipboard(text);
|
|
@@ -387,14 +646,17 @@ function SourceAnnotator({
|
|
|
387
646
|
setIsAnnotating(false);
|
|
388
647
|
setSelected(null);
|
|
389
648
|
setHoverRect(null);
|
|
649
|
+
setAnnotations([]);
|
|
650
|
+
setPreviewedAnnotation(null);
|
|
390
651
|
setNote("");
|
|
652
|
+
setStatus(null);
|
|
653
|
+
setLinkingAnnotationId(null);
|
|
391
654
|
toast.success("Annotations copied", { description: `${payload.annotations.length} copied to clipboard.` });
|
|
392
|
-
setStatus(`Copied ${payload.annotations.length} annotation${payload.annotations.length === 1 ? "" : "s"}.`);
|
|
393
655
|
} catch (error) {
|
|
394
656
|
toast.error("Copy failed", { description: error instanceof Error ? error.message : "Clipboard copy failed." });
|
|
395
657
|
setStatus(error instanceof Error ? error.message : "Clipboard copy failed.");
|
|
396
658
|
}
|
|
397
|
-
}, [annotations, onCollect, output]);
|
|
659
|
+
}, [annotations, onCollect, output, resolvedTarget.document]);
|
|
398
660
|
if (!enabled) {
|
|
399
661
|
return null;
|
|
400
662
|
}
|
|
@@ -412,11 +674,25 @@ function SourceAnnotator({
|
|
|
412
674
|
}
|
|
413
675
|
),
|
|
414
676
|
isAnnotating && hoverRect ? /* @__PURE__ */ jsx(Box, { rect: hoverRect, kind: "hover" }) : null,
|
|
415
|
-
selected
|
|
416
|
-
isAnnotating ? annotations.map(
|
|
417
|
-
|
|
677
|
+
selected?.targets.map((targetEntry, index) => /* @__PURE__ */ jsx(Box, { rect: targetEntry.rect, kind: "selected" }, index)),
|
|
678
|
+
isAnnotating ? annotations.map(
|
|
679
|
+
(annotation, index) => annotation.targets.map((targetEntry, targetIndex) => /* @__PURE__ */ jsx(
|
|
680
|
+
Pin,
|
|
681
|
+
{
|
|
682
|
+
annotation,
|
|
683
|
+
rect: targetEntry.rect,
|
|
684
|
+
index,
|
|
685
|
+
onEdit: editAnnotation,
|
|
686
|
+
onPreview: setPreviewedAnnotation,
|
|
687
|
+
onPreviewEnd: () => setPreviewedAnnotation(null)
|
|
688
|
+
},
|
|
689
|
+
`${annotation.id}:${targetIndex}`
|
|
690
|
+
))
|
|
691
|
+
) : null,
|
|
692
|
+
isAnnotating && previewedAnnotation ? /* @__PURE__ */ jsx(AnnotationPreview, { annotation: previewedAnnotation }) : null,
|
|
693
|
+
selected?.targets.length ? /* @__PURE__ */ jsxs("div", { style: getPopoverStyle(selected.targets[selected.targets.length - 1].rect), role: "dialog", "aria-label": "Add source annotation", children: [
|
|
418
694
|
/* @__PURE__ */ jsx("div", { style: styles.popoverTitle, children: "Annotation" }),
|
|
419
|
-
/* @__PURE__ */ jsx("div", { style: styles.metaText, children:
|
|
695
|
+
/* @__PURE__ */ jsx("div", { style: styles.metaText, children: formatSelectedTargets(selected.targets) }),
|
|
420
696
|
/* @__PURE__ */ jsx(
|
|
421
697
|
"textarea",
|
|
422
698
|
{
|
|
@@ -430,17 +706,26 @@ function SourceAnnotator({
|
|
|
430
706
|
),
|
|
431
707
|
/* @__PURE__ */ jsxs("div", { style: styles.popoverActions, children: [
|
|
432
708
|
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setSelected(null), style: styles.secondaryButton, children: "Cancel" }),
|
|
433
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: addAnnotation, style: styles.primaryButton, disabled: selected.loading, children: "Save note" })
|
|
709
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: addAnnotation, style: styles.primaryButton, disabled: selected.targets.some((targetEntry) => targetEntry.loading), children: selected.editingId ? "Update note" : "Save note" })
|
|
434
710
|
] })
|
|
435
711
|
] }) : null,
|
|
436
712
|
isAnnotating ? /* @__PURE__ */ jsxs("section", { style: styles.panel, "aria-label": "Collected annotations", children: [
|
|
437
713
|
/* @__PURE__ */ jsxs("div", { style: styles.panelHeader, children: [
|
|
438
714
|
/* @__PURE__ */ jsx("strong", { children: "Annotations" }),
|
|
439
|
-
/* @__PURE__ */ jsx("span", { style: styles.badge, children:
|
|
715
|
+
/* @__PURE__ */ jsx("span", { style: styles.badge, children: annotations.length })
|
|
440
716
|
] }),
|
|
441
|
-
annotations.length ? /* @__PURE__ */ jsx("ol", { style: styles.annotationList, children: annotations.map((annotation) => /* @__PURE__ */ jsxs("li", { style: styles.annotationItem, children: [
|
|
442
|
-
/* @__PURE__ */
|
|
443
|
-
|
|
717
|
+
annotations.length ? /* @__PURE__ */ jsx("ol", { style: styles.annotationList, children: annotations.map((annotation, index) => /* @__PURE__ */ jsxs("li", { style: styles.annotationItem, children: [
|
|
718
|
+
/* @__PURE__ */ jsxs("div", { style: styles.annotationContent, children: [
|
|
719
|
+
/* @__PURE__ */ jsx("div", { style: styles.noteText, children: annotation.note }),
|
|
720
|
+
/* @__PURE__ */ jsx("div", { style: styles.metaText, children: formatStoredAnnotationSummary(annotation) })
|
|
721
|
+
] }),
|
|
722
|
+
/* @__PURE__ */ jsxs("div", { style: styles.annotationActions, children: [
|
|
723
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => startLinkingAnnotation(annotation.id), style: styles.linkButton, children: "Link element" }),
|
|
724
|
+
/* @__PURE__ */ jsxs("button", { type: "button", onClick: () => deleteAnnotation(annotation.id), style: styles.deleteButton, children: [
|
|
725
|
+
"Delete annotation ",
|
|
726
|
+
index + 1
|
|
727
|
+
] })
|
|
728
|
+
] })
|
|
444
729
|
] }, annotation.id)) }) : /* @__PURE__ */ jsx("p", { style: styles.emptyText, children: "Hover an element, click it, then add a note." }),
|
|
445
730
|
/* @__PURE__ */ jsx("button", { type: "button", onClick: collect, style: styles.collectButton, disabled: !annotations.length, children: "Collect" }),
|
|
446
731
|
status ? /* @__PURE__ */ jsx("div", { style: styles.status, children: status }) : null
|
|
@@ -451,6 +736,7 @@ function Box({ rect, kind }) {
|
|
|
451
736
|
return /* @__PURE__ */ jsx(
|
|
452
737
|
"div",
|
|
453
738
|
{
|
|
739
|
+
"data-mikuexe-annotator-box": kind,
|
|
454
740
|
style: {
|
|
455
741
|
...styles.box,
|
|
456
742
|
...kind === "selected" ? styles.selectedBox : styles.hoverBox,
|
|
@@ -462,37 +748,115 @@ function Box({ rect, kind }) {
|
|
|
462
748
|
}
|
|
463
749
|
);
|
|
464
750
|
}
|
|
465
|
-
function Pin({
|
|
751
|
+
function Pin({
|
|
752
|
+
annotation,
|
|
753
|
+
rect,
|
|
754
|
+
index,
|
|
755
|
+
onEdit,
|
|
756
|
+
onPreview,
|
|
757
|
+
onPreviewEnd
|
|
758
|
+
}) {
|
|
466
759
|
return /* @__PURE__ */ jsx(
|
|
467
|
-
"
|
|
760
|
+
"button",
|
|
468
761
|
{
|
|
469
|
-
|
|
762
|
+
type: "button",
|
|
763
|
+
style: { ...styles.pin, top: Math.max(8, rect.top - 10), left: Math.max(8, rect.left - 10) },
|
|
470
764
|
title: annotation.note,
|
|
765
|
+
"aria-label": `Edit annotation ${index + 1}`,
|
|
766
|
+
onClick: () => onEdit(annotation),
|
|
767
|
+
onMouseOver: () => onPreview(annotation),
|
|
768
|
+
onMouseOut: onPreviewEnd,
|
|
769
|
+
onFocus: () => onPreview(annotation),
|
|
770
|
+
onBlur: onPreviewEnd,
|
|
471
771
|
children: index + 1
|
|
472
772
|
}
|
|
473
773
|
);
|
|
474
774
|
}
|
|
475
|
-
function
|
|
476
|
-
|
|
775
|
+
function AnnotationPreview({ annotation }) {
|
|
776
|
+
return /* @__PURE__ */ jsxs("div", { role: "tooltip", style: getPreviewStyle(annotation.targets[0]?.rect ?? { top: 8, left: 8, width: 0, height: 0 }), children: [
|
|
777
|
+
/* @__PURE__ */ jsx("div", { style: styles.noteText, children: annotation.note }),
|
|
778
|
+
/* @__PURE__ */ jsx("div", { style: styles.metaText, children: formatStoredAnnotationSummary(annotation) })
|
|
779
|
+
] });
|
|
780
|
+
}
|
|
781
|
+
function stripStoredAnnotations(annotations) {
|
|
782
|
+
return annotations.map((annotation) => ({
|
|
783
|
+
id: annotation.id,
|
|
784
|
+
note: annotation.note,
|
|
785
|
+
targets: annotation.targets.map((targetEntry) => targetEntry.data)
|
|
786
|
+
}));
|
|
787
|
+
}
|
|
788
|
+
function getAnnotatableTarget(target, ownerDocument) {
|
|
789
|
+
if (!isElement(target, ownerDocument)) {
|
|
477
790
|
return null;
|
|
478
791
|
}
|
|
479
792
|
if (target.closest(`[${ROOT_ATTR}]`)) {
|
|
480
793
|
return null;
|
|
481
794
|
}
|
|
482
|
-
if (target ===
|
|
795
|
+
if (target === ownerDocument.body || target === ownerDocument.documentElement) {
|
|
483
796
|
return null;
|
|
484
797
|
}
|
|
485
798
|
return target;
|
|
486
799
|
}
|
|
487
|
-
function getRect(element) {
|
|
800
|
+
function getRect(element, frameElement) {
|
|
488
801
|
const rect = element.getBoundingClientRect();
|
|
802
|
+
const frameRect = frameElement?.getBoundingClientRect();
|
|
489
803
|
return {
|
|
490
|
-
top: rect.top,
|
|
491
|
-
left: rect.left,
|
|
804
|
+
top: rect.top + (frameRect?.top ?? 0),
|
|
805
|
+
left: rect.left + (frameRect?.left ?? 0),
|
|
492
806
|
width: rect.width,
|
|
493
807
|
height: rect.height
|
|
494
808
|
};
|
|
495
809
|
}
|
|
810
|
+
function useResolvedTarget(target) {
|
|
811
|
+
const [navigationVersion, setNavigationVersion] = useState(0);
|
|
812
|
+
const resolvedTarget = useMemo(() => resolveTarget(target), [target, navigationVersion]);
|
|
813
|
+
const currentDocumentRef = useRef(resolvedTarget.document);
|
|
814
|
+
currentDocumentRef.current = resolvedTarget.document;
|
|
815
|
+
useEffect(() => {
|
|
816
|
+
if (typeof HTMLIFrameElement !== "undefined" && target instanceof HTMLIFrameElement) {
|
|
817
|
+
const updateTarget = () => {
|
|
818
|
+
const nextTarget = resolveTarget(target);
|
|
819
|
+
if (nextTarget.document !== currentDocumentRef.current) {
|
|
820
|
+
setNavigationVersion((version) => version + 1);
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
target.addEventListener("load", updateTarget);
|
|
824
|
+
return () => target.removeEventListener("load", updateTarget);
|
|
825
|
+
}
|
|
826
|
+
}, [target]);
|
|
827
|
+
return resolvedTarget;
|
|
828
|
+
}
|
|
829
|
+
function resolveTarget(target) {
|
|
830
|
+
const hostDocument = typeof document === "undefined" ? null : document;
|
|
831
|
+
if (typeof HTMLIFrameElement !== "undefined" && target instanceof HTMLIFrameElement) {
|
|
832
|
+
const frameDocument = target.contentDocument;
|
|
833
|
+
if (!frameDocument) {
|
|
834
|
+
console.warn("@mikuexe/annotator-react: SourceAnnotator target iframe must be same-origin; iframe contentDocument is not accessible.");
|
|
835
|
+
return {
|
|
836
|
+
document: null,
|
|
837
|
+
frameElement: target
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
return {
|
|
841
|
+
document: frameDocument,
|
|
842
|
+
frameElement: target
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
if (typeof Document !== "undefined" && target instanceof Document) {
|
|
846
|
+
return {
|
|
847
|
+
document: target,
|
|
848
|
+
frameElement: null
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
return {
|
|
852
|
+
document: hostDocument,
|
|
853
|
+
frameElement: null
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
function isElement(target, ownerDocument) {
|
|
857
|
+
const elementConstructor = ownerDocument.defaultView?.Element ?? Element;
|
|
858
|
+
return target instanceof elementConstructor;
|
|
859
|
+
}
|
|
496
860
|
function getPopoverStyle(rect) {
|
|
497
861
|
const top = Math.min(window.innerHeight - 260, rect.top + rect.height + 8);
|
|
498
862
|
const left = Math.min(window.innerWidth - 340, Math.max(8, rect.left));
|
|
@@ -502,17 +866,45 @@ function getPopoverStyle(rect) {
|
|
|
502
866
|
left
|
|
503
867
|
};
|
|
504
868
|
}
|
|
505
|
-
function
|
|
506
|
-
const
|
|
507
|
-
|
|
869
|
+
function getPreviewStyle(rect) {
|
|
870
|
+
const top = Math.min(window.innerHeight - 120, rect.top + rect.height + 8);
|
|
871
|
+
const left = Math.min(window.innerWidth - 260, Math.max(8, rect.left));
|
|
872
|
+
return {
|
|
873
|
+
...styles.preview,
|
|
874
|
+
top: Math.max(8, top),
|
|
875
|
+
left
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
function formatSelectedTargets(targets) {
|
|
879
|
+
if (!targets.length) {
|
|
880
|
+
return "Source unavailable";
|
|
881
|
+
}
|
|
882
|
+
if (targets.length === 1) {
|
|
883
|
+
return formatTargetSource(targets[0].target);
|
|
884
|
+
}
|
|
885
|
+
const resolvedCount = targets.filter((targetEntry) => targetEntry.target).length;
|
|
886
|
+
return `${targets.length} elements selected \xB7 ${resolvedCount}/${targets.length} resolved`;
|
|
887
|
+
}
|
|
888
|
+
function formatStoredAnnotationSummary(annotation) {
|
|
889
|
+
const firstTarget = annotation.targets[0]?.data;
|
|
890
|
+
const targetSummary = formatTargetSource(firstTarget);
|
|
891
|
+
const linkedSummary = annotation.targets.length > 1 ? ` \xB7 ${annotation.targets.length} linked elements` : "";
|
|
892
|
+
return `${targetSummary}${linkedSummary}`;
|
|
893
|
+
}
|
|
894
|
+
function formatTargetSource(target) {
|
|
895
|
+
const componentPath = target?.componentPath.length ? target.componentPath.join(" \u203A ") : null;
|
|
896
|
+
if (!target) {
|
|
508
897
|
return "Source unavailable";
|
|
509
898
|
}
|
|
510
|
-
if (!
|
|
511
|
-
return `${
|
|
899
|
+
if (!target.source?.filePath) {
|
|
900
|
+
return `${target.element.selector} \xB7 source unavailable`;
|
|
512
901
|
}
|
|
513
|
-
const line =
|
|
902
|
+
const line = target.source.lineNumber ? `:${target.source.lineNumber}` : "";
|
|
514
903
|
const component = componentPath ? ` \xB7 ${componentPath}` : "";
|
|
515
|
-
return `${
|
|
904
|
+
return `${target.source.filePath}${line}${component}`;
|
|
905
|
+
}
|
|
906
|
+
function shouldExtendSelection(event) {
|
|
907
|
+
return event.metaKey || event.ctrlKey;
|
|
516
908
|
}
|
|
517
909
|
function matchesHotkey(event, hotkey) {
|
|
518
910
|
const parts = hotkey.toLowerCase().split("+").map((part) => part.trim()).filter(Boolean);
|
|
@@ -574,6 +966,7 @@ var styles = {
|
|
|
574
966
|
},
|
|
575
967
|
popover: {
|
|
576
968
|
position: "fixed",
|
|
969
|
+
zIndex: 2,
|
|
577
970
|
width: 320,
|
|
578
971
|
pointerEvents: "auto",
|
|
579
972
|
background: "#ffffff",
|
|
@@ -626,6 +1019,7 @@ var styles = {
|
|
|
626
1019
|
},
|
|
627
1020
|
panel: {
|
|
628
1021
|
position: "fixed",
|
|
1022
|
+
zIndex: 1,
|
|
629
1023
|
right: 16,
|
|
630
1024
|
bottom: 68,
|
|
631
1025
|
width: 300,
|
|
@@ -662,11 +1056,23 @@ var styles = {
|
|
|
662
1056
|
overflow: "auto"
|
|
663
1057
|
},
|
|
664
1058
|
annotationItem: {
|
|
1059
|
+
display: "grid",
|
|
1060
|
+
gap: 8,
|
|
1061
|
+
alignItems: "start",
|
|
665
1062
|
marginBottom: 8
|
|
666
1063
|
},
|
|
1064
|
+
annotationContent: {
|
|
1065
|
+
minWidth: 0
|
|
1066
|
+
},
|
|
1067
|
+
annotationActions: {
|
|
1068
|
+
display: "flex",
|
|
1069
|
+
gap: 8,
|
|
1070
|
+
flexWrap: "wrap"
|
|
1071
|
+
},
|
|
667
1072
|
noteText: {
|
|
668
1073
|
color: "#0f172a",
|
|
669
|
-
fontWeight: 650
|
|
1074
|
+
fontWeight: 650,
|
|
1075
|
+
overflowWrap: "anywhere"
|
|
670
1076
|
},
|
|
671
1077
|
emptyText: {
|
|
672
1078
|
color: "#64748b",
|
|
@@ -687,30 +1093,65 @@ var styles = {
|
|
|
687
1093
|
color: "#475569",
|
|
688
1094
|
fontSize: 12
|
|
689
1095
|
},
|
|
1096
|
+
linkButton: {
|
|
1097
|
+
border: "1px solid #bfdbfe",
|
|
1098
|
+
borderRadius: 999,
|
|
1099
|
+
background: "#eff6ff",
|
|
1100
|
+
color: "#1d4ed8",
|
|
1101
|
+
padding: "4px 7px",
|
|
1102
|
+
fontSize: 11,
|
|
1103
|
+
fontWeight: 750,
|
|
1104
|
+
cursor: "pointer"
|
|
1105
|
+
},
|
|
1106
|
+
deleteButton: {
|
|
1107
|
+
border: "1px solid #fecaca",
|
|
1108
|
+
borderRadius: 999,
|
|
1109
|
+
background: "#fff1f2",
|
|
1110
|
+
color: "#be123c",
|
|
1111
|
+
padding: "4px 7px",
|
|
1112
|
+
fontSize: 11,
|
|
1113
|
+
fontWeight: 750,
|
|
1114
|
+
cursor: "pointer"
|
|
1115
|
+
},
|
|
1116
|
+
preview: {
|
|
1117
|
+
position: "fixed",
|
|
1118
|
+
maxWidth: 240,
|
|
1119
|
+
pointerEvents: "none",
|
|
1120
|
+
background: "#ffffff",
|
|
1121
|
+
border: "1px solid #cbd5e1",
|
|
1122
|
+
borderRadius: 10,
|
|
1123
|
+
padding: 10,
|
|
1124
|
+
boxShadow: "0 14px 35px rgba(15, 23, 42, 0.18)"
|
|
1125
|
+
},
|
|
690
1126
|
pin: {
|
|
691
1127
|
position: "fixed",
|
|
1128
|
+
border: 0,
|
|
692
1129
|
width: 20,
|
|
693
1130
|
height: 20,
|
|
694
1131
|
borderRadius: 999,
|
|
695
1132
|
display: "inline-flex",
|
|
696
1133
|
alignItems: "center",
|
|
697
1134
|
justifyContent: "center",
|
|
698
|
-
pointerEvents: "
|
|
1135
|
+
pointerEvents: "auto",
|
|
699
1136
|
background: "#f97316",
|
|
700
1137
|
color: "#ffffff",
|
|
701
1138
|
fontSize: 12,
|
|
702
1139
|
fontWeight: 800,
|
|
703
|
-
boxShadow: "0 8px 18px rgba(15, 23, 42, 0.2)"
|
|
1140
|
+
boxShadow: "0 8px 18px rgba(15, 23, 42, 0.2)",
|
|
1141
|
+
cursor: "pointer",
|
|
1142
|
+
padding: 0
|
|
704
1143
|
}
|
|
705
1144
|
};
|
|
706
1145
|
export {
|
|
707
1146
|
SourceAnnotator,
|
|
1147
|
+
captureAnnotationTarget,
|
|
708
1148
|
captureElementAnnotation,
|
|
709
1149
|
copyTextToClipboard,
|
|
710
1150
|
createAnnotationCollection,
|
|
711
1151
|
formatAnnotationCollection,
|
|
712
1152
|
formatMarkdown,
|
|
713
1153
|
getElementSelector,
|
|
1154
|
+
getPageContext,
|
|
714
1155
|
trimText
|
|
715
1156
|
};
|
|
716
1157
|
//# sourceMappingURL=index.js.map
|