agentation 1.1.0 → 1.2.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/README.md +69 -0
- package/dist/index.d.mts +41 -27
- package/dist/index.d.ts +41 -27
- package/dist/index.js +34 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +34 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -33,9 +33,78 @@ The toolbar appears in the bottom-right corner. Click to activate, then click an
|
|
|
33
33
|
- **Area selection** – Drag to annotate any region, even empty space
|
|
34
34
|
- **Animation pause** – Freeze CSS animations to capture specific states
|
|
35
35
|
- **Structured output** – Copy markdown with selectors, positions, and context
|
|
36
|
+
- **Programmatic access** – Callback prop for direct integration with tools
|
|
36
37
|
- **Dark/light mode** – Matches your preference or set manually
|
|
37
38
|
- **Zero dependencies** – Pure CSS animations, no runtime libraries
|
|
38
39
|
|
|
40
|
+
## Props
|
|
41
|
+
|
|
42
|
+
| Prop | Type | Default | Description |
|
|
43
|
+
|------|------|---------|-------------|
|
|
44
|
+
| `onAnnotationAdd` | `(annotation: Annotation) => void` | - | Called when an annotation is created |
|
|
45
|
+
| `onAnnotationDelete` | `(annotation: Annotation) => void` | - | Called when an annotation is deleted |
|
|
46
|
+
| `onAnnotationUpdate` | `(annotation: Annotation) => void` | - | Called when an annotation is edited |
|
|
47
|
+
| `onAnnotationsClear` | `(annotations: Annotation[]) => void` | - | Called when all annotations are cleared |
|
|
48
|
+
| `onCopy` | `(markdown: string) => void` | - | Callback with markdown output when copy is clicked |
|
|
49
|
+
| `copyToClipboard` | `boolean` | `true` | Set to false to prevent writing to clipboard |
|
|
50
|
+
|
|
51
|
+
### Programmatic Integration
|
|
52
|
+
|
|
53
|
+
Use callbacks to receive annotation data directly:
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import { Agentation, type Annotation } from 'agentation';
|
|
57
|
+
|
|
58
|
+
function App() {
|
|
59
|
+
const handleAnnotation = (annotation: Annotation) => {
|
|
60
|
+
// Structured data - no parsing needed
|
|
61
|
+
console.log(annotation.element); // "Button"
|
|
62
|
+
console.log(annotation.elementPath); // "body > div > button"
|
|
63
|
+
console.log(annotation.boundingBox); // { x, y, width, height }
|
|
64
|
+
console.log(annotation.cssClasses); // "btn btn-primary"
|
|
65
|
+
|
|
66
|
+
// Send to your agent, API, etc.
|
|
67
|
+
sendToAgent(annotation);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<>
|
|
72
|
+
<YourApp />
|
|
73
|
+
<Agentation
|
|
74
|
+
onAnnotationAdd={handleAnnotation}
|
|
75
|
+
copyToClipboard={false} // Don't write to clipboard
|
|
76
|
+
/>
|
|
77
|
+
</>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Annotation Type
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
type Annotation = {
|
|
86
|
+
id: string;
|
|
87
|
+
x: number; // % of viewport width
|
|
88
|
+
y: number; // px from top (viewport if fixed)
|
|
89
|
+
comment: string; // User's note
|
|
90
|
+
element: string; // e.g., "Button"
|
|
91
|
+
elementPath: string; // e.g., "body > div > button"
|
|
92
|
+
timestamp: number;
|
|
93
|
+
|
|
94
|
+
// Optional metadata (when available)
|
|
95
|
+
selectedText?: string;
|
|
96
|
+
boundingBox?: { x: number; y: number; width: number; height: number };
|
|
97
|
+
nearbyText?: string;
|
|
98
|
+
cssClasses?: string;
|
|
99
|
+
nearbyElements?: string;
|
|
100
|
+
computedStyles?: string;
|
|
101
|
+
fullPath?: string;
|
|
102
|
+
accessibility?: string;
|
|
103
|
+
isMultiSelect?: boolean;
|
|
104
|
+
isFixed?: boolean;
|
|
105
|
+
};
|
|
106
|
+
```
|
|
107
|
+
|
|
39
108
|
## How it works
|
|
40
109
|
|
|
41
110
|
Agentation captures class names, selectors, and element positions so AI agents can `grep` for the exact code you're referring to. Instead of describing "the blue button in the sidebar," you give the agent `.sidebar > button.primary` and your feedback.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
|
+
type Annotation = {
|
|
5
|
+
id: string;
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
comment: string;
|
|
9
|
+
element: string;
|
|
10
|
+
elementPath: string;
|
|
11
|
+
timestamp: number;
|
|
12
|
+
selectedText?: string;
|
|
13
|
+
boundingBox?: {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
};
|
|
19
|
+
nearbyText?: string;
|
|
20
|
+
cssClasses?: string;
|
|
21
|
+
nearbyElements?: string;
|
|
22
|
+
computedStyles?: string;
|
|
23
|
+
fullPath?: string;
|
|
24
|
+
accessibility?: string;
|
|
25
|
+
isMultiSelect?: boolean;
|
|
26
|
+
isFixed?: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
4
29
|
type DemoAnnotation = {
|
|
5
30
|
selector: string;
|
|
6
31
|
comment: string;
|
|
@@ -10,8 +35,22 @@ type PageFeedbackToolbarCSSProps = {
|
|
|
10
35
|
demoAnnotations?: DemoAnnotation[];
|
|
11
36
|
demoDelay?: number;
|
|
12
37
|
enableDemoMode?: boolean;
|
|
38
|
+
/** Callback fired when an annotation is added. */
|
|
39
|
+
onAnnotationAdd?: (annotation: Annotation) => void;
|
|
40
|
+
/** Callback fired when an annotation is deleted. */
|
|
41
|
+
onAnnotationDelete?: (annotation: Annotation) => void;
|
|
42
|
+
/** Callback fired when an annotation comment is edited. */
|
|
43
|
+
onAnnotationUpdate?: (annotation: Annotation) => void;
|
|
44
|
+
/** Callback fired when all annotations are cleared. Receives the annotations that were cleared. */
|
|
45
|
+
onAnnotationsClear?: (annotations: Annotation[]) => void;
|
|
46
|
+
/** Callback fired when the copy button is clicked. Receives the markdown output. */
|
|
47
|
+
onCopy?: (markdown: string) => void;
|
|
48
|
+
/** Whether to copy to clipboard when the copy button is clicked. Defaults to true. */
|
|
49
|
+
copyToClipboard?: boolean;
|
|
13
50
|
};
|
|
14
|
-
|
|
51
|
+
/** Alias for PageFeedbackToolbarCSSProps */
|
|
52
|
+
type AgentationProps = PageFeedbackToolbarCSSProps;
|
|
53
|
+
declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, copyToClipboard, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
|
|
15
54
|
|
|
16
55
|
interface AnnotationPopupCSSProps {
|
|
17
56
|
/** Element name to display in header */
|
|
@@ -163,33 +202,8 @@ declare function identifyAnimationElement(target: HTMLElement): string;
|
|
|
163
202
|
*/
|
|
164
203
|
declare function getElementClasses(target: HTMLElement): string;
|
|
165
204
|
|
|
166
|
-
type Annotation = {
|
|
167
|
-
id: string;
|
|
168
|
-
x: number;
|
|
169
|
-
y: number;
|
|
170
|
-
comment: string;
|
|
171
|
-
element: string;
|
|
172
|
-
elementPath: string;
|
|
173
|
-
timestamp: number;
|
|
174
|
-
selectedText?: string;
|
|
175
|
-
boundingBox?: {
|
|
176
|
-
x: number;
|
|
177
|
-
y: number;
|
|
178
|
-
width: number;
|
|
179
|
-
height: number;
|
|
180
|
-
};
|
|
181
|
-
nearbyText?: string;
|
|
182
|
-
cssClasses?: string;
|
|
183
|
-
nearbyElements?: string;
|
|
184
|
-
computedStyles?: string;
|
|
185
|
-
fullPath?: string;
|
|
186
|
-
accessibility?: string;
|
|
187
|
-
isMultiSelect?: boolean;
|
|
188
|
-
isFixed?: boolean;
|
|
189
|
-
};
|
|
190
|
-
|
|
191
205
|
declare function getStorageKey(pathname: string): string;
|
|
192
206
|
declare function loadAnnotations<T = Annotation>(pathname: string): T[];
|
|
193
207
|
declare function saveAnnotations<T = Annotation>(pathname: string, annotations: T[]): void;
|
|
194
208
|
|
|
195
|
-
export { PageFeedbackToolbarCSS as Agentation, AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconClose, IconCopyAlt, IconCopyAnimated, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSun, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, getElementClasses, getElementPath, getNearbyText, getStorageKey, identifyAnimationElement, identifyElement, loadAnnotations, saveAnnotations };
|
|
209
|
+
export { PageFeedbackToolbarCSS as Agentation, type AgentationProps, AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconClose, IconCopyAlt, IconCopyAnimated, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSun, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, getElementClasses, getElementPath, getNearbyText, getStorageKey, identifyAnimationElement, identifyElement, loadAnnotations, saveAnnotations };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
|
+
type Annotation = {
|
|
5
|
+
id: string;
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
comment: string;
|
|
9
|
+
element: string;
|
|
10
|
+
elementPath: string;
|
|
11
|
+
timestamp: number;
|
|
12
|
+
selectedText?: string;
|
|
13
|
+
boundingBox?: {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
};
|
|
19
|
+
nearbyText?: string;
|
|
20
|
+
cssClasses?: string;
|
|
21
|
+
nearbyElements?: string;
|
|
22
|
+
computedStyles?: string;
|
|
23
|
+
fullPath?: string;
|
|
24
|
+
accessibility?: string;
|
|
25
|
+
isMultiSelect?: boolean;
|
|
26
|
+
isFixed?: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
4
29
|
type DemoAnnotation = {
|
|
5
30
|
selector: string;
|
|
6
31
|
comment: string;
|
|
@@ -10,8 +35,22 @@ type PageFeedbackToolbarCSSProps = {
|
|
|
10
35
|
demoAnnotations?: DemoAnnotation[];
|
|
11
36
|
demoDelay?: number;
|
|
12
37
|
enableDemoMode?: boolean;
|
|
38
|
+
/** Callback fired when an annotation is added. */
|
|
39
|
+
onAnnotationAdd?: (annotation: Annotation) => void;
|
|
40
|
+
/** Callback fired when an annotation is deleted. */
|
|
41
|
+
onAnnotationDelete?: (annotation: Annotation) => void;
|
|
42
|
+
/** Callback fired when an annotation comment is edited. */
|
|
43
|
+
onAnnotationUpdate?: (annotation: Annotation) => void;
|
|
44
|
+
/** Callback fired when all annotations are cleared. Receives the annotations that were cleared. */
|
|
45
|
+
onAnnotationsClear?: (annotations: Annotation[]) => void;
|
|
46
|
+
/** Callback fired when the copy button is clicked. Receives the markdown output. */
|
|
47
|
+
onCopy?: (markdown: string) => void;
|
|
48
|
+
/** Whether to copy to clipboard when the copy button is clicked. Defaults to true. */
|
|
49
|
+
copyToClipboard?: boolean;
|
|
13
50
|
};
|
|
14
|
-
|
|
51
|
+
/** Alias for PageFeedbackToolbarCSSProps */
|
|
52
|
+
type AgentationProps = PageFeedbackToolbarCSSProps;
|
|
53
|
+
declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, copyToClipboard, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
|
|
15
54
|
|
|
16
55
|
interface AnnotationPopupCSSProps {
|
|
17
56
|
/** Element name to display in header */
|
|
@@ -163,33 +202,8 @@ declare function identifyAnimationElement(target: HTMLElement): string;
|
|
|
163
202
|
*/
|
|
164
203
|
declare function getElementClasses(target: HTMLElement): string;
|
|
165
204
|
|
|
166
|
-
type Annotation = {
|
|
167
|
-
id: string;
|
|
168
|
-
x: number;
|
|
169
|
-
y: number;
|
|
170
|
-
comment: string;
|
|
171
|
-
element: string;
|
|
172
|
-
elementPath: string;
|
|
173
|
-
timestamp: number;
|
|
174
|
-
selectedText?: string;
|
|
175
|
-
boundingBox?: {
|
|
176
|
-
x: number;
|
|
177
|
-
y: number;
|
|
178
|
-
width: number;
|
|
179
|
-
height: number;
|
|
180
|
-
};
|
|
181
|
-
nearbyText?: string;
|
|
182
|
-
cssClasses?: string;
|
|
183
|
-
nearbyElements?: string;
|
|
184
|
-
computedStyles?: string;
|
|
185
|
-
fullPath?: string;
|
|
186
|
-
accessibility?: string;
|
|
187
|
-
isMultiSelect?: boolean;
|
|
188
|
-
isFixed?: boolean;
|
|
189
|
-
};
|
|
190
|
-
|
|
191
205
|
declare function getStorageKey(pathname: string): string;
|
|
192
206
|
declare function loadAnnotations<T = Annotation>(pathname: string): T[];
|
|
193
207
|
declare function saveAnnotations<T = Annotation>(pathname: string, annotations: T[]): void;
|
|
194
208
|
|
|
195
|
-
export { PageFeedbackToolbarCSS as Agentation, AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconClose, IconCopyAlt, IconCopyAnimated, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSun, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, getElementClasses, getElementPath, getNearbyText, getStorageKey, identifyAnimationElement, identifyElement, loadAnnotations, saveAnnotations };
|
|
209
|
+
export { PageFeedbackToolbarCSS as Agentation, type AgentationProps, AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconClose, IconCopyAlt, IconCopyAnimated, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSun, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, getElementClasses, getElementPath, getNearbyText, getStorageKey, identifyAnimationElement, identifyElement, loadAnnotations, saveAnnotations };
|
package/dist/index.js
CHANGED
|
@@ -1540,7 +1540,13 @@ function generateOutput(annotations, pathname, detailLevel = "standard") {
|
|
|
1540
1540
|
function PageFeedbackToolbarCSS({
|
|
1541
1541
|
demoAnnotations,
|
|
1542
1542
|
demoDelay = 1e3,
|
|
1543
|
-
enableDemoMode = false
|
|
1543
|
+
enableDemoMode = false,
|
|
1544
|
+
onAnnotationAdd,
|
|
1545
|
+
onAnnotationDelete,
|
|
1546
|
+
onAnnotationUpdate,
|
|
1547
|
+
onAnnotationsClear,
|
|
1548
|
+
onCopy,
|
|
1549
|
+
copyToClipboard = true
|
|
1544
1550
|
} = {}) {
|
|
1545
1551
|
const [isActive, setIsActive] = (0, import_react2.useState)(false);
|
|
1546
1552
|
const [annotations, setAnnotations] = (0, import_react2.useState)([]);
|
|
@@ -2262,6 +2268,7 @@ function PageFeedbackToolbarCSS({
|
|
|
2262
2268
|
setTimeout(() => {
|
|
2263
2269
|
setAnimatedMarkers((prev) => new Set(prev).add(newAnnotation.id));
|
|
2264
2270
|
}, 250);
|
|
2271
|
+
onAnnotationAdd?.(newAnnotation);
|
|
2265
2272
|
setPendingExiting(true);
|
|
2266
2273
|
setTimeout(() => {
|
|
2267
2274
|
setPendingAnnotation(null);
|
|
@@ -2269,7 +2276,7 @@ function PageFeedbackToolbarCSS({
|
|
|
2269
2276
|
}, 150);
|
|
2270
2277
|
window.getSelection()?.removeAllRanges();
|
|
2271
2278
|
},
|
|
2272
|
-
[pendingAnnotation]
|
|
2279
|
+
[pendingAnnotation, onAnnotationAdd]
|
|
2273
2280
|
);
|
|
2274
2281
|
const cancelAnnotation = (0, import_react2.useCallback)(() => {
|
|
2275
2282
|
setPendingExiting(true);
|
|
@@ -2281,8 +2288,12 @@ function PageFeedbackToolbarCSS({
|
|
|
2281
2288
|
const deleteAnnotation = (0, import_react2.useCallback)(
|
|
2282
2289
|
(id) => {
|
|
2283
2290
|
const deletedIndex = annotations.findIndex((a) => a.id === id);
|
|
2291
|
+
const deletedAnnotation = annotations[deletedIndex];
|
|
2284
2292
|
setDeletingMarkerId(id);
|
|
2285
2293
|
setExitingMarkers((prev) => new Set(prev).add(id));
|
|
2294
|
+
if (deletedAnnotation) {
|
|
2295
|
+
onAnnotationDelete?.(deletedAnnotation);
|
|
2296
|
+
}
|
|
2286
2297
|
setTimeout(() => {
|
|
2287
2298
|
setAnnotations((prev) => prev.filter((a) => a.id !== id));
|
|
2288
2299
|
setExitingMarkers((prev) => {
|
|
@@ -2297,7 +2308,7 @@ function PageFeedbackToolbarCSS({
|
|
|
2297
2308
|
}
|
|
2298
2309
|
}, 150);
|
|
2299
2310
|
},
|
|
2300
|
-
[annotations]
|
|
2311
|
+
[annotations, onAnnotationDelete]
|
|
2301
2312
|
);
|
|
2302
2313
|
const startEditAnnotation = (0, import_react2.useCallback)((annotation) => {
|
|
2303
2314
|
setEditingAnnotation(annotation);
|
|
@@ -2306,18 +2317,20 @@ function PageFeedbackToolbarCSS({
|
|
|
2306
2317
|
const updateAnnotation = (0, import_react2.useCallback)(
|
|
2307
2318
|
(newComment) => {
|
|
2308
2319
|
if (!editingAnnotation) return;
|
|
2320
|
+
const updatedAnnotation = { ...editingAnnotation, comment: newComment };
|
|
2309
2321
|
setAnnotations(
|
|
2310
2322
|
(prev) => prev.map(
|
|
2311
|
-
(a) => a.id === editingAnnotation.id ?
|
|
2323
|
+
(a) => a.id === editingAnnotation.id ? updatedAnnotation : a
|
|
2312
2324
|
)
|
|
2313
2325
|
);
|
|
2326
|
+
onAnnotationUpdate?.(updatedAnnotation);
|
|
2314
2327
|
setEditExiting(true);
|
|
2315
2328
|
setTimeout(() => {
|
|
2316
2329
|
setEditingAnnotation(null);
|
|
2317
2330
|
setEditExiting(false);
|
|
2318
2331
|
}, 150);
|
|
2319
2332
|
},
|
|
2320
|
-
[editingAnnotation]
|
|
2333
|
+
[editingAnnotation, onAnnotationUpdate]
|
|
2321
2334
|
);
|
|
2322
2335
|
const cancelEditAnnotation = (0, import_react2.useCallback)(() => {
|
|
2323
2336
|
setEditExiting(true);
|
|
@@ -2329,6 +2342,7 @@ function PageFeedbackToolbarCSS({
|
|
|
2329
2342
|
const clearAll = (0, import_react2.useCallback)(() => {
|
|
2330
2343
|
const count = annotations.length;
|
|
2331
2344
|
if (count === 0) return;
|
|
2345
|
+
onAnnotationsClear?.(annotations);
|
|
2332
2346
|
setIsClearing(true);
|
|
2333
2347
|
setCleared(true);
|
|
2334
2348
|
const totalAnimationTime = count * 30 + 200;
|
|
@@ -2339,11 +2353,17 @@ function PageFeedbackToolbarCSS({
|
|
|
2339
2353
|
setIsClearing(false);
|
|
2340
2354
|
}, totalAnimationTime);
|
|
2341
2355
|
setTimeout(() => setCleared(false), 1500);
|
|
2342
|
-
}, [pathname, annotations
|
|
2356
|
+
}, [pathname, annotations, onAnnotationsClear]);
|
|
2343
2357
|
const copyOutput = (0, import_react2.useCallback)(async () => {
|
|
2344
2358
|
const output = generateOutput(annotations, pathname, settings.outputDetail);
|
|
2345
2359
|
if (!output) return;
|
|
2346
|
-
|
|
2360
|
+
if (copyToClipboard) {
|
|
2361
|
+
try {
|
|
2362
|
+
await navigator.clipboard.writeText(output);
|
|
2363
|
+
} catch {
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
onCopy?.(output);
|
|
2347
2367
|
setCopied(true);
|
|
2348
2368
|
setTimeout(() => setCopied(false), 2e3);
|
|
2349
2369
|
if (settings.autoClearAfterCopy) {
|
|
@@ -2354,7 +2374,9 @@ function PageFeedbackToolbarCSS({
|
|
|
2354
2374
|
pathname,
|
|
2355
2375
|
settings.outputDetail,
|
|
2356
2376
|
settings.autoClearAfterCopy,
|
|
2357
|
-
clearAll
|
|
2377
|
+
clearAll,
|
|
2378
|
+
copyToClipboard,
|
|
2379
|
+
onCopy
|
|
2358
2380
|
]);
|
|
2359
2381
|
(0, import_react2.useEffect)(() => {
|
|
2360
2382
|
if (!dragStartPos) return;
|
|
@@ -2674,7 +2696,7 @@ function PageFeedbackToolbarCSS({
|
|
|
2674
2696
|
] }),
|
|
2675
2697
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: styles_module_default2.settingsVersion, children: [
|
|
2676
2698
|
"v",
|
|
2677
|
-
"1.
|
|
2699
|
+
"1.2.0"
|
|
2678
2700
|
] }),
|
|
2679
2701
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2680
2702
|
"button",
|
|
@@ -2765,10 +2787,10 @@ function PageFeedbackToolbarCSS({
|
|
|
2765
2787
|
className: `${styles_module_default2.colorOption} ${settings.annotationColor === color.value ? styles_module_default2.selected : ""}`,
|
|
2766
2788
|
style: { backgroundColor: color.value },
|
|
2767
2789
|
title: color.label
|
|
2768
|
-
}
|
|
2769
|
-
color.value
|
|
2790
|
+
}
|
|
2770
2791
|
)
|
|
2771
|
-
}
|
|
2792
|
+
},
|
|
2793
|
+
color.value
|
|
2772
2794
|
)) })
|
|
2773
2795
|
] }),
|
|
2774
2796
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: styles_module_default2.settingsSection, children: [
|