@nuasite/notes 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +211 -0
  2. package/dist/overlay.js +1367 -0
  3. package/package.json +51 -0
  4. package/src/apply/apply-suggestion.ts +157 -0
  5. package/src/dev/api-handlers.ts +215 -0
  6. package/src/dev/middleware.ts +65 -0
  7. package/src/dev/request-utils.ts +71 -0
  8. package/src/index.ts +2 -0
  9. package/src/integration.ts +168 -0
  10. package/src/overlay/App.tsx +434 -0
  11. package/src/overlay/components/CommentPopover.tsx +96 -0
  12. package/src/overlay/components/DiffPreview.tsx +29 -0
  13. package/src/overlay/components/ElementHighlight.tsx +33 -0
  14. package/src/overlay/components/SelectionTooltip.tsx +48 -0
  15. package/src/overlay/components/Sidebar.tsx +70 -0
  16. package/src/overlay/components/SidebarItem.tsx +104 -0
  17. package/src/overlay/components/StaleWarning.tsx +19 -0
  18. package/src/overlay/components/SuggestPopover.tsx +139 -0
  19. package/src/overlay/components/Toolbar.tsx +38 -0
  20. package/src/overlay/env.d.ts +4 -0
  21. package/src/overlay/index.tsx +71 -0
  22. package/src/overlay/lib/cms-bridge.ts +33 -0
  23. package/src/overlay/lib/dom-walker.ts +61 -0
  24. package/src/overlay/lib/manifest-fetch.ts +35 -0
  25. package/src/overlay/lib/notes-fetch.ts +121 -0
  26. package/src/overlay/lib/range-anchor.ts +87 -0
  27. package/src/overlay/lib/url-mode.ts +43 -0
  28. package/src/overlay/styles.css +526 -0
  29. package/src/overlay/types.ts +66 -0
  30. package/src/storage/id-gen.ts +32 -0
  31. package/src/storage/json-store.ts +196 -0
  32. package/src/storage/slug.ts +35 -0
  33. package/src/storage/types.ts +100 -0
  34. package/src/tsconfig.json +6 -0
  35. package/src/types.ts +50 -0
