review-lens-react 1.0.0 → 1.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.
@@ -1,132 +1,153 @@
1
- import { jsx as r, jsxs as o, Fragment as re } from "react/jsx-runtime";
2
- import { createContext as st, useMemo as ie, useState as k, useCallback as W, useEffect as _, useContext as ot, useRef as We, useLayoutEffect as lt } from "react";
3
- const ct = [
1
+ import { jsx as i, jsxs as o, Fragment as ae } from "react/jsx-runtime";
2
+ import { createContext as mt, useMemo as se, useState as N, useCallback as W, useEffect as B, useContext as pt, useRef as re, useLayoutEffect as gt } from "react";
3
+ const Be = [
4
4
  "https://www.googleapis.com/auth/spreadsheets",
5
5
  "https://www.googleapis.com/auth/userinfo.email"
6
- ].join(" "), dt = "https://www.googleapis.com/oauth2/v3/userinfo";
7
- function ht(e) {
8
- const t = e.feedbackSheetName ?? "Feedback", n = e.messagesSheetName ?? "Messages", i = e.usersSheetName ?? "Users";
9
- let s, c;
10
- async function g() {
11
- return s ?? (s = St(e.googleClientId)), s;
6
+ ], ft = "https://www.googleapis.com/auth/gmail.send", wt = "https://www.googleapis.com/oauth2/v3/userinfo", bt = "https://gmail.googleapis.com/gmail/v1/users/me/messages/send";
7
+ function vt(e) {
8
+ const t = e.feedbackSheetName ?? "Feedback", n = e.messagesSheetName ?? "Messages", r = e.usersSheetName ?? "Users", s = e.enableEmailNotifications ? [...Be, ft].join(" ") : Be.join(" ");
9
+ let c, h;
10
+ async function w() {
11
+ return c ?? (c = At(e.googleClientId, s)), c;
12
12
  }
13
- async function f(d, v, h) {
14
- const b = await g(), C = await fetch(
15
- `https://sheets.googleapis.com/v4/spreadsheets/${d}${v}`,
13
+ async function p(g, f, m) {
14
+ const S = await w(), x = await fetch(
15
+ `https://sheets.googleapis.com/v4/spreadsheets/${g}${f}`,
16
16
  {
17
- ...h,
17
+ ...m,
18
18
  headers: {
19
- Authorization: `Bearer ${b}`,
19
+ Authorization: `Bearer ${S}`,
20
20
  "Content-Type": "application/json",
21
- ...h == null ? void 0 : h.headers
21
+ ...m == null ? void 0 : m.headers
22
22
  }
23
23
  }
24
24
  );
25
- if (!C.ok)
26
- throw new Error(`Google Sheets request failed with ${C.status}`);
27
- return C.json();
25
+ if (!x.ok)
26
+ throw new Error(`Google Sheets request failed with ${x.status}`);
27
+ return x.json();
28
28
  }
29
- async function p(d, v) {
30
- return (await f(
31
- d,
32
- `/values/${encodeURIComponent(v)}`
29
+ async function b(g, f) {
30
+ return (await p(
31
+ g,
32
+ `/values/${encodeURIComponent(f)}`
33
33
  )).values ?? [];
34
34
  }
35
35
  return {
36
36
  async getCurrentUser() {
37
- if (!c) {
38
- const d = await g(), v = await fetch(dt, {
39
- headers: { Authorization: `Bearer ${d}` }
37
+ if (!h) {
38
+ const g = await w(), f = await fetch(wt, {
39
+ headers: { Authorization: `Bearer ${g}` }
40
40
  });
41
- if (!v.ok)
42
- throw new Error(`Google userinfo request failed with ${v.status}`);
43
- c = (await v.json()).email;
41
+ if (!f.ok)
42
+ throw new Error(`Google userinfo request failed with ${f.status}`);
43
+ h = (await f.json()).email;
44
44
  }
45
- if (!c)
45
+ if (!h)
46
46
  throw new Error("Google account did not return an email address");
47
- return { email: c };
47
+ return { email: h };
48
48
  },
49
- async getPermissions(d) {
50
- const [{ email: v }, h] = await Promise.all([
49
+ async getPermissions(g) {
50
+ const [{ email: f }, m] = await Promise.all([
51
51
  this.getCurrentUser(),
52
- p(e.usersSpreadsheetId, i)
53
- ]), b = ce(h), C = v.toLowerCase(), E = b.find(
54
- (A) => {
55
- var u;
56
- return ((u = A.email) == null ? void 0 : u.toLowerCase()) === C && A.active !== "false" && (!A.projectKey || A.projectKey === d);
52
+ b(e.usersSpreadsheetId, r)
53
+ ]), S = ue(m), x = f.toLowerCase(), E = S.find(
54
+ (l) => {
55
+ var A;
56
+ return ((A = l.email) == null ? void 0 : A.toLowerCase()) === x && l.active !== "false" && (!l.projectKey || l.projectKey === g);
57
57
  }
58
58
  );
59
- return gt((E == null ? void 0 : E.role) ?? "designer");
59
+ return Nt((E == null ? void 0 : E.role) ?? "designer");
60
60
  },
61
- async listFeedback(d) {
62
- return ce(await p(e.contentSpreadsheetId, t)).map(Re).filter((h) => h !== null).filter(
63
- (h) => h.projectKey === d.projectKey && h.contentId === d.contentId && h.normalizedPath === d.normalizedPath
64
- ).sort((h, b) => b.createdAt.localeCompare(h.createdAt));
61
+ async listFeedback(g) {
62
+ return ue(await b(e.contentSpreadsheetId, t)).map(je).filter((m) => m !== null).filter(
63
+ (m) => m.projectKey === g.projectKey && m.contentId === g.contentId && m.normalizedPath === g.normalizedPath
64
+ ).sort((m, S) => S.createdAt.localeCompare(m.createdAt));
65
65
  },
66
- async createFeedback(d) {
67
- const v = (/* @__PURE__ */ new Date()).toISOString(), h = {
68
- ...d,
66
+ async createFeedback(g) {
67
+ const f = (/* @__PURE__ */ new Date()).toISOString(), m = {
68
+ ...g,
69
69
  id: crypto.randomUUID(),
70
70
  attachments: [],
71
- createdAt: v,
72
- updatedAt: v
71
+ createdAt: f,
72
+ updatedAt: f
73
73
  };
74
- return await f(
74
+ return await p(
75
75
  e.contentSpreadsheetId,
76
76
  `/values/${encodeURIComponent(t)}:append?valueInputOption=RAW`,
77
77
  {
78
78
  method: "POST",
79
- body: JSON.stringify({ values: [Te(h)] })
79
+ body: JSON.stringify({ values: [_e(m)] })
80
80
  }
81
- ), h;
81
+ ), m;
82
82
  },
83
- async updateFeedback(d, v) {
84
- const h = await p(e.contentSpreadsheetId, t), b = h[0] ?? Me, C = b.indexOf("id");
85
- if (C === -1)
83
+ async updateFeedback(g, f) {
84
+ const m = await b(e.contentSpreadsheetId, t), S = m[0] ?? Pe, x = S.indexOf("id");
85
+ if (x === -1)
86
86
  throw new Error(`Sheet ${t} is missing an id column`);
87
- const E = h.findIndex((w, N) => N > 0 && w[C] === d);
87
+ const E = m.findIndex((C, F) => F > 0 && C[x] === g);
88
88
  if (E < 1)
89
- throw new Error(`Feedback ${d} was not found`);
90
- const A = (/* @__PURE__ */ new Date()).toISOString(), u = Re(De(b, h[E]));
91
- if (!u)
92
- throw new Error(`Feedback ${d} could not be parsed before updating`);
93
- const R = {
94
- ...u,
95
- ...v,
96
- updatedAt: A
97
- }, y = Te(R);
98
- return await f(
89
+ throw new Error(`Feedback ${g} was not found`);
90
+ const l = (/* @__PURE__ */ new Date()).toISOString(), A = je(Ke(S, m[E]));
91
+ if (!A)
92
+ throw new Error(`Feedback ${g} could not be parsed before updating`);
93
+ const v = {
94
+ ...A,
95
+ ...f,
96
+ updatedAt: l
97
+ }, y = _e(v);
98
+ return await p(
99
99
  e.contentSpreadsheetId,
100
- `/values/${encodeURIComponent(t)}!A${E + 1}:${yt(
101
- Me.length
100
+ `/values/${encodeURIComponent(t)}!A${E + 1}:${Ft(
101
+ Pe.length
102
102
  )}${E + 1}?valueInputOption=RAW`,
103
103
  {
104
104
  method: "PUT",
105
105
  body: JSON.stringify({ values: [y] })
106
106
  }
107
- ), R;
107
+ ), v;
108
108
  },
109
- async listMessages(d) {
110
- return ce(await p(e.contentSpreadsheetId, n)).map(mt).filter((h) => h !== null).filter((h) => h.feedbackId === d).sort((h, b) => h.createdAt.localeCompare(b.createdAt));
109
+ async listMessages(g) {
110
+ return ue(await b(e.contentSpreadsheetId, n)).map(kt).filter((m) => m !== null).filter((m) => m.feedbackId === g).sort((m, S) => m.createdAt.localeCompare(S.createdAt));
111
111
  },
112
- async createMessage(d) {
113
- const v = {
114
- ...d,
112
+ async createMessage(g) {
113
+ const f = {
114
+ ...g,
115
115
  id: crypto.randomUUID(),
116
116
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
117
117
  };
118
- return await f(
118
+ return await p(
119
119
  e.contentSpreadsheetId,
120
120
  `/values/${encodeURIComponent(n)}:append?valueInputOption=RAW`,
121
121
  {
122
122
  method: "POST",
123
- body: JSON.stringify({ values: [pt(v)] })
123
+ body: JSON.stringify({ values: [St(f)] })
124
124
  }
125
- ), v;
125
+ ), f;
126
+ },
127
+ async sendEmail(g) {
128
+ if (!e.enableEmailNotifications || g.to.length === 0)
129
+ return;
130
+ const f = await w(), m = await this.getCurrentUser(), S = await fetch(bt, {
131
+ method: "POST",
132
+ headers: {
133
+ Authorization: `Bearer ${f}`,
134
+ "Content-Type": "application/json"
135
+ },
136
+ body: JSON.stringify({
137
+ raw: It({
138
+ from: m.email,
139
+ to: g.to,
140
+ subject: g.subject,
141
+ text: g.text
142
+ })
143
+ })
144
+ });
145
+ if (!S.ok)
146
+ throw new Error(`Gmail send request failed with ${S.status}`);
126
147
  }
127
148
  };
128
149
  }
129
- const Me = [
150
+ const Pe = [
130
151
  "id",
131
152
  "projectKey",
132
153
  "contentId",
@@ -155,8 +176,8 @@ const Me = [
155
176
  "fixedBy",
156
177
  "resolvedAt",
157
178
  "resolvedBy"
158
- ], ut = ["id", "feedbackId", "body", "authorEmail", "createdAt"];
159
- function Te(e) {
179
+ ], yt = ["id", "feedbackId", "body", "authorEmail", "createdAt"];
180
+ function _e(e) {
160
181
  return [
161
182
  e.id,
162
183
  e.projectKey,
@@ -188,17 +209,17 @@ function Te(e) {
188
209
  e.resolvedBy ?? ""
189
210
  ];
190
211
  }
191
- function pt(e) {
192
- return ut.map((t) => e[t]);
212
+ function St(e) {
213
+ return yt.map((t) => e[t]);
193
214
  }
194
- function ce(e) {
215
+ function ue(e) {
195
216
  const [t, ...n] = e;
196
- return t ? n.map((i) => De(t, i)) : [];
217
+ return t ? n.map((r) => Ke(t, r)) : [];
197
218
  }
198
- function De(e, t) {
199
- return Object.fromEntries(e.map((n, i) => [n, t[i] ?? ""]));
219
+ function Ke(e, t) {
220
+ return Object.fromEntries(e.map((n, r) => [n, t[r] ?? ""]));
200
221
  }
201
- function Re(e) {
222
+ function je(e) {
202
223
  return e.id ? {
203
224
  id: e.id,
204
225
  projectKey: e.projectKey,
@@ -207,24 +228,24 @@ function Re(e) {
207
228
  originalUrl: e.originalUrl,
208
229
  selector: e.selector,
209
230
  selectorStrategy: e.selectorStrategy === "stable-attribute" ? "stable-attribute" : "css-path",
210
- elementFingerprint: ue(e.elementFingerprintJson, {
231
+ elementFingerprint: fe(e.elementFingerprintJson, {
211
232
  tagName: "",
212
233
  width: 0,
213
234
  height: 0
214
235
  }),
215
- createdCssSnapshot: Be(e.createdCssSnapshotJson),
216
- fixedCssSnapshot: e.fixedCssSnapshotJson ? Be(e.fixedCssSnapshotJson) : void 0,
236
+ createdCssSnapshot: Ue(e.createdCssSnapshotJson),
237
+ fixedCssSnapshot: e.fixedCssSnapshotJson ? Ue(e.fixedCssSnapshotJson) : void 0,
217
238
  comment: e.comment,
218
- status: ft(e.status),
219
- severity: bt(e.severity),
220
- category: vt(e.category),
239
+ status: Ct(e.status),
240
+ severity: xt(e.severity),
241
+ category: Et(e.category),
221
242
  assigneeEmail: e.assigneeEmail || void 0,
222
243
  viewportWidth: Number(e.viewportWidth) || 0,
223
244
  viewportHeight: Number(e.viewportHeight) || 0,
224
- viewportPreset: wt(e.viewportPreset),
245
+ viewportPreset: Lt(e.viewportPreset),
225
246
  screenshotUrl: e.screenshotUrl || void 0,
226
247
  screenshotThumbnailUrl: e.screenshotThumbnailUrl || void 0,
227
- attachments: ue(e.attachmentJson, []),
248
+ attachments: fe(e.attachmentJson, []),
228
249
  authorEmail: e.authorEmail,
229
250
  createdAt: e.createdAt,
230
251
  updatedAt: e.updatedAt,
@@ -234,7 +255,7 @@ function Re(e) {
234
255
  resolvedBy: e.resolvedBy || void 0
235
256
  } : null;
236
257
  }
237
- function mt(e) {
258
+ function kt(e) {
238
259
  return !e.id || !e.feedbackId ? null : {
239
260
  id: e.id,
240
261
  feedbackId: e.feedbackId,
@@ -243,15 +264,15 @@ function mt(e) {
243
264
  createdAt: e.createdAt
244
265
  };
245
266
  }
246
- function ue(e, t) {
267
+ function fe(e, t) {
247
268
  try {
248
269
  return e ? JSON.parse(e) : t;
249
270
  } catch {
250
271
  return t;
251
272
  }
252
273
  }
253
- function Be(e) {
254
- const t = ue(e, {});
274
+ function Ue(e) {
275
+ const t = fe(e, {});
255
276
  return {
256
277
  margin: t.margin ?? "",
257
278
  marginTop: t.marginTop ?? "",
@@ -278,54 +299,54 @@ function Be(e) {
278
299
  height: t.height ?? 0
279
300
  };
280
301
  }
281
- function gt(e) {
302
+ function Nt(e) {
282
303
  return e === "admin" ? ["create", "read", "reply", "update", "assign"] : e === "developer" ? ["read", "reply", "update", "assign"] : ["create", "read", "reply"];
283
304
  }
284
- function ft(e) {
305
+ function Ct(e) {
285
306
  return e === "in_progress" || e === "needs_clarification" || e === "fixed" || e === "wontfix" || e === "resolved" ? e : "open";
286
307
  }
287
- function bt(e) {
308
+ function xt(e) {
288
309
  return e === "low" || e === "high" ? e : "medium";
289
310
  }
290
- function vt(e) {
311
+ function Et(e) {
291
312
  return e === "visual" || e === "copy" || e === "accessibility" || e === "responsive" ? e : "bug";
292
313
  }
293
- function wt(e) {
314
+ function Lt(e) {
294
315
  return e === "mobile" || e === "tablet" || e === "desktop" ? e : "custom";
295
316
  }
296
- function yt(e) {
317
+ function Ft(e) {
297
318
  let t = e, n = "";
298
319
  for (; t > 0; ) {
299
- const i = (t - 1) % 26;
300
- n = String.fromCharCode(65 + i) + n, t = Math.floor((t - i) / 26);
320
+ const r = (t - 1) % 26;
321
+ n = String.fromCharCode(65 + r) + n, t = Math.floor((t - r) / 26);
301
322
  }
302
323
  return n;
303
324
  }
304
- async function St(e) {
305
- return await kt(), new Promise((t, n) => {
306
- var s;
307
- const i = (s = window.google) == null ? void 0 : s.accounts.oauth2.initTokenClient({
325
+ async function At(e, t) {
326
+ return await Rt(), new Promise((n, r) => {
327
+ var c;
328
+ const s = (c = window.google) == null ? void 0 : c.accounts.oauth2.initTokenClient({
308
329
  client_id: e,
309
- scope: ct,
310
- callback: (c) => {
311
- if (c.error || !c.access_token) {
312
- n(new Error(c.error ?? "Google OAuth did not return an access token"));
330
+ scope: t,
331
+ callback: (h) => {
332
+ if (h.error || !h.access_token) {
333
+ r(new Error(h.error ?? "Google OAuth did not return an access token"));
313
334
  return;
314
335
  }
315
- t(c.access_token);
336
+ n(h.access_token);
316
337
  }
317
338
  });
318
- i == null || i.requestAccessToken({ prompt: "" });
339
+ s == null || s.requestAccessToken({ prompt: "" });
319
340
  });
320
341
  }
321
- function kt() {
342
+ function Rt() {
322
343
  var e;
323
344
  return (e = window.google) != null && e.accounts.oauth2 ? Promise.resolve() : new Promise((t, n) => {
324
- const i = document.querySelector(
345
+ const r = document.querySelector(
325
346
  'script[src="https://accounts.google.com/gsi/client"]'
326
347
  );
327
- if (i) {
328
- i.addEventListener("load", () => t(), { once: !0 }), i.addEventListener("error", () => n(new Error("Google Identity failed to load")), {
348
+ if (r) {
349
+ r.addEventListener("load", () => t(), { once: !0 }), r.addEventListener("error", () => n(new Error("Google Identity failed to load")), {
329
350
  once: !0
330
351
  });
331
352
  return;
@@ -334,159 +355,261 @@ function kt() {
334
355
  s.src = "https://accounts.google.com/gsi/client", s.async = !0, s.defer = !0, s.onload = () => t(), s.onerror = () => n(new Error("Google Identity failed to load")), document.head.append(s);
335
356
  });
336
357
  }
337
- function Ct(e) {
358
+ function It(e) {
359
+ const t = [
360
+ `From: ${e.from}`,
361
+ `To: ${e.to.join(", ")}`,
362
+ `Subject: ${e.subject}`,
363
+ "Content-Type: text/plain; charset=UTF-8",
364
+ "",
365
+ e.text
366
+ ].join(`\r
367
+ `);
368
+ return Mt(t);
369
+ }
370
+ function Mt(e) {
371
+ const t = new TextEncoder().encode(e);
372
+ let n = "";
373
+ return t.forEach((r) => {
374
+ n += String.fromCharCode(r);
375
+ }), btoa(n).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
376
+ }
377
+ function $t(e) {
338
378
  return new URL(e, window.location.href).pathname.replace(/\/+$/, "") || "/";
339
379
  }
340
- const ze = st(null);
341
- function Qt({ config: e, children: t }) {
342
- const n = ie(() => e.adapter ? e.adapter : ht({
343
- googleClientId: de(e.googleClientId, "googleClientId"),
344
- contentSpreadsheetId: de(e.contentSpreadsheetId, "contentSpreadsheetId"),
345
- usersSpreadsheetId: de(e.usersSpreadsheetId, "usersSpreadsheetId"),
346
- feedbackSheetName: e.sheetName ?? "Feedback"
380
+ const Je = mt(null);
381
+ function wn({ config: e, children: t }) {
382
+ const n = se(() => e.adapter ? e.adapter : vt({
383
+ googleClientId: me(e.googleClientId, "googleClientId"),
384
+ contentSpreadsheetId: me(e.contentSpreadsheetId, "contentSpreadsheetId"),
385
+ usersSpreadsheetId: me(e.usersSpreadsheetId, "usersSpreadsheetId"),
386
+ feedbackSheetName: e.sheetName ?? "Feedback",
387
+ enableEmailNotifications: Oe(e)
347
388
  }), [
348
389
  e.adapter,
349
390
  e.contentSpreadsheetId,
391
+ e.emailNotifications,
350
392
  e.googleClientId,
351
393
  e.sheetName,
352
394
  e.usersSpreadsheetId
353
- ]), i = e.currentUrl ?? window.location.href, s = (e.normalizeUrl ?? Ct)(i), [c, g] = k(), [f, p] = k([]), [d, v] = k([]), h = W(async () => {
354
- const y = await n.listFeedback({
395
+ ]), r = e.currentUrl ?? window.location.href, s = (e.normalizeUrl ?? $t)(r), [c, h] = N(), [w, p] = N([]), [b, g] = N([]), f = W(async () => {
396
+ const v = await n.listFeedback({
355
397
  projectKey: e.projectKey,
356
398
  contentId: e.contentId,
357
399
  normalizedPath: s
358
400
  });
359
- v(y);
401
+ g(v);
360
402
  }, [n, e.contentId, e.projectKey, s]);
361
- _(() => {
362
- let y = !0;
363
- async function w() {
364
- const [N, B] = await Promise.all([
403
+ B(() => {
404
+ let v = !0;
405
+ async function y() {
406
+ const [C, F] = await Promise.all([
365
407
  n.getCurrentUser(),
366
408
  n.getPermissions(e.projectKey)
367
409
  ]);
368
- y && (g(N), p(B), await h());
410
+ v && (h(C), p(F), await f());
369
411
  }
370
- return w(), () => {
371
- y = !1;
412
+ return y(), () => {
413
+ v = !1;
372
414
  };
373
- }, [n, e.projectKey, h]);
374
- const b = W(
375
- async (y) => {
376
- const w = await n.createFeedback(y);
377
- return v((N) => [w, ...N]), w;
415
+ }, [n, e.projectKey, f]);
416
+ const m = W(
417
+ async (v) => {
418
+ const y = await n.createFeedback(v);
419
+ return g((C) => [y, ...C]), pe(e, n, {
420
+ actorEmail: (c == null ? void 0 : c.email) ?? v.authorEmail,
421
+ item: y,
422
+ kind: "created"
423
+ }), y;
378
424
  },
379
- [n]
380
- ), C = W(
381
- async (y, w) => {
382
- const N = await n.updateFeedback(y, w);
383
- return v(
384
- (B) => B.map((D) => D.id === y ? N : D)
385
- ), N;
425
+ [n, e, c == null ? void 0 : c.email]
426
+ ), S = W(
427
+ async (v, y) => {
428
+ const C = b.find((_) => _.id === v), F = await n.updateFeedback(v, y);
429
+ return g(
430
+ (_) => _.map((H) => H.id === v ? F : H)
431
+ ), pe(e, n, {
432
+ actorEmail: c == null ? void 0 : c.email,
433
+ item: F,
434
+ kind: Bt(y),
435
+ previousItem: C
436
+ }), F;
386
437
  },
438
+ [n, e, c == null ? void 0 : c.email, b]
439
+ ), x = W(
440
+ (v) => n.listMessages(v),
387
441
  [n]
388
442
  ), E = W(
389
- (y) => n.listMessages(y),
390
- [n]
391
- ), A = W(
392
- (y) => n.createMessage(y),
393
- [n]
394
- ), u = W(
395
- async (y, w) => {
396
- const N = e.uploadAttachment ?? n.uploadAttachment;
397
- if (!N)
443
+ async (v) => {
444
+ const y = await n.createMessage(v), C = b.find((F) => F.id === v.feedbackId);
445
+ return C && pe(e, n, {
446
+ actorEmail: v.authorEmail,
447
+ item: C,
448
+ kind: "reply",
449
+ replyBody: v.body
450
+ }), y;
451
+ },
452
+ [n, e, b]
453
+ ), l = W(
454
+ async (v, y) => {
455
+ const C = e.uploadAttachment ?? n.uploadAttachment;
456
+ if (!C)
398
457
  throw new Error("Review Lens attachment upload is not configured");
399
- return N(y, w);
458
+ return C(v, y);
400
459
  },
401
460
  [n, e]
402
- ), R = ie(
461
+ ), A = se(
403
462
  () => ({
404
463
  config: e,
405
464
  adapter: n,
406
465
  currentUser: c,
407
- permissions: f,
408
- feedback: d,
466
+ permissions: w,
467
+ feedback: b,
409
468
  normalizedPath: s,
410
- refreshFeedback: h,
411
- createFeedback: b,
412
- updateFeedback: C,
413
- listMessages: E,
414
- createMessage: A,
415
- uploadAttachment: u
469
+ refreshFeedback: f,
470
+ createFeedback: m,
471
+ updateFeedback: S,
472
+ listMessages: x,
473
+ createMessage: E,
474
+ uploadAttachment: l
416
475
  }),
417
476
  [
418
477
  n,
419
478
  e,
420
- b,
479
+ m,
421
480
  c,
422
- d,
481
+ b,
423
482
  s,
483
+ w,
424
484
  f,
425
- h,
426
- C,
485
+ S,
486
+ x,
427
487
  E,
428
- A,
429
- u
488
+ l
430
489
  ]
431
490
  );
432
- return /* @__PURE__ */ r(ze.Provider, { value: R, children: t });
491
+ return /* @__PURE__ */ i(Je.Provider, { value: A, children: t });
433
492
  }
434
- function Nt() {
435
- const e = ot(ze);
493
+ function Tt() {
494
+ const e = pt(Je);
436
495
  if (!e)
437
496
  throw new Error("useReviewLens must be used inside ReviewLensProvider");
438
497
  return e;
439
498
  }
440
- function de(e, t) {
499
+ function me(e, t) {
441
500
  if (!e)
442
501
  throw new Error(`review-lens-react requires config.${t} when no adapter is provided`);
443
502
  return e;
444
503
  }
445
- const xt = [
504
+ function Oe(e) {
505
+ return typeof e.emailNotifications == "object" ? e.emailNotifications.enabled !== !1 : !!e.emailNotifications;
506
+ }
507
+ function Bt(e) {
508
+ return e.status === "resolved" ? "resolved" : e.status === "fixed" || e.fixedAt || e.fixedBy ? "fixed" : e.status ? "status" : "assigneeEmail" in e ? "assigned" : "updated";
509
+ }
510
+ async function pe(e, t, n) {
511
+ if (!Oe(e) || !t.sendEmail)
512
+ return;
513
+ const r = Pt(n);
514
+ if (r.length !== 0)
515
+ try {
516
+ await t.sendEmail({
517
+ to: r,
518
+ subject: _t(e, n),
519
+ text: jt(n)
520
+ });
521
+ } catch (s) {
522
+ console.warn("Review Lens email notification failed", s);
523
+ }
524
+ }
525
+ function Pt(e) {
526
+ var n;
527
+ const t = /* @__PURE__ */ new Set();
528
+ return t.add(e.item.authorEmail), (n = e.previousItem) != null && n.assigneeEmail && t.add(e.previousItem.assigneeEmail), e.item.assigneeEmail && t.add(e.item.assigneeEmail), [...t].filter((r) => {
529
+ var s;
530
+ return r ? r.toLowerCase() !== ((s = e.actorEmail) == null ? void 0 : s.toLowerCase()) : !1;
531
+ });
532
+ }
533
+ function _t(e, t) {
534
+ return `${(typeof e.emailNotifications == "object" ? e.emailNotifications : {}).subjectPrefix ?? "Review Lens"}: ${qe(t)}`;
535
+ }
536
+ function jt(e) {
537
+ const t = [
538
+ "[Review Lens]",
539
+ qe(e),
540
+ Ut(e),
541
+ "",
542
+ `Review: ${e.item.comment}`,
543
+ `Status: ${Ve(e.item.status)}`,
544
+ `Author: ${e.item.authorEmail}`,
545
+ `Assignee: ${e.item.assigneeEmail ?? "Unassigned"}`,
546
+ `Link: ${Wt(e.item)}`
547
+ ];
548
+ return e.replyBody && t.splice(2, 0, `Reply: ${e.replyBody}`, ""), t.join(`
549
+ `);
550
+ }
551
+ function Ut(e) {
552
+ return e.actorEmail ? `Sent by Review Lens on behalf of ${e.actorEmail}.` : "Sent by Review Lens on behalf of the signed-in Google user.";
553
+ }
554
+ function qe(e) {
555
+ return e.kind === "created" ? "New review feedback" : e.kind === "assigned" ? `Review assignment changed to ${e.item.assigneeEmail ?? "unassigned"}` : e.kind === "status" ? `Review status changed to ${Ve(e.item.status)}` : e.kind === "fixed" ? "Review marked fixed" : e.kind === "resolved" ? "Review resolved" : e.kind === "reply" ? "New review reply" : "Review updated";
556
+ }
557
+ function Wt(e) {
558
+ try {
559
+ const t = new URL(e.originalUrl);
560
+ return t.searchParams.set("reviewLensFeedback", e.id), t.toString();
561
+ } catch {
562
+ return e.originalUrl;
563
+ }
564
+ }
565
+ function Ve(e) {
566
+ return e.replace(/_/g, " ");
567
+ }
568
+ const Dt = [
446
569
  "data-review-id",
447
570
  "data-testid",
448
571
  "data-test-id",
449
572
  "aria-label",
450
573
  "name"
451
574
  ];
452
- function X(e) {
453
- const t = e.getBoundingClientRect(), n = Et(e);
575
+ function Q(e) {
576
+ const t = e.getBoundingClientRect(), n = zt(e);
454
577
  return {
455
578
  selector: n.selector,
456
579
  selectorStrategy: n.strategy,
457
- fingerprint: It(e, t),
458
- cssSnapshot: Lt(e, t),
580
+ fingerprint: Kt(e, t),
581
+ cssSnapshot: Jt(e, t),
459
582
  rect: t
460
583
  };
461
584
  }
462
- function Et(e) {
463
- for (const t of xt) {
585
+ function zt(e) {
586
+ for (const t of Dt) {
464
587
  const n = e.getAttribute(t);
465
588
  if (n)
466
589
  return {
467
- selector: `[${t}="${$e(n)}"]`,
590
+ selector: `[${t}="${We(n)}"]`,
468
591
  strategy: "stable-attribute"
469
592
  };
470
593
  }
471
- return e.id ? { selector: `#${$e(e.id)}`, strategy: "stable-attribute" } : { selector: At(e), strategy: "css-path" };
594
+ return e.id ? { selector: `#${We(e.id)}`, strategy: "stable-attribute" } : { selector: Ht(e), strategy: "css-path" };
472
595
  }
473
- function At(e) {
596
+ function Ht(e) {
474
597
  const t = [];
475
598
  let n = e;
476
599
  for (; n && n.nodeType === Node.ELEMENT_NODE && n !== document.body; ) {
477
- const i = n.parentElement, s = n.tagName.toLowerCase();
478
- if (!i) {
600
+ const r = n.parentElement, s = n.tagName.toLowerCase();
601
+ if (!r) {
479
602
  t.unshift(s);
480
603
  break;
481
604
  }
482
- const c = n.tagName, g = Array.from(i.children).filter(
605
+ const c = n.tagName, h = Array.from(r.children).filter(
483
606
  (p) => p.tagName === c
484
- ), f = g.indexOf(n) + 1;
485
- t.unshift(g.length > 1 ? `${s}:nth-of-type(${f})` : s), n = i;
607
+ ), w = h.indexOf(n) + 1;
608
+ t.unshift(h.length > 1 ? `${s}:nth-of-type(${w})` : s), n = r;
486
609
  }
487
610
  return t.join(" > ");
488
611
  }
489
- function It(e, t) {
612
+ function Kt(e, t) {
490
613
  var n;
491
614
  return {
492
615
  tagName: e.tagName.toLowerCase(),
@@ -498,15 +621,15 @@ function It(e, t) {
498
621
  height: Math.round(t.height)
499
622
  };
500
623
  }
501
- function Lt(e, t) {
624
+ function Jt(e, t) {
502
625
  const n = window.getComputedStyle(e);
503
626
  return {
504
- margin: he(n.marginTop, n.marginRight, n.marginBottom, n.marginLeft),
627
+ margin: ge(n.marginTop, n.marginRight, n.marginBottom, n.marginLeft),
505
628
  marginTop: n.marginTop,
506
629
  marginRight: n.marginRight,
507
630
  marginBottom: n.marginBottom,
508
631
  marginLeft: n.marginLeft,
509
- padding: he(
632
+ padding: ge(
510
633
  n.paddingTop,
511
634
  n.paddingRight,
512
635
  n.paddingBottom,
@@ -516,7 +639,7 @@ function Lt(e, t) {
516
639
  paddingRight: n.paddingRight,
517
640
  paddingBottom: n.paddingBottom,
518
641
  paddingLeft: n.paddingLeft,
519
- border: he(
642
+ border: ge(
520
643
  n.borderTopWidth,
521
644
  n.borderRightWidth,
522
645
  n.borderBottomWidth,
@@ -536,277 +659,334 @@ function Lt(e, t) {
536
659
  height: Math.round(t.height)
537
660
  };
538
661
  }
539
- function he(e, t, n, i) {
540
- return e === t && t === n && n === i ? e : `${e} ${t} ${n} ${i}`;
662
+ function ge(e, t, n, r) {
663
+ return e === t && t === n && n === r ? e : `${e} ${t} ${n} ${r}`;
541
664
  }
542
- function $e(e) {
665
+ function We(e) {
543
666
  return typeof CSS < "u" && typeof CSS.escape == "function" ? CSS.escape(e) : e.replace(/["\\]/g, "\\$&");
544
667
  }
545
- const Ft = [
668
+ function Ot({ className: e, title: t = "Review Lens logo" }) {
669
+ return /* @__PURE__ */ o(
670
+ "svg",
671
+ {
672
+ className: e,
673
+ role: "img",
674
+ "aria-label": t,
675
+ viewBox: "0 0 40 40",
676
+ fill: "none",
677
+ xmlns: "http://www.w3.org/2000/svg",
678
+ children: [
679
+ /* @__PURE__ */ i("rect", { x: "4", y: "6", width: "28", height: "28", rx: "8", fill: "#171717" }),
680
+ /* @__PURE__ */ i(
681
+ "path",
682
+ {
683
+ d: "M13 15.5C14.5 13.4 17.1 12 20 12C23.9 12 27.3 14.5 28.7 18C27.3 21.5 23.9 24 20 24C17.1 24 14.5 22.6 13 20.5",
684
+ stroke: "#FFFFFF",
685
+ strokeWidth: "2.2",
686
+ strokeLinecap: "round",
687
+ strokeLinejoin: "round"
688
+ }
689
+ ),
690
+ /* @__PURE__ */ i("circle", { cx: "20", cy: "18", r: "3.4", fill: "#F97316" }),
691
+ /* @__PURE__ */ i(
692
+ "path",
693
+ {
694
+ d: "M28.5 26.5L34.5 32.5",
695
+ stroke: "#2563EB",
696
+ strokeWidth: "4",
697
+ strokeLinecap: "round"
698
+ }
699
+ ),
700
+ /* @__PURE__ */ i("circle", { cx: "31.8", cy: "29.8", r: "2.1", fill: "#FACC15", stroke: "#171717", strokeWidth: "1.4" })
701
+ ]
702
+ }
703
+ );
704
+ }
705
+ const qt = [
546
706
  { label: "Desktop", value: "desktop" },
547
707
  { label: "Tablet", value: "tablet" },
548
708
  { label: "Mobile", value: "mobile" }
549
- ], He = [
709
+ ], Ge = [
550
710
  "open",
551
711
  "in_progress",
552
712
  "needs_clarification",
553
713
  "fixed",
554
714
  "wontfix",
555
715
  "resolved"
556
- ], je = ["low", "medium", "high"], Oe = ["bug", "visual", "copy", "accessibility", "responsive"], ae = {
716
+ ], Ye = ["low", "medium", "high"], Xe = ["bug", "visual", "copy", "accessibility", "responsive"], oe = {
557
717
  open: "Open",
558
718
  in_progress: "In progress",
559
719
  needs_clarification: "Needs clarification",
560
720
  fixed: "Fixed",
561
721
  wontfix: "Won't fix",
562
722
  resolved: "Resolved"
563
- }, Q = {
723
+ }, Z = {
564
724
  low: "Low",
565
725
  medium: "Medium",
566
726
  high: "High"
567
- }, Z = {
727
+ }, ee = {
568
728
  bug: "Bug",
569
729
  visual: "Visual",
570
730
  copy: "Copy",
571
731
  accessibility: "Accessibility",
572
732
  responsive: "Responsive"
573
733
  };
574
- function Zt({
734
+ function bn({
575
735
  open: e,
576
736
  onOpenChange: t,
577
737
  placement: n = "top-right",
578
- showResolved: i = !1,
738
+ showResolved: r = !1,
579
739
  syncSelectionToUrl: s = !1,
580
- responsivePresets: c = Ft
740
+ responsivePresets: c = qt
581
741
  }) {
582
- var Fe;
742
+ var Te;
583
743
  const {
584
- adapter: g,
585
- config: f,
744
+ adapter: h,
745
+ config: w,
586
746
  currentUser: p,
587
- feedback: d,
588
- normalizedPath: v,
589
- permissions: h,
590
- createFeedback: b,
591
- updateFeedback: C,
592
- listMessages: E,
593
- createMessage: A,
594
- uploadAttachment: u
595
- } = Nt(), [R, y] = k(), [w, N] = k(), [B, D] = k(""), [pe, Je] = k("medium"), [me, Ve] = k("visual"), [ge, fe] = k(""), [be, qe] = k(
596
- ((Fe = c[0]) == null ? void 0 : Fe.value) ?? "desktop"
597
- ), [S, H] = k(), [F, $] = k("review"), [Ge, ve] = k(!1), [j, we] = k("all"), [O, ye] = k("all"), [K, Se] = k("all"), [J, ke] = k("all"), [V, Ce] = k("all"), [Ye, Xe] = k(!1), [Qe, Ne] = k({}), [se, oe] = k(""), ee = We(null), M = !!p, T = h.includes("create"), xe = h.includes("reply"), Ee = h.includes("update"), Ze = h.includes("assign"), P = R ?? w, et = !!w, tt = !!(f.captureScreenshot && (f.uploadAttachment || g.uploadAttachment)), nt = ie(() => {
598
- const a = d.map((m) => m.assigneeEmail).filter((m) => !!m);
599
- return p != null && p.email && a.push(p.email), Array.from(new Set(a)).sort((m, l) => m.localeCompare(l));
600
- }, [p == null ? void 0 : p.email, d]), I = ie(
601
- () => d.filter((a) => i || a.status !== "resolved").filter((a) => j === "all" || a.status === j).filter((a) => O === "all" || a.severity === O).filter((a) => K === "all" || a.category === K).filter((a) => J === "all" || a.assigneeEmail === J).filter((a) => V === "all" || a.viewportPreset === V),
747
+ feedback: b,
748
+ normalizedPath: g,
749
+ permissions: f,
750
+ createFeedback: m,
751
+ updateFeedback: S,
752
+ listMessages: x,
753
+ createMessage: E,
754
+ uploadAttachment: l
755
+ } = Tt(), [A, v] = N(), [y, C] = N(), [F, _] = N(""), [H, Ze] = N("medium"), [we, et] = N("visual"), [be, ve] = N(""), [ye, tt] = N(
756
+ ((Te = c[0]) == null ? void 0 : Te.value) ?? "desktop"
757
+ ), [k, K] = N(), [M, P] = N("review"), [nt, Se] = N(!1), [J, ke] = N("all"), [O, Ne] = N("all"), [q, Ce] = N("all"), [V, xe] = N("all"), [G, Ee] = N("all"), [it, rt] = N(!1), [at, Le] = N({}), [le, de] = N(""), te = re(null), Fe = re(e), ce = re(
758
+ s ? new URL(window.location.href).searchParams.get("reviewLensFeedback") : null
759
+ ), $ = !!p, T = f.includes("create"), Ae = f.includes("reply"), Re = f.includes("update"), st = f.includes("assign"), j = A ?? y, ot = !!y, lt = !!(w.captureScreenshot && (w.uploadAttachment || h.uploadAttachment)), dt = se(() => {
760
+ const a = b.map((u) => u.assigneeEmail).filter((u) => !!u);
761
+ return p != null && p.email && a.push(p.email), Array.from(new Set(a)).sort((u, d) => u.localeCompare(d));
762
+ }, [p == null ? void 0 : p.email, b]), R = se(
763
+ () => b.filter((a) => r || a.status !== "resolved").filter((a) => J === "all" || a.status === J).filter((a) => O === "all" || a.severity === O).filter((a) => q === "all" || a.category === q).filter((a) => V === "all" || a.assigneeEmail === V).filter((a) => G === "all" || a.viewportPreset === G),
602
764
  [
603
- J,
604
- K,
605
- d,
765
+ V,
766
+ q,
767
+ b,
606
768
  O,
607
- i,
608
- j,
609
- V
769
+ r,
770
+ J,
771
+ G
610
772
  ]
611
- ), rt = [
612
- j,
613
- O,
614
- K,
773
+ ), ct = [
615
774
  J,
616
- V
775
+ O,
776
+ q,
777
+ V,
778
+ G
617
779
  ].filter((a) => a !== "all").length;
618
- _(() => {
619
- e || (y(void 0), N(void 0), D(""), oe(""), $("review"));
620
- }, [e]), _(() => {
621
- M || (y(void 0), N(void 0));
622
- }, [M]), _(() => {
623
- !w || F !== "review" || window.requestAnimationFrame(() => {
624
- var a, m, l;
625
- (m = (a = ee.current) == null ? void 0 : a.scrollIntoView) == null || m.call(a, { block: "nearest" }), (l = ee.current) == null || l.focus();
780
+ B(() => {
781
+ if (e) {
782
+ Fe.current = !0;
783
+ return;
784
+ }
785
+ if (v(void 0), C(void 0), _(""), de(""), P("review"), s && Fe.current) {
786
+ const a = new URL(window.location.href);
787
+ a.searchParams.has("reviewLensFeedback") && (a.searchParams.delete("reviewLensFeedback"), window.history.replaceState({}, "", a));
788
+ }
789
+ }, [e, s]), B(() => {
790
+ $ || (v(void 0), C(void 0));
791
+ }, [$]), B(() => {
792
+ !y || M !== "review" || window.requestAnimationFrame(() => {
793
+ var a, u, d;
794
+ (u = (a = te.current) == null ? void 0 : a.scrollIntoView) == null || u.call(a, { block: "nearest" }), (d = te.current) == null || d.focus();
626
795
  });
627
- }, [w, F]), _(() => {
628
- if (!S)
796
+ }, [y, M]), B(() => {
797
+ if (!k)
629
798
  return;
630
799
  let a = !0;
631
- return E(S.id).then((m) => {
632
- a && Ne((l) => ({ ...l, [S.id]: m }));
800
+ return x(k.id).then((u) => {
801
+ a && Le((d) => ({ ...d, [k.id]: u }));
633
802
  }), () => {
634
803
  a = !1;
635
804
  };
636
- }, [E, S]), _(() => {
637
- if (!e || !s || S || d.length === 0)
805
+ }, [x, k]), B(() => {
806
+ if (!s || !ce.current || b.length === 0)
807
+ return;
808
+ const a = b.find((u) => u.id === ce.current);
809
+ a && (ce.current = null, t == null || t(!0), D(a, { syncUrl: !1 }));
810
+ }, [b, s]), B(() => {
811
+ if (!e || !s || k || b.length === 0)
638
812
  return;
639
- const a = new URL(window.location.href).searchParams.get("reviewLensFeedback"), m = d.find((l) => l.id === a);
640
- m && q(m, { syncUrl: !1 });
641
- }, [d, e, S, s]), _(() => {
813
+ const a = new URL(window.location.href).searchParams.get("reviewLensFeedback"), u = b.find((d) => d.id === a);
814
+ u && D(u, { syncUrl: !1 });
815
+ }, [b, e, k, s]), B(() => {
642
816
  if (!e)
643
817
  return;
644
- function a(l) {
645
- var x;
646
- if (l.key === "Shift" && ve(!0), l.key === "Escape") {
647
- l.preventDefault(), t == null || t(!1);
818
+ function a(d) {
819
+ var L;
820
+ if (d.key === "Shift" && Se(!0), d.key === "Escape") {
821
+ d.preventDefault(), t == null || t(!1);
648
822
  return;
649
823
  }
650
- Jt(l.target) || ((l.key === "n" || l.key === "ArrowDown") && (l.preventDefault(), Ae(1)), (l.key === "p" || l.key === "ArrowUp") && (l.preventDefault(), Ae(-1)), l.key === "c" && (l.preventDefault(), $("review"), (x = ee.current) == null || x.focus()), l.key === "f" && S && Ee && (l.preventDefault(), Le(S)));
824
+ hn(d.target) || ((d.key === "n" || d.key === "ArrowDown") && (d.preventDefault(), Ie(1)), (d.key === "p" || d.key === "ArrowUp") && (d.preventDefault(), Ie(-1)), d.key === "c" && (d.preventDefault(), P("review"), (L = te.current) == null || L.focus()), d.key === "f" && k && Re && (d.preventDefault(), $e(k)));
651
825
  }
652
- function m(l) {
653
- l.key === "Shift" && ve(!1);
826
+ function u(d) {
827
+ d.key === "Shift" && Se(!1);
654
828
  }
655
- return window.addEventListener("keydown", a), window.addEventListener("keyup", m), () => {
656
- window.removeEventListener("keydown", a), window.removeEventListener("keyup", m);
829
+ return window.addEventListener("keydown", a), window.addEventListener("keyup", u), () => {
830
+ window.removeEventListener("keydown", a), window.removeEventListener("keyup", u);
657
831
  };
658
832
  });
659
- const le = W((a) => {
660
- const m = a.target instanceof Element ? a.target : null;
661
- if (m)
662
- return m.closest("[data-review-lens-ui]") ? null : m;
663
- const l = document.elementFromPoint(a.clientX, a.clientY);
664
- return !l || l.closest("[data-review-lens-ui]") ? null : l;
833
+ const he = W((a) => {
834
+ const u = a.target instanceof Element ? a.target : null;
835
+ if (u)
836
+ return u.closest("[data-review-lens-ui]") ? null : u;
837
+ const d = document.elementFromPoint(a.clientX, a.clientY);
838
+ return !d || d.closest("[data-review-lens-ui]") ? null : d;
665
839
  }, []);
666
- if (_(() => {
667
- if (!e || !M)
840
+ if (B(() => {
841
+ if (!e || !$)
668
842
  return;
669
- function a(l) {
670
- const x = le(l);
671
- y(x ? X(x) : void 0);
843
+ function a(d) {
844
+ const L = he(d);
845
+ v(L ? Q(L) : void 0);
672
846
  }
673
- function m(l) {
674
- const x = le(l);
675
- x && (l.preventDefault(), l.stopPropagation(), N(X(x)), $("review"));
847
+ function u(d) {
848
+ const L = he(d);
849
+ L && (d.preventDefault(), d.stopPropagation(), C(Q(L)), P("review"));
676
850
  }
677
- return window.addEventListener("mousemove", a, !0), window.addEventListener("click", m, !0), () => {
678
- window.removeEventListener("mousemove", a, !0), window.removeEventListener("click", m, !0);
851
+ return window.addEventListener("mousemove", a, !0), window.addEventListener("click", u, !0), () => {
852
+ window.removeEventListener("mousemove", a, !0), window.removeEventListener("click", u, !0);
679
853
  };
680
- }, [M, le, e]), !e)
854
+ }, [$, he, e]), !e)
681
855
  return null;
682
- function q(a, m = { syncUrl: !0 }) {
683
- var x;
684
- if (H(a), N(void 0), $("feedback"), s && m.syncUrl !== !1) {
685
- const te = new URL(window.location.href);
686
- te.searchParams.set("reviewLensFeedback", a.id), window.history.replaceState({}, "", te);
856
+ function D(a, u = { syncUrl: !0 }) {
857
+ var L;
858
+ if (K(a), C(void 0), P("feedback"), s && u.syncUrl !== !1) {
859
+ const ne = new URL(window.location.href);
860
+ ne.searchParams.set("reviewLensFeedback", a.id), window.history.replaceState({}, "", ne);
687
861
  }
688
- const l = z(a.selector);
689
- if (!l) {
690
- y(void 0);
862
+ const d = z(a.selector);
863
+ if (!d) {
864
+ v(void 0);
691
865
  return;
692
866
  }
693
- (x = l.scrollIntoView) == null || x.call(l, { behavior: "smooth", block: "center", inline: "center" }), window.requestAnimationFrame(() => {
694
- y(X(l));
867
+ (L = d.scrollIntoView) == null || L.call(d, { behavior: "smooth", block: "center", inline: "center" }), window.requestAnimationFrame(() => {
868
+ v(Q(d));
695
869
  });
696
870
  }
697
- function Ae(a) {
698
- if (I.length === 0)
871
+ function Ie(a) {
872
+ if (R.length === 0)
699
873
  return;
700
- const m = S ? I.findIndex((x) => x.id === S.id) : -1, l = m < 0 ? a > 0 ? 0 : I.length - 1 : (m + a + I.length) % I.length;
701
- q(I[l]);
874
+ const u = k ? R.findIndex((L) => L.id === k.id) : -1, d = u < 0 ? a > 0 ? 0 : R.length - 1 : (u + a + R.length) % R.length;
875
+ D(R[d]);
702
876
  }
703
- async function Ie() {
704
- if (!w || !B.trim() || !p || !T)
877
+ async function Me() {
878
+ if (!y || !F.trim() || !p || !T)
705
879
  return;
706
- let a = await b({
707
- projectKey: f.projectKey,
708
- contentId: f.contentId,
709
- normalizedPath: v,
710
- originalUrl: f.currentUrl ?? window.location.href,
711
- selector: w.selector,
712
- selectorStrategy: w.selectorStrategy,
713
- elementFingerprint: w.fingerprint,
714
- createdCssSnapshot: w.cssSnapshot,
715
- comment: B.trim(),
880
+ let a = await m({
881
+ projectKey: w.projectKey,
882
+ contentId: w.contentId,
883
+ normalizedPath: g,
884
+ originalUrl: w.currentUrl ?? window.location.href,
885
+ selector: y.selector,
886
+ selectorStrategy: y.selectorStrategy,
887
+ elementFingerprint: y.fingerprint,
888
+ createdCssSnapshot: y.cssSnapshot,
889
+ comment: F.trim(),
716
890
  status: "open",
717
- severity: pe,
718
- category: me,
719
- assigneeEmail: ge.trim() || void 0,
891
+ severity: H,
892
+ category: we,
893
+ assigneeEmail: be.trim() || void 0,
720
894
  viewportWidth: window.innerWidth,
721
895
  viewportHeight: window.innerHeight,
722
- viewportPreset: be,
896
+ viewportPreset: ye,
723
897
  screenshotUrl: void 0,
724
898
  screenshotThumbnailUrl: void 0,
725
899
  authorEmail: p.email
726
900
  });
727
- if (f.captureScreenshot)
901
+ if (w.captureScreenshot)
728
902
  try {
729
- const m = await f.captureScreenshot(w), l = await u(a.id, {
903
+ const u = await w.captureScreenshot(y), d = await l(a.id, {
730
904
  type: "screenshot",
731
- data: m,
905
+ data: u,
732
906
  createdBy: p.email
733
907
  });
734
- a = await C(a.id, {
735
- attachments: [l],
736
- screenshotUrl: l.url,
737
- screenshotThumbnailUrl: l.thumbnailUrl
908
+ a = await S(a.id, {
909
+ attachments: [d],
910
+ screenshotUrl: d.url,
911
+ screenshotThumbnailUrl: d.thumbnailUrl
738
912
  });
739
913
  } catch {
740
914
  }
741
- D(""), fe(""), N(void 0), y(void 0), $("feedback"), H(a);
915
+ if (_(""), ve(""), C(void 0), v(void 0), P("feedback"), K(a), s) {
916
+ const u = new URL(window.location.href);
917
+ u.searchParams.set("reviewLensFeedback", a.id), window.history.replaceState({}, "", u);
918
+ }
742
919
  }
743
- async function it(a, m) {
744
- const l = (/* @__PURE__ */ new Date()).toISOString(), x = m === "resolved" ? { status: m, resolvedAt: l, resolvedBy: p == null ? void 0 : p.email } : { status: m }, te = await C(a.id, x);
745
- H(te);
920
+ async function ht(a, u) {
921
+ const d = (/* @__PURE__ */ new Date()).toISOString(), L = u === "resolved" ? { status: u, resolvedAt: d, resolvedBy: p == null ? void 0 : p.email } : { status: u }, ne = await S(a.id, L);
922
+ K(ne);
746
923
  }
747
- async function Le(a) {
748
- const m = z(a.selector);
749
- if (!m || !p)
924
+ async function $e(a) {
925
+ const u = z(a.selector);
926
+ if (!u || !p)
750
927
  return;
751
- const l = X(m), x = await C(a.id, {
928
+ const d = Q(u), L = await S(a.id, {
752
929
  status: "fixed",
753
- fixedCssSnapshot: l.cssSnapshot,
930
+ fixedCssSnapshot: d.cssSnapshot,
754
931
  fixedAt: (/* @__PURE__ */ new Date()).toISOString(),
755
932
  fixedBy: p.email
756
933
  });
757
- H(x);
934
+ K(L);
758
935
  }
759
- async function at(a) {
760
- if (!se.trim() || !p || !xe)
936
+ async function ut(a) {
937
+ if (!le.trim() || !p || !Ae)
761
938
  return;
762
- const m = await A({
939
+ const u = await E({
763
940
  feedbackId: a.id,
764
- body: se.trim(),
941
+ body: le.trim(),
765
942
  authorEmail: p.email
766
943
  });
767
- Ne((l) => ({
768
- ...l,
769
- [a.id]: [...l[a.id] ?? [], m]
770
- })), oe("");
944
+ Le((d) => ({
945
+ ...d,
946
+ [a.id]: [...d[a.id] ?? [], u]
947
+ })), de("");
771
948
  }
772
949
  return /* @__PURE__ */ o("div", { className: "review-lens-root", "data-review-lens-ui": !0, children: [
773
- M && P ? /* @__PURE__ */ r($t, { target: P, locked: !!w }) : null,
774
- M && w && R && Ge ? /* @__PURE__ */ r(_t, { from: w, to: R }) : null,
775
- M ? /* @__PURE__ */ o(re, { children: [
776
- /* @__PURE__ */ r(
777
- Pt,
950
+ $ && j ? /* @__PURE__ */ i(Zt, { target: j, locked: !!y }) : null,
951
+ $ && y && A && nt ? /* @__PURE__ */ i(en, { from: y, to: A }) : null,
952
+ $ ? /* @__PURE__ */ o(ae, { children: [
953
+ /* @__PURE__ */ i(
954
+ tn,
778
955
  {
779
- feedback: I,
780
- selectedFeedback: S,
781
- onSelect: q
956
+ feedback: R,
957
+ selectedFeedback: k,
958
+ onSelect: D
782
959
  }
783
960
  ),
784
- /* @__PURE__ */ r(
785
- Wt,
961
+ /* @__PURE__ */ i(
962
+ rn,
786
963
  {
787
- feedback: I,
788
- selectedFeedback: S,
789
- onSelect: q
964
+ feedback: R,
965
+ selectedFeedback: k,
966
+ onSelect: D
790
967
  }
791
968
  )
792
969
  ] }) : null,
793
970
  /* @__PURE__ */ o("aside", { className: `review-lens-panel review-lens-panel--${n}`, "data-review-lens-ui": !0, children: [
794
971
  /* @__PURE__ */ o("header", { className: "review-lens-panel__header", children: [
795
- /* @__PURE__ */ o("div", { children: [
796
- /* @__PURE__ */ r("p", { className: "review-lens-kicker", children: "Review Lens" }),
797
- /* @__PURE__ */ r("h2", { children: F === "summary" ? "Summary" : F === "feedback" ? "Feedback" : w ? "Element locked" : "Inspecting" })
972
+ /* @__PURE__ */ o("div", { className: "review-lens-brand", children: [
973
+ /* @__PURE__ */ i(Ot, { className: "review-lens-brand__mark" }),
974
+ /* @__PURE__ */ o("div", { children: [
975
+ /* @__PURE__ */ i("p", { className: "review-lens-kicker", children: "Review Lens" }),
976
+ /* @__PURE__ */ i("h2", { children: M === "summary" ? "Summary" : M === "feedback" ? "Feedback" : y ? "Element locked" : "Inspecting" })
977
+ ] })
798
978
  ] }),
799
- /* @__PURE__ */ r("button", { type: "button", onClick: () => t == null ? void 0 : t(!1), children: "Close" })
979
+ /* @__PURE__ */ i("button", { type: "button", onClick: () => t == null ? void 0 : t(!1), children: "Close" })
800
980
  ] }),
801
981
  /* @__PURE__ */ o("div", { className: "review-lens-panel__body", children: [
802
982
  /* @__PURE__ */ o("div", { className: "review-lens-mode-switch", role: "tablist", "aria-label": "Review Lens mode", children: [
803
- /* @__PURE__ */ r(
983
+ /* @__PURE__ */ i(
804
984
  "button",
805
985
  {
806
986
  type: "button",
807
987
  role: "tab",
808
- "aria-selected": F === "review",
809
- onClick: () => $("review"),
988
+ "aria-selected": M === "review",
989
+ onClick: () => P("review"),
810
990
  children: "Review"
811
991
  }
812
992
  ),
@@ -815,60 +995,60 @@ function Zt({
815
995
  {
816
996
  type: "button",
817
997
  role: "tab",
818
- "aria-selected": F === "feedback",
819
- onClick: () => $("feedback"),
998
+ "aria-selected": M === "feedback",
999
+ onClick: () => P("feedback"),
820
1000
  children: [
821
1001
  "Feedback ",
822
- /* @__PURE__ */ r("span", { children: I.length })
1002
+ /* @__PURE__ */ i("span", { children: R.length })
823
1003
  ]
824
1004
  }
825
1005
  ),
826
- /* @__PURE__ */ r(
1006
+ /* @__PURE__ */ i(
827
1007
  "button",
828
1008
  {
829
1009
  type: "button",
830
1010
  role: "tab",
831
- "aria-selected": F === "summary",
832
- onClick: () => $("summary"),
1011
+ "aria-selected": M === "summary",
1012
+ onClick: () => P("summary"),
833
1013
  children: "Summary"
834
1014
  }
835
1015
  )
836
1016
  ] }),
837
- F === "review" ? /* @__PURE__ */ o("div", { className: "review-lens-review-pane", role: "tabpanel", children: [
1017
+ M === "review" ? /* @__PURE__ */ o("div", { className: "review-lens-review-pane", role: "tabpanel", children: [
838
1018
  /* @__PURE__ */ o("div", { className: "review-lens-inspection", children: [
839
- M ? null : /* @__PURE__ */ r("p", { children: "Authenticate with Google to inspect this page." }),
840
- M && P ? /* @__PURE__ */ o(re, { children: [
841
- /* @__PURE__ */ r(Dt, { target: P }),
842
- /* @__PURE__ */ r(_e, { title: "Accessibility", items: zt(P) }),
843
- /* @__PURE__ */ r(
844
- _e,
1019
+ $ ? null : /* @__PURE__ */ i("p", { children: "Authenticate with Google to inspect this page." }),
1020
+ $ && j ? /* @__PURE__ */ o(ae, { children: [
1021
+ /* @__PURE__ */ i(an, { target: j }),
1022
+ /* @__PURE__ */ i(De, { title: "Accessibility", items: sn(j) }),
1023
+ /* @__PURE__ */ i(
1024
+ De,
845
1025
  {
846
1026
  title: "Design tokens",
847
- items: Ht(P.cssSnapshot, f.designTokens)
1027
+ items: on(j.cssSnapshot, w.designTokens)
848
1028
  }
849
1029
  )
850
1030
  ] }) : null,
851
- M && !P ? /* @__PURE__ */ r("p", { children: "Move over the app to inspect." }) : null
1031
+ $ && !j ? /* @__PURE__ */ i("p", { children: "Move over the app to inspect." }) : null
852
1032
  ] }),
853
- et ? /* @__PURE__ */ r("div", { className: "review-lens-composer-panel", children: /* @__PURE__ */ o(
1033
+ ot ? /* @__PURE__ */ i("div", { className: "review-lens-composer-panel", children: /* @__PURE__ */ o(
854
1034
  "form",
855
1035
  {
856
1036
  className: "review-lens-feedback-form",
857
1037
  onSubmit: (a) => {
858
- a.preventDefault(), Ie();
1038
+ a.preventDefault(), Me();
859
1039
  },
860
1040
  children: [
861
- /* @__PURE__ */ r("label", { htmlFor: "review-lens-comment", children: "New feedback" }),
862
- /* @__PURE__ */ r(
1041
+ /* @__PURE__ */ i("label", { htmlFor: "review-lens-comment", children: "New feedback" }),
1042
+ /* @__PURE__ */ i(
863
1043
  "textarea",
864
1044
  {
865
- ref: ee,
1045
+ ref: te,
866
1046
  id: "review-lens-comment",
867
- value: B,
1047
+ value: F,
868
1048
  disabled: !T,
869
- onChange: (a) => D(a.target.value),
1049
+ onChange: (a) => _(a.target.value),
870
1050
  onKeyDown: (a) => {
871
- a.key === "Enter" && a.metaKey && (a.preventDefault(), Ie());
1051
+ a.key === "Enter" && a.metaKey && (a.preventDefault(), Me());
872
1052
  },
873
1053
  placeholder: T ? "Describe the UX issue..." : "You do not have permission to comment."
874
1054
  }
@@ -876,35 +1056,35 @@ function Zt({
876
1056
  /* @__PURE__ */ o("div", { className: "review-lens-form-grid", children: [
877
1057
  /* @__PURE__ */ o("label", { children: [
878
1058
  "Severity",
879
- /* @__PURE__ */ r(
1059
+ /* @__PURE__ */ i(
880
1060
  "select",
881
1061
  {
882
- value: pe,
883
- onChange: (a) => Je(a.target.value),
1062
+ value: H,
1063
+ onChange: (a) => Ze(a.target.value),
884
1064
  disabled: !T,
885
- children: je.map((a) => /* @__PURE__ */ r("option", { value: a, children: Q[a] }, a))
1065
+ children: Ye.map((a) => /* @__PURE__ */ i("option", { value: a, children: Z[a] }, a))
886
1066
  }
887
1067
  )
888
1068
  ] }),
889
1069
  /* @__PURE__ */ o("label", { children: [
890
1070
  "Type",
891
- /* @__PURE__ */ r(
1071
+ /* @__PURE__ */ i(
892
1072
  "select",
893
1073
  {
894
- value: me,
895
- onChange: (a) => Ve(a.target.value),
1074
+ value: we,
1075
+ onChange: (a) => et(a.target.value),
896
1076
  disabled: !T,
897
- children: Oe.map((a) => /* @__PURE__ */ r("option", { value: a, children: Z[a] }, a))
1077
+ children: Xe.map((a) => /* @__PURE__ */ i("option", { value: a, children: ee[a] }, a))
898
1078
  }
899
1079
  )
900
1080
  ] }),
901
1081
  /* @__PURE__ */ o("label", { children: [
902
1082
  "Assignee",
903
- /* @__PURE__ */ r(
1083
+ /* @__PURE__ */ i(
904
1084
  "input",
905
1085
  {
906
- value: ge,
907
- onChange: (a) => fe(a.target.value),
1086
+ value: be,
1087
+ onChange: (a) => ve(a.target.value),
908
1088
  disabled: !T,
909
1089
  placeholder: "optional@email.com"
910
1090
  }
@@ -912,128 +1092,129 @@ function Zt({
912
1092
  ] }),
913
1093
  /* @__PURE__ */ o("label", { children: [
914
1094
  "Viewport",
915
- /* @__PURE__ */ r(
1095
+ /* @__PURE__ */ i(
916
1096
  "select",
917
1097
  {
918
- value: be,
919
- onChange: (a) => qe(a.target.value),
1098
+ value: ye,
1099
+ onChange: (a) => tt(a.target.value),
920
1100
  disabled: !T,
921
- children: c.map((a) => /* @__PURE__ */ r("option", { value: a.value, children: a.label }, a.value))
1101
+ children: c.map((a) => /* @__PURE__ */ i("option", { value: a.value, children: a.label }, a.value))
922
1102
  }
923
1103
  )
924
1104
  ] })
925
1105
  ] }),
926
1106
  T ? /* @__PURE__ */ o("p", { className: "review-lens-feedback-form__hint", children: [
927
1107
  "Press ",
928
- /* @__PURE__ */ r("kbd", { children: "Command" }),
1108
+ /* @__PURE__ */ i("kbd", { children: "Command" }),
929
1109
  " + ",
930
- /* @__PURE__ */ r("kbd", { children: "Enter" }),
1110
+ /* @__PURE__ */ i("kbd", { children: "Enter" }),
931
1111
  " to submit.",
932
- tt ? " Screenshot capture runs after save." : ""
1112
+ lt ? " Screenshot capture runs after save." : ""
933
1113
  ] }) : null,
934
- /* @__PURE__ */ r("div", { className: "review-lens-actions", children: /* @__PURE__ */ r("button", { type: "submit", disabled: !B.trim() || !T, children: "Save feedback" }) })
1114
+ /* @__PURE__ */ i("div", { className: "review-lens-actions", children: /* @__PURE__ */ i("button", { type: "submit", disabled: !F.trim() || !T, children: "Save feedback" }) })
935
1115
  ]
936
1116
  }
937
1117
  ) }) : null
938
1118
  ] }) : null,
939
- F === "feedback" ? /* @__PURE__ */ o("div", { className: "review-lens-comments", children: [
940
- /* @__PURE__ */ r(
941
- Mt,
1119
+ M === "feedback" ? /* @__PURE__ */ o("div", { className: "review-lens-comments", children: [
1120
+ /* @__PURE__ */ i(
1121
+ Vt,
942
1122
  {
943
- open: Ye,
944
- activeCount: rt,
945
- statusFilter: j,
1123
+ open: it,
1124
+ activeCount: ct,
1125
+ statusFilter: J,
946
1126
  severityFilter: O,
947
- categoryFilter: K,
948
- assigneeFilter: J,
949
- viewportFilter: V,
950
- assignees: nt,
1127
+ categoryFilter: q,
1128
+ assigneeFilter: V,
1129
+ viewportFilter: G,
1130
+ assignees: dt,
951
1131
  responsivePresets: c,
952
- onStatusChange: we,
953
- onSeverityChange: ye,
954
- onCategoryChange: Se,
955
- onAssigneeChange: ke,
956
- onViewportChange: Ce,
957
- onToggle: () => Xe((a) => !a),
1132
+ onStatusChange: ke,
1133
+ onSeverityChange: Ne,
1134
+ onCategoryChange: Ce,
1135
+ onAssigneeChange: xe,
1136
+ onViewportChange: Ee,
1137
+ onToggle: () => rt((a) => !a),
958
1138
  onClear: () => {
959
- we("all"), ye("all"), Se("all"), ke("all"), Ce("all");
1139
+ ke("all"), Ne("all"), Ce("all"), xe("all"), Ee("all");
960
1140
  }
961
1141
  }
962
1142
  ),
963
1143
  /* @__PURE__ */ o("div", { className: "review-lens-list-panel", children: [
964
1144
  /* @__PURE__ */ o("div", { className: "review-lens-comments__header", children: [
965
- /* @__PURE__ */ r("h3", { children: "All feedback" }),
966
- /* @__PURE__ */ r("span", { children: I.length })
1145
+ /* @__PURE__ */ i("h3", { children: "All feedback" }),
1146
+ /* @__PURE__ */ i("span", { children: R.length })
967
1147
  ] }),
968
1148
  /* @__PURE__ */ o("div", { className: "review-lens-comments__list", children: [
969
- I.length === 0 ? /* @__PURE__ */ r("p", { children: "No feedback for this view." }) : null,
970
- I.map((a) => /* @__PURE__ */ r(
971
- Tt,
1149
+ R.length === 0 ? /* @__PURE__ */ i("p", { children: "No feedback for this view." }) : null,
1150
+ R.map((a) => /* @__PURE__ */ i(
1151
+ Gt,
972
1152
  {
973
1153
  item: a,
974
- selected: (S == null ? void 0 : S.id) === a.id,
975
- onSelect: q
1154
+ selected: (k == null ? void 0 : k.id) === a.id,
1155
+ onSelect: D
976
1156
  },
977
1157
  a.id
978
1158
  ))
979
1159
  ] })
980
1160
  ] }),
981
- S ? /* @__PURE__ */ o("div", { className: "review-lens-selected-panel", children: [
982
- /* @__PURE__ */ r("div", { className: "review-lens-selected-panel__label", children: "Selected feedback" }),
983
- /* @__PURE__ */ r(
984
- Rt,
1161
+ k ? /* @__PURE__ */ o("div", { className: "review-lens-selected-panel", children: [
1162
+ /* @__PURE__ */ i("div", { className: "review-lens-selected-panel__label", children: "Selected feedback" }),
1163
+ /* @__PURE__ */ i(
1164
+ Yt,
985
1165
  {
986
- item: S,
987
- messages: Qe[S.id] ?? [],
988
- messageDraft: se,
989
- canReply: xe,
990
- canUpdate: Ee,
991
- canAssign: Ze,
992
- onMessageDraftChange: oe,
993
- onSubmitMessage: () => void at(S),
994
- onStatusChange: (a) => void it(S, a),
995
- onAssigneeChange: (a) => void C(S.id, {
1166
+ item: k,
1167
+ messages: at[k.id] ?? [],
1168
+ messageDraft: le,
1169
+ canReply: Ae,
1170
+ canUpdate: Re,
1171
+ canAssign: st,
1172
+ syncSelectionToUrl: s,
1173
+ onMessageDraftChange: de,
1174
+ onSubmitMessage: () => void ut(k),
1175
+ onStatusChange: (a) => void ht(k, a),
1176
+ onAssigneeChange: (a) => void S(k.id, {
996
1177
  assigneeEmail: a.trim() || void 0
997
- }).then(H),
998
- onMarkFixed: () => void Le(S)
1178
+ }).then(K),
1179
+ onMarkFixed: () => void $e(k)
999
1180
  },
1000
- S.id
1181
+ k.id
1001
1182
  )
1002
1183
  ] }) : /* @__PURE__ */ o("div", { className: "review-lens-selected-panel review-lens-selected-panel--empty", children: [
1003
- /* @__PURE__ */ r("div", { className: "review-lens-selected-panel__label", children: "Selected feedback" }),
1004
- /* @__PURE__ */ r("p", { children: "Select a feedback item above to review status, assignment, drift, and replies." })
1184
+ /* @__PURE__ */ i("div", { className: "review-lens-selected-panel__label", children: "Selected feedback" }),
1185
+ /* @__PURE__ */ i("p", { children: "Select a feedback item above to review status, assignment, drift, and replies." })
1005
1186
  ] })
1006
1187
  ] }) : null,
1007
- F === "summary" ? /* @__PURE__ */ r(Bt, { feedback: d }) : null
1188
+ M === "summary" ? /* @__PURE__ */ i(Qt, { feedback: b }) : null
1008
1189
  ] })
1009
1190
  ] })
1010
1191
  ] });
1011
1192
  }
1012
- function Mt({
1193
+ function Vt({
1013
1194
  open: e,
1014
1195
  activeCount: t,
1015
1196
  statusFilter: n,
1016
- severityFilter: i,
1197
+ severityFilter: r,
1017
1198
  categoryFilter: s,
1018
1199
  assigneeFilter: c,
1019
- viewportFilter: g,
1020
- assignees: f,
1200
+ viewportFilter: h,
1201
+ assignees: w,
1021
1202
  responsivePresets: p,
1022
- onStatusChange: d,
1023
- onSeverityChange: v,
1024
- onCategoryChange: h,
1025
- onAssigneeChange: b,
1026
- onViewportChange: C,
1027
- onToggle: E,
1028
- onClear: A
1203
+ onStatusChange: b,
1204
+ onSeverityChange: g,
1205
+ onCategoryChange: f,
1206
+ onAssigneeChange: m,
1207
+ onViewportChange: S,
1208
+ onToggle: x,
1209
+ onClear: E
1029
1210
  }) {
1030
1211
  return /* @__PURE__ */ o("div", { className: "review-lens-filter-shell", children: [
1031
1212
  /* @__PURE__ */ o("div", { className: "review-lens-filter-bar", children: [
1032
- /* @__PURE__ */ o("button", { type: "button", "aria-expanded": e, onClick: E, children: [
1213
+ /* @__PURE__ */ o("button", { type: "button", "aria-expanded": e, onClick: x, children: [
1033
1214
  "Filters",
1034
- t > 0 ? /* @__PURE__ */ r("span", { children: t }) : null
1215
+ t > 0 ? /* @__PURE__ */ i("span", { children: t }) : null
1035
1216
  ] }),
1036
- t > 0 ? /* @__PURE__ */ r("button", { type: "button", onClick: A, children: "Clear" }) : null
1217
+ t > 0 ? /* @__PURE__ */ i("button", { type: "button", onClick: E, children: "Clear" }) : null
1037
1218
  ] }),
1038
1219
  e ? /* @__PURE__ */ o("div", { className: "review-lens-filters", children: [
1039
1220
  /* @__PURE__ */ o("label", { children: [
@@ -1043,10 +1224,10 @@ function Mt({
1043
1224
  {
1044
1225
  "aria-label": "Filter status",
1045
1226
  value: n,
1046
- onChange: (u) => d(u.target.value),
1227
+ onChange: (l) => b(l.target.value),
1047
1228
  children: [
1048
- /* @__PURE__ */ r("option", { value: "all", children: "All statuses" }),
1049
- He.map((u) => /* @__PURE__ */ r("option", { value: u, children: ae[u] }, u))
1229
+ /* @__PURE__ */ i("option", { value: "all", children: "All statuses" }),
1230
+ Ge.map((l) => /* @__PURE__ */ i("option", { value: l, children: oe[l] }, l))
1050
1231
  ]
1051
1232
  }
1052
1233
  )
@@ -1057,11 +1238,11 @@ function Mt({
1057
1238
  "select",
1058
1239
  {
1059
1240
  "aria-label": "Filter severity",
1060
- value: i,
1061
- onChange: (u) => v(u.target.value),
1241
+ value: r,
1242
+ onChange: (l) => g(l.target.value),
1062
1243
  children: [
1063
- /* @__PURE__ */ r("option", { value: "all", children: "All priorities" }),
1064
- je.map((u) => /* @__PURE__ */ r("option", { value: u, children: Q[u] }, u))
1244
+ /* @__PURE__ */ i("option", { value: "all", children: "All priorities" }),
1245
+ Ye.map((l) => /* @__PURE__ */ i("option", { value: l, children: Z[l] }, l))
1065
1246
  ]
1066
1247
  }
1067
1248
  )
@@ -1073,10 +1254,10 @@ function Mt({
1073
1254
  {
1074
1255
  "aria-label": "Filter type",
1075
1256
  value: s,
1076
- onChange: (u) => h(u.target.value),
1257
+ onChange: (l) => f(l.target.value),
1077
1258
  children: [
1078
- /* @__PURE__ */ r("option", { value: "all", children: "All types" }),
1079
- Oe.map((u) => /* @__PURE__ */ r("option", { value: u, children: Z[u] }, u))
1259
+ /* @__PURE__ */ i("option", { value: "all", children: "All types" }),
1260
+ Xe.map((l) => /* @__PURE__ */ i("option", { value: l, children: ee[l] }, l))
1080
1261
  ]
1081
1262
  }
1082
1263
  )
@@ -1088,10 +1269,10 @@ function Mt({
1088
1269
  {
1089
1270
  "aria-label": "Filter assignee",
1090
1271
  value: c,
1091
- onChange: (u) => b(u.target.value),
1272
+ onChange: (l) => m(l.target.value),
1092
1273
  children: [
1093
- /* @__PURE__ */ r("option", { value: "all", children: "All assignees" }),
1094
- f.map((u) => /* @__PURE__ */ r("option", { value: u, children: u }, u))
1274
+ /* @__PURE__ */ i("option", { value: "all", children: "All assignees" }),
1275
+ w.map((l) => /* @__PURE__ */ i("option", { value: l, children: l }, l))
1095
1276
  ]
1096
1277
  }
1097
1278
  )
@@ -1102,11 +1283,11 @@ function Mt({
1102
1283
  "select",
1103
1284
  {
1104
1285
  "aria-label": "Filter viewport",
1105
- value: g,
1106
- onChange: (u) => C(u.target.value),
1286
+ value: h,
1287
+ onChange: (l) => S(l.target.value),
1107
1288
  children: [
1108
- /* @__PURE__ */ r("option", { value: "all", children: "All viewports" }),
1109
- p.map((u) => /* @__PURE__ */ r("option", { value: u.value, children: u.label }, u.value))
1289
+ /* @__PURE__ */ i("option", { value: "all", children: "All viewports" }),
1290
+ p.map((l) => /* @__PURE__ */ i("option", { value: l.value, children: l.label }, l.value))
1110
1291
  ]
1111
1292
  }
1112
1293
  )
@@ -1114,12 +1295,12 @@ function Mt({
1114
1295
  ] }) : null
1115
1296
  ] });
1116
1297
  }
1117
- function Tt({
1298
+ function Gt({
1118
1299
  item: e,
1119
1300
  selected: t,
1120
1301
  onSelect: n
1121
1302
  }) {
1122
- const i = Ke(e);
1303
+ const r = Qe(e);
1123
1304
  return /* @__PURE__ */ o(
1124
1305
  "article",
1125
1306
  {
@@ -1135,154 +1316,185 @@ function Tt({
1135
1316
  },
1136
1317
  children: [
1137
1318
  /* @__PURE__ */ o("div", { className: "review-lens-comment__header", children: [
1138
- /* @__PURE__ */ r("span", { children: ae[e.status] }),
1139
- /* @__PURE__ */ r("strong", { children: Q[e.severity] })
1319
+ /* @__PURE__ */ i("span", { children: oe[e.status] }),
1320
+ /* @__PURE__ */ i("strong", { children: Z[e.severity] })
1140
1321
  ] }),
1141
1322
  /* @__PURE__ */ o("div", { className: "review-lens-comment__content", children: [
1142
- /* @__PURE__ */ r("p", { children: e.comment }),
1323
+ /* @__PURE__ */ i("p", { children: e.comment }),
1143
1324
  /* @__PURE__ */ o("span", { children: [
1144
1325
  e.authorEmail,
1145
1326
  e.assigneeEmail ? ` -> ${e.assigneeEmail}` : ""
1146
1327
  ] })
1147
1328
  ] }),
1148
1329
  /* @__PURE__ */ o("div", { className: "review-lens-tags", children: [
1149
- /* @__PURE__ */ r("span", { children: Z[e.category] }),
1150
- /* @__PURE__ */ r("span", { children: e.viewportPreset }),
1151
- /* @__PURE__ */ r("span", { children: i.label })
1330
+ /* @__PURE__ */ i("span", { children: ee[e.category] }),
1331
+ /* @__PURE__ */ i("span", { children: e.viewportPreset }),
1332
+ /* @__PURE__ */ i("span", { children: r.label })
1152
1333
  ] })
1153
1334
  ]
1154
1335
  }
1155
1336
  );
1156
1337
  }
1157
- function Rt({
1338
+ function Yt({
1158
1339
  item: e,
1159
1340
  messages: t,
1160
1341
  messageDraft: n,
1161
- canReply: i,
1342
+ canReply: r,
1162
1343
  canUpdate: s,
1163
1344
  canAssign: c,
1164
- onMessageDraftChange: g,
1165
- onSubmitMessage: f,
1166
- onStatusChange: p,
1167
- onAssigneeChange: d,
1168
- onMarkFixed: v
1345
+ syncSelectionToUrl: h,
1346
+ onMessageDraftChange: w,
1347
+ onSubmitMessage: p,
1348
+ onStatusChange: b,
1349
+ onAssigneeChange: g,
1350
+ onMarkFixed: f
1169
1351
  }) {
1170
- const h = Ke(e);
1352
+ const [m, S] = N(!1), x = Qe(e);
1353
+ function E() {
1354
+ const l = new URL(window.location.href);
1355
+ l.searchParams.set("reviewLensFeedback", e.id), Xt(l.toString()).then((A) => {
1356
+ A && (S(!0), setTimeout(() => S(!1), 2e3));
1357
+ });
1358
+ }
1171
1359
  return /* @__PURE__ */ o("section", { className: "review-lens-detail", "aria-label": "Selected feedback detail", children: [
1172
1360
  /* @__PURE__ */ o("div", { className: "review-lens-detail__header", children: [
1173
1361
  /* @__PURE__ */ o("h3", { children: [
1174
- Z[e.category],
1362
+ ee[e.category],
1175
1363
  " feedback"
1176
1364
  ] }),
1177
- /* @__PURE__ */ r("strong", { children: Q[e.severity] })
1365
+ /* @__PURE__ */ o("div", { className: "review-lens-detail__header-actions", children: [
1366
+ h ? /* @__PURE__ */ i(
1367
+ "button",
1368
+ {
1369
+ type: "button",
1370
+ className: "review-lens-copy-link",
1371
+ onClick: E,
1372
+ "aria-label": "Copy link to this feedback",
1373
+ children: m ? "Copied!" : "Copy link"
1374
+ }
1375
+ ) : null,
1376
+ /* @__PURE__ */ i("strong", { children: Z[e.severity] })
1377
+ ] })
1178
1378
  ] }),
1179
- /* @__PURE__ */ r("blockquote", { children: e.comment }),
1379
+ /* @__PURE__ */ i("blockquote", { children: e.comment }),
1180
1380
  /* @__PURE__ */ o("dl", { className: "review-lens-detail-meta", children: [
1181
1381
  /* @__PURE__ */ o("div", { children: [
1182
- /* @__PURE__ */ r("dt", { children: "Target" }),
1183
- /* @__PURE__ */ r("dd", { children: h.label })
1382
+ /* @__PURE__ */ i("dt", { children: "Target" }),
1383
+ /* @__PURE__ */ i("dd", { children: x.label })
1184
1384
  ] }),
1185
1385
  /* @__PURE__ */ o("div", { children: [
1186
- /* @__PURE__ */ r("dt", { children: "Viewport" }),
1187
- /* @__PURE__ */ r("dd", { children: e.viewportPreset })
1386
+ /* @__PURE__ */ i("dt", { children: "Viewport" }),
1387
+ /* @__PURE__ */ i("dd", { children: e.viewportPreset })
1188
1388
  ] }),
1189
1389
  e.screenshotUrl ? /* @__PURE__ */ o("div", { children: [
1190
- /* @__PURE__ */ r("dt", { children: "Evidence" }),
1191
- /* @__PURE__ */ r("dd", { children: /* @__PURE__ */ r("a", { href: e.screenshotUrl, target: "_blank", rel: "noreferrer", children: "Screenshot" }) })
1390
+ /* @__PURE__ */ i("dt", { children: "Evidence" }),
1391
+ /* @__PURE__ */ i("dd", { children: /* @__PURE__ */ i("a", { href: e.screenshotUrl, target: "_blank", rel: "noreferrer", children: "Screenshot" }) })
1192
1392
  ] }) : null
1193
1393
  ] }),
1194
1394
  /* @__PURE__ */ o("div", { className: "review-lens-form-grid", children: [
1195
1395
  /* @__PURE__ */ o("label", { children: [
1196
1396
  "Status",
1197
- /* @__PURE__ */ r(
1397
+ /* @__PURE__ */ i(
1198
1398
  "select",
1199
1399
  {
1200
1400
  value: e.status,
1201
1401
  disabled: !s,
1202
- onChange: (b) => p(b.target.value),
1203
- children: He.map((b) => /* @__PURE__ */ r("option", { value: b, children: ae[b] }, b))
1402
+ onChange: (l) => b(l.target.value),
1403
+ children: Ge.map((l) => /* @__PURE__ */ i("option", { value: l, children: oe[l] }, l))
1204
1404
  }
1205
1405
  )
1206
1406
  ] }),
1207
1407
  /* @__PURE__ */ o("label", { children: [
1208
1408
  "Assignee",
1209
- /* @__PURE__ */ r(
1409
+ /* @__PURE__ */ i(
1210
1410
  "input",
1211
1411
  {
1212
1412
  defaultValue: e.assigneeEmail ?? "",
1213
1413
  disabled: !c,
1214
- onBlur: (b) => d(b.target.value),
1414
+ onBlur: (l) => g(l.target.value),
1215
1415
  placeholder: "optional@email.com"
1216
1416
  }
1217
1417
  )
1218
1418
  ] })
1219
1419
  ] }),
1220
1420
  /* @__PURE__ */ o("div", { className: "review-lens-status-actions", children: [
1221
- /* @__PURE__ */ r(
1421
+ /* @__PURE__ */ i(
1222
1422
  "button",
1223
1423
  {
1224
1424
  type: "button",
1225
1425
  className: "review-lens-button-secondary",
1226
1426
  disabled: !s,
1227
- onClick: v,
1427
+ onClick: f,
1228
1428
  children: "Mark fixed"
1229
1429
  }
1230
1430
  ),
1231
- /* @__PURE__ */ r(
1431
+ /* @__PURE__ */ i(
1232
1432
  "button",
1233
1433
  {
1234
1434
  type: "button",
1235
1435
  className: "review-lens-button-primary",
1236
1436
  disabled: !s,
1237
- onClick: () => p("resolved"),
1437
+ onClick: () => b("resolved"),
1238
1438
  children: "Resolve"
1239
1439
  }
1240
1440
  )
1241
1441
  ] }),
1242
1442
  /* @__PURE__ */ o("div", { className: "review-lens-thread", children: [
1243
1443
  /* @__PURE__ */ o("div", { className: "review-lens-thread__header", children: [
1244
- /* @__PURE__ */ r("h3", { children: "Thread" }),
1245
- /* @__PURE__ */ r("span", { children: t.length })
1444
+ /* @__PURE__ */ i("h3", { children: "Thread" }),
1445
+ /* @__PURE__ */ i("span", { children: t.length })
1246
1446
  ] }),
1247
- t.length === 0 ? /* @__PURE__ */ r("p", { children: "No replies yet." }) : null,
1248
- t.map((b) => /* @__PURE__ */ o("div", { className: "review-lens-thread__message", children: [
1249
- /* @__PURE__ */ r("p", { children: b.body }),
1250
- /* @__PURE__ */ r("span", { children: b.authorEmail })
1251
- ] }, b.id)),
1252
- /* @__PURE__ */ r(
1447
+ t.length === 0 ? /* @__PURE__ */ i("p", { children: "No replies yet." }) : null,
1448
+ t.map((l) => /* @__PURE__ */ o("div", { className: "review-lens-thread__message", children: [
1449
+ /* @__PURE__ */ i("p", { children: l.body }),
1450
+ /* @__PURE__ */ i("span", { children: l.authorEmail })
1451
+ ] }, l.id)),
1452
+ /* @__PURE__ */ i(
1253
1453
  "textarea",
1254
1454
  {
1255
1455
  "aria-label": "Reply",
1256
1456
  value: n,
1257
- disabled: !i,
1258
- onChange: (b) => g(b.target.value),
1259
- placeholder: i ? "Reply..." : "You do not have permission to reply."
1457
+ disabled: !r,
1458
+ onChange: (l) => w(l.target.value),
1459
+ placeholder: r ? "Reply..." : "You do not have permission to reply."
1260
1460
  }
1261
1461
  ),
1262
- /* @__PURE__ */ r("div", { className: "review-lens-actions", children: /* @__PURE__ */ r("button", { type: "button", disabled: !n.trim() || !i, onClick: f, children: "Reply" }) })
1462
+ /* @__PURE__ */ i("div", { className: "review-lens-actions", children: /* @__PURE__ */ i("button", { type: "button", disabled: !n.trim() || !r, onClick: p, children: "Reply" }) })
1263
1463
  ] })
1264
1464
  ] });
1265
1465
  }
1266
- function Bt({ feedback: e }) {
1466
+ async function Xt(e) {
1467
+ var n;
1468
+ if ((n = navigator.clipboard) != null && n.writeText)
1469
+ return await navigator.clipboard.writeText(e), !0;
1470
+ const t = document.createElement("textarea");
1471
+ t.value = e, t.setAttribute("readonly", ""), t.style.position = "fixed", t.style.opacity = "0", document.body.append(t), t.select();
1472
+ try {
1473
+ return document.execCommand("copy");
1474
+ } finally {
1475
+ t.remove();
1476
+ }
1477
+ }
1478
+ function Qt({ feedback: e }) {
1267
1479
  return /* @__PURE__ */ o("div", { className: "review-lens-summary", role: "tabpanel", children: [
1268
- /* @__PURE__ */ r(G, { title: "Status", values: Y(e, (t) => ae[t.status]) }),
1269
- /* @__PURE__ */ r(G, { title: "Severity", values: Y(e, (t) => Q[t.severity]) }),
1270
- /* @__PURE__ */ r(G, { title: "Type", values: Y(e, (t) => Z[t.category]) }),
1271
- /* @__PURE__ */ r(G, { title: "Assignee", values: Y(e, (t) => t.assigneeEmail ?? "Unassigned") }),
1272
- /* @__PURE__ */ r(G, { title: "Viewport", values: Y(e, (t) => t.viewportPreset) })
1480
+ /* @__PURE__ */ i(Y, { title: "Status", values: X(e, (t) => oe[t.status]) }),
1481
+ /* @__PURE__ */ i(Y, { title: "Severity", values: X(e, (t) => Z[t.severity]) }),
1482
+ /* @__PURE__ */ i(Y, { title: "Type", values: X(e, (t) => ee[t.category]) }),
1483
+ /* @__PURE__ */ i(Y, { title: "Assignee", values: X(e, (t) => t.assigneeEmail ?? "Unassigned") }),
1484
+ /* @__PURE__ */ i(Y, { title: "Viewport", values: X(e, (t) => t.viewportPreset) })
1273
1485
  ] });
1274
1486
  }
1275
- function G({ title: e, values: t }) {
1487
+ function Y({ title: e, values: t }) {
1276
1488
  return /* @__PURE__ */ o("section", { children: [
1277
- /* @__PURE__ */ r("h3", { children: e }),
1278
- /* @__PURE__ */ r("dl", { children: t.map(([n, i]) => /* @__PURE__ */ o("div", { children: [
1279
- /* @__PURE__ */ r("dt", { children: n }),
1280
- /* @__PURE__ */ r("dd", { children: i })
1489
+ /* @__PURE__ */ i("h3", { children: e }),
1490
+ /* @__PURE__ */ i("dl", { children: t.map(([n, r]) => /* @__PURE__ */ o("div", { children: [
1491
+ /* @__PURE__ */ i("dt", { children: n }),
1492
+ /* @__PURE__ */ i("dd", { children: r })
1281
1493
  ] }, n)) })
1282
1494
  ] });
1283
1495
  }
1284
- function $t({ target: e, locked: t }) {
1285
- const n = Gt(e), i = Ot(e.fingerprint);
1496
+ function Zt({ target: e, locked: t }) {
1497
+ const n = pn(e), r = dn(e.fingerprint);
1286
1498
  return /* @__PURE__ */ o(
1287
1499
  "div",
1288
1500
  {
@@ -1294,7 +1506,7 @@ function $t({ target: e, locked: t }) {
1294
1506
  height: n.margin.height
1295
1507
  },
1296
1508
  children: [
1297
- /* @__PURE__ */ r(
1509
+ /* @__PURE__ */ i(
1298
1510
  "div",
1299
1511
  {
1300
1512
  className: "review-lens-highlight__border",
@@ -1306,7 +1518,7 @@ function $t({ target: e, locked: t }) {
1306
1518
  }
1307
1519
  }
1308
1520
  ),
1309
- /* @__PURE__ */ r(
1521
+ /* @__PURE__ */ i(
1310
1522
  "div",
1311
1523
  {
1312
1524
  className: "review-lens-highlight__padding",
@@ -1318,7 +1530,7 @@ function $t({ target: e, locked: t }) {
1318
1530
  }
1319
1531
  }
1320
1532
  ),
1321
- /* @__PURE__ */ r(
1533
+ /* @__PURE__ */ i(
1322
1534
  "div",
1323
1535
  {
1324
1536
  className: "review-lens-highlight__content",
@@ -1331,7 +1543,7 @@ function $t({ target: e, locked: t }) {
1331
1543
  }
1332
1544
  ),
1333
1545
  /* @__PURE__ */ o("div", { className: "review-lens-highlight__label", children: [
1334
- /* @__PURE__ */ r("strong", { children: i }),
1546
+ /* @__PURE__ */ i("strong", { children: r }),
1335
1547
  /* @__PURE__ */ o("span", { children: [
1336
1548
  Math.round(e.rect.width),
1337
1549
  " x ",
@@ -1342,60 +1554,60 @@ function $t({ target: e, locked: t }) {
1342
1554
  }
1343
1555
  );
1344
1556
  }
1345
- function _t({ from: e, to: t }) {
1346
- const n = Kt(e.rect, t.rect);
1347
- return n.length === 0 ? null : /* @__PURE__ */ r(re, { children: n.map((i) => /* @__PURE__ */ r(
1557
+ function en({ from: e, to: t }) {
1558
+ const n = cn(e.rect, t.rect);
1559
+ return n.length === 0 ? null : /* @__PURE__ */ i(ae, { children: n.map((r) => /* @__PURE__ */ i(
1348
1560
  "div",
1349
1561
  {
1350
- className: `review-lens-distance review-lens-distance--${i.axis}`,
1562
+ className: `review-lens-distance review-lens-distance--${r.axis}`,
1351
1563
  style: {
1352
- top: i.top,
1353
- left: i.left,
1354
- width: i.width,
1355
- height: i.height
1564
+ top: r.top,
1565
+ left: r.left,
1566
+ width: r.width,
1567
+ height: r.height
1356
1568
  },
1357
- children: /* @__PURE__ */ r("span", { children: i.label })
1569
+ children: /* @__PURE__ */ i("span", { children: r.label })
1358
1570
  },
1359
- i.key
1571
+ r.key
1360
1572
  )) });
1361
1573
  }
1362
- function Pt({
1574
+ function tn({
1363
1575
  feedback: e,
1364
1576
  selectedFeedback: t,
1365
1577
  onSelect: n
1366
1578
  }) {
1367
- return /* @__PURE__ */ r(re, { children: e.map((i) => /* @__PURE__ */ r(
1368
- Ut,
1579
+ return /* @__PURE__ */ i(ae, { children: e.map((r) => /* @__PURE__ */ i(
1580
+ nn,
1369
1581
  {
1370
- feedback: i,
1371
- selected: (t == null ? void 0 : t.id) === i.id,
1582
+ feedback: r,
1583
+ selected: (t == null ? void 0 : t.id) === r.id,
1372
1584
  onSelect: n
1373
1585
  },
1374
- i.id
1586
+ r.id
1375
1587
  )) });
1376
1588
  }
1377
- function Ut({
1589
+ function nn({
1378
1590
  feedback: e,
1379
1591
  selected: t,
1380
1592
  onSelect: n
1381
1593
  }) {
1382
- const i = We(null);
1383
- return lt(() => {
1594
+ const r = re(null);
1595
+ return gt(() => {
1384
1596
  let s = 0;
1385
1597
  const c = () => {
1386
1598
  s = 0;
1387
- const f = i.current, p = z(e.selector), d = p == null ? void 0 : p.getBoundingClientRect();
1388
- !f || !d || (f.style.top = `${d.top}px`, f.style.left = `${d.right}px`, f.hidden = d.bottom < 0 || d.top > window.innerHeight);
1389
- }, g = () => {
1599
+ const w = r.current, p = z(e.selector), b = p == null ? void 0 : p.getBoundingClientRect();
1600
+ !w || !b || (w.style.top = `${b.top}px`, w.style.left = `${b.right}px`, w.hidden = b.bottom < 0 || b.top > window.innerHeight);
1601
+ }, h = () => {
1390
1602
  s || (s = window.requestAnimationFrame(c));
1391
1603
  };
1392
- return c(), window.addEventListener("scroll", g, !0), window.addEventListener("resize", g), () => {
1393
- s && window.cancelAnimationFrame(s), window.removeEventListener("scroll", g, !0), window.removeEventListener("resize", g);
1604
+ return c(), window.addEventListener("scroll", h, !0), window.addEventListener("resize", h), () => {
1605
+ s && window.cancelAnimationFrame(s), window.removeEventListener("scroll", h, !0), window.removeEventListener("resize", h);
1394
1606
  };
1395
- }, [e.selector]), /* @__PURE__ */ r(
1607
+ }, [e.selector]), /* @__PURE__ */ i(
1396
1608
  "button",
1397
1609
  {
1398
- ref: i,
1610
+ ref: r,
1399
1611
  type: "button",
1400
1612
  className: t ? "review-lens-marker review-lens-marker--selected" : "review-lens-marker",
1401
1613
  onClick: () => n(e),
@@ -1403,23 +1615,23 @@ function Ut({
1403
1615
  }
1404
1616
  );
1405
1617
  }
1406
- function Wt({
1618
+ function rn({
1407
1619
  feedback: e,
1408
1620
  selectedFeedback: t,
1409
1621
  onSelect: n
1410
1622
  }) {
1411
- const i = e.map((s) => {
1412
- const c = z(s.selector), g = c == null ? void 0 : c.getBoundingClientRect(), f = Math.max(
1623
+ const r = e.map((s) => {
1624
+ const c = z(s.selector), h = c == null ? void 0 : c.getBoundingClientRect(), w = Math.max(
1413
1625
  document.documentElement.scrollHeight,
1414
1626
  document.body.scrollHeight,
1415
1627
  window.innerHeight
1416
1628
  );
1417
- return !g || f <= 0 ? null : {
1629
+ return !h || w <= 0 ? null : {
1418
1630
  item: s,
1419
- top: Math.min(100, Math.max(0, (g.top + window.scrollY) / f * 100))
1631
+ top: Math.min(100, Math.max(0, (h.top + window.scrollY) / w * 100))
1420
1632
  };
1421
1633
  }).filter((s) => s !== null);
1422
- return i.length === 0 ? null : /* @__PURE__ */ r("div", { className: "review-lens-minimap", "data-review-lens-ui": !0, "aria-label": "Feedback map", children: i.map((s) => /* @__PURE__ */ r(
1634
+ return r.length === 0 ? null : /* @__PURE__ */ i("div", { className: "review-lens-minimap", "data-review-lens-ui": !0, "aria-label": "Feedback map", children: r.map((s) => /* @__PURE__ */ i(
1423
1635
  "button",
1424
1636
  {
1425
1637
  type: "button",
@@ -1431,7 +1643,7 @@ function Wt({
1431
1643
  s.item.id
1432
1644
  )) });
1433
1645
  }
1434
- function Dt({ target: e }) {
1646
+ function an({ target: e }) {
1435
1647
  const t = [
1436
1648
  ["Selector", e.selector],
1437
1649
  ["Size", `${e.cssSnapshot.width} x ${e.cssSnapshot.height}`],
@@ -1444,16 +1656,16 @@ function Dt({ target: e }) {
1444
1656
  ["Color", e.cssSnapshot.color],
1445
1657
  ["Background", e.cssSnapshot.backgroundColor]
1446
1658
  ];
1447
- return /* @__PURE__ */ r("dl", { className: "review-lens-metrics", children: t.map(([n, i]) => /* @__PURE__ */ o("div", { children: [
1448
- /* @__PURE__ */ r("dt", { children: n }),
1449
- /* @__PURE__ */ r("dd", { children: i })
1659
+ return /* @__PURE__ */ i("dl", { className: "review-lens-metrics", children: t.map(([n, r]) => /* @__PURE__ */ o("div", { children: [
1660
+ /* @__PURE__ */ i("dt", { children: n }),
1661
+ /* @__PURE__ */ i("dd", { children: r })
1450
1662
  ] }, n)) });
1451
1663
  }
1452
- function _e({ title: e, items: t }) {
1664
+ function De({ title: e, items: t }) {
1453
1665
  return /* @__PURE__ */ o("section", { className: "review-lens-insights", children: [
1454
- /* @__PURE__ */ r("h3", { children: e }),
1455
- t.length === 0 ? /* @__PURE__ */ r("p", { children: "No issues detected." }) : null,
1456
- t.length > 0 ? /* @__PURE__ */ r("ul", { children: t.map((n) => /* @__PURE__ */ r("li", { children: n }, n)) }) : null
1666
+ /* @__PURE__ */ i("h3", { children: e }),
1667
+ t.length === 0 ? /* @__PURE__ */ i("p", { children: "No issues detected." }) : null,
1668
+ t.length > 0 ? /* @__PURE__ */ i("ul", { children: t.map((n) => /* @__PURE__ */ i("li", { children: n }, n)) }) : null
1457
1669
  ] });
1458
1670
  }
1459
1671
  function z(e) {
@@ -1463,127 +1675,127 @@ function z(e) {
1463
1675
  return null;
1464
1676
  }
1465
1677
  }
1466
- function Ke(e) {
1678
+ function Qe(e) {
1467
1679
  const t = z(e.selector);
1468
1680
  if (!t)
1469
1681
  return { label: "Target missing", level: "warning" };
1470
- const n = X(t);
1682
+ const n = Q(t);
1471
1683
  return n.fingerprint.tagName !== e.elementFingerprint.tagName ? { label: "Element changed", level: "warning" } : Math.abs(n.fingerprint.width - e.elementFingerprint.width) > 2 || Math.abs(n.fingerprint.height - e.elementFingerprint.height) > 2 ? { label: "Size changed", level: "warning" } : n.cssSnapshot.fontSize !== e.createdCssSnapshot.fontSize || n.cssSnapshot.color !== e.createdCssSnapshot.color || n.cssSnapshot.padding !== e.createdCssSnapshot.padding ? { label: "Style changed", level: "warning" } : { label: "Target unchanged", level: "ok" };
1472
1684
  }
1473
- function zt(e) {
1685
+ function sn(e) {
1474
1686
  var p;
1475
1687
  const t = z(e.selector);
1476
1688
  if (!t)
1477
1689
  return ["Selected element is no longer available."];
1478
- const n = [], i = t.tagName.toLowerCase(), s = t.getAttribute("role"), c = ["button", "a", "input", "select", "textarea"].includes(i) || s === "button" || s === "link", g = t.getAttribute("aria-label") || t.getAttribute("title") || ((p = t.textContent) == null ? void 0 : p.trim());
1479
- c && !g && n.push("Interactive element has no accessible name."), c && (e.rect.width < 44 || e.rect.height < 44) && n.push("Tap target is smaller than 44 x 44."), i === "img" && !t.getAttribute("alt") && n.push("Image is missing alt text.");
1480
- const f = /^h[1-6]$/.test(i) ? Number(i.slice(1)) : 0;
1481
- return f > 1 && !document.querySelector(`h${f - 1}`) && n.push("Heading may skip the previous level."), Vt(e.cssSnapshot.color, e.cssSnapshot.backgroundColor) && n.push("Text contrast may be low."), n;
1690
+ const n = [], r = t.tagName.toLowerCase(), s = t.getAttribute("role"), c = ["button", "a", "input", "select", "textarea"].includes(r) || s === "button" || s === "link", h = t.getAttribute("aria-label") || t.getAttribute("title") || ((p = t.textContent) == null ? void 0 : p.trim());
1691
+ c && !h && n.push("Interactive element has no accessible name."), c && (e.rect.width < 44 || e.rect.height < 44) && n.push("Tap target is smaller than 44 x 44."), r === "img" && !t.getAttribute("alt") && n.push("Image is missing alt text.");
1692
+ const w = /^h[1-6]$/.test(r) ? Number(r.slice(1)) : 0;
1693
+ return w > 1 && !document.querySelector(`h${w - 1}`) && n.push("Heading may skip the previous level."), un(e.cssSnapshot.color, e.cssSnapshot.backgroundColor) && n.push("Text contrast may be low."), n;
1482
1694
  }
1483
- function Ht(e, t = {}) {
1695
+ function on(e, t = {}) {
1484
1696
  const n = [];
1485
1697
  return U("Padding", e.padding, t.spacing, n, { allowComposite: !0 }), U("Margin", e.margin, t.spacing, n, { allowComposite: !0 }), U("Font size", e.fontSize, t.fontSize, n), U("Line height", e.lineHeight, t.lineHeight, n), U("Text color", e.color, t.color, n), U("Background", e.backgroundColor, t.color, n), U("Radius", e.borderRadius, t.radius, n, { allowComposite: !0 }), n;
1486
1698
  }
1487
- function U(e, t, n, i, s = {}) {
1488
- !n || n.length === 0 || !t || jt(t, n, s) || i.push(`${e} ${t} is outside configured tokens.`);
1699
+ function U(e, t, n, r, s = {}) {
1700
+ !n || n.length === 0 || !t || ln(t, n, s) || r.push(`${e} ${t} is outside configured tokens.`);
1489
1701
  }
1490
- function jt(e, t, n = {}) {
1702
+ function ln(e, t, n = {}) {
1491
1703
  if (t.includes(e))
1492
1704
  return !0;
1493
1705
  if (!n.allowComposite)
1494
1706
  return !1;
1495
- const i = e.trim().split(/\s+/);
1496
- return i.length > 1 && i.every((s) => t.includes(s));
1707
+ const r = e.trim().split(/\s+/);
1708
+ return r.length > 1 && r.every((s) => t.includes(s));
1497
1709
  }
1498
- function Ot(e) {
1499
- const t = e.id ? `#${e.id}` : "", n = e.className ? `.${e.className.split(/\s+/).filter(Boolean).slice(0, 2).join(".")}` : "", i = e.ariaLabel ? `[aria-label="${e.ariaLabel}"]` : "";
1500
- return `${e.tagName}${t}${n}${i}` || e.tagName;
1710
+ function dn(e) {
1711
+ const t = e.id ? `#${e.id}` : "", n = e.className ? `.${e.className.split(/\s+/).filter(Boolean).slice(0, 2).join(".")}` : "", r = e.ariaLabel ? `[aria-label="${e.ariaLabel}"]` : "";
1712
+ return `${e.tagName}${t}${n}${r}` || e.tagName;
1501
1713
  }
1502
- function Kt(e, t) {
1503
- const n = [], i = (Math.max(e.left, t.left) + Math.min(e.right, t.right)) / 2, s = (Math.max(e.top, t.top) + Math.min(e.bottom, t.bottom)) / 2;
1714
+ function cn(e, t) {
1715
+ const n = [], r = (Math.max(e.left, t.left) + Math.min(e.right, t.right)) / 2, s = (Math.max(e.top, t.top) + Math.min(e.bottom, t.bottom)) / 2;
1504
1716
  if (e.right <= t.left || t.right <= e.left) {
1505
- const c = e.right <= t.left ? e.right : t.right, g = e.right <= t.left ? t.left : e.left;
1717
+ const c = e.right <= t.left ? e.right : t.right, h = e.right <= t.left ? t.left : e.left;
1506
1718
  n.push({
1507
1719
  key: "horizontal",
1508
1720
  axis: "horizontal",
1509
- top: Pe(s, 0, window.innerHeight),
1721
+ top: ze(s, 0, window.innerHeight),
1510
1722
  left: c,
1511
- width: Math.max(g - c, 1),
1723
+ width: Math.max(h - c, 1),
1512
1724
  height: 1,
1513
- label: `${Math.round(g - c)}px`
1725
+ label: `${Math.round(h - c)}px`
1514
1726
  });
1515
1727
  }
1516
1728
  if (e.bottom <= t.top || t.bottom <= e.top) {
1517
- const c = e.bottom <= t.top ? e.bottom : t.bottom, g = e.bottom <= t.top ? t.top : e.top;
1729
+ const c = e.bottom <= t.top ? e.bottom : t.bottom, h = e.bottom <= t.top ? t.top : e.top;
1518
1730
  n.push({
1519
1731
  key: "vertical",
1520
1732
  axis: "vertical",
1521
1733
  top: c,
1522
- left: Pe(i, 0, window.innerWidth),
1734
+ left: ze(r, 0, window.innerWidth),
1523
1735
  width: 1,
1524
- height: Math.max(g - c, 1),
1525
- label: `${Math.round(g - c)}px`
1736
+ height: Math.max(h - c, 1),
1737
+ label: `${Math.round(h - c)}px`
1526
1738
  });
1527
1739
  }
1528
1740
  return n;
1529
1741
  }
1530
- function Pe(e, t, n) {
1742
+ function ze(e, t, n) {
1531
1743
  return Math.min(Math.max(e, t), n);
1532
1744
  }
1533
- function Y(e, t) {
1745
+ function X(e, t) {
1534
1746
  const n = /* @__PURE__ */ new Map();
1535
- for (const i of e) {
1536
- const s = t(i);
1747
+ for (const r of e) {
1748
+ const s = t(r);
1537
1749
  n.set(s, (n.get(s) ?? 0) + 1);
1538
1750
  }
1539
- return Array.from(n.entries()).sort((i, s) => s[1] - i[1] || i[0].localeCompare(s[0]));
1751
+ return Array.from(n.entries()).sort((r, s) => s[1] - r[1] || r[0].localeCompare(s[0]));
1540
1752
  }
1541
- function Jt(e) {
1753
+ function hn(e) {
1542
1754
  return e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement || e instanceof HTMLSelectElement || e instanceof HTMLElement && e.isContentEditable;
1543
1755
  }
1544
- function Vt(e, t) {
1545
- const n = Ue(e), i = Ue(t);
1546
- return !n || !i || i.alpha === 0 ? !1 : qt(n, i) < 4.5;
1756
+ function un(e, t) {
1757
+ const n = He(e), r = He(t);
1758
+ return !n || !r || r.alpha === 0 ? !1 : mn(n, r) < 4.5;
1547
1759
  }
1548
- function Ue(e) {
1760
+ function He(e) {
1549
1761
  const t = e.match(/rgba?\(([^)]+)\)/);
1550
1762
  if (!t)
1551
1763
  return null;
1552
- const [n, i, s, c = "1"] = t[1].split(",").map((g) => g.trim());
1764
+ const [n, r, s, c = "1"] = t[1].split(",").map((h) => h.trim());
1553
1765
  return {
1554
1766
  red: Number(n),
1555
- green: Number(i),
1767
+ green: Number(r),
1556
1768
  blue: Number(s),
1557
1769
  alpha: Number(c)
1558
1770
  };
1559
1771
  }
1560
- function qt(e, t) {
1561
- const n = Math.max(ne(e), ne(t)), i = Math.min(ne(e), ne(t));
1562
- return (n + 0.05) / (i + 0.05);
1772
+ function mn(e, t) {
1773
+ const n = Math.max(ie(e), ie(t)), r = Math.min(ie(e), ie(t));
1774
+ return (n + 0.05) / (r + 0.05);
1563
1775
  }
1564
- function ne(e) {
1776
+ function ie(e) {
1565
1777
  const t = [e.red, e.green, e.blue].map((n) => {
1566
- const i = n / 255;
1567
- return i <= 0.03928 ? i / 12.92 : ((i + 0.055) / 1.055) ** 2.4;
1778
+ const r = n / 255;
1779
+ return r <= 0.03928 ? r / 12.92 : ((r + 0.055) / 1.055) ** 2.4;
1568
1780
  });
1569
1781
  return t[0] * 0.2126 + t[1] * 0.7152 + t[2] * 0.0722;
1570
1782
  }
1571
- function Gt(e) {
1783
+ function pn(e) {
1572
1784
  const t = {
1573
- top: L(e.cssSnapshot.marginTop),
1574
- right: L(e.cssSnapshot.marginRight),
1575
- bottom: L(e.cssSnapshot.marginBottom),
1576
- left: L(e.cssSnapshot.marginLeft)
1785
+ top: I(e.cssSnapshot.marginTop),
1786
+ right: I(e.cssSnapshot.marginRight),
1787
+ bottom: I(e.cssSnapshot.marginBottom),
1788
+ left: I(e.cssSnapshot.marginLeft)
1577
1789
  }, n = {
1578
- top: L(e.cssSnapshot.borderTopWidth),
1579
- right: L(e.cssSnapshot.borderRightWidth),
1580
- bottom: L(e.cssSnapshot.borderBottomWidth),
1581
- left: L(e.cssSnapshot.borderLeftWidth)
1582
- }, i = {
1583
- top: L(e.cssSnapshot.paddingTop),
1584
- right: L(e.cssSnapshot.paddingRight),
1585
- bottom: L(e.cssSnapshot.paddingBottom),
1586
- left: L(e.cssSnapshot.paddingLeft)
1790
+ top: I(e.cssSnapshot.borderTopWidth),
1791
+ right: I(e.cssSnapshot.borderRightWidth),
1792
+ bottom: I(e.cssSnapshot.borderBottomWidth),
1793
+ left: I(e.cssSnapshot.borderLeftWidth)
1794
+ }, r = {
1795
+ top: I(e.cssSnapshot.paddingTop),
1796
+ right: I(e.cssSnapshot.paddingRight),
1797
+ bottom: I(e.cssSnapshot.paddingBottom),
1798
+ left: I(e.cssSnapshot.paddingLeft)
1587
1799
  }, s = {
1588
1800
  top: e.rect.top,
1589
1801
  left: e.rect.left,
@@ -1594,33 +1806,34 @@ function Gt(e) {
1594
1806
  left: s.left - t.left,
1595
1807
  width: s.width + t.left + t.right,
1596
1808
  height: s.height + t.top + t.bottom
1597
- }, g = {
1809
+ }, h = {
1598
1810
  top: s.top + n.top,
1599
1811
  left: s.left + n.left,
1600
1812
  width: Math.max(s.width - n.left - n.right, 0),
1601
1813
  height: Math.max(s.height - n.top - n.bottom, 0)
1602
- }, f = {
1603
- top: g.top + i.top,
1604
- left: g.left + i.left,
1605
- width: Math.max(g.width - i.left - i.right, 0),
1606
- height: Math.max(g.height - i.top - i.bottom, 0)
1814
+ }, w = {
1815
+ top: h.top + r.top,
1816
+ left: h.left + r.left,
1817
+ width: Math.max(h.width - r.left - r.right, 0),
1818
+ height: Math.max(h.height - r.top - r.bottom, 0)
1607
1819
  };
1608
1820
  return {
1609
1821
  margin: c,
1610
1822
  border: s,
1611
- padding: g,
1612
- content: f
1823
+ padding: h,
1824
+ content: w
1613
1825
  };
1614
1826
  }
1615
- function L(e) {
1827
+ function I(e) {
1616
1828
  const t = Number.parseFloat(e);
1617
1829
  return Number.isFinite(t) ? t : 0;
1618
1830
  }
1619
1831
  export {
1620
- Zt as ReviewLensOverlay,
1621
- Qt as ReviewLensProvider,
1622
- X as buildElementTarget,
1623
- ht as createGoogleSheetsAdapter,
1624
- Ct as normalizeReviewUrl,
1625
- Nt as useReviewLens
1832
+ Ot as ReviewLensLogo,
1833
+ bn as ReviewLensOverlay,
1834
+ wn as ReviewLensProvider,
1835
+ Q as buildElementTarget,
1836
+ vt as createGoogleSheetsAdapter,
1837
+ $t as normalizeReviewUrl,
1838
+ Tt as useReviewLens
1626
1839
  };