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