review-lens-react 0.2.0 → 0.2.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.
@@ -5,7 +5,7 @@ const ct = [
5
5
  "https://www.googleapis.com/auth/userinfo.email"
6
6
  ].join(" "), dt = "https://www.googleapis.com/oauth2/v3/userinfo";
7
7
  function ht(e) {
8
- const t = e.feedbackSheetName ?? "Feedback", n = e.messagesSheetName ?? "Messages", a = e.usersSheetName ?? "Users";
8
+ const t = e.feedbackSheetName ?? "Feedback", n = e.messagesSheetName ?? "Messages", r = e.usersSheetName ?? "Users";
9
9
  let s, c;
10
10
  async function g() {
11
11
  return s ?? (s = St(e.googleClientId)), s;
@@ -46,7 +46,7 @@ function ht(e) {
46
46
  return { email: c };
47
47
  },
48
48
  async getPermissions(d) {
49
- const [{ email: v }, p] = await Promise.all([this.getCurrentUser(), u(a)]), b = ce(p), E = v.toLowerCase(), x = b.find(
49
+ const [{ email: v }, p] = await Promise.all([this.getCurrentUser(), u(r)]), b = ce(p), E = v.toLowerCase(), x = b.find(
50
50
  (A) => {
51
51
  var h;
52
52
  return ((h = A.email) == null ? void 0 : h.toLowerCase()) === E && A.active !== "false" && (!A.projectKey || A.projectKey === d);
@@ -180,10 +180,10 @@ function pt(e) {
180
180
  }
181
181
  function ce(e) {
182
182
  const [t, ...n] = e;
183
- return t ? n.map((a) => De(t, a)) : [];
183
+ return t ? n.map((r) => De(t, r)) : [];
184
184
  }
185
185
  function De(e, t) {
186
- return Object.fromEntries(e.map((n, a) => [n, t[a] ?? ""]));
186
+ return Object.fromEntries(e.map((n, r) => [n, t[r] ?? ""]));
187
187
  }
188
188
  function Te(e) {
189
189
  return e.id ? {
@@ -283,15 +283,15 @@ function wt(e) {
283
283
  function yt(e) {
284
284
  let t = e, n = "";
285
285
  for (; t > 0; ) {
286
- const a = (t - 1) % 26;
287
- n = String.fromCharCode(65 + a) + n, t = Math.floor((t - a) / 26);
286
+ const r = (t - 1) % 26;
287
+ n = String.fromCharCode(65 + r) + n, t = Math.floor((t - r) / 26);
288
288
  }
289
289
  return n;
290
290
  }
291
291
  async function St(e) {
292
292
  return await kt(), new Promise((t, n) => {
293
293
  var s;
294
- const a = (s = window.google) == null ? void 0 : s.accounts.oauth2.initTokenClient({
294
+ const r = (s = window.google) == null ? void 0 : s.accounts.oauth2.initTokenClient({
295
295
  client_id: e,
296
296
  scope: ct,
297
297
  callback: (c) => {
@@ -302,17 +302,17 @@ async function St(e) {
302
302
  t(c.access_token);
303
303
  }
304
304
  });
305
- a == null || a.requestAccessToken({ prompt: "" });
305
+ r == null || r.requestAccessToken({ prompt: "" });
306
306
  });
307
307
  }
308
308
  function kt() {
309
309
  var e;
310
310
  return (e = window.google) != null && e.accounts.oauth2 ? Promise.resolve() : new Promise((t, n) => {
311
- const a = document.querySelector(
311
+ const r = document.querySelector(
312
312
  'script[src="https://accounts.google.com/gsi/client"]'
313
313
  );
314
- if (a) {
315
- a.addEventListener("load", () => t(), { once: !0 }), a.addEventListener("error", () => n(new Error("Google Identity failed to load")), {
314
+ if (r) {
315
+ r.addEventListener("load", () => t(), { once: !0 }), r.addEventListener("error", () => n(new Error("Google Identity failed to load")), {
316
316
  once: !0
317
317
  });
318
318
  return;
@@ -325,12 +325,12 @@ function Ct(e) {
325
325
  return new URL(e, window.location.href).pathname.replace(/\/+$/, "") || "/";
326
326
  }
327
327
  const ze = st(null);
328
- function Xt({ config: e, children: t }) {
328
+ function Qt({ config: e, children: t }) {
329
329
  const n = re(() => e.adapter ? e.adapter : ht({
330
330
  googleClientId: Be(e.googleClientId, "googleClientId"),
331
331
  spreadsheetId: Be(e.spreadsheetId, "spreadsheetId"),
332
332
  feedbackSheetName: e.sheetName ?? "Feedback"
333
- }), [e.adapter, e.googleClientId, e.sheetName, e.spreadsheetId]), a = e.currentUrl ?? window.location.href, s = (e.normalizeUrl ?? Ct)(a), [c, g] = k(), [f, u] = k([]), [d, v] = k([]), p = W(async () => {
333
+ }), [e.adapter, e.googleClientId, e.sheetName, e.spreadsheetId]), r = e.currentUrl ?? window.location.href, s = (e.normalizeUrl ?? Ct)(r), [c, g] = k(), [f, u] = k([]), [d, v] = k([]), p = W(async () => {
334
334
  const y = await n.listFeedback({
335
335
  projectKey: e.projectKey,
336
336
  contentId: e.contentId,
@@ -454,15 +454,15 @@ function At(e) {
454
454
  const t = [];
455
455
  let n = e;
456
456
  for (; n && n.nodeType === Node.ELEMENT_NODE && n !== document.body; ) {
457
- const a = n.parentElement, s = n.tagName.toLowerCase();
458
- if (!a) {
457
+ const r = n.parentElement, s = n.tagName.toLowerCase();
458
+ if (!r) {
459
459
  t.unshift(s);
460
460
  break;
461
461
  }
462
- const c = n.tagName, g = Array.from(a.children).filter(
462
+ const c = n.tagName, g = Array.from(r.children).filter(
463
463
  (u) => u.tagName === c
464
464
  ), f = g.indexOf(n) + 1;
465
- t.unshift(g.length > 1 ? `${s}:nth-of-type(${f})` : s), n = a;
465
+ t.unshift(g.length > 1 ? `${s}:nth-of-type(${f})` : s), n = r;
466
466
  }
467
467
  return t.join(" > ");
468
468
  }
@@ -516,8 +516,8 @@ function Ft(e, t) {
516
516
  height: Math.round(t.height)
517
517
  };
518
518
  }
519
- function de(e, t, n, a) {
520
- return e === t && t === n && n === a ? e : `${e} ${t} ${n} ${a}`;
519
+ function de(e, t, n, r) {
520
+ return e === t && t === n && n === r ? e : `${e} ${t} ${n} ${r}`;
521
521
  }
522
522
  function $e(e) {
523
523
  return typeof CSS < "u" && typeof CSS.escape == "function" ? CSS.escape(e) : e.replace(/["\\]/g, "\\$&");
@@ -551,11 +551,11 @@ const Mt = [
551
551
  accessibility: "Accessibility",
552
552
  responsive: "Responsive"
553
553
  };
554
- function Qt({
554
+ function Zt({
555
555
  open: e,
556
556
  onOpenChange: t,
557
557
  placement: n = "top-right",
558
- showResolved: a = !1,
558
+ showResolved: r = !1,
559
559
  syncSelectionToUrl: s = !1,
560
560
  responsivePresets: c = Mt
561
561
  }) {
@@ -572,81 +572,81 @@ function Qt({
572
572
  listMessages: x,
573
573
  createMessage: A,
574
574
  uploadAttachment: h
575
- } = Nt(), [R, y] = k(), [w, C] = k(), [B, D] = k(""), [ue, Je] = k("medium"), [pe, qe] = k("visual"), [me, ge] = k(""), [fe, Ve] = k(
575
+ } = Nt(), [R, y] = k(), [w, C] = k(), [B, D] = k(""), [ue, Je] = k("medium"), [pe, Ve] = k("visual"), [me, ge] = k(""), [fe, qe] = k(
576
576
  ((Fe = c[0]) == null ? void 0 : Fe.value) ?? "desktop"
577
- ), [S, H] = k(), [M, $] = k("review"), [Ge, be] = k(!1), [j, ve] = k("all"), [O, we] = k("all"), [K, ye] = k("all"), [J, Se] = k("all"), [q, ke] = k("all"), [Ye, Xe] = k(!1), [Qe, Ce] = k({}), [se, oe] = k(""), ee = We(null), I = !!u, T = p.includes("create"), Ne = p.includes("reply"), xe = p.includes("update"), Ze = p.includes("assign"), P = R ?? w, et = !!w, tt = !!(f.captureScreenshot && (f.uploadAttachment || g.uploadAttachment)), nt = re(() => {
578
- const r = d.map((m) => m.assigneeEmail).filter((m) => !!m);
579
- return u != null && u.email && r.push(u.email), Array.from(new Set(r)).sort((m, l) => m.localeCompare(l));
577
+ ), [S, H] = k(), [M, $] = k("review"), [Ge, be] = k(!1), [j, ve] = k("all"), [O, we] = k("all"), [K, ye] = k("all"), [J, Se] = k("all"), [V, ke] = k("all"), [Ye, Xe] = k(!1), [Qe, Ce] = k({}), [se, oe] = k(""), ee = We(null), I = !!u, T = p.includes("create"), Ne = p.includes("reply"), xe = p.includes("update"), Ze = p.includes("assign"), P = R ?? w, et = !!w, tt = !!(f.captureScreenshot && (f.uploadAttachment || g.uploadAttachment)), nt = re(() => {
578
+ const a = d.map((m) => m.assigneeEmail).filter((m) => !!m);
579
+ return u != null && u.email && a.push(u.email), Array.from(new Set(a)).sort((m, l) => m.localeCompare(l));
580
580
  }, [u == null ? void 0 : u.email, d]), L = re(
581
- () => d.filter((r) => a || r.status !== "resolved").filter((r) => j === "all" || r.status === j).filter((r) => O === "all" || r.severity === O).filter((r) => K === "all" || r.category === K).filter((r) => J === "all" || r.assigneeEmail === J).filter((r) => q === "all" || r.viewportPreset === q),
581
+ () => d.filter((a) => r || 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),
582
582
  [
583
583
  J,
584
584
  K,
585
585
  d,
586
586
  O,
587
- a,
587
+ r,
588
588
  j,
589
- q
589
+ V
590
590
  ]
591
591
  ), it = [
592
592
  j,
593
593
  O,
594
594
  K,
595
595
  J,
596
- q
597
- ].filter((r) => r !== "all").length;
596
+ V
597
+ ].filter((a) => a !== "all").length;
598
598
  _(() => {
599
599
  e || (y(void 0), C(void 0), D(""), oe(""), $("review"));
600
600
  }, [e]), _(() => {
601
601
  I || (y(void 0), C(void 0));
602
602
  }, [I]), _(() => {
603
603
  !w || M !== "review" || window.requestAnimationFrame(() => {
604
- var r, m, l;
605
- (m = (r = ee.current) == null ? void 0 : r.scrollIntoView) == null || m.call(r, { block: "nearest" }), (l = ee.current) == null || l.focus();
604
+ var a, m, l;
605
+ (m = (a = ee.current) == null ? void 0 : a.scrollIntoView) == null || m.call(a, { block: "nearest" }), (l = ee.current) == null || l.focus();
606
606
  });
607
607
  }, [w, M]), _(() => {
608
608
  if (!S)
609
609
  return;
610
- let r = !0;
610
+ let a = !0;
611
611
  return x(S.id).then((m) => {
612
- r && Ce((l) => ({ ...l, [S.id]: m }));
612
+ a && Ce((l) => ({ ...l, [S.id]: m }));
613
613
  }), () => {
614
- r = !1;
614
+ a = !1;
615
615
  };
616
616
  }, [x, S]), _(() => {
617
617
  if (!e || !s || S || d.length === 0)
618
618
  return;
619
- const r = new URL(window.location.href).searchParams.get("reviewLensFeedback"), m = d.find((l) => l.id === r);
620
- m && V(m, { syncUrl: !1 });
619
+ const a = new URL(window.location.href).searchParams.get("reviewLensFeedback"), m = d.find((l) => l.id === a);
620
+ m && q(m, { syncUrl: !1 });
621
621
  }, [d, e, S, s]), _(() => {
622
622
  if (!e)
623
623
  return;
624
- function r(l) {
624
+ function a(l) {
625
625
  var N;
626
626
  if (l.key === "Shift" && be(!0), l.key === "Escape") {
627
627
  l.preventDefault(), t == null || t(!1);
628
628
  return;
629
629
  }
630
- Kt(l.target) || ((l.key === "n" || l.key === "ArrowDown") && (l.preventDefault(), Ee(1)), (l.key === "p" || l.key === "ArrowUp") && (l.preventDefault(), Ee(-1)), l.key === "c" && (l.preventDefault(), $("review"), (N = ee.current) == null || N.focus()), l.key === "f" && S && xe && (l.preventDefault(), Le(S)));
630
+ Jt(l.target) || ((l.key === "n" || l.key === "ArrowDown") && (l.preventDefault(), Ee(1)), (l.key === "p" || l.key === "ArrowUp") && (l.preventDefault(), Ee(-1)), l.key === "c" && (l.preventDefault(), $("review"), (N = ee.current) == null || N.focus()), l.key === "f" && S && xe && (l.preventDefault(), Le(S)));
631
631
  }
632
632
  function m(l) {
633
633
  l.key === "Shift" && be(!1);
634
634
  }
635
- return window.addEventListener("keydown", r), window.addEventListener("keyup", m), () => {
636
- window.removeEventListener("keydown", r), window.removeEventListener("keyup", m);
635
+ return window.addEventListener("keydown", a), window.addEventListener("keyup", m), () => {
636
+ window.removeEventListener("keydown", a), window.removeEventListener("keyup", m);
637
637
  };
638
638
  });
639
- const le = W((r) => {
640
- const m = r.target instanceof Element ? r.target : null;
639
+ const le = W((a) => {
640
+ const m = a.target instanceof Element ? a.target : null;
641
641
  if (m)
642
642
  return m.closest("[data-review-lens-ui]") ? null : m;
643
- const l = document.elementFromPoint(r.clientX, r.clientY);
643
+ const l = document.elementFromPoint(a.clientX, a.clientY);
644
644
  return !l || l.closest("[data-review-lens-ui]") ? null : l;
645
645
  }, []);
646
646
  if (_(() => {
647
647
  if (!e || !I)
648
648
  return;
649
- function r(l) {
649
+ function a(l) {
650
650
  const N = le(l);
651
651
  y(N ? X(N) : void 0);
652
652
  }
@@ -654,18 +654,18 @@ function Qt({
654
654
  const N = le(l);
655
655
  N && (l.preventDefault(), l.stopPropagation(), C(X(N)), $("review"));
656
656
  }
657
- return window.addEventListener("mousemove", r, !0), window.addEventListener("click", m, !0), () => {
658
- window.removeEventListener("mousemove", r, !0), window.removeEventListener("click", m, !0);
657
+ return window.addEventListener("mousemove", a, !0), window.addEventListener("click", m, !0), () => {
658
+ window.removeEventListener("mousemove", a, !0), window.removeEventListener("click", m, !0);
659
659
  };
660
660
  }, [I, le, e]), !e)
661
661
  return null;
662
- function V(r, m = { syncUrl: !0 }) {
662
+ function q(a, m = { syncUrl: !0 }) {
663
663
  var N;
664
- if (H(r), C(void 0), $("feedback"), s && m.syncUrl !== !1) {
664
+ if (H(a), C(void 0), $("feedback"), s && m.syncUrl !== !1) {
665
665
  const te = new URL(window.location.href);
666
- te.searchParams.set("reviewLensFeedback", r.id), window.history.replaceState({}, "", te);
666
+ te.searchParams.set("reviewLensFeedback", a.id), window.history.replaceState({}, "", te);
667
667
  }
668
- const l = z(r.selector);
668
+ const l = z(a.selector);
669
669
  if (!l) {
670
670
  y(void 0);
671
671
  return;
@@ -674,16 +674,16 @@ function Qt({
674
674
  y(X(l));
675
675
  });
676
676
  }
677
- function Ee(r) {
677
+ function Ee(a) {
678
678
  if (L.length === 0)
679
679
  return;
680
- const m = S ? L.findIndex((N) => N.id === S.id) : -1, l = m < 0 ? r > 0 ? 0 : L.length - 1 : (m + r + L.length) % L.length;
681
- V(L[l]);
680
+ const m = S ? L.findIndex((N) => N.id === S.id) : -1, l = m < 0 ? a > 0 ? 0 : L.length - 1 : (m + a + L.length) % L.length;
681
+ q(L[l]);
682
682
  }
683
683
  async function Ae() {
684
684
  if (!w || !B.trim() || !u || !T)
685
685
  return;
686
- let r = await b({
686
+ let a = await b({
687
687
  projectKey: f.projectKey,
688
688
  contentId: f.contentId,
689
689
  normalizedPath: v,
@@ -706,29 +706,29 @@ function Qt({
706
706
  });
707
707
  if (f.captureScreenshot)
708
708
  try {
709
- const m = await f.captureScreenshot(w), l = await h(r.id, {
709
+ const m = await f.captureScreenshot(w), l = await h(a.id, {
710
710
  type: "screenshot",
711
711
  data: m,
712
712
  createdBy: u.email
713
713
  });
714
- r = await E(r.id, {
714
+ a = await E(a.id, {
715
715
  attachments: [l],
716
716
  screenshotUrl: l.url,
717
717
  screenshotThumbnailUrl: l.thumbnailUrl
718
718
  });
719
719
  } catch {
720
720
  }
721
- D(""), ge(""), C(void 0), y(void 0), $("feedback"), H(r);
721
+ D(""), ge(""), C(void 0), y(void 0), $("feedback"), H(a);
722
722
  }
723
- async function rt(r, m) {
724
- const l = (/* @__PURE__ */ new Date()).toISOString(), N = m === "resolved" ? { status: m, resolvedAt: l, resolvedBy: u == null ? void 0 : u.email } : { status: m }, te = await E(r.id, N);
723
+ async function rt(a, m) {
724
+ const l = (/* @__PURE__ */ new Date()).toISOString(), N = m === "resolved" ? { status: m, resolvedAt: l, resolvedBy: u == null ? void 0 : u.email } : { status: m }, te = await E(a.id, N);
725
725
  H(te);
726
726
  }
727
- async function Le(r) {
728
- const m = z(r.selector);
727
+ async function Le(a) {
728
+ const m = z(a.selector);
729
729
  if (!m || !u)
730
730
  return;
731
- const l = X(m), N = await E(r.id, {
731
+ const l = X(m), N = await E(a.id, {
732
732
  status: "fixed",
733
733
  fixedCssSnapshot: l.cssSnapshot,
734
734
  fixedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -736,17 +736,17 @@ function Qt({
736
736
  });
737
737
  H(N);
738
738
  }
739
- async function at(r) {
739
+ async function at(a) {
740
740
  if (!se.trim() || !u || !Ne)
741
741
  return;
742
742
  const m = await A({
743
- feedbackId: r.id,
743
+ feedbackId: a.id,
744
744
  body: se.trim(),
745
745
  authorEmail: u.email
746
746
  });
747
747
  Ce((l) => ({
748
748
  ...l,
749
- [r.id]: [...l[r.id] ?? [], m]
749
+ [a.id]: [...l[a.id] ?? [], m]
750
750
  })), oe("");
751
751
  }
752
752
  return /* @__PURE__ */ o("div", { className: "review-lens-root", "data-review-lens-ui": !0, children: [
@@ -758,7 +758,7 @@ function Qt({
758
758
  {
759
759
  feedback: L,
760
760
  selectedFeedback: S,
761
- onSelect: V
761
+ onSelect: q
762
762
  }
763
763
  ),
764
764
  /* @__PURE__ */ i(
@@ -766,7 +766,7 @@ function Qt({
766
766
  {
767
767
  feedback: L,
768
768
  selectedFeedback: S,
769
- onSelect: V
769
+ onSelect: q
770
770
  }
771
771
  )
772
772
  ] }) : null,
@@ -834,8 +834,8 @@ function Qt({
834
834
  "form",
835
835
  {
836
836
  className: "review-lens-feedback-form",
837
- onSubmit: (r) => {
838
- r.preventDefault(), Ae();
837
+ onSubmit: (a) => {
838
+ a.preventDefault(), Ae();
839
839
  },
840
840
  children: [
841
841
  /* @__PURE__ */ i("label", { htmlFor: "review-lens-comment", children: "New feedback" }),
@@ -846,9 +846,9 @@ function Qt({
846
846
  id: "review-lens-comment",
847
847
  value: B,
848
848
  disabled: !T,
849
- onChange: (r) => D(r.target.value),
850
- onKeyDown: (r) => {
851
- r.key === "Enter" && r.metaKey && (r.preventDefault(), Ae());
849
+ onChange: (a) => D(a.target.value),
850
+ onKeyDown: (a) => {
851
+ a.key === "Enter" && a.metaKey && (a.preventDefault(), Ae());
852
852
  },
853
853
  placeholder: T ? "Describe the UX issue..." : "You do not have permission to comment."
854
854
  }
@@ -860,9 +860,9 @@ function Qt({
860
860
  "select",
861
861
  {
862
862
  value: ue,
863
- onChange: (r) => Je(r.target.value),
863
+ onChange: (a) => Je(a.target.value),
864
864
  disabled: !T,
865
- children: je.map((r) => /* @__PURE__ */ i("option", { value: r, children: Q[r] }, r))
865
+ children: je.map((a) => /* @__PURE__ */ i("option", { value: a, children: Q[a] }, a))
866
866
  }
867
867
  )
868
868
  ] }),
@@ -872,9 +872,9 @@ function Qt({
872
872
  "select",
873
873
  {
874
874
  value: pe,
875
- onChange: (r) => qe(r.target.value),
875
+ onChange: (a) => Ve(a.target.value),
876
876
  disabled: !T,
877
- children: Oe.map((r) => /* @__PURE__ */ i("option", { value: r, children: Z[r] }, r))
877
+ children: Oe.map((a) => /* @__PURE__ */ i("option", { value: a, children: Z[a] }, a))
878
878
  }
879
879
  )
880
880
  ] }),
@@ -884,7 +884,7 @@ function Qt({
884
884
  "input",
885
885
  {
886
886
  value: me,
887
- onChange: (r) => ge(r.target.value),
887
+ onChange: (a) => ge(a.target.value),
888
888
  disabled: !T,
889
889
  placeholder: "optional@email.com"
890
890
  }
@@ -896,9 +896,9 @@ function Qt({
896
896
  "select",
897
897
  {
898
898
  value: fe,
899
- onChange: (r) => Ve(r.target.value),
899
+ onChange: (a) => qe(a.target.value),
900
900
  disabled: !T,
901
- children: c.map((r) => /* @__PURE__ */ i("option", { value: r.value, children: r.label }, r.value))
901
+ children: c.map((a) => /* @__PURE__ */ i("option", { value: a.value, children: a.label }, a.value))
902
902
  }
903
903
  )
904
904
  ] })
@@ -926,7 +926,7 @@ function Qt({
926
926
  severityFilter: O,
927
927
  categoryFilter: K,
928
928
  assigneeFilter: J,
929
- viewportFilter: q,
929
+ viewportFilter: V,
930
930
  assignees: nt,
931
931
  responsivePresets: c,
932
932
  onStatusChange: ve,
@@ -934,7 +934,7 @@ function Qt({
934
934
  onCategoryChange: ye,
935
935
  onAssigneeChange: Se,
936
936
  onViewportChange: ke,
937
- onToggle: () => Xe((r) => !r),
937
+ onToggle: () => Xe((a) => !a),
938
938
  onClear: () => {
939
939
  ve("all"), we("all"), ye("all"), Se("all"), ke("all");
940
940
  }
@@ -947,14 +947,14 @@ function Qt({
947
947
  ] }),
948
948
  /* @__PURE__ */ o("div", { className: "review-lens-comments__list", children: [
949
949
  L.length === 0 ? /* @__PURE__ */ i("p", { children: "No feedback for this view." }) : null,
950
- L.map((r) => /* @__PURE__ */ i(
950
+ L.map((a) => /* @__PURE__ */ i(
951
951
  Tt,
952
952
  {
953
- item: r,
954
- selected: (S == null ? void 0 : S.id) === r.id,
955
- onSelect: V
953
+ item: a,
954
+ selected: (S == null ? void 0 : S.id) === a.id,
955
+ onSelect: q
956
956
  },
957
- r.id
957
+ a.id
958
958
  ))
959
959
  ] })
960
960
  ] }),
@@ -971,9 +971,9 @@ function Qt({
971
971
  canAssign: Ze,
972
972
  onMessageDraftChange: oe,
973
973
  onSubmitMessage: () => void at(S),
974
- onStatusChange: (r) => void rt(S, r),
975
- onAssigneeChange: (r) => void E(S.id, {
976
- assigneeEmail: r.trim() || void 0
974
+ onStatusChange: (a) => void rt(S, a),
975
+ onAssigneeChange: (a) => void E(S.id, {
976
+ assigneeEmail: a.trim() || void 0
977
977
  }).then(H),
978
978
  onMarkFixed: () => void Le(S)
979
979
  },
@@ -993,7 +993,7 @@ function It({
993
993
  open: e,
994
994
  activeCount: t,
995
995
  statusFilter: n,
996
- severityFilter: a,
996
+ severityFilter: r,
997
997
  categoryFilter: s,
998
998
  assigneeFilter: c,
999
999
  viewportFilter: g,
@@ -1037,7 +1037,7 @@ function It({
1037
1037
  "select",
1038
1038
  {
1039
1039
  "aria-label": "Filter severity",
1040
- value: a,
1040
+ value: r,
1041
1041
  onChange: (h) => v(h.target.value),
1042
1042
  children: [
1043
1043
  /* @__PURE__ */ i("option", { value: "all", children: "All priorities" }),
@@ -1099,7 +1099,7 @@ function Tt({
1099
1099
  selected: t,
1100
1100
  onSelect: n
1101
1101
  }) {
1102
- const a = Ke(e);
1102
+ const r = Ke(e);
1103
1103
  return /* @__PURE__ */ o(
1104
1104
  "article",
1105
1105
  {
@@ -1128,7 +1128,7 @@ function Tt({
1128
1128
  /* @__PURE__ */ o("div", { className: "review-lens-tags", children: [
1129
1129
  /* @__PURE__ */ i("span", { children: Z[e.category] }),
1130
1130
  /* @__PURE__ */ i("span", { children: e.viewportPreset }),
1131
- /* @__PURE__ */ i("span", { children: a.label })
1131
+ /* @__PURE__ */ i("span", { children: r.label })
1132
1132
  ] })
1133
1133
  ]
1134
1134
  }
@@ -1138,7 +1138,7 @@ function Rt({
1138
1138
  item: e,
1139
1139
  messages: t,
1140
1140
  messageDraft: n,
1141
- canReply: a,
1141
+ canReply: r,
1142
1142
  canUpdate: s,
1143
1143
  canAssign: c,
1144
1144
  onMessageDraftChange: g,
@@ -1234,12 +1234,12 @@ function Rt({
1234
1234
  {
1235
1235
  "aria-label": "Reply",
1236
1236
  value: n,
1237
- disabled: !a,
1237
+ disabled: !r,
1238
1238
  onChange: (b) => g(b.target.value),
1239
- placeholder: a ? "Reply..." : "You do not have permission to reply."
1239
+ placeholder: r ? "Reply..." : "You do not have permission to reply."
1240
1240
  }
1241
1241
  ),
1242
- /* @__PURE__ */ i("div", { className: "review-lens-actions", children: /* @__PURE__ */ i("button", { type: "button", disabled: !n.trim() || !a, onClick: f, children: "Reply" }) })
1242
+ /* @__PURE__ */ i("div", { className: "review-lens-actions", children: /* @__PURE__ */ i("button", { type: "button", disabled: !n.trim() || !r, onClick: f, children: "Reply" }) })
1243
1243
  ] })
1244
1244
  ] });
1245
1245
  }
@@ -1255,14 +1255,14 @@ function Bt({ feedback: e }) {
1255
1255
  function G({ title: e, values: t }) {
1256
1256
  return /* @__PURE__ */ o("section", { children: [
1257
1257
  /* @__PURE__ */ i("h3", { children: e }),
1258
- /* @__PURE__ */ i("dl", { children: t.map(([n, a]) => /* @__PURE__ */ o("div", { children: [
1258
+ /* @__PURE__ */ i("dl", { children: t.map(([n, r]) => /* @__PURE__ */ o("div", { children: [
1259
1259
  /* @__PURE__ */ i("dt", { children: n }),
1260
- /* @__PURE__ */ i("dd", { children: a })
1260
+ /* @__PURE__ */ i("dd", { children: r })
1261
1261
  ] }, n)) })
1262
1262
  ] });
1263
1263
  }
1264
1264
  function $t({ target: e, locked: t }) {
1265
- const n = Vt(e), a = jt(e.fingerprint);
1265
+ const n = Gt(e), r = Ot(e.fingerprint);
1266
1266
  return /* @__PURE__ */ o(
1267
1267
  "div",
1268
1268
  {
@@ -1311,7 +1311,7 @@ function $t({ target: e, locked: t }) {
1311
1311
  }
1312
1312
  ),
1313
1313
  /* @__PURE__ */ o("div", { className: "review-lens-highlight__label", children: [
1314
- /* @__PURE__ */ i("strong", { children: a }),
1314
+ /* @__PURE__ */ i("strong", { children: r }),
1315
1315
  /* @__PURE__ */ o("span", { children: [
1316
1316
  Math.round(e.rect.width),
1317
1317
  " x ",
@@ -1323,20 +1323,20 @@ function $t({ target: e, locked: t }) {
1323
1323
  );
1324
1324
  }
1325
1325
  function _t({ from: e, to: t }) {
1326
- const n = Ot(e.rect, t.rect);
1327
- return n.length === 0 ? null : /* @__PURE__ */ i(ie, { children: n.map((a) => /* @__PURE__ */ i(
1326
+ const n = Kt(e.rect, t.rect);
1327
+ return n.length === 0 ? null : /* @__PURE__ */ i(ie, { children: n.map((r) => /* @__PURE__ */ i(
1328
1328
  "div",
1329
1329
  {
1330
- className: `review-lens-distance review-lens-distance--${a.axis}`,
1330
+ className: `review-lens-distance review-lens-distance--${r.axis}`,
1331
1331
  style: {
1332
- top: a.top,
1333
- left: a.left,
1334
- width: a.width,
1335
- height: a.height
1332
+ top: r.top,
1333
+ left: r.left,
1334
+ width: r.width,
1335
+ height: r.height
1336
1336
  },
1337
- children: /* @__PURE__ */ i("span", { children: a.label })
1337
+ children: /* @__PURE__ */ i("span", { children: r.label })
1338
1338
  },
1339
- a.key
1339
+ r.key
1340
1340
  )) });
1341
1341
  }
1342
1342
  function Pt({
@@ -1344,14 +1344,14 @@ function Pt({
1344
1344
  selectedFeedback: t,
1345
1345
  onSelect: n
1346
1346
  }) {
1347
- return /* @__PURE__ */ i(ie, { children: e.map((a) => /* @__PURE__ */ i(
1347
+ return /* @__PURE__ */ i(ie, { children: e.map((r) => /* @__PURE__ */ i(
1348
1348
  Ut,
1349
1349
  {
1350
- feedback: a,
1351
- selected: (t == null ? void 0 : t.id) === a.id,
1350
+ feedback: r,
1351
+ selected: (t == null ? void 0 : t.id) === r.id,
1352
1352
  onSelect: n
1353
1353
  },
1354
- a.id
1354
+ r.id
1355
1355
  )) });
1356
1356
  }
1357
1357
  function Ut({
@@ -1359,12 +1359,12 @@ function Ut({
1359
1359
  selected: t,
1360
1360
  onSelect: n
1361
1361
  }) {
1362
- const a = We(null);
1362
+ const r = We(null);
1363
1363
  return lt(() => {
1364
1364
  let s = 0;
1365
1365
  const c = () => {
1366
1366
  s = 0;
1367
- const f = a.current, u = z(e.selector), d = u == null ? void 0 : u.getBoundingClientRect();
1367
+ const f = r.current, u = z(e.selector), d = u == null ? void 0 : u.getBoundingClientRect();
1368
1368
  !f || !d || (f.style.top = `${d.top}px`, f.style.left = `${d.right}px`, f.hidden = d.bottom < 0 || d.top > window.innerHeight);
1369
1369
  }, g = () => {
1370
1370
  s || (s = window.requestAnimationFrame(c));
@@ -1375,7 +1375,7 @@ function Ut({
1375
1375
  }, [e.selector]), /* @__PURE__ */ i(
1376
1376
  "button",
1377
1377
  {
1378
- ref: a,
1378
+ ref: r,
1379
1379
  type: "button",
1380
1380
  className: t ? "review-lens-marker review-lens-marker--selected" : "review-lens-marker",
1381
1381
  onClick: () => n(e),
@@ -1388,7 +1388,7 @@ function Wt({
1388
1388
  selectedFeedback: t,
1389
1389
  onSelect: n
1390
1390
  }) {
1391
- const a = e.map((s) => {
1391
+ const r = e.map((s) => {
1392
1392
  const c = z(s.selector), g = c == null ? void 0 : c.getBoundingClientRect(), f = Math.max(
1393
1393
  document.documentElement.scrollHeight,
1394
1394
  document.body.scrollHeight,
@@ -1399,7 +1399,7 @@ function Wt({
1399
1399
  top: Math.min(100, Math.max(0, (g.top + window.scrollY) / f * 100))
1400
1400
  };
1401
1401
  }).filter((s) => s !== null);
1402
- return a.length === 0 ? null : /* @__PURE__ */ i("div", { className: "review-lens-minimap", "data-review-lens-ui": !0, "aria-label": "Feedback map", children: a.map((s) => /* @__PURE__ */ i(
1402
+ 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(
1403
1403
  "button",
1404
1404
  {
1405
1405
  type: "button",
@@ -1424,9 +1424,9 @@ function Dt({ target: e }) {
1424
1424
  ["Color", e.cssSnapshot.color],
1425
1425
  ["Background", e.cssSnapshot.backgroundColor]
1426
1426
  ];
1427
- return /* @__PURE__ */ i("dl", { className: "review-lens-metrics", children: t.map(([n, a]) => /* @__PURE__ */ o("div", { children: [
1427
+ return /* @__PURE__ */ i("dl", { className: "review-lens-metrics", children: t.map(([n, r]) => /* @__PURE__ */ o("div", { children: [
1428
1428
  /* @__PURE__ */ i("dt", { children: n }),
1429
- /* @__PURE__ */ i("dd", { children: a })
1429
+ /* @__PURE__ */ i("dd", { children: r })
1430
1430
  ] }, n)) });
1431
1431
  }
1432
1432
  function _e({ title: e, items: t }) {
@@ -1455,24 +1455,32 @@ function zt(e) {
1455
1455
  const t = z(e.selector);
1456
1456
  if (!t)
1457
1457
  return ["Selected element is no longer available."];
1458
- const n = [], a = t.tagName.toLowerCase(), s = t.getAttribute("role"), c = ["button", "a", "input", "select", "textarea"].includes(a) || s === "button" || s === "link", g = t.getAttribute("aria-label") || t.getAttribute("title") || ((u = t.textContent) == null ? void 0 : u.trim());
1459
- 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."), a === "img" && !t.getAttribute("alt") && n.push("Image is missing alt text.");
1460
- const f = /^h[1-6]$/.test(a) ? Number(a.slice(1)) : 0;
1461
- return f > 1 && !document.querySelector(`h${f - 1}`) && n.push("Heading may skip the previous level."), Jt(e.cssSnapshot.color, e.cssSnapshot.backgroundColor) && n.push("Text contrast may be low."), n;
1458
+ const n = [], r = t.tagName.toLowerCase(), s = t.getAttribute("role"), c = ["button", "a", "input", "select", "textarea"].includes(r) || s === "button" || s === "link", g = t.getAttribute("aria-label") || t.getAttribute("title") || ((u = t.textContent) == null ? void 0 : u.trim());
1459
+ 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."), r === "img" && !t.getAttribute("alt") && n.push("Image is missing alt text.");
1460
+ const f = /^h[1-6]$/.test(r) ? Number(r.slice(1)) : 0;
1461
+ 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;
1462
1462
  }
1463
1463
  function Ht(e, t = {}) {
1464
1464
  const n = [];
1465
- return U("Padding", e.padding, t.spacing, n), U("Margin", e.margin, t.spacing, n), 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), n;
1465
+ 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;
1466
1466
  }
1467
- function U(e, t, n, a) {
1468
- !n || n.length === 0 || !t || n.includes(t) || a.push(`${e} ${t} is outside configured tokens.`);
1467
+ function U(e, t, n, r, s = {}) {
1468
+ !n || n.length === 0 || !t || jt(t, n, s) || r.push(`${e} ${t} is outside configured tokens.`);
1469
1469
  }
1470
- function jt(e) {
1471
- const t = e.id ? `#${e.id}` : "", n = e.className ? `.${e.className.split(/\s+/).filter(Boolean).slice(0, 2).join(".")}` : "", a = e.ariaLabel ? `[aria-label="${e.ariaLabel}"]` : "";
1472
- return `${e.tagName}${t}${n}${a}` || e.tagName;
1470
+ function jt(e, t, n = {}) {
1471
+ if (t.includes(e))
1472
+ return !0;
1473
+ if (!n.allowComposite)
1474
+ return !1;
1475
+ const r = e.trim().split(/\s+/);
1476
+ return r.length > 1 && r.every((s) => t.includes(s));
1473
1477
  }
1474
- function Ot(e, t) {
1475
- const n = [], a = (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;
1478
+ function Ot(e) {
1479
+ 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}"]` : "";
1480
+ return `${e.tagName}${t}${n}${r}` || e.tagName;
1481
+ }
1482
+ function Kt(e, t) {
1483
+ 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;
1476
1484
  if (e.right <= t.left || t.right <= e.left) {
1477
1485
  const c = e.right <= t.left ? e.right : t.right, g = e.right <= t.left ? t.left : e.left;
1478
1486
  n.push({
@@ -1491,7 +1499,7 @@ function Ot(e, t) {
1491
1499
  key: "vertical",
1492
1500
  axis: "vertical",
1493
1501
  top: c,
1494
- left: Pe(a, 0, window.innerWidth),
1502
+ left: Pe(r, 0, window.innerWidth),
1495
1503
  width: 1,
1496
1504
  height: Math.max(g - c, 1),
1497
1505
  label: `${Math.round(g - c)}px`
@@ -1504,43 +1512,43 @@ function Pe(e, t, n) {
1504
1512
  }
1505
1513
  function Y(e, t) {
1506
1514
  const n = /* @__PURE__ */ new Map();
1507
- for (const a of e) {
1508
- const s = t(a);
1515
+ for (const r of e) {
1516
+ const s = t(r);
1509
1517
  n.set(s, (n.get(s) ?? 0) + 1);
1510
1518
  }
1511
- return Array.from(n.entries()).sort((a, s) => s[1] - a[1] || a[0].localeCompare(s[0]));
1519
+ return Array.from(n.entries()).sort((r, s) => s[1] - r[1] || r[0].localeCompare(s[0]));
1512
1520
  }
1513
- function Kt(e) {
1521
+ function Jt(e) {
1514
1522
  return e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement || e instanceof HTMLSelectElement || e instanceof HTMLElement && e.isContentEditable;
1515
1523
  }
1516
- function Jt(e, t) {
1517
- const n = Ue(e), a = Ue(t);
1518
- return !n || !a || a.alpha === 0 ? !1 : qt(n, a) < 4.5;
1524
+ function Vt(e, t) {
1525
+ const n = Ue(e), r = Ue(t);
1526
+ return !n || !r || r.alpha === 0 ? !1 : qt(n, r) < 4.5;
1519
1527
  }
1520
1528
  function Ue(e) {
1521
1529
  const t = e.match(/rgba?\(([^)]+)\)/);
1522
1530
  if (!t)
1523
1531
  return null;
1524
- const [n, a, s, c = "1"] = t[1].split(",").map((g) => g.trim());
1532
+ const [n, r, s, c = "1"] = t[1].split(",").map((g) => g.trim());
1525
1533
  return {
1526
1534
  red: Number(n),
1527
- green: Number(a),
1535
+ green: Number(r),
1528
1536
  blue: Number(s),
1529
1537
  alpha: Number(c)
1530
1538
  };
1531
1539
  }
1532
1540
  function qt(e, t) {
1533
- const n = Math.max(ne(e), ne(t)), a = Math.min(ne(e), ne(t));
1534
- return (n + 0.05) / (a + 0.05);
1541
+ const n = Math.max(ne(e), ne(t)), r = Math.min(ne(e), ne(t));
1542
+ return (n + 0.05) / (r + 0.05);
1535
1543
  }
1536
1544
  function ne(e) {
1537
1545
  const t = [e.red, e.green, e.blue].map((n) => {
1538
- const a = n / 255;
1539
- return a <= 0.03928 ? a / 12.92 : ((a + 0.055) / 1.055) ** 2.4;
1546
+ const r = n / 255;
1547
+ return r <= 0.03928 ? r / 12.92 : ((r + 0.055) / 1.055) ** 2.4;
1540
1548
  });
1541
1549
  return t[0] * 0.2126 + t[1] * 0.7152 + t[2] * 0.0722;
1542
1550
  }
1543
- function Vt(e) {
1551
+ function Gt(e) {
1544
1552
  const t = {
1545
1553
  top: F(e.cssSnapshot.marginTop),
1546
1554
  right: F(e.cssSnapshot.marginRight),
@@ -1551,7 +1559,7 @@ function Vt(e) {
1551
1559
  right: F(e.cssSnapshot.borderRightWidth),
1552
1560
  bottom: F(e.cssSnapshot.borderBottomWidth),
1553
1561
  left: F(e.cssSnapshot.borderLeftWidth)
1554
- }, a = {
1562
+ }, r = {
1555
1563
  top: F(e.cssSnapshot.paddingTop),
1556
1564
  right: F(e.cssSnapshot.paddingRight),
1557
1565
  bottom: F(e.cssSnapshot.paddingBottom),
@@ -1572,10 +1580,10 @@ function Vt(e) {
1572
1580
  width: Math.max(s.width - n.left - n.right, 0),
1573
1581
  height: Math.max(s.height - n.top - n.bottom, 0)
1574
1582
  }, f = {
1575
- top: g.top + a.top,
1576
- left: g.left + a.left,
1577
- width: Math.max(g.width - a.left - a.right, 0),
1578
- height: Math.max(g.height - a.top - a.bottom, 0)
1583
+ top: g.top + r.top,
1584
+ left: g.left + r.left,
1585
+ width: Math.max(g.width - r.left - r.right, 0),
1586
+ height: Math.max(g.height - r.top - r.bottom, 0)
1579
1587
  };
1580
1588
  return {
1581
1589
  margin: c,
@@ -1589,8 +1597,8 @@ function F(e) {
1589
1597
  return Number.isFinite(t) ? t : 0;
1590
1598
  }
1591
1599
  export {
1592
- Qt as ReviewLensOverlay,
1593
- Xt as ReviewLensProvider,
1600
+ Zt as ReviewLensOverlay,
1601
+ Qt as ReviewLensProvider,
1594
1602
  X as buildElementTarget,
1595
1603
  ht as createGoogleSheetsAdapter,
1596
1604
  Ct as normalizeReviewUrl,
@@ -1 +1 @@
1
- (function(x,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],r):(x=typeof globalThis<"u"?globalThis:x||self,r(x.ReviewLensReact={},x.jsxRuntime,x.React))})(this,(function(x,r,l){"use strict";const Ke=["https://www.googleapis.com/auth/spreadsheets","https://www.googleapis.com/auth/userinfo.email"].join(" "),Je="https://www.googleapis.com/oauth2/v3/userinfo";function le(e){const t=e.feedbackSheetName??"Feedback",n=e.messagesSheetName??"Messages",a=e.usersSheetName??"Users";let i,d;async function f(){return i??(i=tt(e.googleClientId)),i}async function b(c,w){const u=await f(),v=await fetch(`https://sheets.googleapis.com/v4/spreadsheets/${e.spreadsheetId}${c}`,{...w,headers:{Authorization:`Bearer ${u}`,"Content-Type":"application/json",...w==null?void 0:w.headers}});if(!v.ok)throw new Error(`Google Sheets request failed with ${v.status}`);return v.json()}async function p(c){return(await b(`/values/${encodeURIComponent(c)}`)).values??[]}return{async getCurrentUser(){if(!d){const c=await f(),w=await fetch(Je,{headers:{Authorization:`Bearer ${c}`}});if(!w.ok)throw new Error(`Google userinfo request failed with ${w.status}`);d=(await w.json()).email}if(!d)throw new Error("Google account did not return an email address");return{email:d}},async getPermissions(c){const[{email:w},u]=await Promise.all([this.getCurrentUser(),p(a)]),v=ne(u),E=w.toLowerCase(),N=v.find(A=>{var h;return((h=A.email)==null?void 0:h.toLowerCase())===E&&A.active!=="false"&&(!A.projectKey||A.projectKey===c)});return Ye((N==null?void 0:N.role)??"designer")},async listFeedback(c){return ne(await p(t)).map(pe).filter(u=>u!==null).filter(u=>u.projectKey===c.projectKey&&u.contentId===c.contentId&&u.normalizedPath===c.normalizedPath).sort((u,v)=>v.createdAt.localeCompare(u.createdAt))},async createFeedback(c){const w=new Date().toISOString(),u={...c,id:crypto.randomUUID(),attachments:[],createdAt:w,updatedAt:w};return await b(`/values/${encodeURIComponent(t)}:append?valueInputOption=RAW`,{method:"POST",body:JSON.stringify({values:[ce(u)]})}),u},async updateFeedback(c,w){const u=await p(t),v=u[0]??de,E=v.indexOf("id");if(E===-1)throw new Error(`Sheet ${t} is missing an id column`);const N=u.findIndex((m,k)=>k>0&&m[E]===c);if(N<1)throw new Error(`Feedback ${c} was not found`);const A=new Date().toISOString(),h=pe(he(v,u[N]));if(!h)throw new Error(`Feedback ${c} could not be parsed before updating`);const B={...h,...w,updatedAt:A},y=ce(B);return await b(`/values/${encodeURIComponent(t)}!A${N+1}:${et(de.length)}${N+1}?valueInputOption=RAW`,{method:"PUT",body:JSON.stringify({values:[y]})}),B},async listMessages(c){return ne(await p(n)).map(Ge).filter(u=>u!==null).filter(u=>u.feedbackId===c).sort((u,v)=>u.createdAt.localeCompare(v.createdAt))},async createMessage(c){const w={...c,id:crypto.randomUUID(),createdAt:new Date().toISOString()};return await b(`/values/${encodeURIComponent(n)}:append?valueInputOption=RAW`,{method:"POST",body:JSON.stringify({values:[Ve(w)]})}),w}}}const de=["id","projectKey","contentId","normalizedPath","originalUrl","selector","selectorStrategy","elementFingerprintJson","createdCssSnapshotJson","comment","status","severity","category","assigneeEmail","viewportWidth","viewportHeight","viewportPreset","screenshotUrl","screenshotThumbnailUrl","attachmentJson","authorEmail","createdAt","updatedAt","fixedCssSnapshotJson","fixedAt","fixedBy","resolvedAt","resolvedBy"],qe=["id","feedbackId","body","authorEmail","createdAt"];function ce(e){return[e.id,e.projectKey,e.contentId,e.normalizedPath,e.originalUrl,e.selector,e.selectorStrategy,JSON.stringify(e.elementFingerprint),JSON.stringify(e.createdCssSnapshot),e.comment,e.status,e.severity,e.category,e.assigneeEmail??"",String(e.viewportWidth),String(e.viewportHeight),e.viewportPreset,e.screenshotUrl??"",e.screenshotThumbnailUrl??"",JSON.stringify(e.attachments),e.authorEmail,e.createdAt,e.updatedAt,e.fixedCssSnapshot?JSON.stringify(e.fixedCssSnapshot):"",e.fixedAt??"",e.fixedBy??"",e.resolvedAt??"",e.resolvedBy??""]}function Ve(e){return qe.map(t=>e[t])}function ne(e){const[t,...n]=e;return t?n.map(a=>he(t,a)):[]}function he(e,t){return Object.fromEntries(e.map((n,a)=>[n,t[a]??""]))}function pe(e){return e.id?{id:e.id,projectKey:e.projectKey,contentId:e.contentId,normalizedPath:e.normalizedPath,originalUrl:e.originalUrl,selector:e.selector,selectorStrategy:e.selectorStrategy==="stable-attribute"?"stable-attribute":"css-path",elementFingerprint:re(e.elementFingerprintJson,{tagName:"",width:0,height:0}),createdCssSnapshot:ue(e.createdCssSnapshotJson),fixedCssSnapshot:e.fixedCssSnapshotJson?ue(e.fixedCssSnapshotJson):void 0,comment:e.comment,status:Xe(e.status),severity:Qe(e.severity),category:Ze(e.category),assigneeEmail:e.assigneeEmail||void 0,viewportWidth:Number(e.viewportWidth)||0,viewportHeight:Number(e.viewportHeight)||0,viewportPreset:Re(e.viewportPreset),screenshotUrl:e.screenshotUrl||void 0,screenshotThumbnailUrl:e.screenshotThumbnailUrl||void 0,attachments:re(e.attachmentJson,[]),authorEmail:e.authorEmail,createdAt:e.createdAt,updatedAt:e.updatedAt,fixedAt:e.fixedAt||void 0,fixedBy:e.fixedBy||void 0,resolvedAt:e.resolvedAt||void 0,resolvedBy:e.resolvedBy||void 0}:null}function Ge(e){return!e.id||!e.feedbackId?null:{id:e.id,feedbackId:e.feedbackId,body:e.body,authorEmail:e.authorEmail,createdAt:e.createdAt}}function re(e,t){try{return e?JSON.parse(e):t}catch{return t}}function ue(e){const t=re(e,{});return{margin:t.margin??"",marginTop:t.marginTop??"",marginRight:t.marginRight??"",marginBottom:t.marginBottom??"",marginLeft:t.marginLeft??"",padding:t.padding??"",paddingTop:t.paddingTop??"",paddingRight:t.paddingRight??"",paddingBottom:t.paddingBottom??"",paddingLeft:t.paddingLeft??"",border:t.border??"",borderTopWidth:t.borderTopWidth??"",borderRightWidth:t.borderRightWidth??"",borderBottomWidth:t.borderBottomWidth??"",borderLeftWidth:t.borderLeftWidth??"",fontFamily:t.fontFamily??"",fontSize:t.fontSize??"",lineHeight:t.lineHeight??"",color:t.color??"",backgroundColor:t.backgroundColor??"",borderRadius:t.borderRadius??"",width:t.width??0,height:t.height??0}}function Ye(e){return e==="admin"?["create","read","reply","update","assign"]:e==="developer"?["read","reply","update","assign"]:["create","read","reply"]}function Xe(e){return e==="in_progress"||e==="needs_clarification"||e==="fixed"||e==="wontfix"||e==="resolved"?e:"open"}function Qe(e){return e==="low"||e==="high"?e:"medium"}function Ze(e){return e==="visual"||e==="copy"||e==="accessibility"||e==="responsive"?e:"bug"}function Re(e){return e==="mobile"||e==="tablet"||e==="desktop"?e:"custom"}function et(e){let t=e,n="";for(;t>0;){const a=(t-1)%26;n=String.fromCharCode(65+a)+n,t=Math.floor((t-a)/26)}return n}async function tt(e){return await nt(),new Promise((t,n)=>{var i;const a=(i=window.google)==null?void 0:i.accounts.oauth2.initTokenClient({client_id:e,scope:Ke,callback:d=>{if(d.error||!d.access_token){n(new Error(d.error??"Google OAuth did not return an access token"));return}t(d.access_token)}});a==null||a.requestAccessToken({prompt:""})})}function nt(){var e;return(e=window.google)!=null&&e.accounts.oauth2?Promise.resolve():new Promise((t,n)=>{const a=document.querySelector('script[src="https://accounts.google.com/gsi/client"]');if(a){a.addEventListener("load",()=>t(),{once:!0}),a.addEventListener("error",()=>n(new Error("Google Identity failed to load")),{once:!0});return}const i=document.createElement("script");i.src="https://accounts.google.com/gsi/client",i.async=!0,i.defer=!0,i.onload=()=>t(),i.onerror=()=>n(new Error("Google Identity failed to load")),document.head.append(i)})}function ge(e){return new URL(e,window.location.href).pathname.replace(/\/+$/,"")||"/"}const fe=l.createContext(null);function rt({config:e,children:t}){const n=l.useMemo(()=>e.adapter?e.adapter:le({googleClientId:ve(e.googleClientId,"googleClientId"),spreadsheetId:ve(e.spreadsheetId,"spreadsheetId"),feedbackSheetName:e.sheetName??"Feedback"}),[e.adapter,e.googleClientId,e.sheetName,e.spreadsheetId]),a=e.currentUrl??window.location.href,i=(e.normalizeUrl??ge)(a),[d,f]=l.useState(),[b,p]=l.useState([]),[c,w]=l.useState([]),u=l.useCallback(async()=>{const y=await n.listFeedback({projectKey:e.projectKey,contentId:e.contentId,normalizedPath:i});w(y)},[n,e.contentId,e.projectKey,i]);l.useEffect(()=>{let y=!0;async function m(){const[k,$]=await Promise.all([n.getCurrentUser(),n.getPermissions(e.projectKey)]);y&&(f(k),p($),await u())}return m(),()=>{y=!1}},[n,e.projectKey,u]);const v=l.useCallback(async y=>{const m=await n.createFeedback(y);return w(k=>[m,...k]),m},[n]),E=l.useCallback(async(y,m)=>{const k=await n.updateFeedback(y,m);return w($=>$.map(z=>z.id===y?k:z)),k},[n]),N=l.useCallback(y=>n.listMessages(y),[n]),A=l.useCallback(y=>n.createMessage(y),[n]),h=l.useCallback(async(y,m)=>{const k=e.uploadAttachment??n.uploadAttachment;if(!k)throw new Error("Review Lens attachment upload is not configured");return k(y,m)},[n,e]),B=l.useMemo(()=>({config:e,adapter:n,currentUser:d,permissions:b,feedback:c,normalizedPath:i,refreshFeedback:u,createFeedback:v,updateFeedback:E,listMessages:N,createMessage:A,uploadAttachment:h}),[n,e,v,d,c,i,b,u,E,N,A,h]);return r.jsx(fe.Provider,{value:B,children:t})}function be(){const e=l.useContext(fe);if(!e)throw new Error("useReviewLens must be used inside ReviewLensProvider");return e}function ve(e,t){if(!e)throw new Error(`review-lens-react requires config.${t} when no adapter is provided`);return e}const st=["data-review-id","data-testid","data-test-id","aria-label","name"];function W(e){const t=e.getBoundingClientRect(),n=at(e);return{selector:n.selector,selectorStrategy:n.strategy,fingerprint:ot(e,t),cssSnapshot:lt(e,t),rect:t}}function at(e){for(const t of st){const n=e.getAttribute(t);if(n)return{selector:`[${t}="${we(n)}"]`,strategy:"stable-attribute"}}return e.id?{selector:`#${we(e.id)}`,strategy:"stable-attribute"}:{selector:it(e),strategy:"css-path"}}function it(e){const t=[];let n=e;for(;n&&n.nodeType===Node.ELEMENT_NODE&&n!==document.body;){const a=n.parentElement,i=n.tagName.toLowerCase();if(!a){t.unshift(i);break}const d=n.tagName,f=Array.from(a.children).filter(p=>p.tagName===d),b=f.indexOf(n)+1;t.unshift(f.length>1?`${i}:nth-of-type(${b})`:i),n=a}return t.join(" > ")}function ot(e,t){var n;return{tagName:e.tagName.toLowerCase(),id:e.id||void 0,className:e.getAttribute("class")||void 0,textSnippet:((n=e.textContent)==null?void 0:n.trim().slice(0,80))||void 0,ariaLabel:e.getAttribute("aria-label")||void 0,width:Math.round(t.width),height:Math.round(t.height)}}function lt(e,t){const n=window.getComputedStyle(e);return{margin:se(n.marginTop,n.marginRight,n.marginBottom,n.marginLeft),marginTop:n.marginTop,marginRight:n.marginRight,marginBottom:n.marginBottom,marginLeft:n.marginLeft,padding:se(n.paddingTop,n.paddingRight,n.paddingBottom,n.paddingLeft),paddingTop:n.paddingTop,paddingRight:n.paddingRight,paddingBottom:n.paddingBottom,paddingLeft:n.paddingLeft,border:se(n.borderTopWidth,n.borderRightWidth,n.borderBottomWidth,n.borderLeftWidth),borderTopWidth:n.borderTopWidth,borderRightWidth:n.borderRightWidth,borderBottomWidth:n.borderBottomWidth,borderLeftWidth:n.borderLeftWidth,fontFamily:n.fontFamily,fontSize:n.fontSize,lineHeight:n.lineHeight,color:n.color,backgroundColor:n.backgroundColor,borderRadius:n.borderRadius,width:Math.round(t.width),height:Math.round(t.height)}}function se(e,t,n,a){return e===t&&t===n&&n===a?e:`${e} ${t} ${n} ${a}`}function we(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/["\\]/g,"\\$&")}const dt=[{label:"Desktop",value:"desktop"},{label:"Tablet",value:"tablet"},{label:"Mobile",value:"mobile"}],me=["open","in_progress","needs_clarification","fixed","wontfix","resolved"],ye=["low","medium","high"],Se=["bug","visual","copy","accessibility","responsive"],Z={open:"Open",in_progress:"In progress",needs_clarification:"Needs clarification",fixed:"Fixed",wontfix:"Won't fix",resolved:"Resolved"},H={low:"Low",medium:"Medium",high:"High"},j={bug:"Bug",visual:"Visual",copy:"Copy",accessibility:"Accessibility",responsive:"Responsive"};function ct({open:e,onOpenChange:t,placement:n="top-right",showResolved:a=!1,syncSelectionToUrl:i=!1,responsivePresets:d=dt}){var Oe;const{adapter:f,config:b,currentUser:p,feedback:c,normalizedPath:w,permissions:u,createFeedback:v,updateFeedback:E,listMessages:N,createMessage:A,uploadAttachment:h}=be(),[B,y]=l.useState(),[m,k]=l.useState(),[$,z]=l.useState(""),[xe,Ft]=l.useState("medium"),[Ae,Mt]=l.useState("visual"),[Le,Fe]=l.useState(""),[Me,Tt]=l.useState(((Oe=d[0])==null?void 0:Oe.value)??"desktop"),[S,J]=l.useState(),[M,P]=l.useState("review"),[It,Te]=l.useState(!1),[q,Ie]=l.useState("all"),[V,Be]=l.useState("all"),[G,$e]=l.useState("all"),[Y,Pe]=l.useState("all"),[X,_e]=l.useState("all"),[Bt,$t]=l.useState(!1),[Pt,Ue]=l.useState({}),[ae,ie]=l.useState(""),ee=l.useRef(null),T=!!p,I=u.includes("create"),We=u.includes("reply"),De=u.includes("update"),_t=u.includes("assign"),U=B??m,Ut=!!m,Wt=!!(b.captureScreenshot&&(b.uploadAttachment||f.uploadAttachment)),Dt=l.useMemo(()=>{const s=c.map(g=>g.assigneeEmail).filter(g=>!!g);return p!=null&&p.email&&s.push(p.email),Array.from(new Set(s)).sort((g,o)=>g.localeCompare(o))},[p==null?void 0:p.email,c]),F=l.useMemo(()=>c.filter(s=>a||s.status!=="resolved").filter(s=>q==="all"||s.status===q).filter(s=>V==="all"||s.severity===V).filter(s=>G==="all"||s.category===G).filter(s=>Y==="all"||s.assigneeEmail===Y).filter(s=>X==="all"||s.viewportPreset===X),[Y,G,c,V,a,q,X]),zt=[q,V,G,Y,X].filter(s=>s!=="all").length;l.useEffect(()=>{e||(y(void 0),k(void 0),z(""),ie(""),P("review"))},[e]),l.useEffect(()=>{T||(y(void 0),k(void 0))},[T]),l.useEffect(()=>{!m||M!=="review"||window.requestAnimationFrame(()=>{var s,g,o;(g=(s=ee.current)==null?void 0:s.scrollIntoView)==null||g.call(s,{block:"nearest"}),(o=ee.current)==null||o.focus()})},[m,M]),l.useEffect(()=>{if(!S)return;let s=!0;return N(S.id).then(g=>{s&&Ue(o=>({...o,[S.id]:g}))}),()=>{s=!1}},[N,S]),l.useEffect(()=>{if(!e||!i||S||c.length===0)return;const s=new URL(window.location.href).searchParams.get("reviewLensFeedback"),g=c.find(o=>o.id===s);g&&Q(g,{syncUrl:!1})},[c,e,S,i]),l.useEffect(()=>{if(!e)return;function s(o){var C;if(o.key==="Shift"&&Te(!0),o.key==="Escape"){o.preventDefault(),t==null||t(!1);return}Et(o.target)||((o.key==="n"||o.key==="ArrowDown")&&(o.preventDefault(),ze(1)),(o.key==="p"||o.key==="ArrowUp")&&(o.preventDefault(),ze(-1)),o.key==="c"&&(o.preventDefault(),P("review"),(C=ee.current)==null||C.focus()),o.key==="f"&&S&&De&&(o.preventDefault(),je(S)))}function g(o){o.key==="Shift"&&Te(!1)}return window.addEventListener("keydown",s),window.addEventListener("keyup",g),()=>{window.removeEventListener("keydown",s),window.removeEventListener("keyup",g)}});const oe=l.useCallback(s=>{const g=s.target instanceof Element?s.target:null;if(g)return g.closest("[data-review-lens-ui]")?null:g;const o=document.elementFromPoint(s.clientX,s.clientY);return!o||o.closest("[data-review-lens-ui]")?null:o},[]);if(l.useEffect(()=>{if(!e||!T)return;function s(o){const C=oe(o);y(C?W(C):void 0)}function g(o){const C=oe(o);C&&(o.preventDefault(),o.stopPropagation(),k(W(C)),P("review"))}return window.addEventListener("mousemove",s,!0),window.addEventListener("click",g,!0),()=>{window.removeEventListener("mousemove",s,!0),window.removeEventListener("click",g,!0)}},[T,oe,e]),!e)return null;function Q(s,g={syncUrl:!0}){var C;if(J(s),k(void 0),P("feedback"),i&&g.syncUrl!==!1){const te=new URL(window.location.href);te.searchParams.set("reviewLensFeedback",s.id),window.history.replaceState({},"",te)}const o=D(s.selector);if(!o){y(void 0);return}(C=o.scrollIntoView)==null||C.call(o,{behavior:"smooth",block:"center",inline:"center"}),window.requestAnimationFrame(()=>{y(W(o))})}function ze(s){if(F.length===0)return;const g=S?F.findIndex(C=>C.id===S.id):-1,o=g<0?s>0?0:F.length-1:(g+s+F.length)%F.length;Q(F[o])}async function He(){if(!m||!$.trim()||!p||!I)return;let s=await v({projectKey:b.projectKey,contentId:b.contentId,normalizedPath:w,originalUrl:b.currentUrl??window.location.href,selector:m.selector,selectorStrategy:m.selectorStrategy,elementFingerprint:m.fingerprint,createdCssSnapshot:m.cssSnapshot,comment:$.trim(),status:"open",severity:xe,category:Ae,assigneeEmail:Le.trim()||void 0,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight,viewportPreset:Me,screenshotUrl:void 0,screenshotThumbnailUrl:void 0,authorEmail:p.email});if(b.captureScreenshot)try{const g=await b.captureScreenshot(m),o=await h(s.id,{type:"screenshot",data:g,createdBy:p.email});s=await E(s.id,{attachments:[o],screenshotUrl:o.url,screenshotThumbnailUrl:o.thumbnailUrl})}catch{}z(""),Fe(""),k(void 0),y(void 0),P("feedback"),J(s)}async function Ht(s,g){const o=new Date().toISOString(),C=g==="resolved"?{status:g,resolvedAt:o,resolvedBy:p==null?void 0:p.email}:{status:g},te=await E(s.id,C);J(te)}async function je(s){const g=D(s.selector);if(!g||!p)return;const o=W(g),C=await E(s.id,{status:"fixed",fixedCssSnapshot:o.cssSnapshot,fixedAt:new Date().toISOString(),fixedBy:p.email});J(C)}async function jt(s){if(!ae.trim()||!p||!We)return;const g=await A({feedbackId:s.id,body:ae.trim(),authorEmail:p.email});Ue(o=>({...o,[s.id]:[...o[s.id]??[],g]})),ie("")}return r.jsxs("div",{className:"review-lens-root","data-review-lens-ui":!0,children:[T&&U?r.jsx(ft,{target:U,locked:!!m}):null,T&&m&&B&&It?r.jsx(bt,{from:m,to:B}):null,T?r.jsxs(r.Fragment,{children:[r.jsx(vt,{feedback:F,selectedFeedback:S,onSelect:Q}),r.jsx(mt,{feedback:F,selectedFeedback:S,onSelect:Q})]}):null,r.jsxs("aside",{className:`review-lens-panel review-lens-panel--${n}`,"data-review-lens-ui":!0,children:[r.jsxs("header",{className:"review-lens-panel__header",children:[r.jsxs("div",{children:[r.jsx("p",{className:"review-lens-kicker",children:"Review Lens"}),r.jsx("h2",{children:M==="summary"?"Summary":M==="feedback"?"Feedback":m?"Element locked":"Inspecting"})]}),r.jsx("button",{type:"button",onClick:()=>t==null?void 0:t(!1),children:"Close"})]}),r.jsxs("div",{className:"review-lens-panel__body",children:[r.jsxs("div",{className:"review-lens-mode-switch",role:"tablist","aria-label":"Review Lens mode",children:[r.jsx("button",{type:"button",role:"tab","aria-selected":M==="review",onClick:()=>P("review"),children:"Review"}),r.jsxs("button",{type:"button",role:"tab","aria-selected":M==="feedback",onClick:()=>P("feedback"),children:["Feedback ",r.jsx("span",{children:F.length})]}),r.jsx("button",{type:"button",role:"tab","aria-selected":M==="summary",onClick:()=>P("summary"),children:"Summary"})]}),M==="review"?r.jsxs("div",{className:"review-lens-review-pane",role:"tabpanel",children:[r.jsxs("div",{className:"review-lens-inspection",children:[T?null:r.jsx("p",{children:"Authenticate with Google to inspect this page."}),T&&U?r.jsxs(r.Fragment,{children:[r.jsx(yt,{target:U}),r.jsx(ke,{title:"Accessibility",items:St(U)}),r.jsx(ke,{title:"Design tokens",items:kt(U.cssSnapshot,b.designTokens)})]}):null,T&&!U?r.jsx("p",{children:"Move over the app to inspect."}):null]}),Ut?r.jsx("div",{className:"review-lens-composer-panel",children:r.jsxs("form",{className:"review-lens-feedback-form",onSubmit:s=>{s.preventDefault(),He()},children:[r.jsx("label",{htmlFor:"review-lens-comment",children:"New feedback"}),r.jsx("textarea",{ref:ee,id:"review-lens-comment",value:$,disabled:!I,onChange:s=>z(s.target.value),onKeyDown:s=>{s.key==="Enter"&&s.metaKey&&(s.preventDefault(),He())},placeholder:I?"Describe the UX issue...":"You do not have permission to comment."}),r.jsxs("div",{className:"review-lens-form-grid",children:[r.jsxs("label",{children:["Severity",r.jsx("select",{value:xe,onChange:s=>Ft(s.target.value),disabled:!I,children:ye.map(s=>r.jsx("option",{value:s,children:H[s]},s))})]}),r.jsxs("label",{children:["Type",r.jsx("select",{value:Ae,onChange:s=>Mt(s.target.value),disabled:!I,children:Se.map(s=>r.jsx("option",{value:s,children:j[s]},s))})]}),r.jsxs("label",{children:["Assignee",r.jsx("input",{value:Le,onChange:s=>Fe(s.target.value),disabled:!I,placeholder:"optional@email.com"})]}),r.jsxs("label",{children:["Viewport",r.jsx("select",{value:Me,onChange:s=>Tt(s.target.value),disabled:!I,children:d.map(s=>r.jsx("option",{value:s.value,children:s.label},s.value))})]})]}),I?r.jsxs("p",{className:"review-lens-feedback-form__hint",children:["Press ",r.jsx("kbd",{children:"Command"})," + ",r.jsx("kbd",{children:"Enter"})," to submit.",Wt?" Screenshot capture runs after save.":""]}):null,r.jsx("div",{className:"review-lens-actions",children:r.jsx("button",{type:"submit",disabled:!$.trim()||!I,children:"Save feedback"})})]})}):null]}):null,M==="feedback"?r.jsxs("div",{className:"review-lens-comments",children:[r.jsx(ht,{open:Bt,activeCount:zt,statusFilter:q,severityFilter:V,categoryFilter:G,assigneeFilter:Y,viewportFilter:X,assignees:Dt,responsivePresets:d,onStatusChange:Ie,onSeverityChange:Be,onCategoryChange:$e,onAssigneeChange:Pe,onViewportChange:_e,onToggle:()=>$t(s=>!s),onClear:()=>{Ie("all"),Be("all"),$e("all"),Pe("all"),_e("all")}}),r.jsxs("div",{className:"review-lens-list-panel",children:[r.jsxs("div",{className:"review-lens-comments__header",children:[r.jsx("h3",{children:"All feedback"}),r.jsx("span",{children:F.length})]}),r.jsxs("div",{className:"review-lens-comments__list",children:[F.length===0?r.jsx("p",{children:"No feedback for this view."}):null,F.map(s=>r.jsx(pt,{item:s,selected:(S==null?void 0:S.id)===s.id,onSelect:Q},s.id))]})]}),S?r.jsxs("div",{className:"review-lens-selected-panel",children:[r.jsx("div",{className:"review-lens-selected-panel__label",children:"Selected feedback"}),r.jsx(ut,{item:S,messages:Pt[S.id]??[],messageDraft:ae,canReply:We,canUpdate:De,canAssign:_t,onMessageDraftChange:ie,onSubmitMessage:()=>void jt(S),onStatusChange:s=>void Ht(S,s),onAssigneeChange:s=>void E(S.id,{assigneeEmail:s.trim()||void 0}).then(J),onMarkFixed:()=>void je(S)},S.id)]}):r.jsxs("div",{className:"review-lens-selected-panel review-lens-selected-panel--empty",children:[r.jsx("div",{className:"review-lens-selected-panel__label",children:"Selected feedback"}),r.jsx("p",{children:"Select a feedback item above to review status, assignment, drift, and replies."})]})]}):null,M==="summary"?r.jsx(gt,{feedback:c}):null]})]})]})}function ht({open:e,activeCount:t,statusFilter:n,severityFilter:a,categoryFilter:i,assigneeFilter:d,viewportFilter:f,assignees:b,responsivePresets:p,onStatusChange:c,onSeverityChange:w,onCategoryChange:u,onAssigneeChange:v,onViewportChange:E,onToggle:N,onClear:A}){return r.jsxs("div",{className:"review-lens-filter-shell",children:[r.jsxs("div",{className:"review-lens-filter-bar",children:[r.jsxs("button",{type:"button","aria-expanded":e,onClick:N,children:["Filters",t>0?r.jsx("span",{children:t}):null]}),t>0?r.jsx("button",{type:"button",onClick:A,children:"Clear"}):null]}),e?r.jsxs("div",{className:"review-lens-filters",children:[r.jsxs("label",{children:["Status",r.jsxs("select",{"aria-label":"Filter status",value:n,onChange:h=>c(h.target.value),children:[r.jsx("option",{value:"all",children:"All statuses"}),me.map(h=>r.jsx("option",{value:h,children:Z[h]},h))]})]}),r.jsxs("label",{children:["Priority",r.jsxs("select",{"aria-label":"Filter severity",value:a,onChange:h=>w(h.target.value),children:[r.jsx("option",{value:"all",children:"All priorities"}),ye.map(h=>r.jsx("option",{value:h,children:H[h]},h))]})]}),r.jsxs("label",{children:["Type",r.jsxs("select",{"aria-label":"Filter type",value:i,onChange:h=>u(h.target.value),children:[r.jsx("option",{value:"all",children:"All types"}),Se.map(h=>r.jsx("option",{value:h,children:j[h]},h))]})]}),r.jsxs("label",{children:["Assignee",r.jsxs("select",{"aria-label":"Filter assignee",value:d,onChange:h=>v(h.target.value),children:[r.jsx("option",{value:"all",children:"All assignees"}),b.map(h=>r.jsx("option",{value:h,children:h},h))]})]}),r.jsxs("label",{children:["Viewport",r.jsxs("select",{"aria-label":"Filter viewport",value:f,onChange:h=>E(h.target.value),children:[r.jsx("option",{value:"all",children:"All viewports"}),p.map(h=>r.jsx("option",{value:h.value,children:h.label},h.value))]})]})]}):null]})}function pt({item:e,selected:t,onSelect:n}){const a=Ce(e);return r.jsxs("article",{tabIndex:0,className:["review-lens-comment",`review-lens-comment--${e.severity}`,t?"review-lens-comment--selected":""].filter(Boolean).join(" "),onClick:()=>n(e),onKeyDown:i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),n(e))},children:[r.jsxs("div",{className:"review-lens-comment__header",children:[r.jsx("span",{children:Z[e.status]}),r.jsx("strong",{children:H[e.severity]})]}),r.jsxs("div",{className:"review-lens-comment__content",children:[r.jsx("p",{children:e.comment}),r.jsxs("span",{children:[e.authorEmail,e.assigneeEmail?` -> ${e.assigneeEmail}`:""]})]}),r.jsxs("div",{className:"review-lens-tags",children:[r.jsx("span",{children:j[e.category]}),r.jsx("span",{children:e.viewportPreset}),r.jsx("span",{children:a.label})]})]})}function ut({item:e,messages:t,messageDraft:n,canReply:a,canUpdate:i,canAssign:d,onMessageDraftChange:f,onSubmitMessage:b,onStatusChange:p,onAssigneeChange:c,onMarkFixed:w}){const u=Ce(e);return r.jsxs("section",{className:"review-lens-detail","aria-label":"Selected feedback detail",children:[r.jsxs("div",{className:"review-lens-detail__header",children:[r.jsxs("h3",{children:[j[e.category]," feedback"]}),r.jsx("strong",{children:H[e.severity]})]}),r.jsx("blockquote",{children:e.comment}),r.jsxs("dl",{className:"review-lens-detail-meta",children:[r.jsxs("div",{children:[r.jsx("dt",{children:"Target"}),r.jsx("dd",{children:u.label})]}),r.jsxs("div",{children:[r.jsx("dt",{children:"Viewport"}),r.jsx("dd",{children:e.viewportPreset})]}),e.screenshotUrl?r.jsxs("div",{children:[r.jsx("dt",{children:"Evidence"}),r.jsx("dd",{children:r.jsx("a",{href:e.screenshotUrl,target:"_blank",rel:"noreferrer",children:"Screenshot"})})]}):null]}),r.jsxs("div",{className:"review-lens-form-grid",children:[r.jsxs("label",{children:["Status",r.jsx("select",{value:e.status,disabled:!i,onChange:v=>p(v.target.value),children:me.map(v=>r.jsx("option",{value:v,children:Z[v]},v))})]}),r.jsxs("label",{children:["Assignee",r.jsx("input",{defaultValue:e.assigneeEmail??"",disabled:!d,onBlur:v=>c(v.target.value),placeholder:"optional@email.com"})]})]}),r.jsxs("div",{className:"review-lens-status-actions",children:[r.jsx("button",{type:"button",className:"review-lens-button-secondary",disabled:!i,onClick:w,children:"Mark fixed"}),r.jsx("button",{type:"button",className:"review-lens-button-primary",disabled:!i,onClick:()=>p("resolved"),children:"Resolve"})]}),r.jsxs("div",{className:"review-lens-thread",children:[r.jsxs("div",{className:"review-lens-thread__header",children:[r.jsx("h3",{children:"Thread"}),r.jsx("span",{children:t.length})]}),t.length===0?r.jsx("p",{children:"No replies yet."}):null,t.map(v=>r.jsxs("div",{className:"review-lens-thread__message",children:[r.jsx("p",{children:v.body}),r.jsx("span",{children:v.authorEmail})]},v.id)),r.jsx("textarea",{"aria-label":"Reply",value:n,disabled:!a,onChange:v=>f(v.target.value),placeholder:a?"Reply...":"You do not have permission to reply."}),r.jsx("div",{className:"review-lens-actions",children:r.jsx("button",{type:"button",disabled:!n.trim()||!a,onClick:b,children:"Reply"})})]})]})}function gt({feedback:e}){return r.jsxs("div",{className:"review-lens-summary",role:"tabpanel",children:[r.jsx(O,{title:"Status",values:K(e,t=>Z[t.status])}),r.jsx(O,{title:"Severity",values:K(e,t=>H[t.severity])}),r.jsx(O,{title:"Type",values:K(e,t=>j[t.category])}),r.jsx(O,{title:"Assignee",values:K(e,t=>t.assigneeEmail??"Unassigned")}),r.jsx(O,{title:"Viewport",values:K(e,t=>t.viewportPreset)})]})}function O({title:e,values:t}){return r.jsxs("section",{children:[r.jsx("h3",{children:e}),r.jsx("dl",{children:t.map(([n,a])=>r.jsxs("div",{children:[r.jsx("dt",{children:n}),r.jsx("dd",{children:a})]},n))})]})}function ft({target:e,locked:t}){const n=Lt(e),a=Ct(e.fingerprint);return r.jsxs("div",{className:t?"review-lens-highlight review-lens-highlight--locked":"review-lens-highlight",style:{top:n.margin.top,left:n.margin.left,width:n.margin.width,height:n.margin.height},children:[r.jsx("div",{className:"review-lens-highlight__border",style:{top:n.border.top-n.margin.top,left:n.border.left-n.margin.left,width:n.border.width,height:n.border.height}}),r.jsx("div",{className:"review-lens-highlight__padding",style:{top:n.padding.top-n.margin.top,left:n.padding.left-n.margin.left,width:n.padding.width,height:n.padding.height}}),r.jsx("div",{className:"review-lens-highlight__content",style:{top:n.content.top-n.margin.top,left:n.content.left-n.margin.left,width:n.content.width,height:n.content.height}}),r.jsxs("div",{className:"review-lens-highlight__label",children:[r.jsx("strong",{children:a}),r.jsxs("span",{children:[Math.round(e.rect.width)," x ",Math.round(e.rect.height)]})]})]})}function bt({from:e,to:t}){const n=Nt(e.rect,t.rect);return n.length===0?null:r.jsx(r.Fragment,{children:n.map(a=>r.jsx("div",{className:`review-lens-distance review-lens-distance--${a.axis}`,style:{top:a.top,left:a.left,width:a.width,height:a.height},children:r.jsx("span",{children:a.label})},a.key))})}function vt({feedback:e,selectedFeedback:t,onSelect:n}){return r.jsx(r.Fragment,{children:e.map(a=>r.jsx(wt,{feedback:a,selected:(t==null?void 0:t.id)===a.id,onSelect:n},a.id))})}function wt({feedback:e,selected:t,onSelect:n}){const a=l.useRef(null);return l.useLayoutEffect(()=>{let i=0;const d=()=>{i=0;const b=a.current,p=D(e.selector),c=p==null?void 0:p.getBoundingClientRect();!b||!c||(b.style.top=`${c.top}px`,b.style.left=`${c.right}px`,b.hidden=c.bottom<0||c.top>window.innerHeight)},f=()=>{i||(i=window.requestAnimationFrame(d))};return d(),window.addEventListener("scroll",f,!0),window.addEventListener("resize",f),()=>{i&&window.cancelAnimationFrame(i),window.removeEventListener("scroll",f,!0),window.removeEventListener("resize",f)}},[e.selector]),r.jsx("button",{ref:a,type:"button",className:t?"review-lens-marker review-lens-marker--selected":"review-lens-marker",onClick:()=>n(e),"aria-label":`Open feedback from ${e.authorEmail}`})}function mt({feedback:e,selectedFeedback:t,onSelect:n}){const a=e.map(i=>{const d=D(i.selector),f=d==null?void 0:d.getBoundingClientRect(),b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight,window.innerHeight);return!f||b<=0?null:{item:i,top:Math.min(100,Math.max(0,(f.top+window.scrollY)/b*100))}}).filter(i=>i!==null);return a.length===0?null:r.jsx("div",{className:"review-lens-minimap","data-review-lens-ui":!0,"aria-label":"Feedback map",children:a.map(i=>r.jsx("button",{type:"button",className:(t==null?void 0:t.id)===i.item.id?"review-lens-minimap__point review-lens-minimap__point--selected":"review-lens-minimap__point",style:{top:`${i.top}%`},onClick:()=>n(i.item),"aria-label":`Jump to feedback from ${i.item.authorEmail}`},i.item.id))})}function yt({target:e}){const t=[["Selector",e.selector],["Size",`${e.cssSnapshot.width} x ${e.cssSnapshot.height}`],["Margin",e.cssSnapshot.margin],["Padding",e.cssSnapshot.padding],["Border",e.cssSnapshot.border],["Radius",e.cssSnapshot.borderRadius],["Font",`${e.cssSnapshot.fontSize} / ${e.cssSnapshot.lineHeight}`],["Family",e.cssSnapshot.fontFamily],["Color",e.cssSnapshot.color],["Background",e.cssSnapshot.backgroundColor]];return r.jsx("dl",{className:"review-lens-metrics",children:t.map(([n,a])=>r.jsxs("div",{children:[r.jsx("dt",{children:n}),r.jsx("dd",{children:a})]},n))})}function ke({title:e,items:t}){return r.jsxs("section",{className:"review-lens-insights",children:[r.jsx("h3",{children:e}),t.length===0?r.jsx("p",{children:"No issues detected."}):null,t.length>0?r.jsx("ul",{children:t.map(n=>r.jsx("li",{children:n},n))}):null]})}function D(e){try{return document.querySelector(e)}catch{return null}}function Ce(e){const t=D(e.selector);if(!t)return{label:"Target missing",level:"warning"};const n=W(t);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"}}function St(e){var p;const t=D(e.selector);if(!t)return["Selected element is no longer available."];const n=[],a=t.tagName.toLowerCase(),i=t.getAttribute("role"),d=["button","a","input","select","textarea"].includes(a)||i==="button"||i==="link",f=t.getAttribute("aria-label")||t.getAttribute("title")||((p=t.textContent)==null?void 0:p.trim());d&&!f&&n.push("Interactive element has no accessible name."),d&&(e.rect.width<44||e.rect.height<44)&&n.push("Tap target is smaller than 44 x 44."),a==="img"&&!t.getAttribute("alt")&&n.push("Image is missing alt text.");const b=/^h[1-6]$/.test(a)?Number(a.slice(1)):0;return b>1&&!document.querySelector(`h${b-1}`)&&n.push("Heading may skip the previous level."),xt(e.cssSnapshot.color,e.cssSnapshot.backgroundColor)&&n.push("Text contrast may be low."),n}function kt(e,t={}){const n=[];return _("Padding",e.padding,t.spacing,n),_("Margin",e.margin,t.spacing,n),_("Font size",e.fontSize,t.fontSize,n),_("Line height",e.lineHeight,t.lineHeight,n),_("Text color",e.color,t.color,n),_("Background",e.backgroundColor,t.color,n),_("Radius",e.borderRadius,t.radius,n),n}function _(e,t,n,a){!n||n.length===0||!t||n.includes(t)||a.push(`${e} ${t} is outside configured tokens.`)}function Ct(e){const t=e.id?`#${e.id}`:"",n=e.className?`.${e.className.split(/\s+/).filter(Boolean).slice(0,2).join(".")}`:"",a=e.ariaLabel?`[aria-label="${e.ariaLabel}"]`:"";return`${e.tagName}${t}${n}${a}`||e.tagName}function Nt(e,t){const n=[],a=(Math.max(e.left,t.left)+Math.min(e.right,t.right))/2,i=(Math.max(e.top,t.top)+Math.min(e.bottom,t.bottom))/2;if(e.right<=t.left||t.right<=e.left){const d=e.right<=t.left?e.right:t.right,f=e.right<=t.left?t.left:e.left;n.push({key:"horizontal",axis:"horizontal",top:Ne(i,0,window.innerHeight),left:d,width:Math.max(f-d,1),height:1,label:`${Math.round(f-d)}px`})}if(e.bottom<=t.top||t.bottom<=e.top){const d=e.bottom<=t.top?e.bottom:t.bottom,f=e.bottom<=t.top?t.top:e.top;n.push({key:"vertical",axis:"vertical",top:d,left:Ne(a,0,window.innerWidth),width:1,height:Math.max(f-d,1),label:`${Math.round(f-d)}px`})}return n}function Ne(e,t,n){return Math.min(Math.max(e,t),n)}function K(e,t){const n=new Map;for(const a of e){const i=t(a);n.set(i,(n.get(i)??0)+1)}return Array.from(n.entries()).sort((a,i)=>i[1]-a[1]||a[0].localeCompare(i[0]))}function Et(e){return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement||e instanceof HTMLElement&&e.isContentEditable}function xt(e,t){const n=Ee(e),a=Ee(t);return!n||!a||a.alpha===0?!1:At(n,a)<4.5}function Ee(e){const t=e.match(/rgba?\(([^)]+)\)/);if(!t)return null;const[n,a,i,d="1"]=t[1].split(",").map(f=>f.trim());return{red:Number(n),green:Number(a),blue:Number(i),alpha:Number(d)}}function At(e,t){const n=Math.max(R(e),R(t)),a=Math.min(R(e),R(t));return(n+.05)/(a+.05)}function R(e){const t=[e.red,e.green,e.blue].map(n=>{const a=n/255;return a<=.03928?a/12.92:((a+.055)/1.055)**2.4});return t[0]*.2126+t[1]*.7152+t[2]*.0722}function Lt(e){const t={top:L(e.cssSnapshot.marginTop),right:L(e.cssSnapshot.marginRight),bottom:L(e.cssSnapshot.marginBottom),left:L(e.cssSnapshot.marginLeft)},n={top:L(e.cssSnapshot.borderTopWidth),right:L(e.cssSnapshot.borderRightWidth),bottom:L(e.cssSnapshot.borderBottomWidth),left:L(e.cssSnapshot.borderLeftWidth)},a={top:L(e.cssSnapshot.paddingTop),right:L(e.cssSnapshot.paddingRight),bottom:L(e.cssSnapshot.paddingBottom),left:L(e.cssSnapshot.paddingLeft)},i={top:e.rect.top,left:e.rect.left,width:Math.max(e.rect.width,0),height:Math.max(e.rect.height,0)},d={top:i.top-t.top,left:i.left-t.left,width:i.width+t.left+t.right,height:i.height+t.top+t.bottom},f={top:i.top+n.top,left:i.left+n.left,width:Math.max(i.width-n.left-n.right,0),height:Math.max(i.height-n.top-n.bottom,0)},b={top:f.top+a.top,left:f.left+a.left,width:Math.max(f.width-a.left-a.right,0),height:Math.max(f.height-a.top-a.bottom,0)};return{margin:d,border:i,padding:f,content:b}}function L(e){const t=Number.parseFloat(e);return Number.isFinite(t)?t:0}x.ReviewLensOverlay=ct,x.ReviewLensProvider=rt,x.buildElementTarget=W,x.createGoogleSheetsAdapter=le,x.normalizeReviewUrl=ge,x.useReviewLens=be,Object.defineProperty(x,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(x,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],r):(x=typeof globalThis<"u"?globalThis:x||self,r(x.ReviewLensReact={},x.jsxRuntime,x.React))})(this,(function(x,r,l){"use strict";const Ke=["https://www.googleapis.com/auth/spreadsheets","https://www.googleapis.com/auth/userinfo.email"].join(" "),Je="https://www.googleapis.com/oauth2/v3/userinfo";function le(e){const t=e.feedbackSheetName??"Feedback",n=e.messagesSheetName??"Messages",s=e.usersSheetName??"Users";let a,d;async function f(){return a??(a=tt(e.googleClientId)),a}async function b(c,w){const u=await f(),v=await fetch(`https://sheets.googleapis.com/v4/spreadsheets/${e.spreadsheetId}${c}`,{...w,headers:{Authorization:`Bearer ${u}`,"Content-Type":"application/json",...w==null?void 0:w.headers}});if(!v.ok)throw new Error(`Google Sheets request failed with ${v.status}`);return v.json()}async function p(c){return(await b(`/values/${encodeURIComponent(c)}`)).values??[]}return{async getCurrentUser(){if(!d){const c=await f(),w=await fetch(Je,{headers:{Authorization:`Bearer ${c}`}});if(!w.ok)throw new Error(`Google userinfo request failed with ${w.status}`);d=(await w.json()).email}if(!d)throw new Error("Google account did not return an email address");return{email:d}},async getPermissions(c){const[{email:w},u]=await Promise.all([this.getCurrentUser(),p(s)]),v=ne(u),E=w.toLowerCase(),N=v.find(A=>{var h;return((h=A.email)==null?void 0:h.toLowerCase())===E&&A.active!=="false"&&(!A.projectKey||A.projectKey===c)});return Ye((N==null?void 0:N.role)??"designer")},async listFeedback(c){return ne(await p(t)).map(pe).filter(u=>u!==null).filter(u=>u.projectKey===c.projectKey&&u.contentId===c.contentId&&u.normalizedPath===c.normalizedPath).sort((u,v)=>v.createdAt.localeCompare(u.createdAt))},async createFeedback(c){const w=new Date().toISOString(),u={...c,id:crypto.randomUUID(),attachments:[],createdAt:w,updatedAt:w};return await b(`/values/${encodeURIComponent(t)}:append?valueInputOption=RAW`,{method:"POST",body:JSON.stringify({values:[ce(u)]})}),u},async updateFeedback(c,w){const u=await p(t),v=u[0]??de,E=v.indexOf("id");if(E===-1)throw new Error(`Sheet ${t} is missing an id column`);const N=u.findIndex((m,k)=>k>0&&m[E]===c);if(N<1)throw new Error(`Feedback ${c} was not found`);const A=new Date().toISOString(),h=pe(he(v,u[N]));if(!h)throw new Error(`Feedback ${c} could not be parsed before updating`);const B={...h,...w,updatedAt:A},y=ce(B);return await b(`/values/${encodeURIComponent(t)}!A${N+1}:${et(de.length)}${N+1}?valueInputOption=RAW`,{method:"PUT",body:JSON.stringify({values:[y]})}),B},async listMessages(c){return ne(await p(n)).map(Ge).filter(u=>u!==null).filter(u=>u.feedbackId===c).sort((u,v)=>u.createdAt.localeCompare(v.createdAt))},async createMessage(c){const w={...c,id:crypto.randomUUID(),createdAt:new Date().toISOString()};return await b(`/values/${encodeURIComponent(n)}:append?valueInputOption=RAW`,{method:"POST",body:JSON.stringify({values:[Ve(w)]})}),w}}}const de=["id","projectKey","contentId","normalizedPath","originalUrl","selector","selectorStrategy","elementFingerprintJson","createdCssSnapshotJson","comment","status","severity","category","assigneeEmail","viewportWidth","viewportHeight","viewportPreset","screenshotUrl","screenshotThumbnailUrl","attachmentJson","authorEmail","createdAt","updatedAt","fixedCssSnapshotJson","fixedAt","fixedBy","resolvedAt","resolvedBy"],qe=["id","feedbackId","body","authorEmail","createdAt"];function ce(e){return[e.id,e.projectKey,e.contentId,e.normalizedPath,e.originalUrl,e.selector,e.selectorStrategy,JSON.stringify(e.elementFingerprint),JSON.stringify(e.createdCssSnapshot),e.comment,e.status,e.severity,e.category,e.assigneeEmail??"",String(e.viewportWidth),String(e.viewportHeight),e.viewportPreset,e.screenshotUrl??"",e.screenshotThumbnailUrl??"",JSON.stringify(e.attachments),e.authorEmail,e.createdAt,e.updatedAt,e.fixedCssSnapshot?JSON.stringify(e.fixedCssSnapshot):"",e.fixedAt??"",e.fixedBy??"",e.resolvedAt??"",e.resolvedBy??""]}function Ve(e){return qe.map(t=>e[t])}function ne(e){const[t,...n]=e;return t?n.map(s=>he(t,s)):[]}function he(e,t){return Object.fromEntries(e.map((n,s)=>[n,t[s]??""]))}function pe(e){return e.id?{id:e.id,projectKey:e.projectKey,contentId:e.contentId,normalizedPath:e.normalizedPath,originalUrl:e.originalUrl,selector:e.selector,selectorStrategy:e.selectorStrategy==="stable-attribute"?"stable-attribute":"css-path",elementFingerprint:re(e.elementFingerprintJson,{tagName:"",width:0,height:0}),createdCssSnapshot:ue(e.createdCssSnapshotJson),fixedCssSnapshot:e.fixedCssSnapshotJson?ue(e.fixedCssSnapshotJson):void 0,comment:e.comment,status:Xe(e.status),severity:Qe(e.severity),category:Ze(e.category),assigneeEmail:e.assigneeEmail||void 0,viewportWidth:Number(e.viewportWidth)||0,viewportHeight:Number(e.viewportHeight)||0,viewportPreset:Re(e.viewportPreset),screenshotUrl:e.screenshotUrl||void 0,screenshotThumbnailUrl:e.screenshotThumbnailUrl||void 0,attachments:re(e.attachmentJson,[]),authorEmail:e.authorEmail,createdAt:e.createdAt,updatedAt:e.updatedAt,fixedAt:e.fixedAt||void 0,fixedBy:e.fixedBy||void 0,resolvedAt:e.resolvedAt||void 0,resolvedBy:e.resolvedBy||void 0}:null}function Ge(e){return!e.id||!e.feedbackId?null:{id:e.id,feedbackId:e.feedbackId,body:e.body,authorEmail:e.authorEmail,createdAt:e.createdAt}}function re(e,t){try{return e?JSON.parse(e):t}catch{return t}}function ue(e){const t=re(e,{});return{margin:t.margin??"",marginTop:t.marginTop??"",marginRight:t.marginRight??"",marginBottom:t.marginBottom??"",marginLeft:t.marginLeft??"",padding:t.padding??"",paddingTop:t.paddingTop??"",paddingRight:t.paddingRight??"",paddingBottom:t.paddingBottom??"",paddingLeft:t.paddingLeft??"",border:t.border??"",borderTopWidth:t.borderTopWidth??"",borderRightWidth:t.borderRightWidth??"",borderBottomWidth:t.borderBottomWidth??"",borderLeftWidth:t.borderLeftWidth??"",fontFamily:t.fontFamily??"",fontSize:t.fontSize??"",lineHeight:t.lineHeight??"",color:t.color??"",backgroundColor:t.backgroundColor??"",borderRadius:t.borderRadius??"",width:t.width??0,height:t.height??0}}function Ye(e){return e==="admin"?["create","read","reply","update","assign"]:e==="developer"?["read","reply","update","assign"]:["create","read","reply"]}function Xe(e){return e==="in_progress"||e==="needs_clarification"||e==="fixed"||e==="wontfix"||e==="resolved"?e:"open"}function Qe(e){return e==="low"||e==="high"?e:"medium"}function Ze(e){return e==="visual"||e==="copy"||e==="accessibility"||e==="responsive"?e:"bug"}function Re(e){return e==="mobile"||e==="tablet"||e==="desktop"?e:"custom"}function et(e){let t=e,n="";for(;t>0;){const s=(t-1)%26;n=String.fromCharCode(65+s)+n,t=Math.floor((t-s)/26)}return n}async function tt(e){return await nt(),new Promise((t,n)=>{var a;const s=(a=window.google)==null?void 0:a.accounts.oauth2.initTokenClient({client_id:e,scope:Ke,callback:d=>{if(d.error||!d.access_token){n(new Error(d.error??"Google OAuth did not return an access token"));return}t(d.access_token)}});s==null||s.requestAccessToken({prompt:""})})}function nt(){var e;return(e=window.google)!=null&&e.accounts.oauth2?Promise.resolve():new Promise((t,n)=>{const s=document.querySelector('script[src="https://accounts.google.com/gsi/client"]');if(s){s.addEventListener("load",()=>t(),{once:!0}),s.addEventListener("error",()=>n(new Error("Google Identity failed to load")),{once:!0});return}const a=document.createElement("script");a.src="https://accounts.google.com/gsi/client",a.async=!0,a.defer=!0,a.onload=()=>t(),a.onerror=()=>n(new Error("Google Identity failed to load")),document.head.append(a)})}function ge(e){return new URL(e,window.location.href).pathname.replace(/\/+$/,"")||"/"}const fe=l.createContext(null);function rt({config:e,children:t}){const n=l.useMemo(()=>e.adapter?e.adapter:le({googleClientId:ve(e.googleClientId,"googleClientId"),spreadsheetId:ve(e.spreadsheetId,"spreadsheetId"),feedbackSheetName:e.sheetName??"Feedback"}),[e.adapter,e.googleClientId,e.sheetName,e.spreadsheetId]),s=e.currentUrl??window.location.href,a=(e.normalizeUrl??ge)(s),[d,f]=l.useState(),[b,p]=l.useState([]),[c,w]=l.useState([]),u=l.useCallback(async()=>{const y=await n.listFeedback({projectKey:e.projectKey,contentId:e.contentId,normalizedPath:a});w(y)},[n,e.contentId,e.projectKey,a]);l.useEffect(()=>{let y=!0;async function m(){const[k,$]=await Promise.all([n.getCurrentUser(),n.getPermissions(e.projectKey)]);y&&(f(k),p($),await u())}return m(),()=>{y=!1}},[n,e.projectKey,u]);const v=l.useCallback(async y=>{const m=await n.createFeedback(y);return w(k=>[m,...k]),m},[n]),E=l.useCallback(async(y,m)=>{const k=await n.updateFeedback(y,m);return w($=>$.map(z=>z.id===y?k:z)),k},[n]),N=l.useCallback(y=>n.listMessages(y),[n]),A=l.useCallback(y=>n.createMessage(y),[n]),h=l.useCallback(async(y,m)=>{const k=e.uploadAttachment??n.uploadAttachment;if(!k)throw new Error("Review Lens attachment upload is not configured");return k(y,m)},[n,e]),B=l.useMemo(()=>({config:e,adapter:n,currentUser:d,permissions:b,feedback:c,normalizedPath:a,refreshFeedback:u,createFeedback:v,updateFeedback:E,listMessages:N,createMessage:A,uploadAttachment:h}),[n,e,v,d,c,a,b,u,E,N,A,h]);return r.jsx(fe.Provider,{value:B,children:t})}function be(){const e=l.useContext(fe);if(!e)throw new Error("useReviewLens must be used inside ReviewLensProvider");return e}function ve(e,t){if(!e)throw new Error(`review-lens-react requires config.${t} when no adapter is provided`);return e}const st=["data-review-id","data-testid","data-test-id","aria-label","name"];function W(e){const t=e.getBoundingClientRect(),n=it(e);return{selector:n.selector,selectorStrategy:n.strategy,fingerprint:ot(e,t),cssSnapshot:lt(e,t),rect:t}}function it(e){for(const t of st){const n=e.getAttribute(t);if(n)return{selector:`[${t}="${we(n)}"]`,strategy:"stable-attribute"}}return e.id?{selector:`#${we(e.id)}`,strategy:"stable-attribute"}:{selector:at(e),strategy:"css-path"}}function at(e){const t=[];let n=e;for(;n&&n.nodeType===Node.ELEMENT_NODE&&n!==document.body;){const s=n.parentElement,a=n.tagName.toLowerCase();if(!s){t.unshift(a);break}const d=n.tagName,f=Array.from(s.children).filter(p=>p.tagName===d),b=f.indexOf(n)+1;t.unshift(f.length>1?`${a}:nth-of-type(${b})`:a),n=s}return t.join(" > ")}function ot(e,t){var n;return{tagName:e.tagName.toLowerCase(),id:e.id||void 0,className:e.getAttribute("class")||void 0,textSnippet:((n=e.textContent)==null?void 0:n.trim().slice(0,80))||void 0,ariaLabel:e.getAttribute("aria-label")||void 0,width:Math.round(t.width),height:Math.round(t.height)}}function lt(e,t){const n=window.getComputedStyle(e);return{margin:se(n.marginTop,n.marginRight,n.marginBottom,n.marginLeft),marginTop:n.marginTop,marginRight:n.marginRight,marginBottom:n.marginBottom,marginLeft:n.marginLeft,padding:se(n.paddingTop,n.paddingRight,n.paddingBottom,n.paddingLeft),paddingTop:n.paddingTop,paddingRight:n.paddingRight,paddingBottom:n.paddingBottom,paddingLeft:n.paddingLeft,border:se(n.borderTopWidth,n.borderRightWidth,n.borderBottomWidth,n.borderLeftWidth),borderTopWidth:n.borderTopWidth,borderRightWidth:n.borderRightWidth,borderBottomWidth:n.borderBottomWidth,borderLeftWidth:n.borderLeftWidth,fontFamily:n.fontFamily,fontSize:n.fontSize,lineHeight:n.lineHeight,color:n.color,backgroundColor:n.backgroundColor,borderRadius:n.borderRadius,width:Math.round(t.width),height:Math.round(t.height)}}function se(e,t,n,s){return e===t&&t===n&&n===s?e:`${e} ${t} ${n} ${s}`}function we(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/["\\]/g,"\\$&")}const dt=[{label:"Desktop",value:"desktop"},{label:"Tablet",value:"tablet"},{label:"Mobile",value:"mobile"}],me=["open","in_progress","needs_clarification","fixed","wontfix","resolved"],ye=["low","medium","high"],Se=["bug","visual","copy","accessibility","responsive"],Z={open:"Open",in_progress:"In progress",needs_clarification:"Needs clarification",fixed:"Fixed",wontfix:"Won't fix",resolved:"Resolved"},H={low:"Low",medium:"Medium",high:"High"},j={bug:"Bug",visual:"Visual",copy:"Copy",accessibility:"Accessibility",responsive:"Responsive"};function ct({open:e,onOpenChange:t,placement:n="top-right",showResolved:s=!1,syncSelectionToUrl:a=!1,responsivePresets:d=dt}){var Oe;const{adapter:f,config:b,currentUser:p,feedback:c,normalizedPath:w,permissions:u,createFeedback:v,updateFeedback:E,listMessages:N,createMessage:A,uploadAttachment:h}=be(),[B,y]=l.useState(),[m,k]=l.useState(),[$,z]=l.useState(""),[xe,Mt]=l.useState("medium"),[Ae,Tt]=l.useState("visual"),[Le,Fe]=l.useState(""),[Me,It]=l.useState(((Oe=d[0])==null?void 0:Oe.value)??"desktop"),[S,J]=l.useState(),[M,P]=l.useState("review"),[Bt,Te]=l.useState(!1),[q,Ie]=l.useState("all"),[V,Be]=l.useState("all"),[G,$e]=l.useState("all"),[Y,Pe]=l.useState("all"),[X,_e]=l.useState("all"),[$t,Pt]=l.useState(!1),[_t,Ue]=l.useState({}),[ie,ae]=l.useState(""),ee=l.useRef(null),T=!!p,I=u.includes("create"),We=u.includes("reply"),De=u.includes("update"),Ut=u.includes("assign"),U=B??m,Wt=!!m,Dt=!!(b.captureScreenshot&&(b.uploadAttachment||f.uploadAttachment)),zt=l.useMemo(()=>{const i=c.map(g=>g.assigneeEmail).filter(g=>!!g);return p!=null&&p.email&&i.push(p.email),Array.from(new Set(i)).sort((g,o)=>g.localeCompare(o))},[p==null?void 0:p.email,c]),F=l.useMemo(()=>c.filter(i=>s||i.status!=="resolved").filter(i=>q==="all"||i.status===q).filter(i=>V==="all"||i.severity===V).filter(i=>G==="all"||i.category===G).filter(i=>Y==="all"||i.assigneeEmail===Y).filter(i=>X==="all"||i.viewportPreset===X),[Y,G,c,V,s,q,X]),Ht=[q,V,G,Y,X].filter(i=>i!=="all").length;l.useEffect(()=>{e||(y(void 0),k(void 0),z(""),ae(""),P("review"))},[e]),l.useEffect(()=>{T||(y(void 0),k(void 0))},[T]),l.useEffect(()=>{!m||M!=="review"||window.requestAnimationFrame(()=>{var i,g,o;(g=(i=ee.current)==null?void 0:i.scrollIntoView)==null||g.call(i,{block:"nearest"}),(o=ee.current)==null||o.focus()})},[m,M]),l.useEffect(()=>{if(!S)return;let i=!0;return N(S.id).then(g=>{i&&Ue(o=>({...o,[S.id]:g}))}),()=>{i=!1}},[N,S]),l.useEffect(()=>{if(!e||!a||S||c.length===0)return;const i=new URL(window.location.href).searchParams.get("reviewLensFeedback"),g=c.find(o=>o.id===i);g&&Q(g,{syncUrl:!1})},[c,e,S,a]),l.useEffect(()=>{if(!e)return;function i(o){var C;if(o.key==="Shift"&&Te(!0),o.key==="Escape"){o.preventDefault(),t==null||t(!1);return}xt(o.target)||((o.key==="n"||o.key==="ArrowDown")&&(o.preventDefault(),ze(1)),(o.key==="p"||o.key==="ArrowUp")&&(o.preventDefault(),ze(-1)),o.key==="c"&&(o.preventDefault(),P("review"),(C=ee.current)==null||C.focus()),o.key==="f"&&S&&De&&(o.preventDefault(),je(S)))}function g(o){o.key==="Shift"&&Te(!1)}return window.addEventListener("keydown",i),window.addEventListener("keyup",g),()=>{window.removeEventListener("keydown",i),window.removeEventListener("keyup",g)}});const oe=l.useCallback(i=>{const g=i.target instanceof Element?i.target:null;if(g)return g.closest("[data-review-lens-ui]")?null:g;const o=document.elementFromPoint(i.clientX,i.clientY);return!o||o.closest("[data-review-lens-ui]")?null:o},[]);if(l.useEffect(()=>{if(!e||!T)return;function i(o){const C=oe(o);y(C?W(C):void 0)}function g(o){const C=oe(o);C&&(o.preventDefault(),o.stopPropagation(),k(W(C)),P("review"))}return window.addEventListener("mousemove",i,!0),window.addEventListener("click",g,!0),()=>{window.removeEventListener("mousemove",i,!0),window.removeEventListener("click",g,!0)}},[T,oe,e]),!e)return null;function Q(i,g={syncUrl:!0}){var C;if(J(i),k(void 0),P("feedback"),a&&g.syncUrl!==!1){const te=new URL(window.location.href);te.searchParams.set("reviewLensFeedback",i.id),window.history.replaceState({},"",te)}const o=D(i.selector);if(!o){y(void 0);return}(C=o.scrollIntoView)==null||C.call(o,{behavior:"smooth",block:"center",inline:"center"}),window.requestAnimationFrame(()=>{y(W(o))})}function ze(i){if(F.length===0)return;const g=S?F.findIndex(C=>C.id===S.id):-1,o=g<0?i>0?0:F.length-1:(g+i+F.length)%F.length;Q(F[o])}async function He(){if(!m||!$.trim()||!p||!I)return;let i=await v({projectKey:b.projectKey,contentId:b.contentId,normalizedPath:w,originalUrl:b.currentUrl??window.location.href,selector:m.selector,selectorStrategy:m.selectorStrategy,elementFingerprint:m.fingerprint,createdCssSnapshot:m.cssSnapshot,comment:$.trim(),status:"open",severity:xe,category:Ae,assigneeEmail:Le.trim()||void 0,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight,viewportPreset:Me,screenshotUrl:void 0,screenshotThumbnailUrl:void 0,authorEmail:p.email});if(b.captureScreenshot)try{const g=await b.captureScreenshot(m),o=await h(i.id,{type:"screenshot",data:g,createdBy:p.email});i=await E(i.id,{attachments:[o],screenshotUrl:o.url,screenshotThumbnailUrl:o.thumbnailUrl})}catch{}z(""),Fe(""),k(void 0),y(void 0),P("feedback"),J(i)}async function jt(i,g){const o=new Date().toISOString(),C=g==="resolved"?{status:g,resolvedAt:o,resolvedBy:p==null?void 0:p.email}:{status:g},te=await E(i.id,C);J(te)}async function je(i){const g=D(i.selector);if(!g||!p)return;const o=W(g),C=await E(i.id,{status:"fixed",fixedCssSnapshot:o.cssSnapshot,fixedAt:new Date().toISOString(),fixedBy:p.email});J(C)}async function Ot(i){if(!ie.trim()||!p||!We)return;const g=await A({feedbackId:i.id,body:ie.trim(),authorEmail:p.email});Ue(o=>({...o,[i.id]:[...o[i.id]??[],g]})),ae("")}return r.jsxs("div",{className:"review-lens-root","data-review-lens-ui":!0,children:[T&&U?r.jsx(ft,{target:U,locked:!!m}):null,T&&m&&B&&Bt?r.jsx(bt,{from:m,to:B}):null,T?r.jsxs(r.Fragment,{children:[r.jsx(vt,{feedback:F,selectedFeedback:S,onSelect:Q}),r.jsx(mt,{feedback:F,selectedFeedback:S,onSelect:Q})]}):null,r.jsxs("aside",{className:`review-lens-panel review-lens-panel--${n}`,"data-review-lens-ui":!0,children:[r.jsxs("header",{className:"review-lens-panel__header",children:[r.jsxs("div",{children:[r.jsx("p",{className:"review-lens-kicker",children:"Review Lens"}),r.jsx("h2",{children:M==="summary"?"Summary":M==="feedback"?"Feedback":m?"Element locked":"Inspecting"})]}),r.jsx("button",{type:"button",onClick:()=>t==null?void 0:t(!1),children:"Close"})]}),r.jsxs("div",{className:"review-lens-panel__body",children:[r.jsxs("div",{className:"review-lens-mode-switch",role:"tablist","aria-label":"Review Lens mode",children:[r.jsx("button",{type:"button",role:"tab","aria-selected":M==="review",onClick:()=>P("review"),children:"Review"}),r.jsxs("button",{type:"button",role:"tab","aria-selected":M==="feedback",onClick:()=>P("feedback"),children:["Feedback ",r.jsx("span",{children:F.length})]}),r.jsx("button",{type:"button",role:"tab","aria-selected":M==="summary",onClick:()=>P("summary"),children:"Summary"})]}),M==="review"?r.jsxs("div",{className:"review-lens-review-pane",role:"tabpanel",children:[r.jsxs("div",{className:"review-lens-inspection",children:[T?null:r.jsx("p",{children:"Authenticate with Google to inspect this page."}),T&&U?r.jsxs(r.Fragment,{children:[r.jsx(yt,{target:U}),r.jsx(ke,{title:"Accessibility",items:St(U)}),r.jsx(ke,{title:"Design tokens",items:kt(U.cssSnapshot,b.designTokens)})]}):null,T&&!U?r.jsx("p",{children:"Move over the app to inspect."}):null]}),Wt?r.jsx("div",{className:"review-lens-composer-panel",children:r.jsxs("form",{className:"review-lens-feedback-form",onSubmit:i=>{i.preventDefault(),He()},children:[r.jsx("label",{htmlFor:"review-lens-comment",children:"New feedback"}),r.jsx("textarea",{ref:ee,id:"review-lens-comment",value:$,disabled:!I,onChange:i=>z(i.target.value),onKeyDown:i=>{i.key==="Enter"&&i.metaKey&&(i.preventDefault(),He())},placeholder:I?"Describe the UX issue...":"You do not have permission to comment."}),r.jsxs("div",{className:"review-lens-form-grid",children:[r.jsxs("label",{children:["Severity",r.jsx("select",{value:xe,onChange:i=>Mt(i.target.value),disabled:!I,children:ye.map(i=>r.jsx("option",{value:i,children:H[i]},i))})]}),r.jsxs("label",{children:["Type",r.jsx("select",{value:Ae,onChange:i=>Tt(i.target.value),disabled:!I,children:Se.map(i=>r.jsx("option",{value:i,children:j[i]},i))})]}),r.jsxs("label",{children:["Assignee",r.jsx("input",{value:Le,onChange:i=>Fe(i.target.value),disabled:!I,placeholder:"optional@email.com"})]}),r.jsxs("label",{children:["Viewport",r.jsx("select",{value:Me,onChange:i=>It(i.target.value),disabled:!I,children:d.map(i=>r.jsx("option",{value:i.value,children:i.label},i.value))})]})]}),I?r.jsxs("p",{className:"review-lens-feedback-form__hint",children:["Press ",r.jsx("kbd",{children:"Command"})," + ",r.jsx("kbd",{children:"Enter"})," to submit.",Dt?" Screenshot capture runs after save.":""]}):null,r.jsx("div",{className:"review-lens-actions",children:r.jsx("button",{type:"submit",disabled:!$.trim()||!I,children:"Save feedback"})})]})}):null]}):null,M==="feedback"?r.jsxs("div",{className:"review-lens-comments",children:[r.jsx(ht,{open:$t,activeCount:Ht,statusFilter:q,severityFilter:V,categoryFilter:G,assigneeFilter:Y,viewportFilter:X,assignees:zt,responsivePresets:d,onStatusChange:Ie,onSeverityChange:Be,onCategoryChange:$e,onAssigneeChange:Pe,onViewportChange:_e,onToggle:()=>Pt(i=>!i),onClear:()=>{Ie("all"),Be("all"),$e("all"),Pe("all"),_e("all")}}),r.jsxs("div",{className:"review-lens-list-panel",children:[r.jsxs("div",{className:"review-lens-comments__header",children:[r.jsx("h3",{children:"All feedback"}),r.jsx("span",{children:F.length})]}),r.jsxs("div",{className:"review-lens-comments__list",children:[F.length===0?r.jsx("p",{children:"No feedback for this view."}):null,F.map(i=>r.jsx(pt,{item:i,selected:(S==null?void 0:S.id)===i.id,onSelect:Q},i.id))]})]}),S?r.jsxs("div",{className:"review-lens-selected-panel",children:[r.jsx("div",{className:"review-lens-selected-panel__label",children:"Selected feedback"}),r.jsx(ut,{item:S,messages:_t[S.id]??[],messageDraft:ie,canReply:We,canUpdate:De,canAssign:Ut,onMessageDraftChange:ae,onSubmitMessage:()=>void Ot(S),onStatusChange:i=>void jt(S,i),onAssigneeChange:i=>void E(S.id,{assigneeEmail:i.trim()||void 0}).then(J),onMarkFixed:()=>void je(S)},S.id)]}):r.jsxs("div",{className:"review-lens-selected-panel review-lens-selected-panel--empty",children:[r.jsx("div",{className:"review-lens-selected-panel__label",children:"Selected feedback"}),r.jsx("p",{children:"Select a feedback item above to review status, assignment, drift, and replies."})]})]}):null,M==="summary"?r.jsx(gt,{feedback:c}):null]})]})]})}function ht({open:e,activeCount:t,statusFilter:n,severityFilter:s,categoryFilter:a,assigneeFilter:d,viewportFilter:f,assignees:b,responsivePresets:p,onStatusChange:c,onSeverityChange:w,onCategoryChange:u,onAssigneeChange:v,onViewportChange:E,onToggle:N,onClear:A}){return r.jsxs("div",{className:"review-lens-filter-shell",children:[r.jsxs("div",{className:"review-lens-filter-bar",children:[r.jsxs("button",{type:"button","aria-expanded":e,onClick:N,children:["Filters",t>0?r.jsx("span",{children:t}):null]}),t>0?r.jsx("button",{type:"button",onClick:A,children:"Clear"}):null]}),e?r.jsxs("div",{className:"review-lens-filters",children:[r.jsxs("label",{children:["Status",r.jsxs("select",{"aria-label":"Filter status",value:n,onChange:h=>c(h.target.value),children:[r.jsx("option",{value:"all",children:"All statuses"}),me.map(h=>r.jsx("option",{value:h,children:Z[h]},h))]})]}),r.jsxs("label",{children:["Priority",r.jsxs("select",{"aria-label":"Filter severity",value:s,onChange:h=>w(h.target.value),children:[r.jsx("option",{value:"all",children:"All priorities"}),ye.map(h=>r.jsx("option",{value:h,children:H[h]},h))]})]}),r.jsxs("label",{children:["Type",r.jsxs("select",{"aria-label":"Filter type",value:a,onChange:h=>u(h.target.value),children:[r.jsx("option",{value:"all",children:"All types"}),Se.map(h=>r.jsx("option",{value:h,children:j[h]},h))]})]}),r.jsxs("label",{children:["Assignee",r.jsxs("select",{"aria-label":"Filter assignee",value:d,onChange:h=>v(h.target.value),children:[r.jsx("option",{value:"all",children:"All assignees"}),b.map(h=>r.jsx("option",{value:h,children:h},h))]})]}),r.jsxs("label",{children:["Viewport",r.jsxs("select",{"aria-label":"Filter viewport",value:f,onChange:h=>E(h.target.value),children:[r.jsx("option",{value:"all",children:"All viewports"}),p.map(h=>r.jsx("option",{value:h.value,children:h.label},h.value))]})]})]}):null]})}function pt({item:e,selected:t,onSelect:n}){const s=Ce(e);return r.jsxs("article",{tabIndex:0,className:["review-lens-comment",`review-lens-comment--${e.severity}`,t?"review-lens-comment--selected":""].filter(Boolean).join(" "),onClick:()=>n(e),onKeyDown:a=>{(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),n(e))},children:[r.jsxs("div",{className:"review-lens-comment__header",children:[r.jsx("span",{children:Z[e.status]}),r.jsx("strong",{children:H[e.severity]})]}),r.jsxs("div",{className:"review-lens-comment__content",children:[r.jsx("p",{children:e.comment}),r.jsxs("span",{children:[e.authorEmail,e.assigneeEmail?` -> ${e.assigneeEmail}`:""]})]}),r.jsxs("div",{className:"review-lens-tags",children:[r.jsx("span",{children:j[e.category]}),r.jsx("span",{children:e.viewportPreset}),r.jsx("span",{children:s.label})]})]})}function ut({item:e,messages:t,messageDraft:n,canReply:s,canUpdate:a,canAssign:d,onMessageDraftChange:f,onSubmitMessage:b,onStatusChange:p,onAssigneeChange:c,onMarkFixed:w}){const u=Ce(e);return r.jsxs("section",{className:"review-lens-detail","aria-label":"Selected feedback detail",children:[r.jsxs("div",{className:"review-lens-detail__header",children:[r.jsxs("h3",{children:[j[e.category]," feedback"]}),r.jsx("strong",{children:H[e.severity]})]}),r.jsx("blockquote",{children:e.comment}),r.jsxs("dl",{className:"review-lens-detail-meta",children:[r.jsxs("div",{children:[r.jsx("dt",{children:"Target"}),r.jsx("dd",{children:u.label})]}),r.jsxs("div",{children:[r.jsx("dt",{children:"Viewport"}),r.jsx("dd",{children:e.viewportPreset})]}),e.screenshotUrl?r.jsxs("div",{children:[r.jsx("dt",{children:"Evidence"}),r.jsx("dd",{children:r.jsx("a",{href:e.screenshotUrl,target:"_blank",rel:"noreferrer",children:"Screenshot"})})]}):null]}),r.jsxs("div",{className:"review-lens-form-grid",children:[r.jsxs("label",{children:["Status",r.jsx("select",{value:e.status,disabled:!a,onChange:v=>p(v.target.value),children:me.map(v=>r.jsx("option",{value:v,children:Z[v]},v))})]}),r.jsxs("label",{children:["Assignee",r.jsx("input",{defaultValue:e.assigneeEmail??"",disabled:!d,onBlur:v=>c(v.target.value),placeholder:"optional@email.com"})]})]}),r.jsxs("div",{className:"review-lens-status-actions",children:[r.jsx("button",{type:"button",className:"review-lens-button-secondary",disabled:!a,onClick:w,children:"Mark fixed"}),r.jsx("button",{type:"button",className:"review-lens-button-primary",disabled:!a,onClick:()=>p("resolved"),children:"Resolve"})]}),r.jsxs("div",{className:"review-lens-thread",children:[r.jsxs("div",{className:"review-lens-thread__header",children:[r.jsx("h3",{children:"Thread"}),r.jsx("span",{children:t.length})]}),t.length===0?r.jsx("p",{children:"No replies yet."}):null,t.map(v=>r.jsxs("div",{className:"review-lens-thread__message",children:[r.jsx("p",{children:v.body}),r.jsx("span",{children:v.authorEmail})]},v.id)),r.jsx("textarea",{"aria-label":"Reply",value:n,disabled:!s,onChange:v=>f(v.target.value),placeholder:s?"Reply...":"You do not have permission to reply."}),r.jsx("div",{className:"review-lens-actions",children:r.jsx("button",{type:"button",disabled:!n.trim()||!s,onClick:b,children:"Reply"})})]})]})}function gt({feedback:e}){return r.jsxs("div",{className:"review-lens-summary",role:"tabpanel",children:[r.jsx(O,{title:"Status",values:K(e,t=>Z[t.status])}),r.jsx(O,{title:"Severity",values:K(e,t=>H[t.severity])}),r.jsx(O,{title:"Type",values:K(e,t=>j[t.category])}),r.jsx(O,{title:"Assignee",values:K(e,t=>t.assigneeEmail??"Unassigned")}),r.jsx(O,{title:"Viewport",values:K(e,t=>t.viewportPreset)})]})}function O({title:e,values:t}){return r.jsxs("section",{children:[r.jsx("h3",{children:e}),r.jsx("dl",{children:t.map(([n,s])=>r.jsxs("div",{children:[r.jsx("dt",{children:n}),r.jsx("dd",{children:s})]},n))})]})}function ft({target:e,locked:t}){const n=Ft(e),s=Nt(e.fingerprint);return r.jsxs("div",{className:t?"review-lens-highlight review-lens-highlight--locked":"review-lens-highlight",style:{top:n.margin.top,left:n.margin.left,width:n.margin.width,height:n.margin.height},children:[r.jsx("div",{className:"review-lens-highlight__border",style:{top:n.border.top-n.margin.top,left:n.border.left-n.margin.left,width:n.border.width,height:n.border.height}}),r.jsx("div",{className:"review-lens-highlight__padding",style:{top:n.padding.top-n.margin.top,left:n.padding.left-n.margin.left,width:n.padding.width,height:n.padding.height}}),r.jsx("div",{className:"review-lens-highlight__content",style:{top:n.content.top-n.margin.top,left:n.content.left-n.margin.left,width:n.content.width,height:n.content.height}}),r.jsxs("div",{className:"review-lens-highlight__label",children:[r.jsx("strong",{children:s}),r.jsxs("span",{children:[Math.round(e.rect.width)," x ",Math.round(e.rect.height)]})]})]})}function bt({from:e,to:t}){const n=Et(e.rect,t.rect);return n.length===0?null:r.jsx(r.Fragment,{children:n.map(s=>r.jsx("div",{className:`review-lens-distance review-lens-distance--${s.axis}`,style:{top:s.top,left:s.left,width:s.width,height:s.height},children:r.jsx("span",{children:s.label})},s.key))})}function vt({feedback:e,selectedFeedback:t,onSelect:n}){return r.jsx(r.Fragment,{children:e.map(s=>r.jsx(wt,{feedback:s,selected:(t==null?void 0:t.id)===s.id,onSelect:n},s.id))})}function wt({feedback:e,selected:t,onSelect:n}){const s=l.useRef(null);return l.useLayoutEffect(()=>{let a=0;const d=()=>{a=0;const b=s.current,p=D(e.selector),c=p==null?void 0:p.getBoundingClientRect();!b||!c||(b.style.top=`${c.top}px`,b.style.left=`${c.right}px`,b.hidden=c.bottom<0||c.top>window.innerHeight)},f=()=>{a||(a=window.requestAnimationFrame(d))};return d(),window.addEventListener("scroll",f,!0),window.addEventListener("resize",f),()=>{a&&window.cancelAnimationFrame(a),window.removeEventListener("scroll",f,!0),window.removeEventListener("resize",f)}},[e.selector]),r.jsx("button",{ref:s,type:"button",className:t?"review-lens-marker review-lens-marker--selected":"review-lens-marker",onClick:()=>n(e),"aria-label":`Open feedback from ${e.authorEmail}`})}function mt({feedback:e,selectedFeedback:t,onSelect:n}){const s=e.map(a=>{const d=D(a.selector),f=d==null?void 0:d.getBoundingClientRect(),b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight,window.innerHeight);return!f||b<=0?null:{item:a,top:Math.min(100,Math.max(0,(f.top+window.scrollY)/b*100))}}).filter(a=>a!==null);return s.length===0?null:r.jsx("div",{className:"review-lens-minimap","data-review-lens-ui":!0,"aria-label":"Feedback map",children:s.map(a=>r.jsx("button",{type:"button",className:(t==null?void 0:t.id)===a.item.id?"review-lens-minimap__point review-lens-minimap__point--selected":"review-lens-minimap__point",style:{top:`${a.top}%`},onClick:()=>n(a.item),"aria-label":`Jump to feedback from ${a.item.authorEmail}`},a.item.id))})}function yt({target:e}){const t=[["Selector",e.selector],["Size",`${e.cssSnapshot.width} x ${e.cssSnapshot.height}`],["Margin",e.cssSnapshot.margin],["Padding",e.cssSnapshot.padding],["Border",e.cssSnapshot.border],["Radius",e.cssSnapshot.borderRadius],["Font",`${e.cssSnapshot.fontSize} / ${e.cssSnapshot.lineHeight}`],["Family",e.cssSnapshot.fontFamily],["Color",e.cssSnapshot.color],["Background",e.cssSnapshot.backgroundColor]];return r.jsx("dl",{className:"review-lens-metrics",children:t.map(([n,s])=>r.jsxs("div",{children:[r.jsx("dt",{children:n}),r.jsx("dd",{children:s})]},n))})}function ke({title:e,items:t}){return r.jsxs("section",{className:"review-lens-insights",children:[r.jsx("h3",{children:e}),t.length===0?r.jsx("p",{children:"No issues detected."}):null,t.length>0?r.jsx("ul",{children:t.map(n=>r.jsx("li",{children:n},n))}):null]})}function D(e){try{return document.querySelector(e)}catch{return null}}function Ce(e){const t=D(e.selector);if(!t)return{label:"Target missing",level:"warning"};const n=W(t);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"}}function St(e){var p;const t=D(e.selector);if(!t)return["Selected element is no longer available."];const n=[],s=t.tagName.toLowerCase(),a=t.getAttribute("role"),d=["button","a","input","select","textarea"].includes(s)||a==="button"||a==="link",f=t.getAttribute("aria-label")||t.getAttribute("title")||((p=t.textContent)==null?void 0:p.trim());d&&!f&&n.push("Interactive element has no accessible name."),d&&(e.rect.width<44||e.rect.height<44)&&n.push("Tap target is smaller than 44 x 44."),s==="img"&&!t.getAttribute("alt")&&n.push("Image is missing alt text.");const b=/^h[1-6]$/.test(s)?Number(s.slice(1)):0;return b>1&&!document.querySelector(`h${b-1}`)&&n.push("Heading may skip the previous level."),At(e.cssSnapshot.color,e.cssSnapshot.backgroundColor)&&n.push("Text contrast may be low."),n}function kt(e,t={}){const n=[];return _("Padding",e.padding,t.spacing,n,{allowComposite:!0}),_("Margin",e.margin,t.spacing,n,{allowComposite:!0}),_("Font size",e.fontSize,t.fontSize,n),_("Line height",e.lineHeight,t.lineHeight,n),_("Text color",e.color,t.color,n),_("Background",e.backgroundColor,t.color,n),_("Radius",e.borderRadius,t.radius,n,{allowComposite:!0}),n}function _(e,t,n,s,a={}){!n||n.length===0||!t||Ct(t,n,a)||s.push(`${e} ${t} is outside configured tokens.`)}function Ct(e,t,n={}){if(t.includes(e))return!0;if(!n.allowComposite)return!1;const s=e.trim().split(/\s+/);return s.length>1&&s.every(a=>t.includes(a))}function Nt(e){const t=e.id?`#${e.id}`:"",n=e.className?`.${e.className.split(/\s+/).filter(Boolean).slice(0,2).join(".")}`:"",s=e.ariaLabel?`[aria-label="${e.ariaLabel}"]`:"";return`${e.tagName}${t}${n}${s}`||e.tagName}function Et(e,t){const n=[],s=(Math.max(e.left,t.left)+Math.min(e.right,t.right))/2,a=(Math.max(e.top,t.top)+Math.min(e.bottom,t.bottom))/2;if(e.right<=t.left||t.right<=e.left){const d=e.right<=t.left?e.right:t.right,f=e.right<=t.left?t.left:e.left;n.push({key:"horizontal",axis:"horizontal",top:Ne(a,0,window.innerHeight),left:d,width:Math.max(f-d,1),height:1,label:`${Math.round(f-d)}px`})}if(e.bottom<=t.top||t.bottom<=e.top){const d=e.bottom<=t.top?e.bottom:t.bottom,f=e.bottom<=t.top?t.top:e.top;n.push({key:"vertical",axis:"vertical",top:d,left:Ne(s,0,window.innerWidth),width:1,height:Math.max(f-d,1),label:`${Math.round(f-d)}px`})}return n}function Ne(e,t,n){return Math.min(Math.max(e,t),n)}function K(e,t){const n=new Map;for(const s of e){const a=t(s);n.set(a,(n.get(a)??0)+1)}return Array.from(n.entries()).sort((s,a)=>a[1]-s[1]||s[0].localeCompare(a[0]))}function xt(e){return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement||e instanceof HTMLElement&&e.isContentEditable}function At(e,t){const n=Ee(e),s=Ee(t);return!n||!s||s.alpha===0?!1:Lt(n,s)<4.5}function Ee(e){const t=e.match(/rgba?\(([^)]+)\)/);if(!t)return null;const[n,s,a,d="1"]=t[1].split(",").map(f=>f.trim());return{red:Number(n),green:Number(s),blue:Number(a),alpha:Number(d)}}function Lt(e,t){const n=Math.max(R(e),R(t)),s=Math.min(R(e),R(t));return(n+.05)/(s+.05)}function R(e){const t=[e.red,e.green,e.blue].map(n=>{const s=n/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4});return t[0]*.2126+t[1]*.7152+t[2]*.0722}function Ft(e){const t={top:L(e.cssSnapshot.marginTop),right:L(e.cssSnapshot.marginRight),bottom:L(e.cssSnapshot.marginBottom),left:L(e.cssSnapshot.marginLeft)},n={top:L(e.cssSnapshot.borderTopWidth),right:L(e.cssSnapshot.borderRightWidth),bottom:L(e.cssSnapshot.borderBottomWidth),left:L(e.cssSnapshot.borderLeftWidth)},s={top:L(e.cssSnapshot.paddingTop),right:L(e.cssSnapshot.paddingRight),bottom:L(e.cssSnapshot.paddingBottom),left:L(e.cssSnapshot.paddingLeft)},a={top:e.rect.top,left:e.rect.left,width:Math.max(e.rect.width,0),height:Math.max(e.rect.height,0)},d={top:a.top-t.top,left:a.left-t.left,width:a.width+t.left+t.right,height:a.height+t.top+t.bottom},f={top:a.top+n.top,left:a.left+n.left,width:Math.max(a.width-n.left-n.right,0),height:Math.max(a.height-n.top-n.bottom,0)},b={top:f.top+s.top,left:f.left+s.left,width:Math.max(f.width-s.left-s.right,0),height:Math.max(f.height-s.top-s.bottom,0)};return{margin:d,border:a,padding:f,content:b}}function L(e){const t=Number.parseFloat(e);return Number.isFinite(t)?t:0}x.ReviewLensOverlay=ct,x.ReviewLensProvider=rt,x.buildElementTarget=W,x.createGoogleSheetsAdapter=le,x.normalizeReviewUrl=ge,x.useReviewLens=be,Object.defineProperty(x,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "review-lens-react",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "React overlay for UX review feedback backed by Google Sheets.",
5
5
  "type": "module",
6
6
  "main": "./dist/review-lens-react.umd.cjs",