@@ -0,0 +1,1367 @@
1
+ var n, l$1, u$2, i$1, r$1, o$1, e$1, f$2, c$1, s$1, a$1, h$1, p$1, v$1, d$1 = {}, w$1 = [], _ = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i, g = Array.isArray;
2
+ function m$1(n2, l2) {
3
+ for (var u2 in l2) n2[u2] = l2[u2];
4
+ return n2;
5
+ }
6
+ function b(n2) {
7
+ n2 && n2.parentNode && n2.parentNode.removeChild(n2);
8
+ }
9
+ function k$1(l2, u2, t2) {
10
+ var i2, r2, o2, e2 = {};
11
+ for (o2 in u2) "key" == o2 ? i2 = u2[o2] : "ref" == o2 ? r2 = u2[o2] : e2[o2] = u2[o2];
12
+ if (arguments.length > 2 && (e2.children = arguments.length > 3 ? n.call(arguments, 2) : t2), "function" == typeof l2 && null != l2.defaultProps) for (o2 in l2.defaultProps) void 0 === e2[o2] && (e2[o2] = l2.defaultProps[o2]);
13
+ return x(l2, e2, i2, r2, null);
14
+ }
15
+ function x(n2, t2, i2, r2, o2) {
16
+ var e2 = { type: n2, props: t2, key: i2, ref: r2, __k: null, __: null, __b: 0, __e: null, __c: null, constructor: void 0, __v: null == o2 ? ++u$2 : o2, __i: -1, __u: 0 };
17
+ return null == o2 && null != l$1.vnode && l$1.vnode(e2), e2;
18
+ }
19
+ function S(n2) {
20
+ return n2.children;
21
+ }
22
+ function C$1(n2, l2) {
23
+ this.props = n2, this.context = l2;
24
+ }
25
+ function $(n2, l2) {
26
+ if (null == l2) return n2.__ ? $(n2.__, n2.__i + 1) : null;
27
+ for (var u2; l2 < n2.__k.length; l2++) if (null != (u2 = n2.__k[l2]) && null != u2.__e) return u2.__e;
28
+ return "function" == typeof n2.type ? $(n2) : null;
29
+ }
30
+ function I(n2) {
31
+ if (n2.__P && n2.__d) {
32
+ var u2 = n2.__v, t2 = u2.__e, i2 = [], r2 = [], o2 = m$1({}, u2);
33
+ o2.__v = u2.__v + 1, l$1.vnode && l$1.vnode(o2), q$1(n2.__P, o2, u2, n2.__n, n2.__P.namespaceURI, 32 & u2.__u ? [t2] : null, i2, null == t2 ? $(u2) : t2, !!(32 & u2.__u), r2), o2.__v = u2.__v, o2.__.__k[o2.__i] = o2, D$1(i2, o2, r2), u2.__e = u2.__ = null, o2.__e != t2 && P(o2);
34
+ }
35
+ }
36
+ function P(n2) {
37
+ if (null != (n2 = n2.__) && null != n2.__c) return n2.__e = n2.__c.base = null, n2.__k.some(function(l2) {
38
+ if (null != l2 && null != l2.__e) return n2.__e = n2.__c.base = l2.__e;
39
+ }), P(n2);
40
+ }
41
+ function A$1(n2) {
42
+ (!n2.__d && (n2.__d = true) && i$1.push(n2) && !H.__r++ || r$1 != l$1.debounceRendering) && ((r$1 = l$1.debounceRendering) || o$1)(H);
43
+ }
44
+ function H() {
45
+ try {
46
+ for (var n2, l2 = 1; i$1.length; ) i$1.length > l2 && i$1.sort(e$1), n2 = i$1.shift(), l2 = i$1.length, I(n2);
47
+ } finally {
48
+ i$1.length = H.__r = 0;
49
+ }
50
+ }
51
+ function L(n2, l2, u2, t2, i2, r2, o2, e2, f2, c2, s2) {
52
+ var a2, h2, p2, v2, y2, _2, g2, m2 = t2 && t2.__k || w$1, b2 = l2.length;
53
+ for (f2 = T$1(u2, l2, m2, f2, b2), a2 = 0; a2 < b2; a2++) null != (p2 = u2.__k[a2]) && (h2 = -1 != p2.__i && m2[p2.__i] || d$1, p2.__i = a2, _2 = q$1(n2, p2, h2, i2, r2, o2, e2, f2, c2, s2), v2 = p2.__e, p2.ref && h2.ref != p2.ref && (h2.ref && J(h2.ref, null, p2), s2.push(p2.ref, p2.__c || v2, p2)), null == y2 && null != v2 && (y2 = v2), (g2 = !!(4 & p2.__u)) || h2.__k === p2.__k ? (f2 = j$1(p2, f2, n2, g2), g2 && h2.__e && (h2.__e = null)) : "function" == typeof p2.type && void 0 !== _2 ? f2 = _2 : v2 && (f2 = v2.nextSibling), p2.__u &= -7);
54
+ return u2.__e = y2, f2;
55
+ }
56
+ function T$1(n2, l2, u2, t2, i2) {
57
+ var r2, o2, e2, f2, c2, s2 = u2.length, a2 = s2, h2 = 0;
58
+ for (n2.__k = new Array(i2), r2 = 0; r2 < i2; r2++) null != (o2 = l2[r2]) && "boolean" != typeof o2 && "function" != typeof o2 ? ("string" == typeof o2 || "number" == typeof o2 || "bigint" == typeof o2 || o2.constructor == String ? o2 = n2.__k[r2] = x(null, o2, null, null, null) : g(o2) ? o2 = n2.__k[r2] = x(S, { children: o2 }, null, null, null) : void 0 === o2.constructor && o2.__b > 0 ? o2 = n2.__k[r2] = x(o2.type, o2.props, o2.key, o2.ref ? o2.ref : null, o2.__v) : n2.__k[r2] = o2, f2 = r2 + h2, o2.__ = n2, o2.__b = n2.__b + 1, e2 = null, -1 != (c2 = o2.__i = O(o2, u2, f2, a2)) && (a2--, (e2 = u2[c2]) && (e2.__u |= 2)), null == e2 || null == e2.__v ? (-1 == c2 && (i2 > s2 ? h2-- : i2 < s2 && h2++), "function" != typeof o2.type && (o2.__u |= 4)) : c2 != f2 && (c2 == f2 - 1 ? h2-- : c2 == f2 + 1 ? h2++ : (c2 > f2 ? h2-- : h2++, o2.__u |= 4))) : n2.__k[r2] = null;
59
+ if (a2) for (r2 = 0; r2 < s2; r2++) null != (e2 = u2[r2]) && 0 == (2 & e2.__u) && (e2.__e == t2 && (t2 = $(e2)), K(e2, e2));
60
+ return t2;
61
+ }
62
+ function j$1(n2, l2, u2, t2) {
63
+ var i2, r2;
64
+ if ("function" == typeof n2.type) {
65
+ for (i2 = n2.__k, r2 = 0; i2 && r2 < i2.length; r2++) i2[r2] && (i2[r2].__ = n2, l2 = j$1(i2[r2], l2, u2, t2));
66
+ return l2;
67
+ }
68
+ n2.__e != l2 && (t2 && (l2 && n2.type && !l2.parentNode && (l2 = $(n2)), u2.insertBefore(n2.__e, l2 || null)), l2 = n2.__e);
69
+ do {
70
+ l2 = l2 && l2.nextSibling;
71
+ } while (null != l2 && 8 == l2.nodeType);
72
+ return l2;
73
+ }
74
+ function O(n2, l2, u2, t2) {
75
+ var i2, r2, o2, e2 = n2.key, f2 = n2.type, c2 = l2[u2], s2 = null != c2 && 0 == (2 & c2.__u);
76
+ if (null === c2 && null == e2 || s2 && e2 == c2.key && f2 == c2.type) return u2;
77
+ if (t2 > (s2 ? 1 : 0)) {
78
+ for (i2 = u2 - 1, r2 = u2 + 1; i2 >= 0 || r2 < l2.length; ) if (null != (c2 = l2[o2 = i2 >= 0 ? i2-- : r2++]) && 0 == (2 & c2.__u) && e2 == c2.key && f2 == c2.type) return o2;
79
+ }
80
+ return -1;
81
+ }
82
+ function z$1(n2, l2, u2) {
83
+ "-" == l2[0] ? n2.setProperty(l2, null == u2 ? "" : u2) : n2[l2] = null == u2 ? "" : "number" != typeof u2 || _.test(l2) ? u2 : u2 + "px";
84
+ }
85
+ function N(n2, l2, u2, t2, i2) {
86
+ var r2, o2;
87
+ n: if ("style" == l2) if ("string" == typeof u2) n2.style.cssText = u2;
88
+ else {
89
+ if ("string" == typeof t2 && (n2.style.cssText = t2 = ""), t2) for (l2 in t2) u2 && l2 in u2 || z$1(n2.style, l2, "");
90
+ if (u2) for (l2 in u2) t2 && u2[l2] == t2[l2] || z$1(n2.style, l2, u2[l2]);
91
+ }
92
+ else if ("o" == l2[0] && "n" == l2[1]) r2 = l2 != (l2 = l2.replace(a$1, "$1")), o2 = l2.toLowerCase(), l2 = o2 in n2 || "onFocusOut" == l2 || "onFocusIn" == l2 ? o2.slice(2) : l2.slice(2), n2.l || (n2.l = {}), n2.l[l2 + r2] = u2, u2 ? t2 ? u2[s$1] = t2[s$1] : (u2[s$1] = h$1, n2.addEventListener(l2, r2 ? v$1 : p$1, r2)) : n2.removeEventListener(l2, r2 ? v$1 : p$1, r2);
93
+ else {
94
+ if ("http://www.w3.org/2000/svg" == i2) l2 = l2.replace(/xlink(H|:h)/, "h").replace(/sName$/, "s");
95
+ else if ("width" != l2 && "height" != l2 && "href" != l2 && "list" != l2 && "form" != l2 && "tabIndex" != l2 && "download" != l2 && "rowSpan" != l2 && "colSpan" != l2 && "role" != l2 && "popover" != l2 && l2 in n2) try {
96
+ n2[l2] = null == u2 ? "" : u2;
97
+ break n;
98
+ } catch (n3) {
99
+ }
100
+ "function" == typeof u2 || (null == u2 || false === u2 && "-" != l2[4] ? n2.removeAttribute(l2) : n2.setAttribute(l2, "popover" == l2 && 1 == u2 ? "" : u2));
101
+ }
102
+ }
103
+ function V(n2) {
104
+ return function(u2) {
105
+ if (this.l) {
106
+ var t2 = this.l[u2.type + n2];
107
+ if (null == u2[c$1]) u2[c$1] = h$1++;
108
+ else if (u2[c$1] < t2[s$1]) return;
109
+ return t2(l$1.event ? l$1.event(u2) : u2);
110
+ }
111
+ };
112
+ }
113
+ function q$1(n2, u2, t2, i2, r2, o2, e2, f2, c2, s2) {
114
+ var a2, h2, p2, v2, y2, d2, _2, k2, x2, M, $2, I2, P2, A2, H2, T2 = u2.type;
115
+ if (void 0 !== u2.constructor) return null;
116
+ 128 & t2.__u && (c2 = !!(32 & t2.__u), o2 = [f2 = u2.__e = t2.__e]), (a2 = l$1.__b) && a2(u2);
117
+ n: if ("function" == typeof T2) try {
118
+ if (k2 = u2.props, x2 = T2.prototype && T2.prototype.render, M = (a2 = T2.contextType) && i2[a2.__c], $2 = a2 ? M ? M.props.value : a2.__ : i2, t2.__c ? _2 = (h2 = u2.__c = t2.__c).__ = h2.__E : (x2 ? u2.__c = h2 = new T2(k2, $2) : (u2.__c = h2 = new C$1(k2, $2), h2.constructor = T2, h2.render = Q), M && M.sub(h2), h2.state || (h2.state = {}), h2.__n = i2, p2 = h2.__d = true, h2.__h = [], h2._sb = []), x2 && null == h2.__s && (h2.__s = h2.state), x2 && null != T2.getDerivedStateFromProps && (h2.__s == h2.state && (h2.__s = m$1({}, h2.__s)), m$1(h2.__s, T2.getDerivedStateFromProps(k2, h2.__s))), v2 = h2.props, y2 = h2.state, h2.__v = u2, p2) x2 && null == T2.getDerivedStateFromProps && null != h2.componentWillMount && h2.componentWillMount(), x2 && null != h2.componentDidMount && h2.__h.push(h2.componentDidMount);
119
+ else {
120
+ if (x2 && null == T2.getDerivedStateFromProps && k2 !== v2 && null != h2.componentWillReceiveProps && h2.componentWillReceiveProps(k2, $2), u2.__v == t2.__v || !h2.__e && null != h2.shouldComponentUpdate && false === h2.shouldComponentUpdate(k2, h2.__s, $2)) {
121
+ u2.__v != t2.__v && (h2.props = k2, h2.state = h2.__s, h2.__d = false), u2.__e = t2.__e, u2.__k = t2.__k, u2.__k.some(function(n3) {
122
+ n3 && (n3.__ = u2);
123
+ }), w$1.push.apply(h2.__h, h2._sb), h2._sb = [], h2.__h.length && e2.push(h2);
124
+ break n;
125
+ }
126
+ null != h2.componentWillUpdate && h2.componentWillUpdate(k2, h2.__s, $2), x2 && null != h2.componentDidUpdate && h2.__h.push(function() {
127
+ h2.componentDidUpdate(v2, y2, d2);
128
+ });
129
+ }
130
+ if (h2.context = $2, h2.props = k2, h2.__P = n2, h2.__e = false, I2 = l$1.__r, P2 = 0, x2) h2.state = h2.__s, h2.__d = false, I2 && I2(u2), a2 = h2.render(h2.props, h2.state, h2.context), w$1.push.apply(h2.__h, h2._sb), h2._sb = [];
131
+ else do {
132
+ h2.__d = false, I2 && I2(u2), a2 = h2.render(h2.props, h2.state, h2.context), h2.state = h2.__s;
133
+ } while (h2.__d && ++P2 < 25);
134
+ h2.state = h2.__s, null != h2.getChildContext && (i2 = m$1(m$1({}, i2), h2.getChildContext())), x2 && !p2 && null != h2.getSnapshotBeforeUpdate && (d2 = h2.getSnapshotBeforeUpdate(v2, y2)), A2 = null != a2 && a2.type === S && null == a2.key ? E(a2.props.children) : a2, f2 = L(n2, g(A2) ? A2 : [A2], u2, t2, i2, r2, o2, e2, f2, c2, s2), h2.base = u2.__e, u2.__u &= -161, h2.__h.length && e2.push(h2), _2 && (h2.__E = h2.__ = null);
135
+ } catch (n3) {
136
+ if (u2.__v = null, c2 || null != o2) if (n3.then) {
137
+ for (u2.__u |= c2 ? 160 : 128; f2 && 8 == f2.nodeType && f2.nextSibling; ) f2 = f2.nextSibling;
138
+ o2[o2.indexOf(f2)] = null, u2.__e = f2;
139
+ } else {
140
+ for (H2 = o2.length; H2--; ) b(o2[H2]);
141
+ B$1(u2);
142
+ }
143
+ else u2.__e = t2.__e, u2.__k = t2.__k, n3.then || B$1(u2);
144
+ l$1.__e(n3, u2, t2);
145
+ }
146
+ else null == o2 && u2.__v == t2.__v ? (u2.__k = t2.__k, u2.__e = t2.__e) : f2 = u2.__e = G(t2.__e, u2, t2, i2, r2, o2, e2, c2, s2);
147
+ return (a2 = l$1.diffed) && a2(u2), 128 & u2.__u ? void 0 : f2;
148
+ }
149
+ function B$1(n2) {
150
+ n2 && (n2.__c && (n2.__c.__e = true), n2.__k && n2.__k.some(B$1));
151
+ }
152
+ function D$1(n2, u2, t2) {
153
+ for (var i2 = 0; i2 < t2.length; i2++) J(t2[i2], t2[++i2], t2[++i2]);
154
+ l$1.__c && l$1.__c(u2, n2), n2.some(function(u3) {
155
+ try {
156
+ n2 = u3.__h, u3.__h = [], n2.some(function(n3) {
157
+ n3.call(u3);
158
+ });
159
+ } catch (n3) {
160
+ l$1.__e(n3, u3.__v);
161
+ }
162
+ });
163
+ }
164
+ function E(n2) {
165
+ return "object" != typeof n2 || null == n2 || n2.__b > 0 ? n2 : g(n2) ? n2.map(E) : m$1({}, n2);
166
+ }
167
+ function G(u2, t2, i2, r2, o2, e2, f2, c2, s2) {
168
+ var a2, h2, p2, v2, y2, w2, _2, m2 = i2.props || d$1, k2 = t2.props, x2 = t2.type;
169
+ if ("svg" == x2 ? o2 = "http://www.w3.org/2000/svg" : "math" == x2 ? o2 = "http://www.w3.org/1998/Math/MathML" : o2 || (o2 = "http://www.w3.org/1999/xhtml"), null != e2) {
170
+ for (a2 = 0; a2 < e2.length; a2++) if ((y2 = e2[a2]) && "setAttribute" in y2 == !!x2 && (x2 ? y2.localName == x2 : 3 == y2.nodeType)) {
171
+ u2 = y2, e2[a2] = null;
172
+ break;
173
+ }
174
+ }
175
+ if (null == u2) {
176
+ if (null == x2) return document.createTextNode(k2);
177
+ u2 = document.createElementNS(o2, x2, k2.is && k2), c2 && (l$1.__m && l$1.__m(t2, e2), c2 = false), e2 = null;
178
+ }
179
+ if (null == x2) m2 === k2 || c2 && u2.data == k2 || (u2.data = k2);
180
+ else {
181
+ if (e2 = e2 && n.call(u2.childNodes), !c2 && null != e2) for (m2 = {}, a2 = 0; a2 < u2.attributes.length; a2++) m2[(y2 = u2.attributes[a2]).name] = y2.value;
182
+ for (a2 in m2) y2 = m2[a2], "dangerouslySetInnerHTML" == a2 ? p2 = y2 : "children" == a2 || a2 in k2 || "value" == a2 && "defaultValue" in k2 || "checked" == a2 && "defaultChecked" in k2 || N(u2, a2, null, y2, o2);
183
+ for (a2 in k2) y2 = k2[a2], "children" == a2 ? v2 = y2 : "dangerouslySetInnerHTML" == a2 ? h2 = y2 : "value" == a2 ? w2 = y2 : "checked" == a2 ? _2 = y2 : c2 && "function" != typeof y2 || m2[a2] === y2 || N(u2, a2, y2, m2[a2], o2);
184
+ if (h2) c2 || p2 && (h2.__html == p2.__html || h2.__html == u2.innerHTML) || (u2.innerHTML = h2.__html), t2.__k = [];
185
+ else if (p2 && (u2.innerHTML = ""), L("template" == t2.type ? u2.content : u2, g(v2) ? v2 : [v2], t2, i2, r2, "foreignObject" == x2 ? "http://www.w3.org/1999/xhtml" : o2, e2, f2, e2 ? e2[0] : i2.__k && $(i2, 0), c2, s2), null != e2) for (a2 = e2.length; a2--; ) b(e2[a2]);
186
+ c2 || (a2 = "value", "progress" == x2 && null == w2 ? u2.removeAttribute("value") : null != w2 && (w2 !== u2[a2] || "progress" == x2 && !w2 || "option" == x2 && w2 != m2[a2]) && N(u2, a2, w2, m2[a2], o2), a2 = "checked", null != _2 && _2 != u2[a2] && N(u2, a2, _2, m2[a2], o2));
187
+ }
188
+ return u2;
189
+ }
190
+ function J(n2, u2, t2) {
191
+ try {
192
+ if ("function" == typeof n2) {
193
+ var i2 = "function" == typeof n2.__u;
194
+ i2 && n2.__u(), i2 && null == u2 || (n2.__u = n2(u2));
195
+ } else n2.current = u2;
196
+ } catch (n3) {
197
+ l$1.__e(n3, t2);
198
+ }
199
+ }
200
+ function K(n2, u2, t2) {
201
+ var i2, r2;
202
+ if (l$1.unmount && l$1.unmount(n2), (i2 = n2.ref) && (i2.current && i2.current != n2.__e || J(i2, null, u2)), null != (i2 = n2.__c)) {
203
+ if (i2.componentWillUnmount) try {
204
+ i2.componentWillUnmount();
205
+ } catch (n3) {
206
+ l$1.__e(n3, u2);
207
+ }
208
+ i2.base = i2.__P = null;
209
+ }
210
+ if (i2 = n2.__k) for (r2 = 0; r2 < i2.length; r2++) i2[r2] && K(i2[r2], u2, t2 || "function" != typeof n2.type);
211
+ t2 || b(n2.__e), n2.__c = n2.__ = n2.__e = void 0;
212
+ }
213
+ function Q(n2, l2, u2) {
214
+ return this.constructor(n2, u2);
215
+ }
216
+ function R(u2, t2, i2) {
217
+ var r2, o2, e2, f2;
218
+ t2 == document && (t2 = document.documentElement), l$1.__ && l$1.__(u2, t2), o2 = (r2 = false) ? null : t2.__k, e2 = [], f2 = [], q$1(t2, u2 = t2.__k = k$1(S, null, [u2]), o2 || d$1, d$1, t2.namespaceURI, o2 ? null : t2.firstChild ? n.call(t2.childNodes) : null, e2, o2 ? o2.__e : t2.firstChild, r2, f2), D$1(e2, u2, f2);
219
+ }
220
+ n = w$1.slice, l$1 = { __e: function(n2, l2, u2, t2) {
221
+ for (var i2, r2, o2; l2 = l2.__; ) if ((i2 = l2.__c) && !i2.__) try {
222
+ if ((r2 = i2.constructor) && null != r2.getDerivedStateFromError && (i2.setState(r2.getDerivedStateFromError(n2)), o2 = i2.__d), null != i2.componentDidCatch && (i2.componentDidCatch(n2, t2 || {}), o2 = i2.__d), o2) return i2.__E = i2;
223
+ } catch (l3) {
224
+ n2 = l3;
225
+ }
226
+ throw n2;
227
+ } }, u$2 = 0, C$1.prototype.setState = function(n2, l2) {
228
+ var u2;
229
+ u2 = null != this.__s && this.__s != this.state ? this.__s : this.__s = m$1({}, this.state), "function" == typeof n2 && (n2 = n2(m$1({}, u2), this.props)), n2 && m$1(u2, n2), null != n2 && this.__v && (l2 && this._sb.push(l2), A$1(this));
230
+ }, C$1.prototype.forceUpdate = function(n2) {
231
+ this.__v && (this.__e = true, n2 && this.__h.push(n2), A$1(this));
232
+ }, C$1.prototype.render = S, i$1 = [], o$1 = "function" == typeof Promise ? Promise.prototype.then.bind(Promise.resolve()) : setTimeout, e$1 = function(n2, l2) {
233
+ return n2.__v.__b - l2.__v.__b;
234
+ }, H.__r = 0, f$2 = Math.random().toString(8), c$1 = "__d" + f$2, s$1 = "__a" + f$2, a$1 = /(PointerCapture)$|Capture$/i, h$1 = 0, p$1 = V(false), v$1 = V(true);
235
+ var f$1 = 0;
236
+ function u$1(e2, t2, n2, o2, i2, u2) {
237
+ t2 || (t2 = {});
238
+ var a2, c2, p2 = t2;
239
+ if ("ref" in p2) for (c2 in p2 = {}, t2) "ref" == c2 ? a2 = t2[c2] : p2[c2] = t2[c2];
240
+ var l2 = { type: e2, props: p2, key: n2, ref: a2, __k: null, __: null, __b: 0, __e: null, __c: null, constructor: void 0, __v: --f$1, __i: -1, __u: 0, __source: i2, __self: u2 };
241
+ if ("function" == typeof e2 && (a2 = e2.defaultProps)) for (c2 in a2) void 0 === p2[c2] && (p2[c2] = a2[c2]);
242
+ return l$1.vnode && l$1.vnode(l2), l2;
243
+ }
244
+ var t, r, u, i, o = 0, f = [], c = l$1, e = c.__b, a = c.__r, v = c.diffed, l = c.__c, m = c.unmount, s = c.__;
245
+ function p(n2, t2) {
246
+ c.__h && c.__h(r, n2, o || t2), o = 0;
247
+ var u2 = r.__H || (r.__H = { __: [], __h: [] });
248
+ return n2 >= u2.__.length && u2.__.push({}), u2.__[n2];
249
+ }
250
+ function d(n2) {
251
+ return o = 1, h(D, n2);
252
+ }
253
+ function h(n2, u2, i2) {
254
+ var o2 = p(t++, 2);
255
+ if (o2.t = n2, !o2.__c && (o2.__ = [D(void 0, u2), function(n3) {
256
+ var t2 = o2.__N ? o2.__N[0] : o2.__[0], r2 = o2.t(t2, n3);
257
+ t2 !== r2 && (o2.__N = [r2, o2.__[1]], o2.__c.setState({}));
258
+ }], o2.__c = r, !r.__f)) {
259
+ var f2 = function(n3, t2, r2) {
260
+ if (!o2.__c.__H) return true;
261
+ var u3 = o2.__c.__H.__.filter(function(n4) {
262
+ return n4.__c;
263
+ });
264
+ if (u3.every(function(n4) {
265
+ return !n4.__N;
266
+ })) return !c2 || c2.call(this, n3, t2, r2);
267
+ var i3 = o2.__c.props !== n3;
268
+ return u3.some(function(n4) {
269
+ if (n4.__N) {
270
+ var t3 = n4.__[0];
271
+ n4.__ = n4.__N, n4.__N = void 0, t3 !== n4.__[0] && (i3 = true);
272
+ }
273
+ }), c2 && c2.call(this, n3, t2, r2) || i3;
274
+ };
275
+ r.__f = true;
276
+ var c2 = r.shouldComponentUpdate, e2 = r.componentWillUpdate;
277
+ r.componentWillUpdate = function(n3, t2, r2) {
278
+ if (this.__e) {
279
+ var u3 = c2;
280
+ c2 = void 0, f2(n3, t2, r2), c2 = u3;
281
+ }
282
+ e2 && e2.call(this, n3, t2, r2);
283
+ }, r.shouldComponentUpdate = f2;
284
+ }
285
+ return o2.__N || o2.__;
286
+ }
287
+ function y(n2, u2) {
288
+ var i2 = p(t++, 3);
289
+ !c.__s && C(i2.__H, u2) && (i2.__ = n2, i2.u = u2, r.__H.__h.push(i2));
290
+ }
291
+ function A(n2) {
292
+ return o = 5, T(function() {
293
+ return { current: n2 };
294
+ }, []);
295
+ }
296
+ function T(n2, r2) {
297
+ var u2 = p(t++, 7);
298
+ return C(u2.__H, r2) && (u2.__ = n2(), u2.__H = r2, u2.__h = n2), u2.__;
299
+ }
300
+ function q(n2, t2) {
301
+ return o = 8, T(function() {
302
+ return n2;
303
+ }, t2);
304
+ }
305
+ function j() {
306
+ for (var n2; n2 = f.shift(); ) {
307
+ var t2 = n2.__H;
308
+ if (n2.__P && t2) try {
309
+ t2.__h.some(z), t2.__h.some(B), t2.__h = [];
310
+ } catch (r2) {
311
+ t2.__h = [], c.__e(r2, n2.__v);
312
+ }
313
+ }
314
+ }
315
+ c.__b = function(n2) {
316
+ r = null, e && e(n2);
317
+ }, c.__ = function(n2, t2) {
318
+ n2 && t2.__k && t2.__k.__m && (n2.__m = t2.__k.__m), s && s(n2, t2);
319
+ }, c.__r = function(n2) {
320
+ a && a(n2), t = 0;
321
+ var i2 = (r = n2.__c).__H;
322
+ i2 && (u === r ? (i2.__h = [], r.__h = [], i2.__.some(function(n3) {
323
+ n3.__N && (n3.__ = n3.__N), n3.u = n3.__N = void 0;
324
+ })) : (i2.__h.some(z), i2.__h.some(B), i2.__h = [], t = 0)), u = r;
325
+ }, c.diffed = function(n2) {
326
+ v && v(n2);
327
+ var t2 = n2.__c;
328
+ t2 && t2.__H && (t2.__H.__h.length && (1 !== f.push(t2) && i === c.requestAnimationFrame || ((i = c.requestAnimationFrame) || w)(j)), t2.__H.__.some(function(n3) {
329
+ n3.u && (n3.__H = n3.u), n3.u = void 0;
330
+ })), u = r = null;
331
+ }, c.__c = function(n2, t2) {
332
+ t2.some(function(n3) {
333
+ try {
334
+ n3.__h.some(z), n3.__h = n3.__h.filter(function(n4) {
335
+ return !n4.__ || B(n4);
336
+ });
337
+ } catch (r2) {
338
+ t2.some(function(n4) {
339
+ n4.__h && (n4.__h = []);
340
+ }), t2 = [], c.__e(r2, n3.__v);
341
+ }
342
+ }), l && l(n2, t2);
343
+ }, c.unmount = function(n2) {
344
+ m && m(n2);
345
+ var t2, r2 = n2.__c;
346
+ r2 && r2.__H && (r2.__H.__.some(function(n3) {
347
+ try {
348
+ z(n3);
349
+ } catch (n4) {
350
+ t2 = n4;
351
+ }
352
+ }), r2.__H = void 0, t2 && c.__e(t2, r2.__v));
353
+ };
354
+ var k = "function" == typeof requestAnimationFrame;
355
+ function w(n2) {
356
+ var t2, r2 = function() {
357
+ clearTimeout(u2), k && cancelAnimationFrame(t2), setTimeout(n2);
358
+ }, u2 = setTimeout(r2, 35);
359
+ k && (t2 = requestAnimationFrame(r2));
360
+ }
361
+ function z(n2) {
362
+ var t2 = r, u2 = n2.__c;
363
+ "function" == typeof u2 && (n2.__c = void 0, u2()), r = t2;
364
+ }
365
+ function B(n2) {
366
+ var t2 = r;
367
+ n2.__c = n2.__(), r = t2;
368
+ }
369
+ function C(n2, t2) {
370
+ return !n2 || n2.length !== t2.length || t2.some(function(t3, r2) {
371
+ return t3 !== n2[r2];
372
+ });
373
+ }
374
+ function D(n2, t2) {
375
+ return "function" == typeof t2 ? t2(n2) : t2;
376
+ }
377
+ function CommentPopover({ rect, snippet, defaultAuthor, onCancel, onSubmit }) {
378
+ const [body, setBody] = d("");
379
+ const [author, setAuthor] = d(defaultAuthor);
380
+ const [submitting, setSubmitting] = d(false);
381
+ const textareaRef = A(null);
382
+ y(() => {
383
+ textareaRef.current?.focus();
384
+ }, []);
385
+ const handleSubmit = async () => {
386
+ if (!body.trim() || submitting) return;
387
+ setSubmitting(true);
388
+ try {
389
+ await onSubmit(body.trim(), author.trim() || "Anonymous");
390
+ } finally {
391
+ setSubmitting(false);
392
+ }
393
+ };
394
+ const handleKey = (e2) => {
395
+ if (e2.key === "Escape") {
396
+ e2.preventDefault();
397
+ onCancel();
398
+ } else if (e2.key === "Enter" && (e2.metaKey || e2.ctrlKey)) {
399
+ e2.preventDefault();
400
+ handleSubmit();
401
+ }
402
+ };
403
+ const sidebarWidth = 360;
404
+ const popoverWidth = 320;
405
+ const margin = 12;
406
+ const viewportW = window.innerWidth - sidebarWidth;
407
+ let left = rect.x + rect.width + margin;
408
+ if (left + popoverWidth > viewportW) {
409
+ left = Math.max(margin, rect.x - popoverWidth - margin);
410
+ }
411
+ const top = Math.max(56, Math.min(rect.y, window.innerHeight - 260));
412
+ return /* @__PURE__ */ u$1(
413
+ "div",
414
+ {
415
+ class: "notes-popover",
416
+ style: { left: `${left}px`, top: `${top}px` },
417
+ onClick: (e2) => e2.stopPropagation(),
418
+ onKeyDown: handleKey,
419
+ children: [
420
+ /* @__PURE__ */ u$1("h4", { class: "notes-popover__title", children: "Add comment" }),
421
+ snippet ? /* @__PURE__ */ u$1("div", { class: "notes-popover__snippet", children: snippet }) : null,
422
+ /* @__PURE__ */ u$1(
423
+ "textarea",
424
+ {
425
+ ref: textareaRef,
426
+ placeholder: "Leave a note for the agency...",
427
+ value: body,
428
+ onInput: (e2) => setBody(e2.target.value)
429
+ }
430
+ ),
431
+ /* @__PURE__ */ u$1(
432
+ "input",
433
+ {
434
+ type: "text",
435
+ placeholder: "Your name",
436
+ value: author,
437
+ onInput: (e2) => setAuthor(e2.target.value)
438
+ }
439
+ ),
440
+ /* @__PURE__ */ u$1("div", { class: "notes-popover__row", children: [
441
+ /* @__PURE__ */ u$1("span", { class: "notes-sidebar__hint", children: "⌘+Enter to save" }),
442
+ /* @__PURE__ */ u$1("div", { style: { display: "flex", gap: "6px" }, children: [
443
+ /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost", onClick: onCancel, disabled: submitting, children: "Cancel" }),
444
+ /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--primary", onClick: handleSubmit, disabled: !body.trim() || submitting, children: submitting ? "Saving..." : "Save" })
445
+ ] })
446
+ ] })
447
+ ]
448
+ }
449
+ );
450
+ }
451
+ function ElementHighlight({ rect, persistent }) {
452
+ if (!rect) return null;
453
+ return /* @__PURE__ */ u$1(
454
+ "div",
455
+ {
456
+ class: `notes-highlight ${persistent ? "notes-highlight--persistent" : ""}`,
457
+ style: {
458
+ left: `${rect.x}px`,
459
+ top: `${rect.y}px`,
460
+ width: `${rect.width}px`,
461
+ height: `${rect.height}px`
462
+ }
463
+ }
464
+ );
465
+ }
466
+ function SelectionTooltip({ rect, onComment, onSuggest }) {
467
+ const tooltipWidth = 220;
468
+ const tooltipHeight = 36;
469
+ const margin = 8;
470
+ let left = rect.x + rect.width / 2 - tooltipWidth / 2;
471
+ left = Math.max(margin, Math.min(left, window.innerWidth - tooltipWidth - margin - 360));
472
+ let top = rect.y - tooltipHeight - margin;
473
+ if (top < 56) {
474
+ top = rect.y + rect.height + margin;
475
+ }
476
+ return /* @__PURE__ */ u$1(
477
+ "div",
478
+ {
479
+ class: "notes-selection-tooltip",
480
+ style: { left: `${left}px`, top: `${top}px`, width: `${tooltipWidth}px` },
481
+ onMouseDown: (e2) => {
482
+ e2.preventDefault();
483
+ },
484
+ children: [
485
+ /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost", onClick: onComment, children: "💬 Comment" }),
486
+ /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--primary", onClick: onSuggest, children: "✏️ Suggest edit" })
487
+ ]
488
+ }
489
+ );
490
+ }
491
+ function DiffPreview({ original, suggested }) {
492
+ return /* @__PURE__ */ u$1("div", { class: "notes-diff", children: [
493
+ /* @__PURE__ */ u$1("div", { class: "notes-diff__row notes-diff__row--del", children: [
494
+ /* @__PURE__ */ u$1("span", { class: "notes-diff__marker", children: "−" }),
495
+ /* @__PURE__ */ u$1("span", { class: "notes-strikethrough", children: original })
496
+ ] }),
497
+ /* @__PURE__ */ u$1("div", { class: "notes-diff__row notes-diff__row--ins", children: [
498
+ /* @__PURE__ */ u$1("span", { class: "notes-diff__marker", children: "+" }),
499
+ /* @__PURE__ */ u$1("span", { children: suggested })
500
+ ] })
501
+ ] });
502
+ }
503
+ function StaleWarning({ reason }) {
504
+ return /* @__PURE__ */ u$1("div", { class: "notes-stale", title: reason, children: [
505
+ /* @__PURE__ */ u$1("span", { class: "notes-stale__icon", children: "⚠" }),
506
+ /* @__PURE__ */ u$1("span", { children: "Anchor text not found on this page" })
507
+ ] });
508
+ }
509
+ function formatTime(iso) {
510
+ try {
511
+ const d2 = new Date(iso);
512
+ const now = /* @__PURE__ */ new Date();
513
+ const diffMs = now.getTime() - d2.getTime();
514
+ const diffMin = Math.floor(diffMs / 6e4);
515
+ if (diffMin < 1) return "just now";
516
+ if (diffMin < 60) return `${diffMin}m ago`;
517
+ const diffHr = Math.floor(diffMin / 60);
518
+ if (diffHr < 24) return `${diffHr}h ago`;
519
+ const diffDays = Math.floor(diffHr / 24);
520
+ if (diffDays < 7) return `${diffDays}d ago`;
521
+ return d2.toLocaleDateString();
522
+ } catch {
523
+ return iso;
524
+ }
525
+ }
526
+ function SidebarItem({ item, active, stale, applying, onFocus, onResolve, onReopen, onDelete, onApply }) {
527
+ const isResolved = item.status === "resolved" || item.status === "applied";
528
+ const isApplied = item.status === "applied";
529
+ const isSuggestion = item.type === "suggestion" && item.range;
530
+ const canApply = isSuggestion && !isApplied && !stale;
531
+ return /* @__PURE__ */ u$1(
532
+ "div",
533
+ {
534
+ class: `notes-item ${active ? "notes-item--active" : ""} ${isResolved ? "notes-item--resolved" : ""}`,
535
+ onMouseEnter: onFocus,
536
+ children: [
537
+ /* @__PURE__ */ u$1("div", { class: "notes-item__head", children: [
538
+ /* @__PURE__ */ u$1("div", { children: [
539
+ /* @__PURE__ */ u$1("span", { class: `notes-item__badge notes-item__badge--${item.type}`, children: item.type }),
540
+ isResolved ? /* @__PURE__ */ u$1("span", { class: "notes-item__badge notes-item__badge--resolved", children: item.status }) : null,
541
+ /* @__PURE__ */ u$1("span", { class: "notes-item__author", children: item.author })
542
+ ] }),
543
+ /* @__PURE__ */ u$1("span", { class: "notes-item__time", children: formatTime(item.createdAt) })
544
+ ] }),
545
+ stale && isSuggestion ? /* @__PURE__ */ u$1(StaleWarning, {}) : null,
546
+ isSuggestion && item.range ? /* @__PURE__ */ u$1(S, { children: [
547
+ /* @__PURE__ */ u$1(DiffPreview, { original: item.range.originalText, suggested: item.range.suggestedText }),
548
+ item.range.rationale ? /* @__PURE__ */ u$1("div", { class: "notes-item__rationale", children: [
549
+ /* @__PURE__ */ u$1("span", { class: "notes-item__rationale-label", children: "Why:" }),
550
+ " ",
551
+ item.range.rationale
552
+ ] }) : null,
553
+ item.body ? /* @__PURE__ */ u$1("div", { class: "notes-item__body", children: item.body }) : null
554
+ ] }) : /* @__PURE__ */ u$1(S, { children: [
555
+ item.targetSnippet ? /* @__PURE__ */ u$1("div", { class: "notes-item__snippet", children: item.targetSnippet }) : null,
556
+ /* @__PURE__ */ u$1("div", { class: "notes-item__body", children: item.body })
557
+ ] }),
558
+ /* @__PURE__ */ u$1("div", { class: "notes-item__actions", children: [
559
+ canApply ? /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--primary", onClick: onApply, disabled: applying, children: applying ? "Applying..." : "Apply" }) : null,
560
+ isResolved ? /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost", onClick: onReopen, children: "Reopen" }) : /* @__PURE__ */ u$1("button", { class: "notes-btn", onClick: onResolve, children: "Resolve" }),
561
+ /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost notes-btn--danger", onClick: onDelete, children: "Delete" })
562
+ ] })
563
+ ]
564
+ }
565
+ );
566
+ }
567
+ function Sidebar({ page, items, activeId, picking, error, staleIds, applyingId, onFocus, onResolve, onReopen, onDelete, onApply }) {
568
+ const open = items.filter((i2) => i2.status !== "resolved" && i2.status !== "applied");
569
+ const closed = items.filter((i2) => i2.status === "resolved" || i2.status === "applied");
570
+ const renderItem = (item) => /* @__PURE__ */ u$1(
571
+ SidebarItem,
572
+ {
573
+ item,
574
+ active: item.id === activeId,
575
+ stale: staleIds.has(item.id),
576
+ applying: applyingId === item.id,
577
+ onFocus: () => onFocus(item.id),
578
+ onResolve: () => onResolve(item.id),
579
+ onReopen: () => onReopen(item.id),
580
+ onDelete: () => onDelete(item.id),
581
+ onApply: () => onApply(item.id)
582
+ },
583
+ item.id
584
+ );
585
+ return /* @__PURE__ */ u$1("aside", { class: "notes-sidebar", children: [
586
+ /* @__PURE__ */ u$1("header", { class: "notes-sidebar__header", children: [
587
+ /* @__PURE__ */ u$1("h3", { class: "notes-sidebar__title", children: "Review notes" }),
588
+ /* @__PURE__ */ u$1("div", { class: "notes-sidebar__meta", children: [
589
+ open.length,
590
+ " open · ",
591
+ closed.length,
592
+ " resolved · ",
593
+ /* @__PURE__ */ u$1("code", { children: page })
594
+ ] })
595
+ ] }),
596
+ /* @__PURE__ */ u$1("div", { class: "notes-sidebar__list", children: [
597
+ error ? /* @__PURE__ */ u$1("div", { class: "notes-banner", children: error }) : null,
598
+ items.length === 0 ? /* @__PURE__ */ u$1("div", { class: "notes-sidebar__empty", children: picking ? "Click any text or element on the page to add a comment." : 'Select text on the page to suggest an edit, or click "Pick element" to comment.' }) : null,
599
+ open.map(renderItem),
600
+ closed.length > 0 ? /* @__PURE__ */ u$1(S, { children: [
601
+ /* @__PURE__ */ u$1("div", { class: "notes-sidebar__meta", style: { marginTop: "4px" }, children: "Resolved" }),
602
+ closed.map(renderItem)
603
+ ] }) : null
604
+ ] })
605
+ ] });
606
+ }
607
+ function SuggestPopover({ rect, originalText, defaultAuthor, onCancel, onSubmit }) {
608
+ const [suggested, setSuggested] = d(originalText);
609
+ const [rationale, setRationale] = d("");
610
+ const [body, setBody] = d("");
611
+ const [author, setAuthor] = d(defaultAuthor);
612
+ const [submitting, setSubmitting] = d(false);
613
+ const textareaRef = A(null);
614
+ y(() => {
615
+ const ta = textareaRef.current;
616
+ if (ta) {
617
+ ta.focus();
618
+ ta.select();
619
+ }
620
+ }, []);
621
+ const dirty = suggested.trim() !== originalText.trim();
622
+ const handleSubmit = async () => {
623
+ if (!dirty || submitting) return;
624
+ setSubmitting(true);
625
+ try {
626
+ await onSubmit({
627
+ suggestedText: suggested,
628
+ rationale: rationale.trim(),
629
+ body: body.trim(),
630
+ author: author.trim() || "Anonymous"
631
+ });
632
+ } finally {
633
+ setSubmitting(false);
634
+ }
635
+ };
636
+ const handleKey = (e2) => {
637
+ if (e2.key === "Escape") {
638
+ e2.preventDefault();
639
+ onCancel();
640
+ } else if (e2.key === "Enter" && (e2.metaKey || e2.ctrlKey)) {
641
+ e2.preventDefault();
642
+ handleSubmit();
643
+ }
644
+ };
645
+ const sidebarWidth = 360;
646
+ const popoverWidth = 360;
647
+ const margin = 12;
648
+ const viewportW = window.innerWidth - sidebarWidth;
649
+ let left = rect.x + rect.width + margin;
650
+ if (left + popoverWidth > viewportW) {
651
+ left = Math.max(margin, rect.x - popoverWidth - margin);
652
+ if (left < margin) left = margin;
653
+ }
654
+ const top = Math.max(56, Math.min(rect.y, window.innerHeight - 360));
655
+ return /* @__PURE__ */ u$1(
656
+ "div",
657
+ {
658
+ class: "notes-popover notes-popover--suggest",
659
+ style: { left: `${left}px`, top: `${top}px`, width: `${popoverWidth}px` },
660
+ onClick: (e2) => e2.stopPropagation(),
661
+ onMouseDown: (e2) => e2.stopPropagation(),
662
+ onKeyDown: handleKey,
663
+ children: [
664
+ /* @__PURE__ */ u$1("h4", { class: "notes-popover__title", children: "Suggest edit" }),
665
+ /* @__PURE__ */ u$1("div", { class: "notes-popover__original", children: [
666
+ /* @__PURE__ */ u$1("span", { class: "notes-popover__label", children: "Original" }),
667
+ /* @__PURE__ */ u$1("span", { class: "notes-strikethrough", children: originalText })
668
+ ] }),
669
+ /* @__PURE__ */ u$1("div", { children: [
670
+ /* @__PURE__ */ u$1("label", { class: "notes-popover__label", for: "nua-suggest-text", children: "Replacement" }),
671
+ /* @__PURE__ */ u$1(
672
+ "textarea",
673
+ {
674
+ ref: textareaRef,
675
+ id: "nua-suggest-text",
676
+ value: suggested,
677
+ onInput: (e2) => setSuggested(e2.target.value)
678
+ }
679
+ )
680
+ ] }),
681
+ /* @__PURE__ */ u$1("div", { children: [
682
+ /* @__PURE__ */ u$1("label", { class: "notes-popover__label", for: "nua-suggest-rationale", children: "Why? (optional)" }),
683
+ /* @__PURE__ */ u$1(
684
+ "input",
685
+ {
686
+ type: "text",
687
+ id: "nua-suggest-rationale",
688
+ placeholder: "Stronger framing, fixes typo, ...",
689
+ value: rationale,
690
+ onInput: (e2) => setRationale(e2.target.value)
691
+ }
692
+ )
693
+ ] }),
694
+ /* @__PURE__ */ u$1("div", { children: [
695
+ /* @__PURE__ */ u$1("label", { class: "notes-popover__label", for: "nua-suggest-body", children: "Note (optional)" }),
696
+ /* @__PURE__ */ u$1(
697
+ "input",
698
+ {
699
+ type: "text",
700
+ id: "nua-suggest-body",
701
+ placeholder: "Anything else for the agency",
702
+ value: body,
703
+ onInput: (e2) => setBody(e2.target.value)
704
+ }
705
+ )
706
+ ] }),
707
+ /* @__PURE__ */ u$1(
708
+ "input",
709
+ {
710
+ type: "text",
711
+ placeholder: "Your name",
712
+ value: author,
713
+ onInput: (e2) => setAuthor(e2.target.value)
714
+ }
715
+ ),
716
+ /* @__PURE__ */ u$1("div", { class: "notes-popover__row", children: [
717
+ /* @__PURE__ */ u$1("span", { class: "notes-sidebar__hint", children: dirty ? "⌘+Enter to save" : "Edit the replacement to enable save" }),
718
+ /* @__PURE__ */ u$1("div", { style: { display: "flex", gap: "6px" }, children: [
719
+ /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost", onClick: onCancel, disabled: submitting, children: "Cancel" }),
720
+ /* @__PURE__ */ u$1(
721
+ "button",
722
+ {
723
+ class: "notes-btn notes-btn--primary",
724
+ onClick: handleSubmit,
725
+ disabled: !dirty || submitting,
726
+ children: submitting ? "Saving..." : "Save suggestion"
727
+ }
728
+ )
729
+ ] })
730
+ ] })
731
+ ]
732
+ }
733
+ );
734
+ }
735
+ function Toolbar({ page, count, picking, onTogglePick, onExit }) {
736
+ return /* @__PURE__ */ u$1("div", { class: "notes-toolbar", children: [
737
+ /* @__PURE__ */ u$1("div", { class: "notes-toolbar__brand", children: [
738
+ /* @__PURE__ */ u$1("span", { class: "notes-toolbar__dot" }),
739
+ /* @__PURE__ */ u$1("span", { children: "Notes" }),
740
+ /* @__PURE__ */ u$1("span", { class: "notes-toolbar__page", children: [
741
+ page,
742
+ " · ",
743
+ count,
744
+ " ",
745
+ count === 1 ? "item" : "items"
746
+ ] })
747
+ ] }),
748
+ /* @__PURE__ */ u$1("div", { class: "notes-toolbar__actions", children: [
749
+ /* @__PURE__ */ u$1(
750
+ "button",
751
+ {
752
+ class: `notes-btn ${picking ? "notes-btn--primary" : ""}`,
753
+ onClick: onTogglePick,
754
+ title: "Click any text or element on the page to leave a comment",
755
+ children: picking ? "Cancel pick" : "Pick element"
756
+ }
757
+ ),
758
+ /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost", onClick: onExit, title: "Leave review mode", children: "Exit" })
759
+ ] })
760
+ ] });
761
+ }
762
+ function manifestUrlForPage(page) {
763
+ if (page === "" || page === "/") return "/index.json";
764
+ const trimmed = page.replace(/^\/+|\/+$/g, "");
765
+ return `/${trimmed}.json`;
766
+ }
767
+ async function fetchPageManifest(page) {
768
+ const url = manifestUrlForPage(page);
769
+ try {
770
+ const res = await fetch(url, { headers: { Accept: "application/json" }, signal: AbortSignal.timeout(1e4) });
771
+ if (!res.ok) return null;
772
+ const data = await res.json();
773
+ return data;
774
+ } catch (err) {
775
+ console.warn(`[nuasite-notes] Failed to fetch CMS manifest for "${page}":`, err instanceof Error ? err.message : err);
776
+ return null;
777
+ }
778
+ }
779
+ const BASE = "/_nua/notes";
780
+ const TIMEOUT_MS = 1e4;
781
+ async function postJson(path, body) {
782
+ const res = await fetch(`${BASE}${path}`, {
783
+ method: "POST",
784
+ headers: { "Content-Type": "application/json" },
785
+ body: JSON.stringify(body),
786
+ signal: AbortSignal.timeout(TIMEOUT_MS)
787
+ });
788
+ const text = await res.text();
789
+ let parsed;
790
+ try {
791
+ parsed = text ? JSON.parse(text) : {};
792
+ } catch {
793
+ throw new Error(`notes: invalid JSON response from ${path}`);
794
+ }
795
+ if (!res.ok) {
796
+ throw new Error(parsed?.error ?? `notes: ${path} failed (${res.status})`);
797
+ }
798
+ return parsed;
799
+ }
800
+ async function listNotes(page) {
801
+ const res = await fetch(`${BASE}/list?page=${encodeURIComponent(page)}`, {
802
+ headers: { Accept: "application/json" },
803
+ signal: AbortSignal.timeout(TIMEOUT_MS)
804
+ });
805
+ if (!res.ok) throw new Error(`notes: list failed (${res.status})`);
806
+ return await res.json();
807
+ }
808
+ async function createNote(input) {
809
+ const res = await postJson("/create", input);
810
+ return res.item;
811
+ }
812
+ async function updateNote(page, id, patch) {
813
+ const res = await postJson("/update", { page, id, patch });
814
+ return res.item;
815
+ }
816
+ async function setNoteStatus(page, id, status) {
817
+ if (status === "resolved") {
818
+ const res = await postJson("/resolve", { page, id });
819
+ return res.item;
820
+ }
821
+ if (status === "open") {
822
+ const res = await postJson("/reopen", { page, id });
823
+ return res.item;
824
+ }
825
+ return updateNote(page, id, { status });
826
+ }
827
+ async function deleteNote(page, id) {
828
+ await postJson("/delete", { page, id });
829
+ }
830
+ async function applyNote(page, id) {
831
+ const res = await fetch(`${BASE}/apply`, {
832
+ method: "POST",
833
+ headers: { "Content-Type": "application/json" },
834
+ body: JSON.stringify({ page, id }),
835
+ signal: AbortSignal.timeout(TIMEOUT_MS)
836
+ });
837
+ const text = await res.text();
838
+ let parsed;
839
+ try {
840
+ parsed = text ? JSON.parse(text) : {};
841
+ } catch {
842
+ throw new Error(`notes: invalid JSON response from /apply`);
843
+ }
844
+ if (res.status === 409) {
845
+ return parsed;
846
+ }
847
+ if (!res.ok) {
848
+ throw new Error(parsed?.error ?? `notes: /apply failed (${res.status})`);
849
+ }
850
+ return parsed;
851
+ }
852
+ function collectTextNodes(el) {
853
+ const nodes = [];
854
+ let joined = "";
855
+ const walker = el.ownerDocument.createTreeWalker(el, NodeFilter.SHOW_TEXT);
856
+ let cur = walker.nextNode();
857
+ while (cur) {
858
+ const text = cur.nodeValue ?? "";
859
+ nodes.push({ node: cur, start: joined.length, end: joined.length + text.length });
860
+ joined += text;
861
+ cur = walker.nextNode();
862
+ }
863
+ return { joined, nodes };
864
+ }
865
+ function offsetToNode(nodes, offset) {
866
+ for (const n2 of nodes) {
867
+ if (offset >= n2.start && offset <= n2.end) {
868
+ return { node: n2.node, offset: offset - n2.start };
869
+ }
870
+ }
871
+ return null;
872
+ }
873
+ function rangeFromOffsets(el, start, end) {
874
+ const { joined, nodes } = collectTextNodes(el);
875
+ if (start < 0 || end > joined.length || start >= end) return null;
876
+ const startPos = offsetToNode(nodes, start);
877
+ const endPos = offsetToNode(nodes, end);
878
+ if (!startPos || !endPos) return null;
879
+ const range = el.ownerDocument.createRange();
880
+ range.setStart(startPos.node, startPos.offset);
881
+ range.setEnd(endPos.node, endPos.offset);
882
+ return range;
883
+ }
884
+ function collapseWhitespace(s2) {
885
+ return s2.replace(/\s+/g, " ").trim();
886
+ }
887
+ function findAnchorRange(el, anchorText) {
888
+ if (!anchorText) return null;
889
+ const { joined } = collectTextNodes(el);
890
+ if (!joined) return null;
891
+ const idx = joined.indexOf(anchorText);
892
+ if (idx >= 0) {
893
+ const range2 = rangeFromOffsets(el, idx, idx + anchorText.length);
894
+ if (range2) return { range: range2, rect: range2.getBoundingClientRect(), start: idx, end: idx + anchorText.length };
895
+ }
896
+ const collapsedAnchor = collapseWhitespace(anchorText);
897
+ if (!collapsedAnchor) return null;
898
+ const map = [];
899
+ let collapsed = "";
900
+ let prevWs = false;
901
+ for (let i2 = 0; i2 < joined.length; i2++) {
902
+ const ch = joined[i2];
903
+ const isWs = /\s/.test(ch);
904
+ if (isWs) {
905
+ if (collapsed.length === 0) continue;
906
+ if (prevWs) continue;
907
+ collapsed += " ";
908
+ map.push(i2);
909
+ prevWs = true;
910
+ } else {
911
+ collapsed += ch;
912
+ map.push(i2);
913
+ prevWs = false;
914
+ }
915
+ }
916
+ const trimmed = collapsed.replace(/\s+$/, "");
917
+ const cIdx = trimmed.indexOf(collapsedAnchor);
918
+ if (cIdx < 0) return null;
919
+ const startOrig = map[cIdx];
920
+ const endOrigInclusive = map[cIdx + collapsedAnchor.length - 1];
921
+ if (startOrig == null || endOrigInclusive == null) return null;
922
+ const range = rangeFromOffsets(el, startOrig, endOrigInclusive + 1);
923
+ if (!range) return null;
924
+ return { range, rect: range.getBoundingClientRect(), start: startOrig, end: endOrigInclusive + 1 };
925
+ }
926
+ function selectionInsideElement(el, selection) {
927
+ if (selection.rangeCount === 0) return null;
928
+ const range = selection.getRangeAt(0);
929
+ if (range.collapsed) return null;
930
+ if (!el.contains(range.startContainer) || !el.contains(range.endContainer)) return null;
931
+ const text = range.toString();
932
+ if (!text.trim()) return null;
933
+ return { text, rect: range.getBoundingClientRect() };
934
+ }
935
+ const COOKIE = "nua-notes-mode";
936
+ function isReviewMode(urlFlag) {
937
+ if (typeof window === "undefined") return false;
938
+ const url = new URL(window.location.href);
939
+ if (url.searchParams.has(urlFlag)) return true;
940
+ return document.cookie.split("; ").some((c2) => c2.startsWith(`${COOKIE}=1`));
941
+ }
942
+ function setReviewModeCookie() {
943
+ document.cookie = `${COOKIE}=1; path=/; SameSite=Lax`;
944
+ }
945
+ function clearReviewModeCookie() {
946
+ document.cookie = `${COOKIE}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax`;
947
+ }
948
+ function exitReviewMode(urlFlag) {
949
+ clearReviewModeCookie();
950
+ const url = new URL(window.location.href);
951
+ url.searchParams.delete(urlFlag);
952
+ window.location.href = url.pathname + (url.search || "") + url.hash;
953
+ }
954
+ function getCurrentPagePath() {
955
+ if (typeof window === "undefined") return "/";
956
+ const p2 = window.location.pathname;
957
+ if (p2 === "" || p2 === "/") return "/";
958
+ return p2.endsWith("/") ? p2.slice(0, -1) : p2;
959
+ }
960
+ const AUTHOR_KEY = "nua-notes-author";
961
+ function loadAuthor() {
962
+ try {
963
+ return localStorage.getItem(AUTHOR_KEY) || "";
964
+ } catch {
965
+ return "";
966
+ }
967
+ }
968
+ function saveAuthor(name) {
969
+ try {
970
+ localStorage.setItem(AUTHOR_KEY, name);
971
+ } catch {
972
+ }
973
+ }
974
+ function getRect(el) {
975
+ const r2 = el.getBoundingClientRect();
976
+ return { x: r2.x, y: r2.y, width: r2.width, height: r2.height };
977
+ }
978
+ function rectFromDom(r2) {
979
+ return { x: r2.x, y: r2.y, width: r2.width, height: r2.height };
980
+ }
981
+ function findCmsAncestor(target) {
982
+ let el = target;
983
+ while (el && el.nodeType === 1) {
984
+ if (el.hasAttribute?.("data-cms-id")) return el;
985
+ el = el.parentElement;
986
+ }
987
+ return null;
988
+ }
989
+ function App({ urlFlag }) {
990
+ const page = T(() => getCurrentPagePath(), []);
991
+ const [items, setItems] = d([]);
992
+ const [manifest, setManifest] = d(null);
993
+ const [picking, setPicking] = d(false);
994
+ const [hoverRect, setHoverRect] = d(null);
995
+ const [pendingPick, setPendingPick] = d(null);
996
+ const [pendingSuggest, setPendingSuggest] = d(null);
997
+ const [pendingSelection, setPendingSelection] = d(null);
998
+ const [activeId, setActiveId] = d(null);
999
+ const [activeRect, setActiveRect] = d(null);
1000
+ const [error, setError] = d(null);
1001
+ const [author, setAuthor] = d(() => loadAuthor());
1002
+ const [staleIds, setStaleIds] = d(/* @__PURE__ */ new Set());
1003
+ const [applyingId, setApplyingId] = d(null);
1004
+ y(() => {
1005
+ let alive = true;
1006
+ Promise.all([listNotes(page), fetchPageManifest(page)]).then(([file, mf]) => {
1007
+ if (!alive) return;
1008
+ setItems(file.items);
1009
+ setManifest(mf);
1010
+ }).catch((err) => {
1011
+ if (!alive) return;
1012
+ setError(err instanceof Error ? err.message : String(err));
1013
+ });
1014
+ return () => {
1015
+ alive = false;
1016
+ };
1017
+ }, [page]);
1018
+ y(() => {
1019
+ const stale = /* @__PURE__ */ new Set();
1020
+ for (const item of items) {
1021
+ if (item.type !== "suggestion" || !item.range) continue;
1022
+ const el = document.querySelector(`[data-cms-id="${item.targetCmsId}"]`);
1023
+ if (!el) {
1024
+ stale.add(item.id);
1025
+ continue;
1026
+ }
1027
+ const match = findAnchorRange(el, item.range.anchorText);
1028
+ if (!match) stale.add(item.id);
1029
+ }
1030
+ setStaleIds(stale);
1031
+ }, [items]);
1032
+ y(() => {
1033
+ if (!activeId) {
1034
+ setActiveRect(null);
1035
+ return;
1036
+ }
1037
+ const item = items.find((i2) => i2.id === activeId);
1038
+ if (!item) return;
1039
+ const el = document.querySelector(`[data-cms-id="${item.targetCmsId}"]`);
1040
+ if (!el) {
1041
+ setActiveRect(null);
1042
+ return;
1043
+ }
1044
+ const updateRect = () => {
1045
+ if (item.type === "suggestion" && item.range) {
1046
+ const match = findAnchorRange(el, item.range.anchorText);
1047
+ if (match) {
1048
+ setActiveRect(rectFromDom(match.rect));
1049
+ return;
1050
+ }
1051
+ }
1052
+ setActiveRect(getRect(el));
1053
+ };
1054
+ updateRect();
1055
+ window.addEventListener("scroll", updateRect, true);
1056
+ window.addEventListener("resize", updateRect);
1057
+ return () => {
1058
+ window.removeEventListener("scroll", updateRect, true);
1059
+ window.removeEventListener("resize", updateRect);
1060
+ };
1061
+ }, [activeId, items]);
1062
+ y(() => {
1063
+ if (!picking) {
1064
+ setHoverRect(null);
1065
+ return;
1066
+ }
1067
+ const onMove = (e2) => {
1068
+ const el = findCmsAncestor(e2.target);
1069
+ if (!el) {
1070
+ setHoverRect(null);
1071
+ return;
1072
+ }
1073
+ const cmsId = el.getAttribute("data-cms-id");
1074
+ setHoverRect({ cmsId, rect: getRect(el) });
1075
+ };
1076
+ const onClick = (e2) => {
1077
+ const el = findCmsAncestor(e2.target);
1078
+ if (!el) return;
1079
+ e2.preventDefault();
1080
+ e2.stopPropagation();
1081
+ const cmsId = el.getAttribute("data-cms-id");
1082
+ const text = (el.textContent || "").trim().slice(0, 200);
1083
+ setPendingPick({ cmsId, rect: getRect(el), snippet: text });
1084
+ setPicking(false);
1085
+ };
1086
+ document.addEventListener("mousemove", onMove, true);
1087
+ document.addEventListener("click", onClick, true);
1088
+ return () => {
1089
+ document.removeEventListener("mousemove", onMove, true);
1090
+ document.removeEventListener("click", onClick, true);
1091
+ };
1092
+ }, [picking]);
1093
+ y(() => {
1094
+ if (picking || pendingPick || pendingSuggest) {
1095
+ setPendingSelection(null);
1096
+ return;
1097
+ }
1098
+ const onSelectionChange = () => {
1099
+ const sel = document.getSelection();
1100
+ if (!sel || sel.rangeCount === 0 || sel.isCollapsed) {
1101
+ setPendingSelection(null);
1102
+ return;
1103
+ }
1104
+ const range = sel.getRangeAt(0);
1105
+ const startEl = range.startContainer.nodeType === 3 ? range.startContainer.parentElement : range.startContainer;
1106
+ if (!startEl) return;
1107
+ const cmsEl = findCmsAncestor(startEl);
1108
+ if (!cmsEl) {
1109
+ setPendingSelection(null);
1110
+ return;
1111
+ }
1112
+ if (!cmsEl.contains(range.endContainer)) {
1113
+ setPendingSelection(null);
1114
+ return;
1115
+ }
1116
+ const inside = selectionInsideElement(cmsEl, sel);
1117
+ if (!inside) {
1118
+ setPendingSelection(null);
1119
+ return;
1120
+ }
1121
+ const cmsId = cmsEl.getAttribute("data-cms-id");
1122
+ const elementSnippet = (cmsEl.textContent || "").trim().slice(0, 200);
1123
+ setPendingSelection({
1124
+ cmsId,
1125
+ anchorText: inside.text,
1126
+ rect: rectFromDom(inside.rect),
1127
+ elementRect: getRect(cmsEl),
1128
+ elementSnippet
1129
+ });
1130
+ };
1131
+ document.addEventListener("selectionchange", onSelectionChange);
1132
+ return () => document.removeEventListener("selectionchange", onSelectionChange);
1133
+ }, [picking, pendingPick, pendingSuggest]);
1134
+ const handleCreateComment = q(
1135
+ async (body, authorName) => {
1136
+ if (!pendingPick) return;
1137
+ saveAuthor(authorName);
1138
+ setAuthor(authorName);
1139
+ const entry = manifest?.entries?.[pendingPick.cmsId];
1140
+ try {
1141
+ const item = await createNote({
1142
+ page,
1143
+ type: "comment",
1144
+ targetCmsId: pendingPick.cmsId,
1145
+ targetSourcePath: entry?.sourcePath,
1146
+ targetSourceLine: entry?.sourceLine,
1147
+ targetSnippet: entry?.sourceSnippet ?? pendingPick.snippet,
1148
+ body,
1149
+ author: authorName
1150
+ });
1151
+ setItems((prev) => [...prev, item]);
1152
+ setActiveId(item.id);
1153
+ setPendingPick(null);
1154
+ setError(null);
1155
+ } catch (err) {
1156
+ setError(err instanceof Error ? err.message : String(err));
1157
+ }
1158
+ },
1159
+ [page, pendingPick, manifest]
1160
+ );
1161
+ const handleCreateSuggestion = q(
1162
+ async (input) => {
1163
+ if (!pendingSuggest) return;
1164
+ saveAuthor(input.author);
1165
+ setAuthor(input.author);
1166
+ const entry = manifest?.entries?.[pendingSuggest.cmsId];
1167
+ try {
1168
+ const item = await createNote({
1169
+ page,
1170
+ type: "suggestion",
1171
+ targetCmsId: pendingSuggest.cmsId,
1172
+ targetSourcePath: entry?.sourcePath,
1173
+ targetSourceLine: entry?.sourceLine,
1174
+ targetSnippet: entry?.sourceSnippet ?? pendingSuggest.elementSnippet,
1175
+ range: {
1176
+ anchorText: pendingSuggest.anchorText,
1177
+ originalText: pendingSuggest.anchorText,
1178
+ suggestedText: input.suggestedText,
1179
+ rationale: input.rationale || void 0
1180
+ },
1181
+ body: input.body,
1182
+ author: input.author
1183
+ });
1184
+ setItems((prev) => [...prev, item]);
1185
+ setActiveId(item.id);
1186
+ setPendingSuggest(null);
1187
+ setPendingSelection(null);
1188
+ try {
1189
+ document.getSelection()?.removeAllRanges();
1190
+ } catch {
1191
+ }
1192
+ setError(null);
1193
+ } catch (err) {
1194
+ setError(err instanceof Error ? err.message : String(err));
1195
+ }
1196
+ },
1197
+ [page, pendingSuggest, manifest]
1198
+ );
1199
+ const handleResolve = q(async (id) => {
1200
+ try {
1201
+ const item = await setNoteStatus(page, id, "resolved");
1202
+ setItems((prev) => prev.map((i2) => i2.id === id ? item : i2));
1203
+ } catch (err) {
1204
+ setError(err instanceof Error ? err.message : String(err));
1205
+ }
1206
+ }, [page]);
1207
+ const handleReopen = q(async (id) => {
1208
+ try {
1209
+ const item = await setNoteStatus(page, id, "open");
1210
+ setItems((prev) => prev.map((i2) => i2.id === id ? item : i2));
1211
+ } catch (err) {
1212
+ setError(err instanceof Error ? err.message : String(err));
1213
+ }
1214
+ }, [page]);
1215
+ const handleDelete = q(async (id) => {
1216
+ try {
1217
+ await deleteNote(page, id);
1218
+ setItems((prev) => prev.filter((i2) => i2.id !== id));
1219
+ if (activeId === id) setActiveId(null);
1220
+ } catch (err) {
1221
+ setError(err instanceof Error ? err.message : String(err));
1222
+ }
1223
+ }, [page, activeId]);
1224
+ const handleApply = q(async (id) => {
1225
+ setApplyingId(id);
1226
+ try {
1227
+ const result = await applyNote(page, id);
1228
+ setItems((prev) => prev.map((i2) => i2.id === id ? result.item : i2));
1229
+ if (result.error) {
1230
+ setError(result.error);
1231
+ } else {
1232
+ setError(null);
1233
+ }
1234
+ } catch (err) {
1235
+ setError(err instanceof Error ? err.message : String(err));
1236
+ } finally {
1237
+ setApplyingId(null);
1238
+ }
1239
+ }, [page]);
1240
+ const handleSelectionComment = q(() => {
1241
+ if (!pendingSelection) return;
1242
+ setPendingPick({
1243
+ cmsId: pendingSelection.cmsId,
1244
+ rect: pendingSelection.elementRect,
1245
+ snippet: pendingSelection.anchorText
1246
+ });
1247
+ setPendingSelection(null);
1248
+ }, [pendingSelection]);
1249
+ const handleSelectionSuggest = q(() => {
1250
+ if (!pendingSelection) return;
1251
+ setPendingSuggest(pendingSelection);
1252
+ setPendingSelection(null);
1253
+ }, [pendingSelection]);
1254
+ return /* @__PURE__ */ u$1("div", { class: "notes-root", children: [
1255
+ /* @__PURE__ */ u$1(
1256
+ Toolbar,
1257
+ {
1258
+ page,
1259
+ count: items.length,
1260
+ picking,
1261
+ onTogglePick: () => {
1262
+ setPicking((p2) => !p2);
1263
+ setPendingPick(null);
1264
+ setPendingSuggest(null);
1265
+ },
1266
+ onExit: () => exitReviewMode(urlFlag)
1267
+ }
1268
+ ),
1269
+ /* @__PURE__ */ u$1(
1270
+ Sidebar,
1271
+ {
1272
+ page,
1273
+ items,
1274
+ activeId,
1275
+ picking,
1276
+ error,
1277
+ staleIds,
1278
+ applyingId,
1279
+ onFocus: setActiveId,
1280
+ onResolve: handleResolve,
1281
+ onReopen: handleReopen,
1282
+ onDelete: handleDelete,
1283
+ onApply: handleApply
1284
+ }
1285
+ ),
1286
+ picking && hoverRect ? /* @__PURE__ */ u$1(ElementHighlight, { rect: hoverRect.rect }) : null,
1287
+ activeRect ? /* @__PURE__ */ u$1(ElementHighlight, { rect: activeRect, persistent: true }) : null,
1288
+ pendingSelection && !pendingPick && !pendingSuggest ? /* @__PURE__ */ u$1(
1289
+ SelectionTooltip,
1290
+ {
1291
+ rect: pendingSelection.rect,
1292
+ onComment: handleSelectionComment,
1293
+ onSuggest: handleSelectionSuggest
1294
+ }
1295
+ ) : null,
1296
+ pendingPick ? /* @__PURE__ */ u$1(
1297
+ CommentPopover,
1298
+ {
1299
+ rect: pendingPick.rect,
1300
+ snippet: pendingPick.snippet,
1301
+ defaultAuthor: author,
1302
+ onCancel: () => setPendingPick(null),
1303
+ onSubmit: handleCreateComment
1304
+ }
1305
+ ) : null,
1306
+ pendingSuggest ? /* @__PURE__ */ u$1(
1307
+ SuggestPopover,
1308
+ {
1309
+ rect: pendingSuggest.rect,
1310
+ originalText: pendingSuggest.anchorText,
1311
+ defaultAuthor: author,
1312
+ onCancel: () => {
1313
+ setPendingSuggest(null);
1314
+ try {
1315
+ document.getSelection()?.removeAllRanges();
1316
+ } catch {
1317
+ }
1318
+ },
1319
+ onSubmit: handleCreateSuggestion
1320
+ }
1321
+ ) : null
1322
+ ] });
1323
+ }
1324
+ const STYLE_ID = "nua-notes-cms-bridge";
1325
+ const HIDE_CMS_CSS = `
1326
+ #cms-app-host { display: none !important; }
1327
+ [data-nuasite-cms] { display: none !important; }
1328
+ /* Allow notes to handle clicks on annotated elements without CMS interfering */
1329
+ [data-cms-id] { cursor: default !important; }
1330
+ `;
1331
+ function enableCmsBridge() {
1332
+ if (document.getElementById(STYLE_ID)) return;
1333
+ const style = document.createElement("style");
1334
+ style.id = STYLE_ID;
1335
+ style.textContent = HIDE_CMS_CSS;
1336
+ document.head.appendChild(style);
1337
+ }
1338
+ const OVERLAY_STYLES = "/**\n * @nuasite/notes overlay styles.\n *\n * Imported via Vite's `?inline` query and injected into a shadow root, so\n * these styles never leak into the host page (and the host page can't\n * accidentally style notes UI). Variables on `:host` are the only knobs.\n */\n\n:host {\n --notes-bg: #ffffff;\n --notes-fg: #0f172a;\n --notes-muted: #64748b;\n --notes-border: #e2e8f0;\n --notes-accent: #f59e0b;\n --notes-accent-fg: #1f2937;\n --notes-danger: #dc2626;\n --notes-success: #16a34a;\n --notes-shadow: 0 10px 30px rgba(15, 23, 42, 0.18);\n --notes-radius: 10px;\n --notes-sidebar-w: 360px;\n --notes-z: 2147483600;\n\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n line-height: 1.45;\n color: var(--notes-fg);\n -webkit-font-smoothing: antialiased;\n}\n\n* {\n box-sizing: border-box;\n}\n\nbutton {\n font: inherit;\n cursor: pointer;\n border: none;\n background: none;\n color: inherit;\n padding: 0;\n}\n\ninput,\ntextarea {\n font: inherit;\n color: inherit;\n}\n\n.notes-root {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: var(--notes-z);\n}\n\n/* Toolbar (top, full width) */\n.notes-toolbar {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 44px;\n background: var(--notes-bg);\n border-bottom: 1px solid var(--notes-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 16px;\n box-shadow: var(--notes-shadow);\n pointer-events: auto;\n}\n\n.notes-toolbar__brand {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n}\n\n.notes-toolbar__dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--notes-accent);\n box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.2);\n}\n\n.notes-toolbar__page {\n color: var(--notes-muted);\n font-weight: 400;\n margin-left: 12px;\n font-size: 13px;\n}\n\n.notes-toolbar__actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.notes-btn {\n padding: 6px 12px;\n border-radius: 6px;\n background: #f1f5f9;\n color: var(--notes-fg);\n font-size: 13px;\n font-weight: 500;\n transition: background 0.15s;\n}\n\n.notes-btn:hover {\n background: #e2e8f0;\n}\n\n.notes-btn--primary {\n background: var(--notes-accent);\n color: var(--notes-accent-fg);\n}\n\n.notes-btn--primary:hover {\n background: #d97706;\n color: #ffffff;\n}\n\n.notes-btn--ghost {\n background: transparent;\n color: var(--notes-muted);\n}\n\n.notes-btn--ghost:hover {\n color: var(--notes-fg);\n background: #f1f5f9;\n}\n\n.notes-btn--danger {\n color: var(--notes-danger);\n}\n\n/* Sidebar (right side) */\n.notes-sidebar {\n position: fixed;\n top: 44px;\n right: 0;\n bottom: 0;\n width: var(--notes-sidebar-w);\n background: var(--notes-bg);\n border-left: 1px solid var(--notes-border);\n box-shadow: var(--notes-shadow);\n display: flex;\n flex-direction: column;\n pointer-events: auto;\n}\n\n.notes-sidebar__header {\n padding: 16px 16px 12px;\n border-bottom: 1px solid var(--notes-border);\n}\n\n.notes-sidebar__title {\n font-size: 16px;\n font-weight: 600;\n margin: 0 0 4px;\n}\n\n.notes-sidebar__meta {\n font-size: 12px;\n color: var(--notes-muted);\n}\n\n.notes-sidebar__list {\n flex: 1;\n overflow-y: auto;\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.notes-sidebar__empty {\n padding: 24px 16px;\n text-align: center;\n color: var(--notes-muted);\n font-size: 13px;\n line-height: 1.5;\n}\n\n.notes-sidebar__hint {\n font-size: 12px;\n color: var(--notes-muted);\n margin-top: 6px;\n}\n\n/* Item card */\n.notes-item {\n border: 1px solid var(--notes-border);\n border-radius: var(--notes-radius);\n padding: 12px;\n background: #ffffff;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.notes-item:hover {\n border-color: #cbd5e1;\n}\n\n.notes-item--active {\n border-color: var(--notes-accent);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.12);\n}\n\n.notes-item--resolved {\n opacity: 0.55;\n}\n\n.notes-item__head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 6px;\n}\n\n.notes-item__author {\n font-weight: 600;\n font-size: 13px;\n}\n\n.notes-item__time {\n font-size: 11px;\n color: var(--notes-muted);\n}\n\n.notes-item__snippet {\n font-size: 12px;\n color: var(--notes-muted);\n background: #f8fafc;\n border-left: 3px solid var(--notes-border);\n padding: 6px 8px;\n margin-bottom: 6px;\n border-radius: 0 4px 4px 0;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.notes-item__body {\n font-size: 13px;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.notes-item__actions {\n display: flex;\n gap: 6px;\n margin-top: 10px;\n padding-top: 10px;\n border-top: 1px solid #f1f5f9;\n}\n\n.notes-item__badge {\n display: inline-block;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 2px 6px;\n border-radius: 4px;\n margin-right: 6px;\n}\n\n.notes-item__badge--comment {\n background: #dbeafe;\n color: #1e40af;\n}\n\n.notes-item__badge--suggestion {\n background: #fef3c7;\n color: #92400e;\n}\n\n.notes-item__badge--resolved {\n background: #dcfce7;\n color: #166534;\n}\n\n/* Element highlight ring */\n.notes-highlight {\n position: fixed;\n pointer-events: none;\n border: 2px solid var(--notes-accent);\n border-radius: 4px;\n box-shadow: 0 0 0 4px rgba(245, 158, 11, 0.18);\n transition: all 0.08s ease-out;\n}\n\n.notes-highlight--persistent {\n border-color: rgba(245, 158, 11, 0.6);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.12);\n}\n\n/* Comment popover */\n.notes-popover {\n position: fixed;\n width: 320px;\n background: var(--notes-bg);\n border: 1px solid var(--notes-border);\n border-radius: var(--notes-radius);\n box-shadow: var(--notes-shadow);\n padding: 14px;\n pointer-events: auto;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.notes-popover__title {\n font-size: 13px;\n font-weight: 600;\n margin: 0;\n}\n\n.notes-popover__snippet {\n font-size: 12px;\n color: var(--notes-muted);\n background: #f8fafc;\n border-left: 3px solid var(--notes-border);\n padding: 6px 8px;\n border-radius: 0 4px 4px 0;\n max-height: 60px;\n overflow: hidden;\n}\n\n.notes-popover textarea {\n width: 100%;\n min-height: 80px;\n resize: vertical;\n border: 1px solid var(--notes-border);\n border-radius: 6px;\n padding: 8px 10px;\n background: #ffffff;\n outline: none;\n}\n\n.notes-popover textarea:focus {\n border-color: var(--notes-accent);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.15);\n}\n\n.notes-popover input[type='text'] {\n border: 1px solid var(--notes-border);\n border-radius: 6px;\n padding: 6px 10px;\n background: #ffffff;\n outline: none;\n}\n\n.notes-popover input[type='text']:focus {\n border-color: var(--notes-accent);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.15);\n}\n\n.notes-popover__row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 8px;\n}\n\n/* Selection tooltip */\n.notes-selection-tooltip {\n position: fixed;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n background: #0f172a;\n color: #ffffff;\n border-radius: 8px;\n box-shadow: var(--notes-shadow);\n pointer-events: auto;\n z-index: calc(var(--notes-z) + 5);\n}\n\n.notes-selection-tooltip .notes-btn {\n background: rgba(255, 255, 255, 0.08);\n color: #ffffff;\n font-size: 12px;\n padding: 4px 8px;\n}\n\n.notes-selection-tooltip .notes-btn--primary {\n background: var(--notes-accent);\n color: var(--notes-accent-fg);\n}\n\n.notes-selection-tooltip .notes-btn--ghost {\n color: #e2e8f0;\n}\n\n.notes-selection-tooltip .notes-btn--ghost:hover {\n background: rgba(255, 255, 255, 0.16);\n color: #ffffff;\n}\n\n/* Suggest popover variations */\n.notes-popover--suggest {\n width: 360px;\n}\n\n.notes-popover__label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--notes-muted);\n margin-bottom: 4px;\n}\n\n.notes-popover__original {\n background: #fef3c7;\n border: 1px solid #fde68a;\n border-radius: 6px;\n padding: 8px 10px;\n font-size: 13px;\n color: #78350f;\n max-height: 80px;\n overflow-y: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.notes-strikethrough {\n text-decoration: line-through;\n text-decoration-color: rgba(220, 38, 38, 0.6);\n text-decoration-thickness: 2px;\n}\n\n/* Diff preview in sidebar */\n.notes-diff {\n font-size: 13px;\n border-radius: 6px;\n background: #f8fafc;\n border: 1px solid var(--notes-border);\n overflow: hidden;\n margin-bottom: 8px;\n}\n\n.notes-diff__row {\n padding: 6px 10px;\n display: flex;\n gap: 6px;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.notes-diff__row--del {\n background: #fef2f2;\n color: #7f1d1d;\n border-bottom: 1px solid #fee2e2;\n}\n\n.notes-diff__row--ins {\n background: #f0fdf4;\n color: #14532d;\n}\n\n.notes-diff__marker {\n font-weight: 700;\n font-family: ui-monospace, SFMono-Regular, monospace;\n width: 12px;\n flex-shrink: 0;\n text-align: center;\n}\n\n.notes-item__rationale {\n font-size: 12px;\n color: var(--notes-muted);\n margin-bottom: 6px;\n font-style: italic;\n}\n\n.notes-item__rationale-label {\n font-style: normal;\n font-weight: 600;\n color: var(--notes-fg);\n margin-right: 4px;\n}\n\n/* Stale warning */\n.notes-stale {\n display: flex;\n align-items: center;\n gap: 6px;\n background: #fef3c7;\n border: 1px solid #fde68a;\n color: #92400e;\n font-size: 12px;\n padding: 6px 8px;\n border-radius: 6px;\n margin-bottom: 8px;\n}\n\n.notes-stale__icon {\n font-size: 14px;\n}\n\n/* Persistent highlight variant for suggestion ranges */\n.notes-highlight--suggestion {\n border-color: rgba(250, 204, 21, 0.9);\n box-shadow: 0 0 0 3px rgba(250, 204, 21, 0.18);\n background: rgba(254, 243, 199, 0.25);\n}\n\n/* Banner shown when notes API fails to load */\n.notes-banner {\n position: fixed;\n top: 56px;\n left: 16px;\n right: calc(var(--notes-sidebar-w) + 16px);\n padding: 10px 14px;\n background: #fef2f2;\n border: 1px solid #fecaca;\n color: #991b1b;\n border-radius: var(--notes-radius);\n font-size: 13px;\n pointer-events: auto;\n}\n";
1339
+ function init() {
1340
+ if (window.__nuasiteNotesMounted) return;
1341
+ const config = window.__NuaNotesConfig ?? {};
1342
+ const urlFlag = config.urlFlag ?? "nua-notes";
1343
+ if (!isReviewMode(urlFlag)) return;
1344
+ window.__nuasiteNotesMounted = true;
1345
+ setReviewModeCookie();
1346
+ enableCmsBridge();
1347
+ const host = document.createElement("div");
1348
+ host.id = "nua-notes-host";
1349
+ host.setAttribute("data-nua-notes-host", "");
1350
+ host.style.cssText = "position:fixed;top:0;left:0;width:0;height:0;z-index:2147483600;";
1351
+ document.body.appendChild(host);
1352
+ const shadow = host.attachShadow({ mode: "open" });
1353
+ const styleEl = document.createElement("style");
1354
+ styleEl.textContent = OVERLAY_STYLES;
1355
+ shadow.appendChild(styleEl);
1356
+ const root = document.createElement("div");
1357
+ root.id = "nua-notes-root";
1358
+ shadow.appendChild(root);
1359
+ R(/* @__PURE__ */ u$1(App, { urlFlag }), root);
1360
+ }
1361
+ if (typeof window !== "undefined") {
1362
+ if (document.readyState === "loading") {
1363
+ document.addEventListener("DOMContentLoaded", init, { once: true });
1364
+ } else {
1365
+ init();
1366
+ }
1367
+ }