agentation 0.0.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.

Potentially problematic release.


This version of agentation might be problematic. Click here for more details.

package/dist/index.cjs ADDED
@@ -0,0 +1,2290 @@
1
+ "use client";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ Agentation: () => PageFeedbackToolbar,
25
+ AgentationCSS: () => PageFeedbackToolbarCSS,
26
+ AnnotationPopup: () => AnnotationPopup,
27
+ AnnotationPopupCSS: () => AnnotationPopupCSS,
28
+ AnnotationPopupPresence: () => AnnotationPopupPresence,
29
+ CopyMorphIcon: () => CopyMorphIcon,
30
+ EyeMorphIcon: () => EyeMorphIcon,
31
+ FeedbackToolbar: () => PageFeedbackToolbar,
32
+ IconChevronDown: () => IconChevronDown,
33
+ IconClose: () => IconClose,
34
+ IconExternal: () => IconExternal,
35
+ IconFeedback: () => IconFeedback,
36
+ IconPause: () => IconPause,
37
+ IconPlay: () => IconPlay,
38
+ IconPlus: () => IconPlus,
39
+ IconsCSS: () => icons_css_exports,
40
+ PageFeedbackToolbar: () => PageFeedbackToolbar,
41
+ PageFeedbackToolbarCSS: () => PageFeedbackToolbarCSS,
42
+ TrashMorphIcon: () => TrashMorphIcon,
43
+ getElementClasses: () => getElementClasses,
44
+ getElementPath: () => getElementPath,
45
+ getNearbyText: () => getNearbyText,
46
+ getStorageKey: () => getStorageKey,
47
+ identifyAnimationElement: () => identifyAnimationElement,
48
+ identifyElement: () => identifyElement,
49
+ loadAnnotations: () => loadAnnotations,
50
+ saveAnnotations: () => saveAnnotations
51
+ });
52
+ module.exports = __toCommonJS(index_exports);
53
+
54
+ // src/components/page-toolbar/index.tsx
55
+ var import_react2 = require("react");
56
+ var import_framer_motion3 = require("framer-motion");
57
+ var import_react_dom = require("react-dom");
58
+
59
+ // src/components/annotation-popup/index.tsx
60
+ var import_react = require("react");
61
+ var import_framer_motion = require("framer-motion");
62
+
63
+ // src/components/annotation-popup/styles.module.scss
64
+ var css = '.styles-module__popup___MBQDV {\n position: fixed;\n transform: translateX(-50%);\n width: 280px;\n padding: 0.75rem;\n background: white;\n border-radius: 0.75rem;\n box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.04);\n cursor: default;\n z-index: 100;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n}\n\n.styles-module__header___1q-wa {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 0.5rem;\n}\n\n.styles-module__element___tPxVO {\n font-size: 0.75rem;\n font-weight: 500;\n color: rgba(0, 0, 0, 0.65);\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n}\n\n.styles-module__timestamp___t7PEZ {\n font-size: 0.625rem;\n font-weight: 500;\n color: rgba(0, 0, 0, 0.35);\n font-variant-numeric: tabular-nums;\n margin-left: 0.5rem;\n flex-shrink: 0;\n}\n\n.styles-module__quote___uFJyr {\n font-size: 0.6875rem;\n font-style: italic;\n color: rgba(0, 0, 0, 0.5);\n margin-bottom: 0.5rem;\n padding: 0.4rem 0.5rem;\n background: rgba(0, 0, 0, 0.03);\n border-radius: 0.25rem;\n line-height: 1.45;\n}\n\n.styles-module__textarea___Pw6C4 {\n width: 100%;\n padding: 0.5rem 0.625rem;\n font-size: 0.8125rem;\n font-family: inherit;\n border: 1px solid rgba(0, 0, 0, 0.12);\n border-radius: 0.375rem;\n resize: none;\n outline: none;\n transition: border-color 0.15s ease;\n}\n.styles-module__textarea___Pw6C4:focus {\n border-color: #3c82f7;\n}\n.styles-module__textarea___Pw6C4::placeholder {\n color: rgba(0, 0, 0, 0.35);\n}\n\n.styles-module__actions___bxQCu {\n display: flex;\n justify-content: flex-end;\n gap: 0.375rem;\n margin-top: 0.5rem;\n}\n\n.styles-module__cancel___-xAEc,\n.styles-module__submit___nnXO9 {\n padding: 0.4rem 0.875rem;\n font-size: 0.75rem;\n font-weight: 500;\n border-radius: 1rem;\n border: none;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.styles-module__cancel___-xAEc {\n background: transparent;\n color: rgba(0, 0, 0, 0.5);\n}\n.styles-module__cancel___-xAEc:hover {\n background: rgba(0, 0, 0, 0.05);\n color: rgba(0, 0, 0, 0.7);\n}\n\n.styles-module__submit___nnXO9 {\n background: #3c82f7;\n color: white;\n}\n.styles-module__submit___nnXO9:hover:not(:disabled) {\n background: #2d6fdf;\n}\n.styles-module__submit___nnXO9:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.styles-module__submit___nnXO9.styles-module__green___zdmke {\n background: #34C759;\n}\n.styles-module__submit___nnXO9.styles-module__green___zdmke:hover:not(:disabled) {\n background: #2db84d;\n}';
65
+ var classNames = { "popup": "styles-module__popup___MBQDV", "header": "styles-module__header___1q-wa", "element": "styles-module__element___tPxVO", "timestamp": "styles-module__timestamp___t7PEZ", "quote": "styles-module__quote___uFJyr", "textarea": "styles-module__textarea___Pw6C4", "actions": "styles-module__actions___bxQCu", "cancel": "styles-module__cancel___-xAEc", "submit": "styles-module__submit___nnXO9", "green": "styles-module__green___zdmke" };
66
+ if (typeof document !== "undefined") {
67
+ let style = document.getElementById("feedback-tool-styles-annotation-popup-styles");
68
+ if (!style) {
69
+ style = document.createElement("style");
70
+ style.id = "feedback-tool-styles-annotation-popup-styles";
71
+ style.textContent = css;
72
+ document.head.appendChild(style);
73
+ }
74
+ }
75
+ var styles_module_default = classNames;
76
+
77
+ // src/components/annotation-popup/index.tsx
78
+ var import_jsx_runtime = require("react/jsx-runtime");
79
+ var AnnotationPopup = (0, import_react.forwardRef)(
80
+ function AnnotationPopup2({
81
+ element,
82
+ timestamp,
83
+ selectedText,
84
+ placeholder = "What should change?",
85
+ onSubmit,
86
+ onCancel,
87
+ style,
88
+ variant = "blue"
89
+ }, ref) {
90
+ const [text, setText] = (0, import_react.useState)("");
91
+ const textareaRef = (0, import_react.useRef)(null);
92
+ const controls = (0, import_framer_motion.useAnimation)();
93
+ (0, import_react.useEffect)(() => {
94
+ controls.start({ opacity: 1, scale: 1, y: 0 });
95
+ const timer = setTimeout(() => textareaRef.current?.focus(), 10);
96
+ return () => clearTimeout(timer);
97
+ }, [controls]);
98
+ const shake = (0, import_react.useCallback)(async () => {
99
+ await controls.start({
100
+ x: [0, -3, 3, -2, 2, 0],
101
+ transition: { duration: 0.25, ease: "easeOut" }
102
+ });
103
+ textareaRef.current?.focus();
104
+ }, [controls]);
105
+ (0, import_react.useImperativeHandle)(ref, () => ({
106
+ shake
107
+ }), [shake]);
108
+ const handleSubmit = (0, import_react.useCallback)(() => {
109
+ if (!text.trim()) return;
110
+ onSubmit(text.trim());
111
+ }, [text, onSubmit]);
112
+ const handleKeyDown = (0, import_react.useCallback)(
113
+ (e) => {
114
+ if (e.key === "Enter" && !e.shiftKey) {
115
+ e.preventDefault();
116
+ handleSubmit();
117
+ }
118
+ if (e.key === "Escape") {
119
+ onCancel();
120
+ }
121
+ },
122
+ [handleSubmit, onCancel]
123
+ );
124
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
125
+ import_framer_motion.motion.div,
126
+ {
127
+ className: styles_module_default.popup,
128
+ "data-annotation-popup": true,
129
+ initial: { opacity: 0, scale: 0.95, y: 4 },
130
+ animate: controls,
131
+ exit: { opacity: 0, scale: 0.95, y: 4 },
132
+ transition: { type: "spring", stiffness: 500, damping: 35 },
133
+ style,
134
+ onClick: (e) => e.stopPropagation(),
135
+ children: [
136
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles_module_default.header, children: [
137
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles_module_default.element, children: element }),
138
+ timestamp && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles_module_default.timestamp, children: timestamp })
139
+ ] }),
140
+ selectedText && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles_module_default.quote, children: [
141
+ "\u201C",
142
+ selectedText.slice(0, 80),
143
+ selectedText.length > 80 ? "..." : "",
144
+ "\u201D"
145
+ ] }),
146
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
147
+ "textarea",
148
+ {
149
+ ref: textareaRef,
150
+ className: styles_module_default.textarea,
151
+ placeholder,
152
+ value: text,
153
+ onChange: (e) => setText(e.target.value),
154
+ rows: 2,
155
+ onKeyDown: handleKeyDown
156
+ }
157
+ ),
158
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles_module_default.actions, children: [
159
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: styles_module_default.cancel, onClick: onCancel, children: "Cancel" }),
160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
161
+ "button",
162
+ {
163
+ className: `${styles_module_default.submit} ${variant === "green" ? styles_module_default.green : ""}`,
164
+ onClick: handleSubmit,
165
+ disabled: !text.trim(),
166
+ children: "Add"
167
+ }
168
+ )
169
+ ] })
170
+ ]
171
+ }
172
+ );
173
+ }
174
+ );
175
+ function AnnotationPopupPresence({
176
+ isOpen,
177
+ ...props
178
+ }) {
179
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_framer_motion.AnimatePresence, { children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AnnotationPopup, { ...props }) });
180
+ }
181
+
182
+ // src/components/icons.tsx
183
+ var import_framer_motion2 = require("framer-motion");
184
+ var import_jsx_runtime2 = require("react/jsx-runtime");
185
+ var transition = { type: "spring", stiffness: 500, damping: 30 };
186
+ var IconFeedback = ({ size = 18 }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: [
187
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12,4c4.97,0,8.9,4.56,7.82,9.72c-0.68,3.23-3.4,5.74-6.67,6.2c-1.59,0.22-3.14-0.01-4.58-0.7 c-0.27-0.13-0.56-0.19-0.86-0.19c-0.19,0-0.38,0.03-0.56,0.08l-2.31,0.68c-0.38,0.11-0.74-0.24-0.63-0.63l0.7-2.39 c0.13-0.45,0.07-0.92-0.14-1.35C4.26,14.34,4,13.18,4,12C4,7.59,7.59,4,12,4 M12,2C6.48,2,2,6.48,2,12c0,1.54,0.36,2.98,0.97,4.29 l-1.46,4.96C1.29,22,2,22.71,2.76,22.48l4.96-1.46c1.66,0.79,3.56,1.15,5.58,0.89c4.56-0.59,8.21-4.35,8.66-8.92 C22.53,7.03,17.85,2,12,2L12,2z" }),
188
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12,8L12,8c-0.55,0-1,0.45-1,1v2H9c-0.55,0-1,0.45-1,1v0c0,0.55,0.45,1,1,1h2v2 c0,0.55,0.45,1,1,1h0c0.55,0,1-0.45,1-1v-2h2c0.55,0,1-0.45,1-1v0c0-0.55-0.45-1-1-1h-2V9C13,8.45,12.55,8,12,8z", fillRule: "evenodd" })
189
+ ] });
190
+ var IconPlay = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
191
+ "path",
192
+ {
193
+ d: "M5 3.5v9l7-4.5-7-4.5z",
194
+ stroke: "currentColor",
195
+ strokeWidth: "1.5",
196
+ strokeLinejoin: "round"
197
+ }
198
+ ) });
199
+ var IconPause = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5.5 4v8M10.5 4v8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) });
200
+ var EyeMorphIcon = ({ size = 16, visible }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: [
201
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 4C7 4 2.73 7.11 1 11.5 2.73 15.89 7 19 12 19s9.27-3.11 11-7.5C21.27 7.11 17 4 12 4zm0 12.5c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" }),
202
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
203
+ import_framer_motion2.motion.g,
204
+ {
205
+ initial: false,
206
+ animate: { opacity: visible ? 0 : 1 },
207
+ transition: { duration: 0.15 },
208
+ children: [
209
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "4", y1: "20", x2: "20", y2: "4", stroke: "white", strokeWidth: "4", strokeLinecap: "round" }),
210
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "4", y1: "20", x2: "20", y2: "4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
211
+ ]
212
+ }
213
+ )
214
+ ] });
215
+ var CopyMorphIcon = ({ size = 16, checked }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: [
216
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
217
+ import_framer_motion2.motion.path,
218
+ {
219
+ d: "M14.17,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V9.83c0-0.53-0.21-1.04-0.59-1.41l-4.83-4.83 C15.21,3.21,14.7,3,14.17,3L14.17,3z M8,15h8c0.55,0,1,0.45,1,1v0c0,0.55-0.45,1-1,1H8c-0.55,0-1-0.45-1-1v0C7,15.45,7.45,15,8,15z M8,11h8c0.55,0,1,0.45,1,1v0c0,0.55-0.45,1-1,1H8c-0.55,0-1-0.45-1-1v0C7,11.45,7.45,11,8,11z M8,7h5c0.55,0,1,0.45,1,1v0 c0,0.55-0.45,1-1,1H8C7.45,9,7,8.55,7,8v0C7,7.45,7.45,7,8,7z",
220
+ initial: false,
221
+ animate: { opacity: checked ? 0 : 1 },
222
+ transition: { duration: 0.15 }
223
+ }
224
+ ),
225
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
226
+ import_framer_motion2.motion.path,
227
+ {
228
+ d: "M6 12.5l3.5 3.5L18 7",
229
+ stroke: "currentColor",
230
+ strokeWidth: "2.5",
231
+ strokeLinecap: "round",
232
+ strokeLinejoin: "round",
233
+ fill: "none",
234
+ initial: false,
235
+ animate: { opacity: checked ? 1 : 0, scale: checked ? 1 : 0.5 },
236
+ transition,
237
+ style: { transformOrigin: "12px 12px" }
238
+ }
239
+ )
240
+ ] });
241
+ var TrashMorphIcon = ({ size = 16, checked }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: [
242
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
243
+ import_framer_motion2.motion.path,
244
+ {
245
+ d: "M17.65 6.35c-1.63-1.63-3.94-2.57-6.48-2.31-3.67.37-6.69 3.35-7.1 7.02C3.52 15.91 7.27 20 12 20c3.19 0 5.93-1.87 7.21-4.56.32-.67-.16-1.44-.9-1.44-.37 0-.72.2-.88.53-1.13 2.43-3.84 3.97-6.8 3.31-2.22-.49-4.01-2.3-4.48-4.52C5.31 9.44 8.26 6 12 6c1.66 0 3.14.69 4.22 1.78l-1.51 1.51c-.63.63-.19 1.71.7 1.71H19c.55 0 1-.45 1-1V6.41c0-.89-1.08-1.34-1.71-.71l-.64.65z",
246
+ initial: false,
247
+ animate: { opacity: checked ? 0 : 1 },
248
+ transition: { duration: 0.15 }
249
+ }
250
+ ),
251
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
252
+ import_framer_motion2.motion.path,
253
+ {
254
+ d: "M6 12.5l3.5 3.5L18 7",
255
+ stroke: "currentColor",
256
+ strokeWidth: "2.5",
257
+ strokeLinecap: "round",
258
+ strokeLinejoin: "round",
259
+ fill: "none",
260
+ initial: false,
261
+ animate: { opacity: checked ? 1 : 0, scale: checked ? 1 : 0.5 },
262
+ transition,
263
+ style: { transformOrigin: "12px 12px" }
264
+ }
265
+ )
266
+ ] });
267
+ var IconExternal = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
268
+ "path",
269
+ {
270
+ d: "M6 3h7v7M13 3L6 10",
271
+ stroke: "currentColor",
272
+ strokeWidth: "1.5",
273
+ strokeLinecap: "round",
274
+ strokeLinejoin: "round"
275
+ }
276
+ ) });
277
+ var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
278
+ "path",
279
+ {
280
+ d: "M4 6l4 4 4-4",
281
+ stroke: "currentColor",
282
+ strokeWidth: "1.75",
283
+ strokeLinecap: "round",
284
+ strokeLinejoin: "round"
285
+ }
286
+ ) });
287
+ var IconClose = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 4l8 8M12 4l-8 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) });
288
+ var IconPlus = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 3v10M3 8h10", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) });
289
+
290
+ // src/utils/element-identification.ts
291
+ function getElementPath(target, maxDepth = 4) {
292
+ const parts = [];
293
+ let current = target;
294
+ let depth = 0;
295
+ while (current && depth < maxDepth) {
296
+ const tag = current.tagName.toLowerCase();
297
+ if (tag === "html" || tag === "body") break;
298
+ let identifier = tag;
299
+ if (current.id) {
300
+ identifier = `#${current.id}`;
301
+ } else if (current.className && typeof current.className === "string") {
302
+ const meaningfulClass = current.className.split(/\s+/).find((c) => c.length > 2 && !c.match(/^[a-z]{1,2}$/) && !c.match(/[A-Z0-9]{5,}/));
303
+ if (meaningfulClass) {
304
+ identifier = `.${meaningfulClass.split("_")[0]}`;
305
+ }
306
+ }
307
+ parts.unshift(identifier);
308
+ current = current.parentElement;
309
+ depth++;
310
+ }
311
+ return parts.join(" > ");
312
+ }
313
+ function identifyElement(target) {
314
+ const path = getElementPath(target);
315
+ if (target.dataset.element) {
316
+ return { name: target.dataset.element, path };
317
+ }
318
+ const tag = target.tagName.toLowerCase();
319
+ if (["path", "circle", "rect", "line", "g"].includes(tag)) {
320
+ const svg = target.closest("svg");
321
+ if (svg) {
322
+ const parent = svg.parentElement;
323
+ if (parent) {
324
+ const parentName = identifyElement(parent).name;
325
+ return { name: `graphic in ${parentName}`, path };
326
+ }
327
+ }
328
+ return { name: "graphic element", path };
329
+ }
330
+ if (tag === "svg") {
331
+ const parent = target.parentElement;
332
+ if (parent?.tagName.toLowerCase() === "button") {
333
+ const btnText = parent.textContent?.trim();
334
+ return { name: btnText ? `icon in "${btnText}" button` : "button icon", path };
335
+ }
336
+ return { name: "icon", path };
337
+ }
338
+ if (tag === "button") {
339
+ const text = target.textContent?.trim();
340
+ const ariaLabel = target.getAttribute("aria-label");
341
+ if (ariaLabel) return { name: `button [${ariaLabel}]`, path };
342
+ return { name: text ? `button "${text.slice(0, 25)}"` : "button", path };
343
+ }
344
+ if (tag === "a") {
345
+ const text = target.textContent?.trim();
346
+ const href = target.getAttribute("href");
347
+ if (text) return { name: `link "${text.slice(0, 25)}"`, path };
348
+ if (href) return { name: `link to ${href.slice(0, 30)}`, path };
349
+ return { name: "link", path };
350
+ }
351
+ if (tag === "input") {
352
+ const type = target.getAttribute("type") || "text";
353
+ const placeholder = target.getAttribute("placeholder");
354
+ const name = target.getAttribute("name");
355
+ if (placeholder) return { name: `input "${placeholder}"`, path };
356
+ if (name) return { name: `input [${name}]`, path };
357
+ return { name: `${type} input`, path };
358
+ }
359
+ if (["h1", "h2", "h3", "h4", "h5", "h6"].includes(tag)) {
360
+ const text = target.textContent?.trim();
361
+ return { name: text ? `${tag} "${text.slice(0, 35)}"` : tag, path };
362
+ }
363
+ if (tag === "p") {
364
+ const text = target.textContent?.trim();
365
+ if (text) return { name: `paragraph: "${text.slice(0, 40)}${text.length > 40 ? "..." : ""}"`, path };
366
+ return { name: "paragraph", path };
367
+ }
368
+ if (tag === "span" || tag === "label") {
369
+ const text = target.textContent?.trim();
370
+ if (text && text.length < 40) return { name: `"${text}"`, path };
371
+ return { name: tag, path };
372
+ }
373
+ if (tag === "li") {
374
+ const text = target.textContent?.trim();
375
+ if (text && text.length < 40) return { name: `list item: "${text.slice(0, 35)}"`, path };
376
+ return { name: "list item", path };
377
+ }
378
+ if (tag === "blockquote") return { name: "blockquote", path };
379
+ if (tag === "code") {
380
+ const text = target.textContent?.trim();
381
+ if (text && text.length < 30) return { name: `code: \`${text}\``, path };
382
+ return { name: "code", path };
383
+ }
384
+ if (tag === "pre") return { name: "code block", path };
385
+ if (tag === "img") {
386
+ const alt = target.getAttribute("alt");
387
+ return { name: alt ? `image "${alt.slice(0, 30)}"` : "image", path };
388
+ }
389
+ if (tag === "video") return { name: "video", path };
390
+ if (["div", "section", "article", "nav", "header", "footer", "aside", "main"].includes(tag)) {
391
+ const className = target.className;
392
+ const role = target.getAttribute("role");
393
+ const ariaLabel = target.getAttribute("aria-label");
394
+ if (ariaLabel) return { name: `${tag} [${ariaLabel}]`, path };
395
+ if (role) return { name: `${role}`, path };
396
+ if (typeof className === "string" && className) {
397
+ const words = className.split(/[\s_-]+/).map((c) => c.replace(/[A-Z0-9]{5,}.*$/, "")).filter((c) => c.length > 2 && !/^[a-z]{1,2}$/.test(c)).slice(0, 2);
398
+ if (words.length > 0) return { name: words.join(" "), path };
399
+ }
400
+ return { name: tag === "div" ? "container" : tag, path };
401
+ }
402
+ return { name: tag, path };
403
+ }
404
+ function getNearbyText(element) {
405
+ const texts = [];
406
+ const ownText = element.textContent?.trim();
407
+ if (ownText && ownText.length < 100) {
408
+ texts.push(ownText);
409
+ }
410
+ const prev = element.previousElementSibling;
411
+ if (prev) {
412
+ const prevText = prev.textContent?.trim();
413
+ if (prevText && prevText.length < 50) {
414
+ texts.unshift(`[before: "${prevText.slice(0, 40)}"]`);
415
+ }
416
+ }
417
+ const next = element.nextElementSibling;
418
+ if (next) {
419
+ const nextText = next.textContent?.trim();
420
+ if (nextText && nextText.length < 50) {
421
+ texts.push(`[after: "${nextText.slice(0, 40)}"]`);
422
+ }
423
+ }
424
+ return texts.join(" ");
425
+ }
426
+ function identifyAnimationElement(target) {
427
+ if (target.dataset.element) return target.dataset.element;
428
+ const tag = target.tagName.toLowerCase();
429
+ if (tag === "path") return "path";
430
+ if (tag === "circle") return "circle";
431
+ if (tag === "rect") return "rectangle";
432
+ if (tag === "line") return "line";
433
+ if (tag === "ellipse") return "ellipse";
434
+ if (tag === "polygon") return "polygon";
435
+ if (tag === "g") return "group";
436
+ if (tag === "svg") return "svg";
437
+ if (tag === "button") {
438
+ const text = target.textContent?.trim();
439
+ return text ? `button "${text}"` : "button";
440
+ }
441
+ if (tag === "input") {
442
+ const type = target.getAttribute("type") || "text";
443
+ return `input (${type})`;
444
+ }
445
+ if (tag === "span" || tag === "p" || tag === "label") {
446
+ const text = target.textContent?.trim();
447
+ if (text && text.length < 30) return `"${text}"`;
448
+ return "text";
449
+ }
450
+ if (tag === "div") {
451
+ const className = target.className;
452
+ if (typeof className === "string" && className) {
453
+ const words = className.split(/[\s_-]+/).map((c) => c.replace(/[A-Z0-9]{5,}.*$/, "")).filter((c) => c.length > 2 && !/^[a-z]{1,2}$/.test(c)).slice(0, 2);
454
+ if (words.length > 0) {
455
+ return words.join(" ");
456
+ }
457
+ }
458
+ return "container";
459
+ }
460
+ return tag;
461
+ }
462
+ function getNearbyElements(element) {
463
+ const parent = element.parentElement;
464
+ if (!parent) return "";
465
+ const siblings = Array.from(parent.children).filter(
466
+ (child) => child !== element && child instanceof HTMLElement
467
+ );
468
+ if (siblings.length === 0) return "";
469
+ const siblingIds = siblings.slice(0, 4).map((sib) => {
470
+ const tag = sib.tagName.toLowerCase();
471
+ const className = sib.className;
472
+ let cls = "";
473
+ if (typeof className === "string" && className) {
474
+ const meaningful = className.split(/\s+/).map((c) => c.replace(/[_][a-zA-Z0-9]{5,}.*$/, "")).find((c) => c.length > 2 && !/^[a-z]{1,2}$/.test(c));
475
+ if (meaningful) cls = `.${meaningful}`;
476
+ }
477
+ if (tag === "button" || tag === "a") {
478
+ const text = sib.textContent?.trim().slice(0, 15);
479
+ if (text) return `${tag}${cls} "${text}"`;
480
+ }
481
+ return `${tag}${cls}`;
482
+ });
483
+ const parentTag = parent.tagName.toLowerCase();
484
+ let parentId = parentTag;
485
+ if (typeof parent.className === "string" && parent.className) {
486
+ const parentCls = parent.className.split(/\s+/).map((c) => c.replace(/[_][a-zA-Z0-9]{5,}.*$/, "")).find((c) => c.length > 2 && !/^[a-z]{1,2}$/.test(c));
487
+ if (parentCls) parentId = `.${parentCls}`;
488
+ }
489
+ const total = parent.children.length;
490
+ const suffix = total > siblingIds.length + 1 ? ` (${total} total in ${parentId})` : "";
491
+ return siblingIds.join(", ") + suffix;
492
+ }
493
+ function getElementClasses(target) {
494
+ const className = target.className;
495
+ if (typeof className !== "string" || !className) return "";
496
+ const classes = className.split(/\s+/).filter((c) => c.length > 0).map((c) => {
497
+ const match = c.match(/^([a-zA-Z][a-zA-Z0-9_-]*?)(?:_[a-zA-Z0-9]{5,})?$/);
498
+ return match ? match[1] : c;
499
+ }).filter((c, i, arr) => arr.indexOf(c) === i);
500
+ return classes.join(", ");
501
+ }
502
+ function getComputedStylesSnapshot(target) {
503
+ if (typeof window === "undefined") return "";
504
+ const styles = window.getComputedStyle(target);
505
+ const parts = [];
506
+ const color = styles.color;
507
+ const bg = styles.backgroundColor;
508
+ if (color && color !== "rgb(0, 0, 0)") parts.push(`color: ${color}`);
509
+ if (bg && bg !== "rgba(0, 0, 0, 0)" && bg !== "transparent") parts.push(`bg: ${bg}`);
510
+ const fontSize = styles.fontSize;
511
+ const fontWeight = styles.fontWeight;
512
+ if (fontSize) parts.push(`font: ${fontSize}`);
513
+ if (fontWeight && fontWeight !== "400" && fontWeight !== "normal") parts.push(`weight: ${fontWeight}`);
514
+ const padding = styles.padding;
515
+ const margin = styles.margin;
516
+ if (padding && padding !== "0px") parts.push(`padding: ${padding}`);
517
+ if (margin && margin !== "0px") parts.push(`margin: ${margin}`);
518
+ const display = styles.display;
519
+ const position = styles.position;
520
+ if (display && display !== "block" && display !== "inline") parts.push(`display: ${display}`);
521
+ if (position && position !== "static") parts.push(`position: ${position}`);
522
+ const borderRadius = styles.borderRadius;
523
+ if (borderRadius && borderRadius !== "0px") parts.push(`radius: ${borderRadius}`);
524
+ return parts.join(", ");
525
+ }
526
+ function getAccessibilityInfo(target) {
527
+ const parts = [];
528
+ const role = target.getAttribute("role");
529
+ const ariaLabel = target.getAttribute("aria-label");
530
+ const ariaDescribedBy = target.getAttribute("aria-describedby");
531
+ const tabIndex = target.getAttribute("tabindex");
532
+ const ariaHidden = target.getAttribute("aria-hidden");
533
+ if (role) parts.push(`role="${role}"`);
534
+ if (ariaLabel) parts.push(`aria-label="${ariaLabel}"`);
535
+ if (ariaDescribedBy) parts.push(`aria-describedby="${ariaDescribedBy}"`);
536
+ if (tabIndex) parts.push(`tabindex=${tabIndex}`);
537
+ if (ariaHidden === "true") parts.push("aria-hidden");
538
+ const focusable = target.matches("a, button, input, select, textarea, [tabindex]");
539
+ if (focusable) parts.push("focusable");
540
+ return parts.join(", ");
541
+ }
542
+ function getFullElementPath(target) {
543
+ const parts = [];
544
+ let current = target;
545
+ while (current && current.tagName.toLowerCase() !== "html") {
546
+ const tag = current.tagName.toLowerCase();
547
+ let identifier = tag;
548
+ if (current.id) {
549
+ identifier = `${tag}#${current.id}`;
550
+ } else if (current.className && typeof current.className === "string") {
551
+ const cls = current.className.split(/\s+/).map((c) => c.replace(/[_][a-zA-Z0-9]{5,}.*$/, "")).find((c) => c.length > 2);
552
+ if (cls) identifier = `${tag}.${cls}`;
553
+ }
554
+ parts.unshift(identifier);
555
+ current = current.parentElement;
556
+ }
557
+ return parts.join(" > ");
558
+ }
559
+
560
+ // src/utils/storage.ts
561
+ var STORAGE_PREFIX = "feedback-annotations-";
562
+ var DEFAULT_RETENTION_DAYS = 7;
563
+ function getStorageKey(pathname) {
564
+ return `${STORAGE_PREFIX}${pathname}`;
565
+ }
566
+ function loadAnnotations(pathname) {
567
+ if (typeof window === "undefined") return [];
568
+ try {
569
+ const stored = localStorage.getItem(getStorageKey(pathname));
570
+ if (!stored) return [];
571
+ const data = JSON.parse(stored);
572
+ const cutoff = Date.now() - DEFAULT_RETENTION_DAYS * 24 * 60 * 60 * 1e3;
573
+ return data.filter((a) => !a.timestamp || a.timestamp > cutoff);
574
+ } catch {
575
+ return [];
576
+ }
577
+ }
578
+ function saveAnnotations(pathname, annotations) {
579
+ if (typeof window === "undefined") return;
580
+ try {
581
+ localStorage.setItem(getStorageKey(pathname), JSON.stringify(annotations));
582
+ } catch {
583
+ }
584
+ }
585
+
586
+ // src/components/page-toolbar/styles.module.scss
587
+ var css2 = '.styles-module__toolbar___50aIA {\n position: fixed;\n bottom: 1.25rem;\n right: 1.25rem;\n z-index: 100000;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n}\n\n.styles-module__toggleButton___kgnvI {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 22px;\n border: none;\n background: #1a1a1a;\n color: #fff;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1);\n transition: all 0.15s ease;\n}\n.styles-module__toggleButton___kgnvI svg {\n margin-top: -1px;\n}\n.styles-module__toggleButton___kgnvI:hover {\n background: #2a2a2a;\n}\n\n.styles-module__badge___WRMxo {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: 9px;\n background: #3c82f7;\n color: white;\n font-size: 0.625rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.styles-module__controls___2-kD- {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.375rem;\n border-radius: 1.5rem;\n background: #1a1a1a;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1);\n}\n\n.styles-module__controlButton___RB3R5 {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n height: 34px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: rgba(255, 255, 255, 0.85);\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.styles-module__controlButton___RB3R5:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.12);\n color: #fff;\n}\n.styles-module__controlButton___RB3R5:active:not(:disabled) {\n transform: scale(0.92);\n}\n.styles-module__controlButton___RB3R5:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n.styles-module__controlButton___RB3R5[data-active=true] {\n color: #3c82f7;\n background: rgba(60, 130, 247, 0.25);\n}\n.styles-module__controlButton___RB3R5[data-danger]:hover:not(:disabled) {\n background: rgba(255, 59, 48, 0.25);\n color: #ff3b30;\n}\n\n.styles-module__divider___yO3YX {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n margin: 0 0.125rem;\n}\n\n.styles-module__overlay___pQK74 {\n position: fixed;\n inset: 0;\n z-index: 99999;\n pointer-events: none;\n}\n.styles-module__overlay___pQK74 > * {\n pointer-events: auto;\n}\n\n.styles-module__hoverHighlight___iUTDq {\n position: fixed;\n border: 2px solid rgba(60, 130, 247, 0.5);\n border-radius: 4px;\n pointer-events: none !important;\n background: rgba(60, 130, 247, 0.04);\n box-sizing: border-box;\n will-change: opacity;\n contain: layout style;\n}\n\n.styles-module__hoverTooltip___eOid- {\n position: fixed;\n font-size: 0.6875rem;\n font-weight: 500;\n color: #fff;\n background: rgba(0, 0, 0, 0.85);\n padding: 0.35rem 0.6rem;\n border-radius: 0.375rem;\n pointer-events: none !important;\n white-space: nowrap;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.styles-module__markersLayer___RFGiE {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n z-index: 99998;\n pointer-events: none;\n}\n.styles-module__markersLayer___RFGiE > * {\n pointer-events: auto;\n}\n\n.styles-module__marker___XNegd {\n position: absolute;\n width: 22px;\n height: 22px;\n background: #3c82f7;\n color: white;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.6875rem;\n font-weight: 600;\n transform: translate(-50%, -50%);\n cursor: pointer;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n transition: background 0.15s ease;\n user-select: none;\n will-change: transform;\n contain: layout style;\n}\n.styles-module__marker___XNegd.styles-module__pending___h4sf4 {\n position: fixed;\n background: #3c82f7;\n}\n.styles-module__marker___XNegd.styles-module__hovered___WMoLv {\n background: #ff3b30;\n}\n\n.styles-module__markerTooltip___pbJGs {\n position: absolute;\n top: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n background: white;\n padding: 0.625rem 0.75rem;\n border-radius: 0.5rem;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04);\n min-width: 160px;\n max-width: 280px;\n pointer-events: none;\n cursor: default;\n}\n\n.styles-module__markerQuote___bZuZt {\n display: block;\n font-size: 0.6875rem;\n font-style: italic;\n color: rgba(0, 0, 0, 0.5);\n margin-bottom: 0.375rem;\n line-height: 1.4;\n}\n\n.styles-module__markerNote___AvTvH {\n display: block;\n font-size: 0.75rem;\n font-weight: 450;\n line-height: 1.4;\n color: #333;\n white-space: normal;\n}\n\n.styles-module__markerHint___drxqW {\n display: block;\n font-size: 0.625rem;\n font-weight: 400;\n color: rgba(0, 0, 0, 0.3);\n margin-top: 0.375rem;\n}';
588
+ var classNames2 = { "toolbar": "styles-module__toolbar___50aIA", "toggleButton": "styles-module__toggleButton___kgnvI", "badge": "styles-module__badge___WRMxo", "controls": "styles-module__controls___2-kD-", "controlButton": "styles-module__controlButton___RB3R5", "divider": "styles-module__divider___yO3YX", "overlay": "styles-module__overlay___pQK74", "hoverHighlight": "styles-module__hoverHighlight___iUTDq", "hoverTooltip": "styles-module__hoverTooltip___eOid-", "markersLayer": "styles-module__markersLayer___RFGiE", "marker": "styles-module__marker___XNegd", "pending": "styles-module__pending___h4sf4", "hovered": "styles-module__hovered___WMoLv", "markerTooltip": "styles-module__markerTooltip___pbJGs", "markerQuote": "styles-module__markerQuote___bZuZt", "markerNote": "styles-module__markerNote___AvTvH", "markerHint": "styles-module__markerHint___drxqW" };
589
+ if (typeof document !== "undefined") {
590
+ let style = document.getElementById("feedback-tool-styles-page-toolbar-styles");
591
+ if (!style) {
592
+ style = document.createElement("style");
593
+ style.id = "feedback-tool-styles-page-toolbar-styles";
594
+ style.textContent = css2;
595
+ document.head.appendChild(style);
596
+ }
597
+ }
598
+ var styles_module_default2 = classNames2;
599
+
600
+ // src/components/page-toolbar/index.tsx
601
+ var import_jsx_runtime3 = require("react/jsx-runtime");
602
+ function generateOutput(annotations, pathname) {
603
+ if (annotations.length === 0) return "";
604
+ const viewport = typeof window !== "undefined" ? `${window.innerWidth}\xD7${window.innerHeight}` : "unknown";
605
+ let output = `## Page Feedback: ${pathname}
606
+ `;
607
+ output += `**Viewport:** ${viewport}
608
+
609
+ `;
610
+ annotations.forEach((a, i) => {
611
+ output += `### ${i + 1}. ${a.element}
612
+ `;
613
+ output += `**Location:** ${a.elementPath}
614
+ `;
615
+ if (a.cssClasses) {
616
+ output += `**Classes:** ${a.cssClasses}
617
+ `;
618
+ }
619
+ if (a.boundingBox) {
620
+ output += `**Position:** ${Math.round(a.boundingBox.x)}px, ${Math.round(a.boundingBox.y)}px (${Math.round(a.boundingBox.width)}\xD7${Math.round(a.boundingBox.height)}px)
621
+ `;
622
+ }
623
+ if (a.selectedText) {
624
+ output += `**Selected text:** "${a.selectedText}"
625
+ `;
626
+ }
627
+ if (a.nearbyText && !a.selectedText) {
628
+ output += `**Context:** ${a.nearbyText.slice(0, 100)}
629
+ `;
630
+ }
631
+ output += `**Feedback:** ${a.comment}
632
+
633
+ `;
634
+ });
635
+ return output.trim();
636
+ }
637
+ function PageFeedbackToolbar() {
638
+ const [isActive, setIsActive] = (0, import_react2.useState)(false);
639
+ const [annotations, setAnnotations] = (0, import_react2.useState)([]);
640
+ const [showMarkers, setShowMarkers] = (0, import_react2.useState)(true);
641
+ const [hoverInfo, setHoverInfo] = (0, import_react2.useState)(null);
642
+ const [hoverPosition, setHoverPosition] = (0, import_react2.useState)({ x: 0, y: 0 });
643
+ const [pendingAnnotation, setPendingAnnotation] = (0, import_react2.useState)(null);
644
+ const [copied, setCopied] = (0, import_react2.useState)(false);
645
+ const [cleared, setCleared] = (0, import_react2.useState)(false);
646
+ const [hoveredMarkerId, setHoveredMarkerId] = (0, import_react2.useState)(null);
647
+ const [scrollY, setScrollY] = (0, import_react2.useState)(0);
648
+ const [mounted, setMounted] = (0, import_react2.useState)(false);
649
+ const [isFrozen, setIsFrozen] = (0, import_react2.useState)(false);
650
+ const popupRef = (0, import_react2.useRef)(null);
651
+ const pathname = typeof window !== "undefined" ? window.location.pathname : "/";
652
+ (0, import_react2.useEffect)(() => {
653
+ setMounted(true);
654
+ setScrollY(window.scrollY);
655
+ const stored = loadAnnotations(pathname);
656
+ setAnnotations(stored);
657
+ }, [pathname]);
658
+ (0, import_react2.useEffect)(() => {
659
+ const handleScroll = () => setScrollY(window.scrollY);
660
+ window.addEventListener("scroll", handleScroll, { passive: true });
661
+ return () => window.removeEventListener("scroll", handleScroll);
662
+ }, []);
663
+ (0, import_react2.useEffect)(() => {
664
+ if (mounted && annotations.length > 0) {
665
+ saveAnnotations(pathname, annotations);
666
+ } else if (mounted && annotations.length === 0) {
667
+ localStorage.removeItem(getStorageKey(pathname));
668
+ }
669
+ }, [annotations, pathname, mounted]);
670
+ const freezeAnimations = (0, import_react2.useCallback)(() => {
671
+ if (isFrozen) return;
672
+ const style = document.createElement("style");
673
+ style.id = "feedback-freeze-styles";
674
+ style.textContent = `
675
+ *, *::before, *::after {
676
+ animation-play-state: paused !important;
677
+ transition: none !important;
678
+ }
679
+ `;
680
+ document.head.appendChild(style);
681
+ document.querySelectorAll("video").forEach((video) => {
682
+ if (!video.paused) {
683
+ video.dataset.wasPaused = "false";
684
+ video.pause();
685
+ }
686
+ });
687
+ setIsFrozen(true);
688
+ }, [isFrozen]);
689
+ const unfreezeAnimations = (0, import_react2.useCallback)(() => {
690
+ if (!isFrozen) return;
691
+ const style = document.getElementById("feedback-freeze-styles");
692
+ if (style) style.remove();
693
+ document.querySelectorAll("video").forEach((video) => {
694
+ if (video.dataset.wasPaused === "false") {
695
+ video.play();
696
+ delete video.dataset.wasPaused;
697
+ }
698
+ });
699
+ setIsFrozen(false);
700
+ }, [isFrozen]);
701
+ const toggleFreeze = (0, import_react2.useCallback)(() => {
702
+ if (isFrozen) {
703
+ unfreezeAnimations();
704
+ } else {
705
+ freezeAnimations();
706
+ }
707
+ }, [isFrozen, freezeAnimations, unfreezeAnimations]);
708
+ (0, import_react2.useEffect)(() => {
709
+ if (!isActive) {
710
+ setPendingAnnotation(null);
711
+ setHoverInfo(null);
712
+ if (isFrozen) {
713
+ unfreezeAnimations();
714
+ }
715
+ }
716
+ }, [isActive, isFrozen, unfreezeAnimations]);
717
+ (0, import_react2.useEffect)(() => {
718
+ if (!isActive || pendingAnnotation) return;
719
+ const handleMouseMove = (e) => {
720
+ if (e.target.closest("[data-feedback-toolbar]")) {
721
+ setHoverInfo(null);
722
+ return;
723
+ }
724
+ const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
725
+ if (!elementUnder || elementUnder.closest("[data-feedback-toolbar]")) {
726
+ setHoverInfo(null);
727
+ return;
728
+ }
729
+ const { name, path } = identifyElement(elementUnder);
730
+ const rect = elementUnder.getBoundingClientRect();
731
+ setHoverInfo({ element: name, elementPath: path, rect });
732
+ setHoverPosition({ x: e.clientX, y: e.clientY });
733
+ };
734
+ document.addEventListener("mousemove", handleMouseMove);
735
+ return () => document.removeEventListener("mousemove", handleMouseMove);
736
+ }, [isActive, pendingAnnotation]);
737
+ (0, import_react2.useEffect)(() => {
738
+ if (!isActive) return;
739
+ const handleClick = (e) => {
740
+ const target = e.target;
741
+ if (target.closest("[data-feedback-toolbar]")) return;
742
+ if (target.closest("[data-annotation-popup]")) return;
743
+ if (target.closest("[data-annotation-marker]")) return;
744
+ e.preventDefault();
745
+ if (pendingAnnotation) {
746
+ popupRef.current?.shake();
747
+ return;
748
+ }
749
+ const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
750
+ if (!elementUnder) return;
751
+ const { name, path } = identifyElement(elementUnder);
752
+ const rect = elementUnder.getBoundingClientRect();
753
+ const x = e.clientX / window.innerWidth * 100;
754
+ const y = e.clientY + window.scrollY;
755
+ const selection = window.getSelection();
756
+ let selectedText;
757
+ if (selection && selection.toString().trim().length > 0) {
758
+ selectedText = selection.toString().trim().slice(0, 500);
759
+ }
760
+ setPendingAnnotation({
761
+ x,
762
+ y,
763
+ clientY: e.clientY,
764
+ element: name,
765
+ elementPath: path,
766
+ selectedText,
767
+ boundingBox: { x: rect.left, y: rect.top + window.scrollY, width: rect.width, height: rect.height },
768
+ nearbyText: getNearbyText(elementUnder),
769
+ cssClasses: getElementClasses(elementUnder)
770
+ });
771
+ setHoverInfo(null);
772
+ };
773
+ document.addEventListener("click", handleClick);
774
+ return () => document.removeEventListener("click", handleClick);
775
+ }, [isActive, pendingAnnotation]);
776
+ const addAnnotation = (0, import_react2.useCallback)((comment) => {
777
+ if (!pendingAnnotation) return;
778
+ const newAnnotation = {
779
+ id: Date.now().toString(),
780
+ x: pendingAnnotation.x,
781
+ y: pendingAnnotation.y,
782
+ comment,
783
+ element: pendingAnnotation.element,
784
+ elementPath: pendingAnnotation.elementPath,
785
+ timestamp: Date.now(),
786
+ selectedText: pendingAnnotation.selectedText,
787
+ boundingBox: pendingAnnotation.boundingBox,
788
+ nearbyText: pendingAnnotation.nearbyText,
789
+ cssClasses: pendingAnnotation.cssClasses
790
+ };
791
+ setAnnotations((prev) => [...prev, newAnnotation]);
792
+ setPendingAnnotation(null);
793
+ window.getSelection()?.removeAllRanges();
794
+ }, [pendingAnnotation]);
795
+ const cancelAnnotation = (0, import_react2.useCallback)(() => {
796
+ setPendingAnnotation(null);
797
+ }, []);
798
+ const deleteAnnotation = (0, import_react2.useCallback)((id) => {
799
+ setAnnotations((prev) => prev.filter((a) => a.id !== id));
800
+ }, []);
801
+ const copyOutput = (0, import_react2.useCallback)(async () => {
802
+ const output = generateOutput(annotations, pathname);
803
+ if (!output) return;
804
+ await navigator.clipboard.writeText(output);
805
+ setCopied(true);
806
+ setTimeout(() => setCopied(false), 2e3);
807
+ }, [annotations, pathname]);
808
+ const clearAll = (0, import_react2.useCallback)(() => {
809
+ setAnnotations([]);
810
+ localStorage.removeItem(getStorageKey(pathname));
811
+ setCleared(true);
812
+ setTimeout(() => setCleared(false), 1500);
813
+ }, [pathname]);
814
+ (0, import_react2.useEffect)(() => {
815
+ const handleKeyDown = (e) => {
816
+ if (e.key === "Escape") {
817
+ if (pendingAnnotation) {
818
+ } else if (isActive) {
819
+ setIsActive(false);
820
+ }
821
+ }
822
+ };
823
+ document.addEventListener("keydown", handleKeyDown);
824
+ return () => document.removeEventListener("keydown", handleKeyDown);
825
+ }, [isActive, pendingAnnotation]);
826
+ if (!mounted) return null;
827
+ const hasAnnotations = annotations.length > 0;
828
+ const toViewportY = (absoluteY) => absoluteY - scrollY;
829
+ return (0, import_react_dom.createPortal)(
830
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
831
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: styles_module_default2.toolbar, "data-feedback-toolbar": true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_framer_motion3.AnimatePresence, { mode: "wait", initial: false, children: !isActive ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
832
+ import_framer_motion3.motion.button,
833
+ {
834
+ className: styles_module_default2.toggleButton,
835
+ onClick: (e) => {
836
+ e.stopPropagation();
837
+ setIsActive(true);
838
+ },
839
+ initial: { opacity: 0, scale: 0.8 },
840
+ animate: { opacity: 1, scale: 1 },
841
+ exit: { opacity: 0, scale: 0.8 },
842
+ transition: {
843
+ type: "spring",
844
+ stiffness: 500,
845
+ damping: 30,
846
+ mass: 0.8
847
+ },
848
+ title: "Start feedback mode",
849
+ children: [
850
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconFeedback, { size: 18 }),
851
+ hasAnnotations && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: styles_module_default2.badge, children: annotations.length })
852
+ ]
853
+ },
854
+ "toggle"
855
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
856
+ import_framer_motion3.motion.div,
857
+ {
858
+ className: styles_module_default2.controls,
859
+ initial: { opacity: 0, scale: 0.85, y: 8 },
860
+ animate: { opacity: 1, scale: 1, y: 0 },
861
+ exit: { opacity: 0, scale: 0.85, y: 8 },
862
+ transition: {
863
+ type: "spring",
864
+ stiffness: 600,
865
+ damping: 35,
866
+ mass: 0.6
867
+ },
868
+ children: [
869
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
870
+ import_framer_motion3.motion.button,
871
+ {
872
+ className: styles_module_default2.controlButton,
873
+ onClick: (e) => {
874
+ e.stopPropagation();
875
+ toggleFreeze();
876
+ },
877
+ title: isFrozen ? "Resume animations" : "Pause animations",
878
+ "data-active": isFrozen,
879
+ whileTap: { scale: 0.95 },
880
+ children: isFrozen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconPlay, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconPause, { size: 16 })
881
+ }
882
+ ),
883
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
884
+ import_framer_motion3.motion.button,
885
+ {
886
+ className: styles_module_default2.controlButton,
887
+ onClick: (e) => {
888
+ e.stopPropagation();
889
+ setShowMarkers(!showMarkers);
890
+ },
891
+ title: showMarkers ? "Hide markers" : "Show markers",
892
+ whileTap: { scale: 0.95 },
893
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EyeMorphIcon, { size: 16, visible: showMarkers })
894
+ }
895
+ ),
896
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
897
+ import_framer_motion3.motion.button,
898
+ {
899
+ className: styles_module_default2.controlButton,
900
+ onClick: (e) => {
901
+ e.stopPropagation();
902
+ copyOutput();
903
+ },
904
+ disabled: !hasAnnotations,
905
+ title: "Copy feedback",
906
+ whileTap: { scale: 0.95 },
907
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CopyMorphIcon, { size: 16, checked: copied })
908
+ }
909
+ ),
910
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
911
+ import_framer_motion3.motion.button,
912
+ {
913
+ className: styles_module_default2.controlButton,
914
+ onClick: (e) => {
915
+ e.stopPropagation();
916
+ clearAll();
917
+ },
918
+ disabled: !hasAnnotations,
919
+ title: "Clear all",
920
+ "data-danger": true,
921
+ whileTap: { scale: 0.95 },
922
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TrashMorphIcon, { size: 16, checked: cleared })
923
+ }
924
+ ),
925
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: styles_module_default2.divider }),
926
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
927
+ import_framer_motion3.motion.button,
928
+ {
929
+ className: styles_module_default2.controlButton,
930
+ onClick: (e) => {
931
+ e.stopPropagation();
932
+ setIsActive(false);
933
+ },
934
+ title: "Exit feedback mode",
935
+ whileTap: { scale: 0.95 },
936
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconChevronDown, { size: 16 })
937
+ }
938
+ )
939
+ ]
940
+ },
941
+ "controls"
942
+ ) }) }),
943
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: styles_module_default2.markersLayer, "data-feedback-toolbar": true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_framer_motion3.AnimatePresence, { children: isActive && showMarkers && annotations.map((annotation, index) => {
944
+ const viewportY = toViewportY(annotation.y);
945
+ const isVisible = viewportY > -30 && viewportY < window.innerHeight + 30;
946
+ if (!isVisible) return null;
947
+ const isHovered = hoveredMarkerId === annotation.id;
948
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
949
+ import_framer_motion3.motion.div,
950
+ {
951
+ className: `${styles_module_default2.marker} ${isHovered ? styles_module_default2.hovered : ""}`,
952
+ "data-annotation-marker": true,
953
+ initial: { scale: 0, opacity: 0 },
954
+ animate: {
955
+ scale: 1,
956
+ opacity: 1,
957
+ transition: {
958
+ type: "spring",
959
+ stiffness: 400,
960
+ damping: 25,
961
+ delay: index * 0.03
962
+ }
963
+ },
964
+ exit: {
965
+ scale: 0,
966
+ opacity: 0,
967
+ transition: { duration: 0.15, ease: "easeIn" }
968
+ },
969
+ whileHover: { scale: 1.1 },
970
+ style: {
971
+ left: `${annotation.x}%`,
972
+ top: viewportY
973
+ },
974
+ onMouseEnter: () => setHoveredMarkerId(annotation.id),
975
+ onMouseLeave: () => setHoveredMarkerId(null),
976
+ onClick: (e) => {
977
+ e.stopPropagation();
978
+ deleteAnnotation(annotation.id);
979
+ },
980
+ children: [
981
+ isHovered ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconClose, { size: 10 }) : index + 1,
982
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_framer_motion3.AnimatePresence, { children: isHovered && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
983
+ import_framer_motion3.motion.div,
984
+ {
985
+ className: styles_module_default2.markerTooltip,
986
+ initial: { opacity: 0, y: 2, scale: 0.98 },
987
+ animate: { opacity: 1, y: 0, scale: 1 },
988
+ exit: { opacity: 0, y: 2, scale: 0.98 },
989
+ transition: { duration: 0.1, ease: "easeOut" },
990
+ children: [
991
+ annotation.selectedText && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: styles_module_default2.markerQuote, children: [
992
+ "\u201C",
993
+ annotation.selectedText.slice(0, 50),
994
+ annotation.selectedText.length > 50 ? "..." : "",
995
+ "\u201D"
996
+ ] }),
997
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: styles_module_default2.markerNote, children: annotation.comment }),
998
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: styles_module_default2.markerHint, children: "Click to remove" })
999
+ ]
1000
+ }
1001
+ ) })
1002
+ ]
1003
+ },
1004
+ annotation.id
1005
+ );
1006
+ }) }) }),
1007
+ isActive && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: styles_module_default2.overlay, "data-feedback-toolbar": true, children: [
1008
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_framer_motion3.AnimatePresence, { children: hoverInfo?.rect && !pendingAnnotation && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1009
+ import_framer_motion3.motion.div,
1010
+ {
1011
+ className: styles_module_default2.hoverHighlight,
1012
+ initial: { opacity: 0, scale: 0.98 },
1013
+ animate: { opacity: 1, scale: 1 },
1014
+ exit: { opacity: 0, scale: 0.98 },
1015
+ transition: { duration: 0.12, ease: "easeOut" },
1016
+ style: {
1017
+ left: hoverInfo.rect.left,
1018
+ top: hoverInfo.rect.top,
1019
+ width: hoverInfo.rect.width,
1020
+ height: hoverInfo.rect.height
1021
+ }
1022
+ },
1023
+ "hover-highlight"
1024
+ ) }),
1025
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_framer_motion3.AnimatePresence, { children: hoverInfo && !pendingAnnotation && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1026
+ import_framer_motion3.motion.div,
1027
+ {
1028
+ className: styles_module_default2.hoverTooltip,
1029
+ initial: { opacity: 0, scale: 0.95, y: 4 },
1030
+ animate: { opacity: 1, scale: 1, y: 0 },
1031
+ exit: { opacity: 0, scale: 0.95, y: 4 },
1032
+ transition: { duration: 0.1, ease: "easeOut" },
1033
+ style: {
1034
+ left: Math.min(hoverPosition.x, window.innerWidth - 150),
1035
+ top: Math.max(hoverPosition.y - 32, 8)
1036
+ },
1037
+ children: hoverInfo.element
1038
+ },
1039
+ "hover-tooltip"
1040
+ ) }),
1041
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_framer_motion3.AnimatePresence, { children: pendingAnnotation && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1042
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1043
+ import_framer_motion3.motion.div,
1044
+ {
1045
+ className: `${styles_module_default2.marker} ${styles_module_default2.pending}`,
1046
+ initial: { scale: 0, opacity: 0 },
1047
+ animate: { scale: 1, opacity: 1 },
1048
+ exit: { scale: 0, opacity: 0, transition: { duration: 0.15, ease: "easeIn" } },
1049
+ transition: { type: "spring", stiffness: 500, damping: 30 },
1050
+ style: {
1051
+ left: `${pendingAnnotation.x}%`,
1052
+ top: pendingAnnotation.clientY
1053
+ },
1054
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconPlus, { size: 12 })
1055
+ }
1056
+ ),
1057
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1058
+ AnnotationPopup,
1059
+ {
1060
+ ref: popupRef,
1061
+ element: pendingAnnotation.element,
1062
+ selectedText: pendingAnnotation.selectedText,
1063
+ onSubmit: addAnnotation,
1064
+ onCancel: cancelAnnotation,
1065
+ style: {
1066
+ left: `${Math.min(Math.max(pendingAnnotation.x, 15), 85)}%`,
1067
+ top: Math.min(pendingAnnotation.clientY + 20, window.innerHeight - 180)
1068
+ }
1069
+ }
1070
+ )
1071
+ ] }) })
1072
+ ] })
1073
+ ] }),
1074
+ document.body
1075
+ );
1076
+ }
1077
+
1078
+ // src/components/page-toolbar/index-css.tsx
1079
+ var import_react4 = require("react");
1080
+ var import_react_dom2 = require("react-dom");
1081
+
1082
+ // src/components/annotation-popup/index-css.tsx
1083
+ var import_react3 = require("react");
1084
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1085
+ var cssAnimationStyles = `
1086
+ @keyframes agentation-popup-in {
1087
+ from {
1088
+ opacity: 0;
1089
+ transform: translateX(-50%) scale(0.95) translateY(4px);
1090
+ }
1091
+ to {
1092
+ opacity: 1;
1093
+ transform: translateX(-50%) scale(1) translateY(0);
1094
+ }
1095
+ }
1096
+
1097
+ @keyframes agentation-popup-shake {
1098
+ 0%, 100% { transform: translateX(-50%); }
1099
+ 15% { transform: translateX(-50%) translateX(-3px); }
1100
+ 30% { transform: translateX(-50%) translateX(3px); }
1101
+ 45% { transform: translateX(-50%) translateX(-2px); }
1102
+ 60% { transform: translateX(-50%) translateX(2px); }
1103
+ 75% { transform: translateX(-50%) translateX(-1px); }
1104
+ 90% { transform: translateX(-50%) translateX(1px); }
1105
+ }
1106
+
1107
+ .agentation-popup-animate-in {
1108
+ animation: agentation-popup-in 0.2s ease-out forwards;
1109
+ }
1110
+
1111
+ .agentation-popup-shake {
1112
+ animation: agentation-popup-shake 0.3s ease-out forwards !important;
1113
+ }
1114
+ `;
1115
+ if (typeof document !== "undefined") {
1116
+ if (!document.getElementById("agentation-popup-css-animations")) {
1117
+ const style = document.createElement("style");
1118
+ style.id = "agentation-popup-css-animations";
1119
+ style.textContent = cssAnimationStyles;
1120
+ document.head.appendChild(style);
1121
+ }
1122
+ }
1123
+ var AnnotationPopupCSS = (0, import_react3.forwardRef)(
1124
+ function AnnotationPopupCSS2({
1125
+ element,
1126
+ timestamp,
1127
+ selectedText,
1128
+ placeholder = "What should change?",
1129
+ onSubmit,
1130
+ onCancel,
1131
+ style,
1132
+ variant = "blue"
1133
+ }, ref) {
1134
+ const [text, setText] = (0, import_react3.useState)("");
1135
+ const [hasAnimatedIn, setHasAnimatedIn] = (0, import_react3.useState)(false);
1136
+ const textareaRef = (0, import_react3.useRef)(null);
1137
+ const containerRef = (0, import_react3.useRef)(null);
1138
+ (0, import_react3.useEffect)(() => {
1139
+ const timer = setTimeout(() => textareaRef.current?.focus(), 10);
1140
+ return () => clearTimeout(timer);
1141
+ }, []);
1142
+ const shake = (0, import_react3.useCallback)(() => {
1143
+ const el = containerRef.current;
1144
+ if (!el) return;
1145
+ el.classList.remove("agentation-popup-shake");
1146
+ void el.offsetWidth;
1147
+ el.classList.add("agentation-popup-shake");
1148
+ }, []);
1149
+ const handleAnimationEnd = (0, import_react3.useCallback)((e) => {
1150
+ if (e.animationName === "agentation-popup-in") {
1151
+ setHasAnimatedIn(true);
1152
+ }
1153
+ if (e.animationName === "agentation-popup-shake") {
1154
+ textareaRef.current?.focus();
1155
+ }
1156
+ }, []);
1157
+ (0, import_react3.useImperativeHandle)(ref, () => ({ shake }), [shake]);
1158
+ const handleSubmit = (0, import_react3.useCallback)(() => {
1159
+ if (!text.trim()) return;
1160
+ onSubmit(text.trim());
1161
+ }, [text, onSubmit]);
1162
+ const handleKeyDown = (0, import_react3.useCallback)(
1163
+ (e) => {
1164
+ if (e.key === "Enter" && !e.shiftKey) {
1165
+ e.preventDefault();
1166
+ handleSubmit();
1167
+ }
1168
+ if (e.key === "Escape") {
1169
+ onCancel();
1170
+ }
1171
+ },
1172
+ [handleSubmit, onCancel]
1173
+ );
1174
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1175
+ "div",
1176
+ {
1177
+ ref: containerRef,
1178
+ className: `${styles_module_default.popup} ${!hasAnimatedIn ? "agentation-popup-animate-in" : ""}`,
1179
+ "data-annotation-popup": true,
1180
+ style,
1181
+ onClick: (e) => e.stopPropagation(),
1182
+ onAnimationEnd: handleAnimationEnd,
1183
+ children: [
1184
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: styles_module_default.header, children: [
1185
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles_module_default.element, children: element }),
1186
+ timestamp && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles_module_default.timestamp, children: timestamp })
1187
+ ] }),
1188
+ selectedText && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: styles_module_default.quote, children: [
1189
+ "\u201C",
1190
+ selectedText.slice(0, 80),
1191
+ selectedText.length > 80 ? "..." : "",
1192
+ "\u201D"
1193
+ ] }),
1194
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1195
+ "textarea",
1196
+ {
1197
+ ref: textareaRef,
1198
+ className: styles_module_default.textarea,
1199
+ placeholder,
1200
+ value: text,
1201
+ onChange: (e) => setText(e.target.value),
1202
+ rows: 2,
1203
+ onKeyDown: handleKeyDown
1204
+ }
1205
+ ),
1206
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: styles_module_default.actions, children: [
1207
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: styles_module_default.cancel, onClick: onCancel, children: "Cancel" }),
1208
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1209
+ "button",
1210
+ {
1211
+ className: `${styles_module_default.submit} ${variant === "green" ? styles_module_default.green : ""}`,
1212
+ onClick: handleSubmit,
1213
+ disabled: !text.trim(),
1214
+ children: "Add"
1215
+ }
1216
+ )
1217
+ ] })
1218
+ ]
1219
+ }
1220
+ );
1221
+ }
1222
+ );
1223
+
1224
+ // src/components/icons-css.tsx
1225
+ var icons_css_exports = {};
1226
+ __export(icons_css_exports, {
1227
+ CopyMorphIcon: () => CopyMorphIcon2,
1228
+ EyeMorphIcon: () => EyeMorphIcon2,
1229
+ IconChevronDown: () => IconChevronDown2,
1230
+ IconClose: () => IconClose2,
1231
+ IconExternal: () => IconExternal2,
1232
+ IconFeedback: () => IconFeedback2,
1233
+ IconPause: () => IconPause2,
1234
+ IconPlay: () => IconPlay2,
1235
+ IconPlus: () => IconPlus2,
1236
+ TrashMorphIcon: () => TrashMorphIcon2
1237
+ });
1238
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1239
+ var IconFeedback2 = ({ size = 18 }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: [
1240
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12,4c4.97,0,8.9,4.56,7.82,9.72c-0.68,3.23-3.4,5.74-6.67,6.2c-1.59,0.22-3.14-0.01-4.58-0.7 c-0.27-0.13-0.56-0.19-0.86-0.19c-0.19,0-0.38,0.03-0.56,0.08l-2.31,0.68c-0.38,0.11-0.74-0.24-0.63-0.63l0.7-2.39 c0.13-0.45,0.07-0.92-0.14-1.35C4.26,14.34,4,13.18,4,12C4,7.59,7.59,4,12,4 M12,2C6.48,2,2,6.48,2,12c0,1.54,0.36,2.98,0.97,4.29 l-1.46,4.96C1.29,22,2,22.71,2.76,22.48l4.96-1.46c1.66,0.79,3.56,1.15,5.58,0.89c4.56-0.59,8.21-4.35,8.66-8.92 C22.53,7.03,17.85,2,12,2L12,2z" }),
1241
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12,8L12,8c-0.55,0-1,0.45-1,1v2H9c-0.55,0-1,0.45-1,1v0c0,0.55,0.45,1,1,1h2v2 c0,0.55,0.45,1,1,1h0c0.55,0,1-0.45,1-1v-2h2c0.55,0,1-0.45,1-1v0c0-0.55-0.45-1-1-1h-2V9C13,8.45,12.55,8,12,8z", fillRule: "evenodd" })
1242
+ ] });
1243
+ var IconPlay2 = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1244
+ "path",
1245
+ {
1246
+ d: "M5 3.5v9l7-4.5-7-4.5z",
1247
+ stroke: "currentColor",
1248
+ strokeWidth: "1.5",
1249
+ strokeLinejoin: "round"
1250
+ }
1251
+ ) });
1252
+ var IconPause2 = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M5.5 4v8M10.5 4v8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) });
1253
+ var EyeMorphIcon2 = ({ size = 16, visible }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: [
1254
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12 4C7 4 2.73 7.11 1 11.5 2.73 15.89 7 19 12 19s9.27-3.11 11-7.5C21.27 7.11 17 4 12 4zm0 12.5c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" }),
1255
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("g", { style: { opacity: visible ? 0 : 1, transition: "opacity 0.15s ease" }, children: [
1256
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "20", x2: "20", y2: "4", stroke: "white", strokeWidth: "4", strokeLinecap: "round" }),
1257
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "20", x2: "20", y2: "4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
1258
+ ] })
1259
+ ] });
1260
+ var CopyMorphIcon2 = ({ size = 16, checked }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: [
1261
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1262
+ "path",
1263
+ {
1264
+ d: "M14.17,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V9.83c0-0.53-0.21-1.04-0.59-1.41l-4.83-4.83 C15.21,3.21,14.7,3,14.17,3L14.17,3z M8,15h8c0.55,0,1,0.45,1,1v0c0,0.55-0.45,1-1,1H8c-0.55,0-1-0.45-1-1v0C7,15.45,7.45,15,8,15z M8,11h8c0.55,0,1,0.45,1,1v0c0,0.55-0.45,1-1,1H8c-0.55,0-1-0.45-1-1v0C7,11.45,7.45,11,8,11z M8,7h5c0.55,0,1,0.45,1,1v0 c0,0.55-0.45,1-1,1H8C7.45,9,7,8.55,7,8v0C7,7.45,7.45,7,8,7z",
1265
+ style: { opacity: checked ? 0 : 1, transition: "opacity 0.15s ease" }
1266
+ }
1267
+ ),
1268
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1269
+ "path",
1270
+ {
1271
+ d: "M6 12.5l3.5 3.5L18 7",
1272
+ stroke: "currentColor",
1273
+ strokeWidth: "2.5",
1274
+ strokeLinecap: "round",
1275
+ strokeLinejoin: "round",
1276
+ fill: "none",
1277
+ style: {
1278
+ opacity: checked ? 1 : 0,
1279
+ transform: checked ? "scale(1)" : "scale(0.5)",
1280
+ transformOrigin: "12px 12px",
1281
+ transition: "opacity 0.2s ease, transform 0.2s ease"
1282
+ }
1283
+ }
1284
+ )
1285
+ ] });
1286
+ var TrashMorphIcon2 = ({ size = 16, checked }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1287
+ "svg",
1288
+ {
1289
+ width: size,
1290
+ height: size,
1291
+ viewBox: "0 0 24 24",
1292
+ fill: "currentColor",
1293
+ style: {
1294
+ transform: checked ? "rotate(360deg)" : "rotate(0deg)",
1295
+ transition: "transform 0.5s cubic-bezier(0.4, 0, 0.2, 1)"
1296
+ },
1297
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M17.65 6.35c-1.63-1.63-3.94-2.57-6.48-2.31-3.67.37-6.69 3.35-7.1 7.02C3.52 15.91 7.27 20 12 20c3.19 0 5.93-1.87 7.21-4.56.32-.67-.16-1.44-.9-1.44-.37 0-.72.2-.88.53-1.13 2.43-3.84 3.97-6.8 3.31-2.22-.49-4.01-2.3-4.48-4.52C5.31 9.44 8.26 6 12 6c1.66 0 3.14.69 4.22 1.78l-1.51 1.51c-.63.63-.19 1.71.7 1.71H19c.55 0 1-.45 1-1V6.41c0-.89-1.08-1.34-1.71-.71l-.64.65z" })
1298
+ }
1299
+ );
1300
+ var IconExternal2 = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1301
+ "path",
1302
+ {
1303
+ d: "M6 3h7v7M13 3L6 10",
1304
+ stroke: "currentColor",
1305
+ strokeWidth: "1.5",
1306
+ strokeLinecap: "round",
1307
+ strokeLinejoin: "round"
1308
+ }
1309
+ ) });
1310
+ var IconChevronDown2 = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1311
+ "path",
1312
+ {
1313
+ d: "M4 6l4 4 4-4",
1314
+ stroke: "currentColor",
1315
+ strokeWidth: "1.75",
1316
+ strokeLinecap: "round",
1317
+ strokeLinejoin: "round"
1318
+ }
1319
+ ) });
1320
+ var IconClose2 = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M4 4l8 8M12 4l-8 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) });
1321
+ var IconPlus2 = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M8 3v10M3 8h10", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) });
1322
+
1323
+ // src/components/page-toolbar/index-css.tsx
1324
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1325
+ var cssAnimationStyles2 = `
1326
+ /* Toolbar toggle button - calmer animation */
1327
+ @keyframes agentation-toggle-in {
1328
+ from { opacity: 0; transform: scale(0.92); }
1329
+ to { opacity: 1; transform: scale(1); }
1330
+ }
1331
+
1332
+ .agentation-toggle-enter {
1333
+ animation: agentation-toggle-in 0.2s ease-out forwards;
1334
+ }
1335
+
1336
+ /* Controls bar - calmer animation */
1337
+ @keyframes agentation-controls-in {
1338
+ from { opacity: 0; transform: scale(0.96); }
1339
+ to { opacity: 1; transform: scale(1); }
1340
+ }
1341
+
1342
+ .agentation-controls-enter {
1343
+ animation: agentation-controls-in 0.2s ease-out forwards;
1344
+ }
1345
+
1346
+ /* Hover highlight - simple fast fade */
1347
+ .agentation-highlight-animate {
1348
+ animation: agentation-fade-in 0.08s ease-out forwards;
1349
+ }
1350
+
1351
+ @keyframes agentation-fade-in {
1352
+ from { opacity: 0; }
1353
+ to { opacity: 1; }
1354
+ }
1355
+
1356
+ /* Marker animations - only for newly added markers */
1357
+ /* Note: markers use position: absolute with transform: translate(-50%, -50%) for centering */
1358
+ @keyframes agentation-marker-in {
1359
+ from { opacity: 0; transform: translate(-50%, -50%) scale(0); }
1360
+ to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
1361
+ }
1362
+
1363
+ @keyframes agentation-marker-out {
1364
+ from { opacity: 1; transform: translate(-50%, -50%) scale(1); }
1365
+ to { opacity: 0; transform: translate(-50%, -50%) scale(0); }
1366
+ }
1367
+
1368
+ .agentation-marker-new {
1369
+ animation: agentation-marker-in 0.2s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
1370
+ }
1371
+
1372
+ .agentation-marker-exit {
1373
+ animation: agentation-marker-out 0.15s ease-in forwards;
1374
+ pointer-events: none;
1375
+ }
1376
+
1377
+ /* Markers layer fade for visibility toggle and toolbar close */
1378
+ .agentation-markers-layer {
1379
+ transition: opacity 0.15s ease-out;
1380
+ }
1381
+
1382
+ .agentation-markers-layer.hiding {
1383
+ opacity: 0;
1384
+ pointer-events: none;
1385
+ }
1386
+
1387
+ /* Pending marker animation */
1388
+ @keyframes agentation-pending-in {
1389
+ from { opacity: 0; transform: translate(-50%, -50%) scale(0); }
1390
+ to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
1391
+ }
1392
+
1393
+ @keyframes agentation-pending-out {
1394
+ from { opacity: 1; transform: translate(-50%, -50%) scale(1); }
1395
+ to { opacity: 0; transform: translate(-50%, -50%) scale(0); }
1396
+ }
1397
+
1398
+ .agentation-pending-enter {
1399
+ animation: agentation-pending-in 0.2s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
1400
+ }
1401
+
1402
+ .agentation-pending-exit {
1403
+ animation: agentation-pending-out 0.15s ease-in forwards;
1404
+ pointer-events: none;
1405
+ }
1406
+
1407
+ /* Tooltip animations */
1408
+ @keyframes agentation-tooltip-in {
1409
+ from { opacity: 0; transform: translateX(-50%) translateY(4px); }
1410
+ to { opacity: 1; transform: translateX(-50%) translateY(0); }
1411
+ }
1412
+
1413
+ .agentation-tooltip-animate {
1414
+ animation: agentation-tooltip-in 0.1s ease-out forwards;
1415
+ }
1416
+
1417
+ /* Hover tooltip fade */
1418
+ .agentation-hover-tooltip-animate {
1419
+ animation: agentation-fade-in 0.08s ease-out forwards;
1420
+ }
1421
+
1422
+ /* Hide hover elements during scroll - applied to body */
1423
+ body.agentation-scrolling .agentation-hover-highlight,
1424
+ body.agentation-scrolling .agentation-hover-tooltip {
1425
+ opacity: 0 !important;
1426
+ pointer-events: none !important;
1427
+ }
1428
+
1429
+ /* Cursor styles for annotation mode */
1430
+ .agentation-active-cursor {
1431
+ cursor: crosshair !important;
1432
+ }
1433
+
1434
+ .agentation-active-cursor *:not([data-feedback-toolbar] *):not([data-annotation-popup] *):not([data-annotation-marker]) {
1435
+ cursor: crosshair !important;
1436
+ }
1437
+
1438
+ /* Allow text cursor for text selection */
1439
+ .agentation-active-cursor p,
1440
+ .agentation-active-cursor span,
1441
+ .agentation-active-cursor a,
1442
+ .agentation-active-cursor h1,
1443
+ .agentation-active-cursor h2,
1444
+ .agentation-active-cursor h3,
1445
+ .agentation-active-cursor h4,
1446
+ .agentation-active-cursor h5,
1447
+ .agentation-active-cursor h6,
1448
+ .agentation-active-cursor li,
1449
+ .agentation-active-cursor label,
1450
+ .agentation-active-cursor blockquote,
1451
+ .agentation-active-cursor code,
1452
+ .agentation-active-cursor pre {
1453
+ cursor: text !important;
1454
+ }
1455
+ `;
1456
+ if (typeof document !== "undefined") {
1457
+ if (!document.getElementById("agentation-toolbar-css-animations")) {
1458
+ const style = document.createElement("style");
1459
+ style.id = "agentation-toolbar-css-animations";
1460
+ style.textContent = cssAnimationStyles2;
1461
+ document.head.appendChild(style);
1462
+ }
1463
+ }
1464
+ function stylizeFeedback(comment, element, style) {
1465
+ if (style === "direct") {
1466
+ return comment;
1467
+ }
1468
+ const lower = comment.toLowerCase();
1469
+ if (style === "instructional") {
1470
+ const actionStarts = ["fix", "change", "update", "add", "remove", "delete", "move", "resize", "replace", "make", "set", "increase", "decrease", "adjust"];
1471
+ if (actionStarts.some((v) => lower.startsWith(v))) {
1472
+ return comment;
1473
+ }
1474
+ if (lower.includes("typo") || lower.includes("misspell") || lower.includes("\u2192") || lower.includes("->")) {
1475
+ return `Fix typo: ${comment}`;
1476
+ }
1477
+ if (lower.includes("missing") || lower.includes("need") || lower.includes("should have") || lower.includes("no ")) {
1478
+ return `Add: ${comment}`;
1479
+ }
1480
+ if (lower.includes("wrong") || lower.includes("incorrect") || lower.includes("should be") || lower.includes("should say")) {
1481
+ return `Change: ${comment}`;
1482
+ }
1483
+ if (lower.includes("broken") || lower.includes("doesn't work") || lower.includes("not working")) {
1484
+ return `Fix: ${comment}`;
1485
+ }
1486
+ if (lower.includes("too ")) {
1487
+ return `Adjust: ${comment}`;
1488
+ }
1489
+ return comment;
1490
+ }
1491
+ if (style === "contextual") {
1492
+ if (lower.includes("typo") || lower.includes("misspell") || lower.includes("\u2192") || lower.includes("->") || lower.includes("spelling")) {
1493
+ return `${comment} \u2014 looks unprofessional`;
1494
+ }
1495
+ if (lower.includes("missing") || lower.includes("can't find") || lower.includes("should have") || lower.includes("need")) {
1496
+ return `${comment} \u2014 users expect this`;
1497
+ }
1498
+ if (lower.includes("confus") || lower.includes("unclear") || lower.includes("don't understand") || lower.includes("hard to")) {
1499
+ return `${comment} \u2014 hurts usability`;
1500
+ }
1501
+ if (lower.includes("broken") || lower.includes("doesn't work") || lower.includes("not working") || lower.includes("bug")) {
1502
+ return `${comment} \u2014 blocks user flow`;
1503
+ }
1504
+ if (lower.includes("slow") || lower.includes("lag") || lower.includes("loading")) {
1505
+ return `${comment} \u2014 feels sluggish`;
1506
+ }
1507
+ if (lower.includes("align") || lower.includes("spacing") || lower.includes("margin") || lower.includes("position")) {
1508
+ return `${comment} \u2014 visual inconsistency`;
1509
+ }
1510
+ if (lower.includes("color") || lower.includes("contrast") || lower.includes("can't read") || lower.includes("hard to see")) {
1511
+ return `${comment} \u2014 accessibility concern`;
1512
+ }
1513
+ if (lower.includes("too small") || lower.includes("too big") || lower.includes("too large") || lower.includes("size")) {
1514
+ return `${comment} \u2014 affects tap/click target`;
1515
+ }
1516
+ return comment;
1517
+ }
1518
+ return comment;
1519
+ }
1520
+ function generateOutput2(annotations, pathname, format = "standard", style = "direct") {
1521
+ if (annotations.length === 0) return "";
1522
+ const viewport = typeof window !== "undefined" ? `${window.innerWidth}\xD7${window.innerHeight}` : "unknown";
1523
+ if (format === "compact") {
1524
+ let output2 = `## Feedback: ${pathname}
1525
+
1526
+ `;
1527
+ annotations.forEach((a, i) => {
1528
+ const selector = a.cssClasses ? `.${a.cssClasses.split(",")[0].trim()}` : a.elementPath;
1529
+ output2 += `${i + 1}. **${a.element}** (\`${selector}\`)`;
1530
+ if (a.selectedText) output2 += `
1531
+ > "${a.selectedText.slice(0, 50)}..."`;
1532
+ output2 += `
1533
+ ${stylizeFeedback(a.comment, a.element, style)}
1534
+
1535
+ `;
1536
+ });
1537
+ return output2.trim();
1538
+ }
1539
+ if (format === "detailed") {
1540
+ let output2 = `## Page Feedback: ${pathname}
1541
+ `;
1542
+ output2 += `**Viewport:** ${viewport}
1543
+ `;
1544
+ output2 += `**URL:** ${typeof window !== "undefined" ? window.location.href : pathname}
1545
+ `;
1546
+ output2 += `**User Agent:** ${typeof navigator !== "undefined" ? navigator.userAgent.split(" ").slice(-2).join(" ") : "unknown"}
1547
+
1548
+ `;
1549
+ output2 += `---
1550
+
1551
+ `;
1552
+ annotations.forEach((a, i) => {
1553
+ output2 += `### ${i + 1}. ${a.element}
1554
+
1555
+ `;
1556
+ output2 += `**Selector:** \`${a.elementPath}\`
1557
+ `;
1558
+ if (a.cssClasses) {
1559
+ const classes = a.cssClasses.split(" ").map((c) => `.${c}`).join(", ");
1560
+ output2 += `**Classes:** \`${classes}\`
1561
+ `;
1562
+ }
1563
+ if (a.boundingBox) {
1564
+ output2 += `**Bounding box:** x:${Math.round(a.boundingBox.x)}, y:${Math.round(a.boundingBox.y)}, ${Math.round(a.boundingBox.width)}\xD7${Math.round(a.boundingBox.height)}px
1565
+ `;
1566
+ }
1567
+ if (a.computedStyles) {
1568
+ output2 += `**Styles:** ${a.computedStyles}
1569
+ `;
1570
+ }
1571
+ if (a.selectedText) {
1572
+ output2 += `**Selected text:** "${a.selectedText}"
1573
+ `;
1574
+ }
1575
+ if (a.nearbyText) {
1576
+ output2 += `**Nearby text:** "${a.nearbyText.slice(0, 150)}"
1577
+ `;
1578
+ }
1579
+ if (a.nearbyElements) {
1580
+ output2 += `**Siblings:** ${a.nearbyElements}
1581
+ `;
1582
+ }
1583
+ output2 += `
1584
+ **Issue:** ${stylizeFeedback(a.comment, a.element, style)}
1585
+
1586
+ `;
1587
+ output2 += `---
1588
+
1589
+ `;
1590
+ });
1591
+ output2 += `**Search tips:** Use the class names or selectors above to find these elements in your codebase. Try \`grep -r "className.*submit-btn"\` or search for the nearby text content.
1592
+ `;
1593
+ return output2.trim();
1594
+ }
1595
+ if (format === "forensic") {
1596
+ let output2 = `## Page Feedback: ${pathname}
1597
+
1598
+ `;
1599
+ output2 += `**Environment:**
1600
+ `;
1601
+ output2 += `- Viewport: ${viewport}
1602
+ `;
1603
+ output2 += `- URL: ${typeof window !== "undefined" ? window.location.href : pathname}
1604
+ `;
1605
+ output2 += `- User Agent: ${typeof navigator !== "undefined" ? navigator.userAgent : "unknown"}
1606
+ `;
1607
+ output2 += `- Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
1608
+ `;
1609
+ output2 += `- Device Pixel Ratio: ${typeof window !== "undefined" ? window.devicePixelRatio : "unknown"}
1610
+
1611
+ `;
1612
+ output2 += `---
1613
+
1614
+ `;
1615
+ annotations.forEach((a, i) => {
1616
+ output2 += `### ${i + 1}. ${a.element}
1617
+
1618
+ `;
1619
+ if (a.fullPath) {
1620
+ output2 += `**Full DOM Path:**
1621
+ \`\`\`
1622
+ ${a.fullPath}
1623
+ \`\`\`
1624
+
1625
+ `;
1626
+ } else {
1627
+ output2 += `**Selector:** \`${a.elementPath}\`
1628
+ `;
1629
+ }
1630
+ if (a.cssClasses) {
1631
+ output2 += `**CSS Classes:** \`${a.cssClasses}\`
1632
+ `;
1633
+ }
1634
+ if (a.boundingBox) {
1635
+ output2 += `**Position:**
1636
+ `;
1637
+ output2 += `- Bounding box: x:${Math.round(a.boundingBox.x)}, y:${Math.round(a.boundingBox.y)}
1638
+ `;
1639
+ output2 += `- Dimensions: ${Math.round(a.boundingBox.width)}\xD7${Math.round(a.boundingBox.height)}px
1640
+ `;
1641
+ output2 += `- Annotation at: ${a.x.toFixed(1)}% from left, ${Math.round(a.y)}px from top
1642
+ `;
1643
+ }
1644
+ if (a.computedStyles) {
1645
+ output2 += `**Computed Styles:** ${a.computedStyles}
1646
+ `;
1647
+ }
1648
+ if (a.accessibility) {
1649
+ output2 += `**Accessibility:** ${a.accessibility}
1650
+ `;
1651
+ }
1652
+ if (a.selectedText) {
1653
+ output2 += `**Selected Text:** "${a.selectedText}"
1654
+ `;
1655
+ }
1656
+ if (a.nearbyText) {
1657
+ output2 += `**Nearby Text:** "${a.nearbyText}"
1658
+ `;
1659
+ }
1660
+ if (a.nearbyElements) {
1661
+ output2 += `**Sibling Elements:** ${a.nearbyElements}
1662
+ `;
1663
+ }
1664
+ output2 += `
1665
+ **Issue:** ${stylizeFeedback(a.comment, a.element, style)}
1666
+
1667
+ `;
1668
+ output2 += `---
1669
+
1670
+ `;
1671
+ });
1672
+ output2 += `## Search Strategies
1673
+
1674
+ `;
1675
+ output2 += `1. **By class name:** \`grep -r "className.*yourClass" src/\`
1676
+ `;
1677
+ output2 += `2. **By text content:** \`grep -r "the text you see" src/\`
1678
+ `;
1679
+ output2 += `3. **By element path:** Use the DOM path to locate nested components
1680
+ `;
1681
+ output2 += `4. **By computed styles:** If a style looks wrong, search for those CSS values
1682
+ `;
1683
+ return output2.trim();
1684
+ }
1685
+ let output = `## Page Feedback: ${pathname}
1686
+ `;
1687
+ output += `**Viewport:** ${viewport}
1688
+
1689
+ `;
1690
+ annotations.forEach((a, i) => {
1691
+ output += `### ${i + 1}. ${a.element}
1692
+ `;
1693
+ output += `**Selector:** \`${a.elementPath}\`
1694
+ `;
1695
+ if (a.cssClasses) {
1696
+ output += `**Classes:** \`${a.cssClasses}\`
1697
+ `;
1698
+ }
1699
+ if (a.boundingBox) {
1700
+ output += `**Position:** ${Math.round(a.boundingBox.x)}, ${Math.round(a.boundingBox.y)} (${Math.round(a.boundingBox.width)}\xD7${Math.round(a.boundingBox.height)})
1701
+ `;
1702
+ }
1703
+ if (a.selectedText) {
1704
+ output += `**Selected:** "${a.selectedText}"
1705
+ `;
1706
+ } else if (a.nearbyText) {
1707
+ output += `**Context:** "${a.nearbyText.slice(0, 80)}"
1708
+ `;
1709
+ }
1710
+ if (a.nearbyElements) {
1711
+ output += `**Siblings:** ${a.nearbyElements}
1712
+ `;
1713
+ }
1714
+ output += `**Feedback:** ${stylizeFeedback(a.comment, a.element, style)}
1715
+
1716
+ `;
1717
+ });
1718
+ return output.trim();
1719
+ }
1720
+ function PageFeedbackToolbarCSS() {
1721
+ const [isActive, setIsActive] = (0, import_react4.useState)(false);
1722
+ const [annotations, setAnnotations] = (0, import_react4.useState)([]);
1723
+ const [showMarkers, setShowMarkers] = (0, import_react4.useState)(true);
1724
+ const [markersHiding, setMarkersHiding] = (0, import_react4.useState)(false);
1725
+ const [hoverInfo, setHoverInfo] = (0, import_react4.useState)(null);
1726
+ const [hoverPosition, setHoverPosition] = (0, import_react4.useState)({ x: 0, y: 0 });
1727
+ const [pendingAnnotation, setPendingAnnotation] = (0, import_react4.useState)(null);
1728
+ const [pendingExiting, setPendingExiting] = (0, import_react4.useState)(false);
1729
+ const [copied, setCopied] = (0, import_react4.useState)(false);
1730
+ const [cleared, setCleared] = (0, import_react4.useState)(false);
1731
+ const [hoveredMarkerId, setHoveredMarkerId] = (0, import_react4.useState)(null);
1732
+ const [scrollY, setScrollY] = (0, import_react4.useState)(0);
1733
+ const [mounted, setMounted] = (0, import_react4.useState)(false);
1734
+ const [isFrozen, setIsFrozen] = (0, import_react4.useState)(false);
1735
+ const [exitingIds, setExitingIds] = (0, import_react4.useState)(/* @__PURE__ */ new Set());
1736
+ const [outputFormat, setOutputFormat] = (0, import_react4.useState)("standard");
1737
+ const [feedbackStyle, setFeedbackStyle] = (0, import_react4.useState)("direct");
1738
+ const popupRef = (0, import_react4.useRef)(null);
1739
+ const overlayRef = (0, import_react4.useRef)(null);
1740
+ const isScrollingRef = (0, import_react4.useRef)(false);
1741
+ const animatedIdsRef = (0, import_react4.useRef)(/* @__PURE__ */ new Set());
1742
+ const recentlyAddedIdRef = (0, import_react4.useRef)(null);
1743
+ const scrollTimeoutRef = (0, import_react4.useRef)(null);
1744
+ const pathname = typeof window !== "undefined" ? window.location.pathname : "/";
1745
+ (0, import_react4.useEffect)(() => {
1746
+ setMounted(true);
1747
+ setScrollY(window.scrollY);
1748
+ const stored = loadAnnotations(pathname);
1749
+ setAnnotations(stored);
1750
+ const savedFormat = localStorage.getItem("agentation-output-format");
1751
+ if (savedFormat && ["compact", "standard", "detailed", "forensic"].includes(savedFormat)) {
1752
+ setOutputFormat(savedFormat);
1753
+ }
1754
+ const savedStyle = localStorage.getItem("agentation-feedback-style");
1755
+ if (savedStyle && ["direct", "instructional", "contextual"].includes(savedStyle)) {
1756
+ setFeedbackStyle(savedStyle);
1757
+ }
1758
+ }, [pathname]);
1759
+ (0, import_react4.useEffect)(() => {
1760
+ const handleFormatChange = (e) => {
1761
+ setOutputFormat(e.detail);
1762
+ };
1763
+ window.addEventListener("agentation-format-change", handleFormatChange);
1764
+ return () => window.removeEventListener("agentation-format-change", handleFormatChange);
1765
+ }, []);
1766
+ (0, import_react4.useEffect)(() => {
1767
+ const handleStyleChange = (e) => {
1768
+ setFeedbackStyle(e.detail);
1769
+ };
1770
+ window.addEventListener("agentation-style-change", handleStyleChange);
1771
+ return () => window.removeEventListener("agentation-style-change", handleStyleChange);
1772
+ }, []);
1773
+ (0, import_react4.useEffect)(() => {
1774
+ const handleScroll = () => {
1775
+ setScrollY(window.scrollY);
1776
+ if (!isScrollingRef.current) {
1777
+ isScrollingRef.current = true;
1778
+ document.body.classList.add("agentation-scrolling");
1779
+ }
1780
+ if (scrollTimeoutRef.current) {
1781
+ clearTimeout(scrollTimeoutRef.current);
1782
+ }
1783
+ scrollTimeoutRef.current = setTimeout(() => {
1784
+ isScrollingRef.current = false;
1785
+ document.body.classList.remove("agentation-scrolling");
1786
+ setHoverInfo(null);
1787
+ }, 100);
1788
+ };
1789
+ window.addEventListener("scroll", handleScroll, { passive: true });
1790
+ return () => {
1791
+ window.removeEventListener("scroll", handleScroll);
1792
+ document.body.classList.remove("agentation-scrolling");
1793
+ if (scrollTimeoutRef.current) {
1794
+ clearTimeout(scrollTimeoutRef.current);
1795
+ }
1796
+ };
1797
+ }, []);
1798
+ (0, import_react4.useEffect)(() => {
1799
+ if (mounted && annotations.length > 0) {
1800
+ saveAnnotations(pathname, annotations);
1801
+ } else if (mounted && annotations.length === 0) {
1802
+ localStorage.removeItem(getStorageKey(pathname));
1803
+ }
1804
+ }, [annotations, pathname, mounted]);
1805
+ const freezeAnimations = (0, import_react4.useCallback)(() => {
1806
+ if (isFrozen) return;
1807
+ const style = document.createElement("style");
1808
+ style.id = "feedback-freeze-styles";
1809
+ style.textContent = `
1810
+ *:not([data-feedback-toolbar] *):not([data-annotation-popup] *):not([data-annotation-marker] *),
1811
+ *:not([data-feedback-toolbar] *)::before,
1812
+ *:not([data-feedback-toolbar] *)::after {
1813
+ animation-play-state: paused !important;
1814
+ transition: none !important;
1815
+ }
1816
+ `;
1817
+ document.head.appendChild(style);
1818
+ document.querySelectorAll("video").forEach((video) => {
1819
+ if (!video.paused) {
1820
+ video.dataset.wasPaused = "false";
1821
+ video.pause();
1822
+ }
1823
+ });
1824
+ setIsFrozen(true);
1825
+ }, [isFrozen]);
1826
+ const unfreezeAnimations = (0, import_react4.useCallback)(() => {
1827
+ if (!isFrozen) return;
1828
+ const style = document.getElementById("feedback-freeze-styles");
1829
+ if (style) style.remove();
1830
+ document.querySelectorAll("video").forEach((video) => {
1831
+ if (video.dataset.wasPaused === "false") {
1832
+ video.play();
1833
+ delete video.dataset.wasPaused;
1834
+ }
1835
+ });
1836
+ setIsFrozen(false);
1837
+ }, [isFrozen]);
1838
+ const toggleFreeze = (0, import_react4.useCallback)(() => {
1839
+ if (isFrozen) unfreezeAnimations();
1840
+ else freezeAnimations();
1841
+ }, [isFrozen, freezeAnimations, unfreezeAnimations]);
1842
+ const handleCloseToolbar = (0, import_react4.useCallback)(() => {
1843
+ if (annotations.length > 0) {
1844
+ setMarkersHiding(true);
1845
+ setTimeout(() => {
1846
+ setIsActive(false);
1847
+ setMarkersHiding(false);
1848
+ }, 150);
1849
+ } else {
1850
+ setIsActive(false);
1851
+ }
1852
+ }, [annotations.length]);
1853
+ const toggleMarkersVisibility = (0, import_react4.useCallback)(() => {
1854
+ if (showMarkers) {
1855
+ setMarkersHiding(true);
1856
+ setTimeout(() => {
1857
+ setShowMarkers(false);
1858
+ setMarkersHiding(false);
1859
+ }, 150);
1860
+ } else {
1861
+ setShowMarkers(true);
1862
+ }
1863
+ }, [showMarkers]);
1864
+ (0, import_react4.useEffect)(() => {
1865
+ if (!isActive) {
1866
+ setPendingAnnotation(null);
1867
+ setHoverInfo(null);
1868
+ if (isFrozen) unfreezeAnimations();
1869
+ animatedIdsRef.current.clear();
1870
+ }
1871
+ }, [isActive, isFrozen, unfreezeAnimations]);
1872
+ (0, import_react4.useEffect)(() => {
1873
+ if (isActive) {
1874
+ document.body.classList.add("agentation-active-cursor");
1875
+ } else {
1876
+ document.body.classList.remove("agentation-active-cursor");
1877
+ }
1878
+ return () => {
1879
+ document.body.classList.remove("agentation-active-cursor");
1880
+ };
1881
+ }, [isActive]);
1882
+ (0, import_react4.useEffect)(() => {
1883
+ if (!isActive || pendingAnnotation) return;
1884
+ const handleMouseMove = (e) => {
1885
+ if (isScrollingRef.current) return;
1886
+ if (e.target.closest("[data-feedback-toolbar]")) {
1887
+ setHoverInfo(null);
1888
+ return;
1889
+ }
1890
+ const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
1891
+ if (!elementUnder || elementUnder.closest("[data-feedback-toolbar]")) {
1892
+ setHoverInfo(null);
1893
+ return;
1894
+ }
1895
+ const { name, path } = identifyElement(elementUnder);
1896
+ const rect = elementUnder.getBoundingClientRect();
1897
+ setHoverInfo({ element: name, elementPath: path, rect });
1898
+ setHoverPosition({ x: e.clientX, y: e.clientY });
1899
+ };
1900
+ document.addEventListener("mousemove", handleMouseMove);
1901
+ return () => document.removeEventListener("mousemove", handleMouseMove);
1902
+ }, [isActive, pendingAnnotation]);
1903
+ (0, import_react4.useEffect)(() => {
1904
+ if (!isActive) return;
1905
+ const handleClick = (e) => {
1906
+ const target = e.target;
1907
+ if (target.closest("[data-feedback-toolbar]")) return;
1908
+ if (target.closest("[data-annotation-popup]")) return;
1909
+ if (target.closest("[data-annotation-marker]")) return;
1910
+ e.preventDefault();
1911
+ if (pendingAnnotation) {
1912
+ popupRef.current?.shake();
1913
+ return;
1914
+ }
1915
+ const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
1916
+ if (!elementUnder) return;
1917
+ const { name, path } = identifyElement(elementUnder);
1918
+ const rect = elementUnder.getBoundingClientRect();
1919
+ const x = e.clientX / window.innerWidth * 100;
1920
+ const y = e.clientY + window.scrollY;
1921
+ const selection = window.getSelection();
1922
+ let selectedText;
1923
+ if (selection && selection.toString().trim().length > 0) {
1924
+ selectedText = selection.toString().trim().slice(0, 500);
1925
+ }
1926
+ setPendingAnnotation({
1927
+ x,
1928
+ y,
1929
+ clientY: e.clientY,
1930
+ element: name,
1931
+ elementPath: path,
1932
+ selectedText,
1933
+ boundingBox: { x: rect.left, y: rect.top + window.scrollY, width: rect.width, height: rect.height },
1934
+ nearbyText: getNearbyText(elementUnder),
1935
+ cssClasses: getElementClasses(elementUnder),
1936
+ nearbyElements: getNearbyElements(elementUnder),
1937
+ computedStyles: getComputedStylesSnapshot(elementUnder),
1938
+ fullPath: getFullElementPath(elementUnder),
1939
+ accessibility: getAccessibilityInfo(elementUnder)
1940
+ });
1941
+ setHoverInfo(null);
1942
+ };
1943
+ document.addEventListener("click", handleClick);
1944
+ return () => document.removeEventListener("click", handleClick);
1945
+ }, [isActive, pendingAnnotation]);
1946
+ const addAnnotation = (0, import_react4.useCallback)((comment) => {
1947
+ if (!pendingAnnotation) return;
1948
+ const newId = Date.now().toString();
1949
+ const newAnnotation = {
1950
+ id: newId,
1951
+ x: pendingAnnotation.x,
1952
+ y: pendingAnnotation.y,
1953
+ comment,
1954
+ element: pendingAnnotation.element,
1955
+ elementPath: pendingAnnotation.elementPath,
1956
+ timestamp: Date.now(),
1957
+ selectedText: pendingAnnotation.selectedText,
1958
+ boundingBox: pendingAnnotation.boundingBox,
1959
+ nearbyText: pendingAnnotation.nearbyText,
1960
+ cssClasses: pendingAnnotation.cssClasses,
1961
+ nearbyElements: pendingAnnotation.nearbyElements,
1962
+ computedStyles: pendingAnnotation.computedStyles,
1963
+ fullPath: pendingAnnotation.fullPath,
1964
+ accessibility: pendingAnnotation.accessibility
1965
+ };
1966
+ setAnnotations((prev) => [...prev, newAnnotation]);
1967
+ setPendingAnnotation(null);
1968
+ window.getSelection()?.removeAllRanges();
1969
+ recentlyAddedIdRef.current = newId;
1970
+ setTimeout(() => {
1971
+ recentlyAddedIdRef.current = null;
1972
+ }, 300);
1973
+ }, [pendingAnnotation]);
1974
+ const cancelAnnotation = (0, import_react4.useCallback)(() => {
1975
+ setPendingExiting(true);
1976
+ setTimeout(() => {
1977
+ setPendingExiting(false);
1978
+ setPendingAnnotation(null);
1979
+ }, 150);
1980
+ }, []);
1981
+ const deleteAnnotation = (0, import_react4.useCallback)((id) => {
1982
+ setExitingIds((prev) => new Set(prev).add(id));
1983
+ setTimeout(() => {
1984
+ setAnnotations((prev) => prev.filter((a) => a.id !== id));
1985
+ setExitingIds((prev) => {
1986
+ const next = new Set(prev);
1987
+ next.delete(id);
1988
+ return next;
1989
+ });
1990
+ animatedIdsRef.current.delete(id);
1991
+ }, 150);
1992
+ }, []);
1993
+ const copyOutput = (0, import_react4.useCallback)(async () => {
1994
+ const output = generateOutput2(annotations, pathname, outputFormat, feedbackStyle);
1995
+ if (!output) return;
1996
+ await navigator.clipboard.writeText(output);
1997
+ setCopied(true);
1998
+ setTimeout(() => setCopied(false), 2e3);
1999
+ }, [annotations, pathname, outputFormat, feedbackStyle]);
2000
+ const clearAll = (0, import_react4.useCallback)(() => {
2001
+ setAnnotations([]);
2002
+ localStorage.removeItem(getStorageKey(pathname));
2003
+ setCleared(true);
2004
+ setTimeout(() => setCleared(false), 1500);
2005
+ }, [pathname]);
2006
+ (0, import_react4.useEffect)(() => {
2007
+ const handleKeyDown = (e) => {
2008
+ const target = e.target;
2009
+ const isTyping = target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable;
2010
+ if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === "a") {
2011
+ e.preventDefault();
2012
+ if (isActive) {
2013
+ handleCloseToolbar();
2014
+ } else {
2015
+ setIsActive(true);
2016
+ }
2017
+ return;
2018
+ }
2019
+ if (e.key === "Escape") {
2020
+ if (pendingAnnotation) {
2021
+ } else if (isActive) {
2022
+ handleCloseToolbar();
2023
+ }
2024
+ return;
2025
+ }
2026
+ if (isActive && !isTyping && !pendingAnnotation) {
2027
+ switch (e.key.toLowerCase()) {
2028
+ case "p":
2029
+ e.preventDefault();
2030
+ toggleFreeze();
2031
+ break;
2032
+ case "h":
2033
+ e.preventDefault();
2034
+ toggleMarkersVisibility();
2035
+ break;
2036
+ case "c":
2037
+ if (annotations.length > 0) {
2038
+ e.preventDefault();
2039
+ copyOutput();
2040
+ }
2041
+ break;
2042
+ case "x":
2043
+ if (annotations.length > 0) {
2044
+ e.preventDefault();
2045
+ clearAll();
2046
+ }
2047
+ break;
2048
+ }
2049
+ }
2050
+ };
2051
+ document.addEventListener("keydown", handleKeyDown);
2052
+ return () => document.removeEventListener("keydown", handleKeyDown);
2053
+ }, [isActive, pendingAnnotation, handleCloseToolbar, toggleFreeze, toggleMarkersVisibility, annotations.length, copyOutput, clearAll]);
2054
+ if (!mounted) return null;
2055
+ const hasAnnotations = annotations.length > 0;
2056
+ const isInViewport = (absoluteY) => {
2057
+ const viewportY = absoluteY - scrollY;
2058
+ return viewportY > -30 && viewportY < window.innerHeight + 30;
2059
+ };
2060
+ return (0, import_react_dom2.createPortal)(
2061
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2062
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default2.toolbar, "data-feedback-toolbar": true, children: [
2063
+ !isActive && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2064
+ "button",
2065
+ {
2066
+ className: `${styles_module_default2.toggleButton} agentation-toggle-enter`,
2067
+ onClick: (e) => {
2068
+ e.stopPropagation();
2069
+ setIsActive(true);
2070
+ },
2071
+ title: "Start feedback mode (\u2318\u21E7A)",
2072
+ children: [
2073
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconFeedback2, { size: 18 }),
2074
+ hasAnnotations && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default2.badge, children: annotations.length })
2075
+ ]
2076
+ }
2077
+ ),
2078
+ isActive && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `${styles_module_default2.controls} agentation-controls-enter`, children: [
2079
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2080
+ "button",
2081
+ {
2082
+ className: styles_module_default2.controlButton,
2083
+ onClick: (e) => {
2084
+ e.stopPropagation();
2085
+ toggleFreeze();
2086
+ },
2087
+ title: isFrozen ? "Resume animations (P)" : "Pause animations (P)",
2088
+ "data-active": isFrozen,
2089
+ children: isFrozen ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconPlay2, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconPause2, { size: 16 })
2090
+ }
2091
+ ),
2092
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2093
+ "button",
2094
+ {
2095
+ className: styles_module_default2.controlButton,
2096
+ onClick: (e) => {
2097
+ e.stopPropagation();
2098
+ toggleMarkersVisibility();
2099
+ },
2100
+ title: showMarkers ? "Hide markers (H)" : "Show markers (H)",
2101
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EyeMorphIcon2, { size: 16, visible: showMarkers })
2102
+ }
2103
+ ),
2104
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2105
+ "button",
2106
+ {
2107
+ className: styles_module_default2.controlButton,
2108
+ onClick: (e) => {
2109
+ e.stopPropagation();
2110
+ copyOutput();
2111
+ },
2112
+ disabled: !hasAnnotations,
2113
+ title: "Copy feedback (C)",
2114
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CopyMorphIcon2, { size: 16, checked: copied })
2115
+ }
2116
+ ),
2117
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2118
+ "button",
2119
+ {
2120
+ className: styles_module_default2.controlButton,
2121
+ onClick: (e) => {
2122
+ e.stopPropagation();
2123
+ clearAll();
2124
+ },
2125
+ disabled: !hasAnnotations,
2126
+ title: "Clear all (X)",
2127
+ "data-danger": true,
2128
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TrashMorphIcon2, { size: 16, checked: cleared })
2129
+ }
2130
+ ),
2131
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default2.divider }),
2132
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2133
+ "button",
2134
+ {
2135
+ className: styles_module_default2.controlButton,
2136
+ onClick: (e) => {
2137
+ e.stopPropagation();
2138
+ handleCloseToolbar();
2139
+ },
2140
+ title: "Exit feedback mode (Esc)",
2141
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconChevronDown2, { size: 16 })
2142
+ }
2143
+ )
2144
+ ] })
2145
+ ] }),
2146
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2147
+ "div",
2148
+ {
2149
+ className: `${styles_module_default2.markersLayer} agentation-markers-layer ${markersHiding ? "hiding" : ""}`,
2150
+ "data-feedback-toolbar": true,
2151
+ children: isActive && showMarkers && annotations.map((annotation, index) => {
2152
+ if (!isInViewport(annotation.y)) return null;
2153
+ const isHovered = hoveredMarkerId === annotation.id;
2154
+ const isExiting = exitingIds.has(annotation.id);
2155
+ const isNew = !animatedIdsRef.current.has(annotation.id) && !isExiting;
2156
+ const showAsHovered = isHovered || isExiting;
2157
+ if (isNew) {
2158
+ animatedIdsRef.current.add(annotation.id);
2159
+ }
2160
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2161
+ "div",
2162
+ {
2163
+ className: `${styles_module_default2.marker} ${showAsHovered ? styles_module_default2.hovered : ""} ${isExiting ? "agentation-marker-exit" : ""} ${isNew ? "agentation-marker-new" : ""}`,
2164
+ "data-annotation-marker": true,
2165
+ style: {
2166
+ left: `${annotation.x}%`,
2167
+ top: annotation.y
2168
+ // Absolute document position - browser handles scroll
2169
+ },
2170
+ onMouseEnter: () => !isExiting && annotation.id !== recentlyAddedIdRef.current && setHoveredMarkerId(annotation.id),
2171
+ onMouseLeave: () => setHoveredMarkerId(null),
2172
+ onClick: (e) => {
2173
+ e.stopPropagation();
2174
+ if (!isExiting) deleteAnnotation(annotation.id);
2175
+ },
2176
+ children: [
2177
+ showAsHovered ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconClose2, { size: 10 }) : index + 1,
2178
+ isHovered && !isExiting && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `${styles_module_default2.markerTooltip} agentation-tooltip-animate`, children: [
2179
+ annotation.selectedText && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: styles_module_default2.markerQuote, children: [
2180
+ "\u201C",
2181
+ annotation.selectedText.slice(0, 50),
2182
+ annotation.selectedText.length > 50 ? "..." : "",
2183
+ "\u201D"
2184
+ ] }),
2185
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default2.markerNote, children: annotation.comment }),
2186
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default2.markerHint, children: "Click to remove" })
2187
+ ] })
2188
+ ]
2189
+ },
2190
+ annotation.id
2191
+ );
2192
+ })
2193
+ }
2194
+ ),
2195
+ isActive && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2196
+ "div",
2197
+ {
2198
+ ref: overlayRef,
2199
+ className: styles_module_default2.overlay,
2200
+ "data-feedback-toolbar": true,
2201
+ children: [
2202
+ hoverInfo?.rect && !pendingAnnotation && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2203
+ "div",
2204
+ {
2205
+ className: `${styles_module_default2.hoverHighlight} agentation-highlight-animate agentation-hover-highlight`,
2206
+ style: {
2207
+ left: hoverInfo.rect.left,
2208
+ top: hoverInfo.rect.top,
2209
+ width: hoverInfo.rect.width,
2210
+ height: hoverInfo.rect.height
2211
+ }
2212
+ },
2213
+ `${hoverInfo.rect.left}-${hoverInfo.rect.top}-${hoverInfo.rect.width}`
2214
+ ),
2215
+ hoverInfo && !pendingAnnotation && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2216
+ "div",
2217
+ {
2218
+ className: `${styles_module_default2.hoverTooltip} agentation-hover-tooltip-animate agentation-hover-tooltip`,
2219
+ style: {
2220
+ left: Math.min(hoverPosition.x, window.innerWidth - 150),
2221
+ top: Math.max(hoverPosition.y - 32, 8)
2222
+ },
2223
+ children: hoverInfo.element
2224
+ }
2225
+ ),
2226
+ (pendingAnnotation || pendingExiting) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2227
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2228
+ "div",
2229
+ {
2230
+ className: `${styles_module_default2.marker} ${styles_module_default2.pending} ${pendingExiting ? "agentation-pending-exit" : "agentation-pending-enter"}`,
2231
+ style: {
2232
+ left: `${pendingAnnotation?.x ?? 0}%`,
2233
+ top: pendingAnnotation?.clientY ?? 0
2234
+ },
2235
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconPlus2, { size: 12 })
2236
+ }
2237
+ ),
2238
+ pendingAnnotation && !pendingExiting && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2239
+ AnnotationPopupCSS,
2240
+ {
2241
+ ref: popupRef,
2242
+ element: pendingAnnotation.element,
2243
+ selectedText: pendingAnnotation.selectedText,
2244
+ onSubmit: addAnnotation,
2245
+ onCancel: cancelAnnotation,
2246
+ style: {
2247
+ left: `${Math.min(Math.max(pendingAnnotation.x, 15), 85)}%`,
2248
+ top: Math.min(pendingAnnotation.clientY + 20, window.innerHeight - 180)
2249
+ }
2250
+ }
2251
+ )
2252
+ ] })
2253
+ ]
2254
+ }
2255
+ )
2256
+ ] }),
2257
+ document.body
2258
+ );
2259
+ }
2260
+ // Annotate the CommonJS export names for ESM import in node:
2261
+ 0 && (module.exports = {
2262
+ Agentation,
2263
+ AgentationCSS,
2264
+ AnnotationPopup,
2265
+ AnnotationPopupCSS,
2266
+ AnnotationPopupPresence,
2267
+ CopyMorphIcon,
2268
+ EyeMorphIcon,
2269
+ FeedbackToolbar,
2270
+ IconChevronDown,
2271
+ IconClose,
2272
+ IconExternal,
2273
+ IconFeedback,
2274
+ IconPause,
2275
+ IconPlay,
2276
+ IconPlus,
2277
+ IconsCSS,
2278
+ PageFeedbackToolbar,
2279
+ PageFeedbackToolbarCSS,
2280
+ TrashMorphIcon,
2281
+ getElementClasses,
2282
+ getElementPath,
2283
+ getNearbyText,
2284
+ getStorageKey,
2285
+ identifyAnimationElement,
2286
+ identifyElement,
2287
+ loadAnnotations,
2288
+ saveAnnotations
2289
+ });
2290
+ //# sourceMappingURL=index.cjs.map