@ourroadmaps/web-sdk 1.2.0 → 1.3.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 @@ var chunk4DE2IREA_cjs = require('./chunk-4DE2IREA.cjs');
5
5
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
6
6
  // src/review/api.ts
7
7
  var API_URL = (() => {
8
- if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-M2R3KO66.cjs', document.baseURI).href)) }) !== "undefined" && undefined?.VITE_API_URL) {
8
+ if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-KDMQIQP4.cjs', document.baseURI).href)) }) !== "undefined" && undefined?.VITE_API_URL) {
9
9
  return undefined.VITE_API_URL;
10
10
  }
11
11
  return "https://api.ourroadmaps.com";
@@ -494,33 +494,51 @@ var PinManager = class {
494
494
  }
495
495
  document.body.appendChild(this.container);
496
496
  }
497
- addPin(pinNumber, x, y, isMine) {
497
+ addPin(pinNumber, x, y, isMine, pageUrl) {
498
498
  const pin = document.createElement("div");
499
499
  pin.className = isMine ? "review-pin" : "review-pin review-pin--other";
500
500
  pin.textContent = String(pinNumber);
501
501
  pin.style.left = `${x}%`;
502
502
  pin.style.top = `${y}%`;
503
503
  pin.dataset.pinNumber = String(pinNumber);
504
+ pin.dataset.pageUrl = pageUrl;
504
505
  this.container.appendChild(pin);
505
- this.pins.set(pinNumber, pin);
506
+ this.pins.set(pinNumber, { el: pin, pageUrl });
506
507
  }
507
508
  removePin(pinNumber) {
508
- const pin = this.pins.get(pinNumber);
509
- if (pin) {
510
- pin.remove();
509
+ const entry = this.pins.get(pinNumber);
510
+ if (entry) {
511
+ entry.el.remove();
511
512
  this.pins.delete(pinNumber);
512
513
  }
513
514
  }
514
515
  highlightPin(pinNumber) {
515
- for (const [num, el] of this.pins) {
516
+ for (const [num, { el }] of this.pins) {
516
517
  el.classList.toggle("review-pin--highlighted", num === pinNumber);
517
518
  }
518
519
  }
519
520
  clearHighlight() {
520
- for (const el of this.pins.values()) {
521
+ for (const { el } of this.pins.values()) {
521
522
  el.classList.remove("review-pin--highlighted");
522
523
  }
523
524
  }
525
+ filterByPage(currentPageId) {
526
+ for (const { el, pageUrl } of this.pins.values()) {
527
+ el.style.display = pageUrl === currentPageId ? "" : "none";
528
+ }
529
+ }
530
+ showAll() {
531
+ for (const { el } of this.pins.values()) {
532
+ el.style.display = "";
533
+ }
534
+ }
535
+ countForPage(pageId) {
536
+ let count = 0;
537
+ for (const { pageUrl } of this.pins.values()) {
538
+ if (pageUrl === pageId) count++;
539
+ }
540
+ return count;
541
+ }
524
542
  destroy() {
525
543
  this.container.remove();
526
544
  this.pins.clear();
@@ -612,6 +630,60 @@ var CommentCard = class {
612
630
  }
613
631
  };
614
632
 
633
+ // src/review/PageTracker.ts
634
+ function getCurrentPageId() {
635
+ return window.location.pathname + window.location.search + window.location.hash;
636
+ }
637
+ var PageNavigationListener = class {
638
+ constructor(onChange) {
639
+ this.onChange = onChange;
640
+ chunk4DE2IREA_cjs.__publicField(this, "popstateHandler", null);
641
+ chunk4DE2IREA_cjs.__publicField(this, "hashchangeHandler", null);
642
+ chunk4DE2IREA_cjs.__publicField(this, "originalPushState", null);
643
+ chunk4DE2IREA_cjs.__publicField(this, "originalReplaceState", null);
644
+ chunk4DE2IREA_cjs.__publicField(this, "lastPageId");
645
+ this.lastPageId = getCurrentPageId();
646
+ }
647
+ start() {
648
+ if (this.originalPushState) return;
649
+ const check = () => {
650
+ const current = getCurrentPageId();
651
+ if (current !== this.lastPageId) {
652
+ this.lastPageId = current;
653
+ this.onChange(current);
654
+ }
655
+ };
656
+ this.popstateHandler = check;
657
+ window.addEventListener("popstate", this.popstateHandler);
658
+ this.hashchangeHandler = check;
659
+ window.addEventListener("hashchange", this.hashchangeHandler);
660
+ this.originalPushState = history.pushState.bind(history);
661
+ this.originalReplaceState = history.replaceState.bind(history);
662
+ history.pushState = (...args) => {
663
+ this.originalPushState(...args);
664
+ check();
665
+ };
666
+ history.replaceState = (...args) => {
667
+ this.originalReplaceState(...args);
668
+ check();
669
+ };
670
+ }
671
+ destroy() {
672
+ if (this.popstateHandler) {
673
+ window.removeEventListener("popstate", this.popstateHandler);
674
+ }
675
+ if (this.hashchangeHandler) {
676
+ window.removeEventListener("hashchange", this.hashchangeHandler);
677
+ }
678
+ if (this.originalPushState) {
679
+ history.pushState = this.originalPushState;
680
+ }
681
+ if (this.originalReplaceState) {
682
+ history.replaceState = this.originalReplaceState;
683
+ }
684
+ }
685
+ };
686
+
615
687
  // src/review/ReviewMode.ts
616
688
  var ReviewMode = class {
617
689
  constructor(token, shadowRoot, initData) {
@@ -625,6 +697,7 @@ var ReviewMode = class {
625
697
  chunk4DE2IREA_cjs.__publicField(this, "promptEl", null);
626
698
  chunk4DE2IREA_cjs.__publicField(this, "toolbarEl", null);
627
699
  chunk4DE2IREA_cjs.__publicField(this, "clickHandler", null);
700
+ chunk4DE2IREA_cjs.__publicField(this, "pageListener", null);
628
701
  this.pinManager = new PinManager();
629
702
  this.commentCard = new CommentCard(shadowRoot);
630
703
  this.nextPinNumber = initData.nextPinNumber;
@@ -635,6 +708,11 @@ var ReviewMode = class {
635
708
  this.showPrompt();
636
709
  this.renderToolbar();
637
710
  await this.loadExistingPins();
711
+ this.pinManager.filterByPage(getCurrentPageId());
712
+ this.pageListener = new PageNavigationListener((pageId) => {
713
+ this.pinManager.filterByPage(pageId);
714
+ });
715
+ this.pageListener.start();
638
716
  this.clickHandler = (e) => this.handleClick(e);
639
717
  document.addEventListener("click", this.clickHandler, true);
640
718
  }
@@ -679,7 +757,7 @@ var ReviewMode = class {
679
757
  for (const c of comments) {
680
758
  if (c.pinNumber != null && c.pinData) {
681
759
  const isMine = c.commentText != null;
682
- this.pinManager.addPin(c.pinNumber, c.pinData.pinX, c.pinData.pinY, isMine);
760
+ this.pinManager.addPin(c.pinNumber, c.pinData.pinX, c.pinData.pinY, isMine, c.pageUrl ?? "");
683
761
  }
684
762
  }
685
763
  } catch {
@@ -692,7 +770,7 @@ var ReviewMode = class {
692
770
  this.dismissPrompt();
693
771
  const pinData = captureElementContext(e.clientX, e.clientY);
694
772
  const pinNumber = this.nextPinNumber;
695
- this.pinManager.addPin(pinNumber, pinData.pinX, pinData.pinY, true);
773
+ this.pinManager.addPin(pinNumber, pinData.pinX, pinData.pinY, true, getCurrentPageId());
696
774
  this.pendingPinNumber = pinNumber;
697
775
  this.commentCard.show({
698
776
  x: e.clientX,
@@ -702,7 +780,7 @@ var ReviewMode = class {
702
780
  commentText: text,
703
781
  pinNumber,
704
782
  pinData,
705
- pageUrl: window.location.pathname
783
+ pageUrl: getCurrentPageId()
706
784
  });
707
785
  this.pendingPinNumber = null;
708
786
  this.nextPinNumber++;
@@ -725,7 +803,7 @@ var ReviewMode = class {
725
803
  commentText: text,
726
804
  pinNumber: null,
727
805
  pinData: null,
728
- pageUrl: window.location.pathname
806
+ pageUrl: getCurrentPageId()
729
807
  });
730
808
  this.showToast("Comment saved");
731
809
  },
@@ -745,6 +823,7 @@ var ReviewMode = class {
745
823
  if (this.clickHandler) {
746
824
  document.removeEventListener("click", this.clickHandler, true);
747
825
  }
826
+ this.pageListener?.destroy();
748
827
  this.dismissPrompt();
749
828
  this.toolbarEl?.remove();
750
829
  this.commentCard.hide();
@@ -752,6 +831,34 @@ var ReviewMode = class {
752
831
  }
753
832
  };
754
833
 
834
+ // src/review/TokenStorage.ts
835
+ var STORAGE_KEY = "ourroadmaps:token";
836
+ function storeToken(type, token) {
837
+ try {
838
+ sessionStorage.setItem(STORAGE_KEY, JSON.stringify({ type, token }));
839
+ } catch {
840
+ }
841
+ }
842
+ function getStoredToken() {
843
+ try {
844
+ const raw = sessionStorage.getItem(STORAGE_KEY);
845
+ if (!raw) return null;
846
+ const parsed = JSON.parse(raw);
847
+ if (parsed && typeof parsed.type === "string" && typeof parsed.token === "string") {
848
+ return parsed;
849
+ }
850
+ return null;
851
+ } catch {
852
+ return null;
853
+ }
854
+ }
855
+ function clearStoredToken() {
856
+ try {
857
+ sessionStorage.removeItem(STORAGE_KEY);
858
+ } catch {
859
+ }
860
+ }
861
+
755
862
  // src/review/TriageMode.ts
756
863
  var TriageMode = class {
757
864
  constructor(token, shadowRoot) {
@@ -762,6 +869,8 @@ var TriageMode = class {
762
869
  chunk4DE2IREA_cjs.__publicField(this, "tooltipEl", null);
763
870
  chunk4DE2IREA_cjs.__publicField(this, "comments", []);
764
871
  chunk4DE2IREA_cjs.__publicField(this, "pinClickHandler", null);
872
+ chunk4DE2IREA_cjs.__publicField(this, "pageListener", null);
873
+ chunk4DE2IREA_cjs.__publicField(this, "showAllPages", false);
765
874
  this.pinManager = new PinManager();
766
875
  }
767
876
  async init() {
@@ -770,12 +879,20 @@ var TriageMode = class {
770
879
  this.comments = await fetchComments(this.token);
771
880
  for (const c of this.comments) {
772
881
  if (c.pinNumber != null && c.pinData) {
773
- this.pinManager.addPin(c.pinNumber, c.pinData.pinX, c.pinData.pinY, true);
882
+ this.pinManager.addPin(c.pinNumber, c.pinData.pinX, c.pinData.pinY, true, c.pageUrl ?? "");
774
883
  }
775
884
  }
776
885
  } catch {
777
886
  }
887
+ this.pinManager.filterByPage(getCurrentPageId());
778
888
  this.renderToolbar();
889
+ this.pageListener = new PageNavigationListener((pageId) => {
890
+ if (!this.showAllPages) {
891
+ this.pinManager.filterByPage(pageId);
892
+ }
893
+ this.updateToolbar();
894
+ });
895
+ this.pageListener.start();
779
896
  this.pinClickHandler = (e) => {
780
897
  const target = e.target;
781
898
  if (target.classList?.contains("review-pin")) {
@@ -789,13 +906,48 @@ var TriageMode = class {
789
906
  renderToolbar() {
790
907
  this.toolbarEl = document.createElement("div");
791
908
  this.toolbarEl.className = "review-toolbar";
792
- const count = this.comments.filter((c) => c.pinNumber != null).length;
793
- this.toolbarEl.innerHTML = `
794
- <span style="font-weight:500;">Triage Mode</span>
795
- <span style="opacity:0.7;">${count} pin${count !== 1 ? "s" : ""}</span>
796
- `;
909
+ this.updateToolbar();
797
910
  this.shadowRoot.appendChild(this.toolbarEl);
798
911
  }
912
+ updateToolbar() {
913
+ if (!this.toolbarEl) return;
914
+ const totalCount = this.comments.filter((c) => c.pinNumber != null).length;
915
+ const currentPageId = getCurrentPageId();
916
+ const pageCount = this.pinManager.countForPage(currentPageId);
917
+ const url = new URL(currentPageId, window.location.origin);
918
+ const pagePath = url.hash ? `${url.pathname}${url.hash.split("?")[0]}` : url.pathname || "/";
919
+ this.toolbarEl.innerHTML = "";
920
+ const label = document.createElement("span");
921
+ label.style.fontWeight = "500";
922
+ label.textContent = "Triage Mode";
923
+ this.toolbarEl.appendChild(label);
924
+ const count = document.createElement("span");
925
+ count.style.opacity = "0.7";
926
+ if (this.showAllPages) {
927
+ count.textContent = `${totalCount} pin${totalCount !== 1 ? "s" : ""}`;
928
+ } else {
929
+ count.textContent = `${pageCount} pin${pageCount !== 1 ? "s" : ""} on ${pagePath} (${totalCount} total)`;
930
+ }
931
+ this.toolbarEl.appendChild(count);
932
+ const toggleBtn = document.createElement("button");
933
+ toggleBtn.className = "review-btn review-btn--submit";
934
+ toggleBtn.style.cssText = "margin-left:auto;padding:6px 12px;font-size:13px;";
935
+ toggleBtn.textContent = this.showAllPages ? "This page" : "All pages";
936
+ toggleBtn.addEventListener("click", (e) => {
937
+ e.stopPropagation();
938
+ this.togglePageFilter();
939
+ });
940
+ this.toolbarEl.appendChild(toggleBtn);
941
+ }
942
+ togglePageFilter() {
943
+ this.showAllPages = !this.showAllPages;
944
+ if (this.showAllPages) {
945
+ this.pinManager.showAll();
946
+ } else {
947
+ this.pinManager.filterByPage(getCurrentPageId());
948
+ }
949
+ this.updateToolbar();
950
+ }
799
951
  handlePinClick(pinNumber, e) {
800
952
  this.hideTooltip();
801
953
  this.pinManager.highlightPin(pinNumber);
@@ -826,6 +978,25 @@ var TriageMode = class {
826
978
  timeEl.style.cssText = "font-size:11px;opacity:0.7;";
827
979
  timeEl.textContent = time;
828
980
  this.tooltipEl.appendChild(timeEl);
981
+ const pinPageUrl = comment.pageUrl ?? "";
982
+ if (pinPageUrl && pinPageUrl !== getCurrentPageId()) {
983
+ const navEl = document.createElement("div");
984
+ navEl.style.cssText = "margin-top:6px;padding-top:6px;border-top:1px solid rgba(255,255,255,0.2);font-size:12px;";
985
+ const pageLabel = document.createElement("span");
986
+ pageLabel.style.opacity = "0.7";
987
+ pageLabel.textContent = `Page: ${pinPageUrl.split("?")[0].split("#")[0] || "/"} \u2014 `;
988
+ navEl.appendChild(pageLabel);
989
+ const navLink = document.createElement("a");
990
+ navLink.style.cssText = "color:#a78bfa;cursor:pointer;text-decoration:underline;pointer-events:auto;";
991
+ navLink.textContent = "Navigate there?";
992
+ navLink.addEventListener("click", (e) => {
993
+ e.stopPropagation();
994
+ this.navigateToPin(pinPageUrl, pinNumber);
995
+ });
996
+ navEl.appendChild(navLink);
997
+ this.tooltipEl.appendChild(navEl);
998
+ this.tooltipEl.style.pointerEvents = "auto";
999
+ }
829
1000
  const posX = x ?? window.innerWidth / 2;
830
1001
  const posY = y ?? window.innerHeight / 3;
831
1002
  this.tooltipEl.style.position = "fixed";
@@ -841,6 +1012,13 @@ var TriageMode = class {
841
1012
  };
842
1013
  setTimeout(() => document.addEventListener("click", dismiss, true), 0);
843
1014
  }
1015
+ navigateToPin(pageUrl, pinNumber) {
1016
+ this.hideTooltip();
1017
+ this.pinManager.clearHighlight();
1018
+ const url = new URL(pageUrl, window.location.origin);
1019
+ url.searchParams.set("pin", String(pinNumber));
1020
+ window.location.href = url.toString();
1021
+ }
844
1022
  autoFocusPin() {
845
1023
  const params = new URLSearchParams(window.location.search);
846
1024
  const pinParam = params.get("pin");
@@ -849,6 +1027,19 @@ var TriageMode = class {
849
1027
  if (!pinNumber) return;
850
1028
  const comment = this.comments.find((c) => c.pinNumber === pinNumber);
851
1029
  if (!comment?.pinData) return;
1030
+ const pinPageUrl = comment.pageUrl ?? "";
1031
+ if (pinPageUrl) {
1032
+ const currentUrl = new URL(window.location.href);
1033
+ currentUrl.searchParams.delete("pin");
1034
+ const currentPageWithoutPin = currentUrl.pathname + currentUrl.search + currentUrl.hash;
1035
+ if (pinPageUrl !== currentPageWithoutPin) {
1036
+ this.navigateToPin(pinPageUrl, pinNumber);
1037
+ return;
1038
+ }
1039
+ }
1040
+ this.pinManager.showAll();
1041
+ this.showAllPages = true;
1042
+ this.updateToolbar();
852
1043
  const docEl = document.documentElement;
853
1044
  const scrollX = comment.pinData.pinX / 100 * docEl.scrollWidth;
854
1045
  const scrollY = comment.pinData.pinY / 100 * docEl.scrollHeight;
@@ -870,6 +1061,7 @@ var TriageMode = class {
870
1061
  if (this.pinClickHandler) {
871
1062
  document.removeEventListener("click", this.pinClickHandler, true);
872
1063
  }
1064
+ this.pageListener?.destroy();
873
1065
  this.hideTooltip();
874
1066
  this.toolbarEl?.remove();
875
1067
  this.pinManager.destroy();
@@ -891,29 +1083,42 @@ var Review = class {
891
1083
  this.shadow.appendChild(styleEl);
892
1084
  document.body.appendChild(this.root);
893
1085
  }
894
- async init() {
895
- const params = new URLSearchParams(window.location.search);
896
- const reviewToken = params.get("review");
897
- const triageToken = params.get("triage");
898
- if (reviewToken) {
1086
+ async init(tokenType, token) {
1087
+ if (!tokenType || !token) {
1088
+ const params = new URLSearchParams(window.location.search);
1089
+ const reviewToken = params.get("review");
1090
+ const triageToken = params.get("triage");
1091
+ if (reviewToken) {
1092
+ tokenType = "review";
1093
+ token = reviewToken;
1094
+ } else if (triageToken) {
1095
+ tokenType = "triage";
1096
+ token = triageToken;
1097
+ } else {
1098
+ return;
1099
+ }
1100
+ }
1101
+ if (tokenType === "review") {
899
1102
  try {
900
- const data = await validateToken(reviewToken);
901
- this.mode = new ReviewMode(reviewToken, this.shadow, data);
1103
+ const data = await validateToken(token);
1104
+ this.mode = new ReviewMode(token, this.shadow, data);
902
1105
  await this.mode.init();
903
1106
  } catch (err) {
904
1107
  if (err instanceof ReviewError) {
1108
+ clearStoredToken();
905
1109
  this.showErrorOverlay(
906
1110
  err.code === "expired" ? "This feedback session has expired" : "This review link is no longer valid"
907
1111
  );
908
1112
  }
909
1113
  }
910
- } else if (triageToken) {
1114
+ } else if (tokenType === "triage") {
911
1115
  try {
912
- await validateToken(triageToken);
913
- this.mode = new TriageMode(triageToken, this.shadow);
1116
+ await validateToken(token);
1117
+ this.mode = new TriageMode(token, this.shadow);
914
1118
  await this.mode.init();
915
1119
  } catch (err) {
916
1120
  if (err instanceof ReviewError) {
1121
+ clearStoredToken();
917
1122
  this.showErrorOverlay(
918
1123
  err.code === "expired" ? "This feedback session has expired" : "This review link is no longer valid"
919
1124
  );
@@ -944,5 +1149,7 @@ var Review = class {
944
1149
  };
945
1150
 
946
1151
  exports.Review = Review;
947
- //# sourceMappingURL=chunk-M2R3KO66.cjs.map
948
- //# sourceMappingURL=chunk-M2R3KO66.cjs.map
1152
+ exports.getStoredToken = getStoredToken;
1153
+ exports.storeToken = storeToken;
1154
+ //# sourceMappingURL=chunk-KDMQIQP4.cjs.map
1155
+ //# sourceMappingURL=chunk-KDMQIQP4.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/review/api.ts","../src/review/ElementCapture.ts","../src/review/styles.ts","../src/review/PinManager.ts","../src/review/CommentCard.ts","../src/review/PageTracker.ts","../src/review/ReviewMode.ts","../src/review/TokenStorage.ts","../src/review/TriageMode.ts","../src/review/Review.ts"],"names":["__publicField"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAyQtB,IAAM,mBAAA,GAAsB;AAAA;A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","file":"chunk-KDMQIQP4.cjs","sourcesContent":["import type { PinData, ReviewComment, ReviewInitData } from './types'\n\n// Default to production, override with env var for local dev\nconst API_URL = (() => {\n // Vite dev mode\n if (typeof import.meta !== 'undefined' && import.meta.env?.VITE_API_URL) {\n return import.meta.env.VITE_API_URL\n }\n return 'https://api.ourroadmaps.com'\n})()\n\nexport async function validateToken(token: string): Promise<ReviewInitData> {\n const res = await fetch(`${API_URL}/v1/prototype-review/${token}`)\n if (res.status === 410) throw new ReviewError('expired', 'This feedback session has expired')\n if (res.status === 404) throw new ReviewError('invalid', 'This review link is not valid')\n if (!res.ok) throw new ReviewError('error', 'Something went wrong')\n const body = await res.json()\n return body.data\n}\n\n// TODO: Wire into SDK — show name prompt on first visit, call identify() to transition invite status from 'pending' to 'opened'\nexport async function identify(token: string, name: string): Promise<void> {\n const res = await fetch(`${API_URL}/v1/prototype-review/${token}/identify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name }),\n })\n if (!res.ok) throw new ReviewError('error', 'Failed to identify')\n}\n\nexport async function submitComment(\n token: string,\n comment: { commentText: string; pinNumber: number | null; pinData: PinData | null; pageUrl: string | null },\n): Promise<{ id: string; pinNumber: number | null; createdAt: string }> {\n const res = await fetch(`${API_URL}/v1/prototype-review/${token}/comments`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(comment),\n })\n if (!res.ok) throw new ReviewError('error', 'Failed to submit comment')\n const body = await res.json()\n return body.data\n}\n\nexport async function fetchComments(token: string): Promise<ReviewComment[]> {\n const res = await fetch(`${API_URL}/v1/prototype-review/${token}/comments`)\n if (!res.ok) throw new ReviewError('error', 'Failed to load comments')\n const body = await res.json()\n return body.data\n}\n\nexport class ReviewError extends Error {\n constructor(\n public code: 'expired' | 'invalid' | 'error',\n message: string,\n ) {\n super(message)\n this.name = 'ReviewError'\n }\n}\n","import type { PinData } from './types'\n\nexport function captureElementContext(clientX: number, clientY: number): PinData {\n const el = document.elementFromPoint(clientX, clientY) as HTMLElement | null\n const docEl = document.documentElement\n\n const pinX = ((clientX + window.scrollX) / docEl.scrollWidth) * 100\n const pinY = ((clientY + window.scrollY) / docEl.scrollHeight) * 100\n\n if (!el || el === document.body || el === docEl) {\n return {\n pinX,\n pinY,\n element: {\n selector: 'body',\n tag: 'body',\n text: '',\n ariaLabel: null,\n className: '',\n boundingBox: { x: 0, y: 0, w: docEl.scrollWidth, h: docEl.scrollHeight },\n },\n context: {\n parentTag: '',\n parentText: '',\n grandparentTag: '',\n siblings: [],\n nearbyText: '',\n },\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n }\n }\n\n const rect = el.getBoundingClientRect()\n\n return {\n pinX,\n pinY,\n element: {\n selector: buildSelector(el),\n tag: el.tagName.toLowerCase(),\n text: getDirectText(el).slice(0, 200),\n ariaLabel: el.getAttribute('aria-label'),\n className: el.className && typeof el.className === 'string' ? el.className : '',\n boundingBox: {\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n w: Math.round(rect.width),\n h: Math.round(rect.height),\n },\n },\n context: {\n parentTag: el.parentElement ? `${el.parentElement.tagName.toLowerCase()}${classStr(el.parentElement)}` : '',\n parentText: el.parentElement ? getDirectText(el.parentElement).slice(0, 100) : '',\n grandparentTag: el.parentElement?.parentElement\n ? `${el.parentElement.parentElement.tagName.toLowerCase()}${classStr(el.parentElement.parentElement)}`\n : '',\n siblings: getSiblingsSummary(el),\n nearbyText: getNearbyText(el).slice(0, 200),\n },\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n }\n}\n\nfunction buildSelector(el: HTMLElement): string {\n const parts: string[] = []\n let current: HTMLElement | null = el\n\n while (current && current !== document.body) {\n if (current.id) {\n parts.unshift(`#${current.id}`)\n break\n }\n\n let part = current.tagName.toLowerCase()\n if (current.className && typeof current.className === 'string') {\n const classes = current.className.trim().split(/\\s+/).slice(0, 2).join('.')\n if (classes) part += `.${classes}`\n }\n\n parts.unshift(part)\n current = current.parentElement\n }\n\n return parts.join(' > ')\n}\n\nfunction getDirectText(el: HTMLElement): string {\n let text = ''\n for (const node of el.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n text += node.textContent?.trim() || ''\n }\n }\n return text.trim() || el.textContent?.trim().slice(0, 200) || ''\n}\n\nfunction classStr(el: HTMLElement): string {\n if (!el.className || typeof el.className !== 'string') return ''\n const cls = el.className.trim().split(/\\s+/).slice(0, 2).join('.')\n return cls ? `.${cls}` : ''\n}\n\nfunction getSiblingsSummary(el: HTMLElement): string[] {\n if (!el.parentElement) return []\n const siblings: string[] = []\n for (const child of el.parentElement.children) {\n if (child === el) continue\n const tag = child.tagName.toLowerCase()\n const text = (child.textContent?.trim() || '').slice(0, 50)\n siblings.push(text ? `${tag}:${text}` : tag)\n if (siblings.length >= 4) break\n }\n return siblings\n}\n\nfunction getNearbyText(el: HTMLElement): string {\n // Walk up to find the nearest container with meaningful text\n let current: HTMLElement | null = el.parentElement\n let depth = 0\n while (current && depth < 3) {\n const text = getDirectText(current)\n if (text && text !== getDirectText(el)) return text\n current = current.parentElement\n depth++\n }\n return ''\n}\n","export const REVIEW_STYLES = `\n:host {\n all: initial;\n}\n\n/* ─── Pin Container (rendered outside shadow DOM) ─── */\n.pin-container {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 10000;\n}\n\n/* ─── Pin Marker ─── */\n.review-pin {\n position: absolute;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background: #7c3aed;\n color: #fff;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 12px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n transform: translate(-50%, -50%);\n pointer-events: auto;\n cursor: pointer;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n transition: transform 0.15s ease, box-shadow 0.15s ease;\n user-select: none;\n z-index: 1;\n}\n\n.review-pin:hover {\n transform: translate(-50%, -50%) scale(1.15);\n box-shadow: 0 3px 10px rgba(124, 58, 237, 0.4);\n}\n\n.review-pin--other {\n opacity: 0.5;\n}\n\n.review-pin--highlighted {\n transform: translate(-50%, -50%) scale(1.2);\n box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.3), 0 3px 10px rgba(124, 58, 237, 0.4);\n z-index: 2;\n}\n\n/* ─── Toolbar ─── */\n.review-toolbar {\n position: fixed;\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.85);\n color: #fff;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 14px;\n border-radius: 12px 12px 0 0;\n padding: 10px 20px;\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\n z-index: 10001;\n backdrop-filter: blur(8px);\n box-shadow: 0 -2px 16px rgba(0, 0, 0, 0.2);\n}\n\n/* ─── Comment Card ─── */\n.review-comment-card {\n position: fixed;\n background: #fff;\n border-radius: 10px;\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15), 0 1px 4px rgba(0, 0, 0, 0.08);\n width: 300px;\n padding: 16px;\n z-index: 10002;\n font-family: system-ui, -apple-system, sans-serif;\n border: 1px solid rgba(0, 0, 0, 0.08);\n}\n\n/* ─── Comment Textarea ─── */\n.review-comment-input {\n width: 100%;\n border: 1px solid #d1d5db;\n border-radius: 8px;\n padding: 10px 12px;\n resize: vertical;\n font-family: inherit;\n font-size: 14px;\n line-height: 1.5;\n color: #1f2937;\n background: #fafafa;\n box-sizing: border-box;\n outline: none;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n}\n\n.review-comment-input:focus {\n border-color: #7c3aed;\n box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.15);\n background: #fff;\n}\n\n.review-comment-input::placeholder {\n color: #9ca3af;\n}\n\n.review-comment-input:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* ─── Comment Actions ─── */\n.review-comment-actions {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 12px;\n}\n\n/* ─── Buttons ─── */\n.review-btn {\n padding: 6px 14px;\n border-radius: 6px;\n cursor: pointer;\n font-family: inherit;\n font-size: 13px;\n font-weight: 500;\n border: none;\n transition: background 0.15s ease, opacity 0.15s ease;\n}\n\n.review-btn--cancel {\n color: #6b7280;\n background: transparent;\n}\n\n.review-btn--cancel:hover {\n background: #f3f4f6;\n}\n\n.review-btn--submit {\n background: #7c3aed;\n color: #fff;\n}\n\n.review-btn--submit:hover {\n background: #6d28d9;\n}\n\n.review-btn--submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* ─── Comment Error ─── */\n.review-comment-error {\n color: #dc2626;\n font-size: 12px;\n margin-top: 8px;\n font-family: system-ui, -apple-system, sans-serif;\n}\n\n/* ─── Name Prompt ─── */\n.review-prompt {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: #fff;\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2), 0 1px 4px rgba(0, 0, 0, 0.08);\n border-radius: 12px;\n padding: 28px 32px;\n z-index: 10002;\n text-align: center;\n font-family: system-ui, -apple-system, sans-serif;\n border: 1px solid rgba(0, 0, 0, 0.06);\n max-width: 360px;\n width: 90%;\n}\n\n/* ─── Expired Overlay ─── */\n.review-expired-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.6);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10003;\n backdrop-filter: blur(2px);\n}\n\n.review-expired-card {\n background: #fff;\n border-radius: 12px;\n padding: 28px 32px;\n text-align: center;\n font-family: system-ui, -apple-system, sans-serif;\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);\n max-width: 400px;\n width: 90%;\n border: 1px solid rgba(0, 0, 0, 0.06);\n}\n\n/* ─── Toast ─── */\n.review-toast {\n position: fixed;\n bottom: 80px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.85);\n color: #fff;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 14px;\n padding: 10px 20px;\n border-radius: 8px;\n z-index: 10003;\n pointer-events: none;\n animation: review-toast-fade 2.5s ease forwards;\n backdrop-filter: blur(8px);\n}\n\n@keyframes review-toast-fade {\n 0% { opacity: 0; transform: translateX(-50%) translateY(8px); }\n 10% { opacity: 1; transform: translateX(-50%) translateY(0); }\n 80% { opacity: 1; transform: translateX(-50%) translateY(0); }\n 100% { opacity: 0; transform: translateX(-50%) translateY(-4px); }\n}\n\n/* ─── Tooltip ─── */\n.review-tooltip {\n position: absolute;\n background: rgba(0, 0, 0, 0.85);\n color: #fff;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n border-radius: 6px;\n padding: 8px 12px;\n max-width: 280px;\n z-index: 10002;\n pointer-events: none;\n backdrop-filter: blur(8px);\n}\n\n/* ─── Reduced Motion ─── */\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n`\n\n/**\n * Subset of styles for pins that render outside the shadow DOM.\n * Injected into document.head by PinManager.\n */\nexport const PIN_DOCUMENT_STYLES = `\nbody {\n position: relative !important;\n}\n\n.pin-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n min-height: 100%;\n pointer-events: none;\n z-index: 10000;\n}\n\n.review-pin {\n position: absolute;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background: #7c3aed;\n color: #fff;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 12px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n transform: translate(-50%, -50%);\n pointer-events: auto;\n cursor: pointer;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n transition: transform 0.15s ease, box-shadow 0.15s ease;\n user-select: none;\n z-index: 1;\n}\n\n.review-pin:hover {\n transform: translate(-50%, -50%) scale(1.15);\n box-shadow: 0 3px 10px rgba(124, 58, 237, 0.4);\n}\n\n.review-pin--other {\n opacity: 0.5;\n}\n\n.review-pin--highlighted {\n transform: translate(-50%, -50%) scale(1.2);\n box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.3), 0 3px 10px rgba(124, 58, 237, 0.4);\n z-index: 2;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .review-pin, .review-pin:hover, .review-pin--highlighted {\n transition-duration: 0.01ms !important;\n }\n}\n`\n","import { PIN_DOCUMENT_STYLES } from './styles'\n\nconst STYLE_ID = 'roadmaps-review-pin-styles'\n\ninterface PinEntry {\n el: HTMLElement\n pageUrl: string\n}\n\nexport class PinManager {\n private container: HTMLDivElement\n private pins: Map<number, PinEntry> = new Map()\n private styleEl: HTMLStyleElement | null = null\n\n constructor() {\n this.container = document.createElement('div')\n this.container.className = 'pin-container'\n }\n\n mount(): void {\n if (!document.getElementById(STYLE_ID)) {\n this.styleEl = document.createElement('style')\n this.styleEl.id = STYLE_ID\n this.styleEl.textContent = PIN_DOCUMENT_STYLES\n document.head.appendChild(this.styleEl)\n }\n\n document.body.appendChild(this.container)\n }\n\n addPin(pinNumber: number, x: number, y: number, isMine: boolean, pageUrl: string): void {\n const pin = document.createElement('div')\n pin.className = isMine ? 'review-pin' : 'review-pin review-pin--other'\n pin.textContent = String(pinNumber)\n pin.style.left = `${x}%`\n pin.style.top = `${y}%`\n pin.dataset.pinNumber = String(pinNumber)\n pin.dataset.pageUrl = pageUrl\n this.container.appendChild(pin)\n this.pins.set(pinNumber, { el: pin, pageUrl })\n }\n\n removePin(pinNumber: number): void {\n const entry = this.pins.get(pinNumber)\n if (entry) {\n entry.el.remove()\n this.pins.delete(pinNumber)\n }\n }\n\n highlightPin(pinNumber: number): void {\n for (const [num, { el }] of this.pins) {\n el.classList.toggle('review-pin--highlighted', num === pinNumber)\n }\n }\n\n clearHighlight(): void {\n for (const { el } of this.pins.values()) {\n el.classList.remove('review-pin--highlighted')\n }\n }\n\n filterByPage(currentPageId: string): void {\n for (const { el, pageUrl } of this.pins.values()) {\n el.style.display = pageUrl === currentPageId ? '' : 'none'\n }\n }\n\n showAll(): void {\n for (const { el } of this.pins.values()) {\n el.style.display = ''\n }\n }\n\n countForPage(pageId: string): number {\n let count = 0\n for (const { pageUrl } of this.pins.values()) {\n if (pageUrl === pageId) count++\n }\n return count\n }\n\n destroy(): void {\n this.container.remove()\n this.pins.clear()\n\n if (this.styleEl) {\n this.styleEl.remove()\n this.styleEl = null\n } else {\n document.getElementById(STYLE_ID)?.remove()\n }\n }\n}\n","export class CommentCard {\n private card: HTMLElement | null = null\n private onSubmit: ((text: string) => Promise<void>) | null = null\n private onCancel: (() => void) | null = null\n\n constructor(private shadowRoot: ShadowRoot) {}\n\n show(options: {\n x: number\n y: number\n onSubmit: (text: string) => Promise<void>\n onCancel: () => void\n }): void {\n this.hide()\n this.onSubmit = options.onSubmit\n this.onCancel = options.onCancel\n\n this.card = document.createElement('div')\n this.card.className = 'review-comment-card'\n // Position near click point, adjust to stay in viewport\n this.card.style.left = `${Math.min(options.x, window.innerWidth - 320)}px`\n this.card.style.top = `${Math.min(options.y + 20, window.innerHeight - 200)}px`\n\n this.card.innerHTML = `\n <textarea class=\"review-comment-input\" placeholder=\"Leave your feedback...\" rows=\"3\"></textarea>\n <div class=\"review-comment-actions\">\n <button class=\"review-btn review-btn--cancel\">Cancel</button>\n <button class=\"review-btn review-btn--submit\">Submit</button>\n </div>\n <div class=\"review-comment-error\" style=\"display:none\"></div>\n `\n\n this.attachListeners()\n this.shadowRoot.appendChild(this.card)\n\n const textarea = this.card.querySelector('textarea')\n textarea?.focus()\n }\n\n hide(): void {\n this.card?.remove()\n this.card = null\n }\n\n showForGeneral(options: {\n onSubmit: (text: string) => Promise<void>\n onCancel: () => void\n }): void {\n // Show centered for general (non-pinned) comments\n this.show({\n x: window.innerWidth / 2 - 150,\n y: window.innerHeight / 2 - 100,\n onSubmit: options.onSubmit,\n onCancel: options.onCancel,\n })\n }\n\n private attachListeners(): void {\n if (!this.card) return\n\n this.card.querySelector('.review-btn--cancel')?.addEventListener('click', () => {\n this.onCancel?.()\n this.hide()\n })\n\n this.card.querySelector('.review-btn--submit')?.addEventListener('click', () => this.handleSubmit())\n\n this.card.querySelector('textarea')?.addEventListener('keydown', (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n e.preventDefault()\n this.handleSubmit()\n }\n })\n }\n\n private async handleSubmit(): Promise<void> {\n if (!this.card) return\n const textarea = this.card.querySelector('textarea') as HTMLTextAreaElement\n const text = textarea.value.trim()\n if (!text) return\n\n const submitBtn = this.card.querySelector('.review-btn--submit') as HTMLButtonElement\n const errorEl = this.card.querySelector('.review-comment-error') as HTMLElement\n submitBtn.disabled = true\n submitBtn.textContent = 'Submitting...'\n textarea.disabled = true\n errorEl.style.display = 'none'\n\n try {\n await this.onSubmit?.(text)\n this.hide()\n } catch (err) {\n submitBtn.disabled = false\n submitBtn.textContent = 'Submit'\n textarea.disabled = false\n errorEl.textContent = err instanceof Error ? err.message : 'Failed to submit'\n errorEl.style.display = 'block'\n }\n }\n}\n","/**\n * Returns the current page identity as pathname + search + hash.\n * This captures all routing strategies: pathname, hash, and query-param based.\n */\nexport function getCurrentPageId(): string {\n return window.location.pathname + window.location.search + window.location.hash\n}\n\n/**\n * Detects page navigation within a prototype.\n * Covers: popstate (back/forward), hashchange (hash routing),\n * and pushState/replaceState (SPA routing via history API).\n */\nexport class PageNavigationListener {\n private popstateHandler: (() => void) | null = null\n private hashchangeHandler: (() => void) | null = null\n private originalPushState: typeof history.pushState | null = null\n private originalReplaceState: typeof history.replaceState | null = null\n private lastPageId: string\n\n constructor(private onChange: (pageId: string) => void) {\n this.lastPageId = getCurrentPageId()\n }\n\n start(): void {\n // Guard against double-start — would capture already-patched history methods\n if (this.originalPushState) return\n\n const check = () => {\n const current = getCurrentPageId()\n if (current !== this.lastPageId) {\n this.lastPageId = current\n this.onChange(current)\n }\n }\n\n this.popstateHandler = check\n window.addEventListener('popstate', this.popstateHandler)\n\n this.hashchangeHandler = check\n window.addEventListener('hashchange', this.hashchangeHandler)\n\n this.originalPushState = history.pushState.bind(history)\n this.originalReplaceState = history.replaceState.bind(history)\n\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n this.originalPushState!(...args)\n check()\n }\n\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n this.originalReplaceState!(...args)\n check()\n }\n }\n\n destroy(): void {\n if (this.popstateHandler) {\n window.removeEventListener('popstate', this.popstateHandler)\n }\n if (this.hashchangeHandler) {\n window.removeEventListener('hashchange', this.hashchangeHandler)\n }\n\n if (this.originalPushState) {\n history.pushState = this.originalPushState\n }\n if (this.originalReplaceState) {\n history.replaceState = this.originalReplaceState\n }\n }\n}\n","import { submitComment, fetchComments } from './api'\nimport { captureElementContext } from './ElementCapture'\nimport { PinManager } from './PinManager'\nimport { CommentCard } from './CommentCard'\nimport type { ReviewInitData } from './types'\nimport { getCurrentPageId, PageNavigationListener } from './PageTracker'\n\nexport class ReviewMode {\n private pinManager: PinManager\n private commentCard: CommentCard\n private nextPinNumber: number\n private pendingPinNumber: number | null = null\n private promptEl: HTMLElement | null = null\n private toolbarEl: HTMLElement | null = null\n private clickHandler: ((e: MouseEvent) => void) | null = null\n private pageListener: PageNavigationListener | null = null\n\n constructor(\n private token: string,\n private shadowRoot: ShadowRoot,\n private initData: ReviewInitData,\n ) {\n this.pinManager = new PinManager()\n this.commentCard = new CommentCard(shadowRoot)\n this.nextPinNumber = initData.nextPinNumber\n }\n\n async init(): Promise<void> {\n // Set crosshair cursor on body\n document.body.style.cursor = 'crosshair'\n\n // Mount pin manager\n this.pinManager.mount()\n\n // Render first-visit prompt\n this.showPrompt()\n\n // Render bottom toolbar\n this.renderToolbar()\n\n // Fetch and render existing pins\n await this.loadExistingPins()\n\n // Filter pins to current page and listen for navigation\n this.pinManager.filterByPage(getCurrentPageId())\n this.pageListener = new PageNavigationListener((pageId) => {\n this.pinManager.filterByPage(pageId)\n })\n this.pageListener.start()\n\n // Listen for clicks to drop pins\n this.clickHandler = (e: MouseEvent) => this.handleClick(e)\n document.addEventListener('click', this.clickHandler, true)\n }\n\n private showPrompt(): void {\n this.promptEl = document.createElement('div')\n this.promptEl.className = 'review-prompt'\n this.promptEl.innerHTML = `\n <h3 style=\"margin:0 0 8px;font-size:16px;\">Click anywhere to leave feedback</h3>\n <p style=\"margin:0;color:#666;font-size:14px;\">Drop numbered pins on elements you want to comment on</p>\n `\n this.shadowRoot.appendChild(this.promptEl)\n\n // Auto-dismiss after 5 seconds\n setTimeout(() => this.dismissPrompt(), 5000)\n }\n\n private dismissPrompt(): void {\n if (this.promptEl) {\n this.promptEl.remove()\n this.promptEl = null\n }\n }\n\n private renderToolbar(): void {\n this.toolbarEl = document.createElement('div')\n this.toolbarEl.className = 'review-toolbar'\n this.updateToolbar()\n this.shadowRoot.appendChild(this.toolbarEl)\n }\n\n private updateToolbar(): void {\n if (!this.toolbarEl) return\n const pinCount = this.nextPinNumber - 1\n this.toolbarEl.innerHTML = `\n <span style=\"font-weight:500;\">${this.initData.session.name}</span>\n <span style=\"opacity:0.7;\">${pinCount} pin${pinCount !== 1 ? 's' : ''}</span>\n <button class=\"review-btn review-btn--submit\" style=\"margin-left:auto;padding:6px 12px;font-size:13px;\">General Comment</button>\n `\n this.toolbarEl.querySelector('button')?.addEventListener('click', (e) => {\n e.stopPropagation()\n this.handleGeneralComment()\n })\n }\n\n private async loadExistingPins(): Promise<void> {\n try {\n const comments = await fetchComments(this.token)\n for (const c of comments) {\n if (c.pinNumber != null && c.pinData) {\n // commentText being non-null means it's the current reviewer's pin\n const isMine = c.commentText != null\n this.pinManager.addPin(c.pinNumber, c.pinData.pinX, c.pinData.pinY, isMine, c.pageUrl ?? '')\n }\n }\n } catch {\n // Silently fail - pins just won't show up\n }\n }\n\n private handleClick(e: MouseEvent): void {\n // Don't intercept clicks on our own shadow DOM elements\n const path = e.composedPath()\n if (path.some((el) => el instanceof HTMLElement && el.closest?.('#ourroadmaps-review'))) return\n\n // Don't intercept if comment card is open\n if (this.pendingPinNumber != null) return\n\n // Dismiss first-visit prompt on first click\n this.dismissPrompt()\n\n const pinData = captureElementContext(e.clientX, e.clientY)\n const pinNumber = this.nextPinNumber\n\n // Add pin at click position\n this.pinManager.addPin(pinNumber, pinData.pinX, pinData.pinY, true, getCurrentPageId())\n this.pendingPinNumber = pinNumber\n\n // Show comment card\n this.commentCard.show({\n x: e.clientX,\n y: e.clientY,\n onSubmit: async (text: string) => {\n await submitComment(this.token, {\n commentText: text,\n pinNumber,\n pinData,\n pageUrl: getCurrentPageId(),\n })\n this.pendingPinNumber = null\n this.nextPinNumber++\n this.updateToolbar()\n this.showToast('Comment saved')\n },\n onCancel: () => {\n // Remove the pending pin\n this.pinManager.removePin(pinNumber)\n this.pendingPinNumber = null\n },\n })\n\n e.preventDefault()\n e.stopPropagation()\n }\n\n private handleGeneralComment(): void {\n if (this.pendingPinNumber != null) return\n\n this.commentCard.showForGeneral({\n onSubmit: async (text: string) => {\n await submitComment(this.token, {\n commentText: text,\n pinNumber: null,\n pinData: null,\n pageUrl: getCurrentPageId(),\n })\n this.showToast('Comment saved')\n },\n onCancel: () => {},\n })\n }\n\n private showToast(message: string): void {\n const toast = document.createElement('div')\n toast.className = 'review-toast'\n toast.textContent = message\n this.shadowRoot.appendChild(toast)\n setTimeout(() => toast.remove(), 2500)\n }\n\n destroy(): void {\n document.body.style.cursor = ''\n if (this.clickHandler) {\n document.removeEventListener('click', this.clickHandler, true)\n }\n this.pageListener?.destroy()\n this.dismissPrompt()\n this.toolbarEl?.remove()\n this.commentCard.hide()\n this.pinManager.destroy()\n }\n}\n","const STORAGE_KEY = 'ourroadmaps:token'\n\ninterface StoredToken {\n type: 'review' | 'triage'\n token: string\n}\n\nexport function storeToken(type: 'review' | 'triage', token: string): void {\n try {\n sessionStorage.setItem(STORAGE_KEY, JSON.stringify({ type, token }))\n } catch {\n // sessionStorage unavailable (private browsing, storage full, etc.)\n }\n}\n\nexport function getStoredToken(): StoredToken | null {\n try {\n const raw = sessionStorage.getItem(STORAGE_KEY)\n if (!raw) return null\n const parsed = JSON.parse(raw)\n if (parsed && typeof parsed.type === 'string' && typeof parsed.token === 'string') {\n return parsed as StoredToken\n }\n return null\n } catch {\n return null\n }\n}\n\nexport function clearStoredToken(): void {\n try {\n sessionStorage.removeItem(STORAGE_KEY)\n } catch {\n // sessionStorage unavailable\n }\n}\n","import { fetchComments } from './api'\nimport { PinManager } from './PinManager'\nimport { getCurrentPageId, PageNavigationListener } from './PageTracker'\nimport type { ReviewComment } from './types'\n\nexport class TriageMode {\n private pinManager: PinManager\n private toolbarEl: HTMLElement | null = null\n private tooltipEl: HTMLElement | null = null\n private comments: ReviewComment[] = []\n private pinClickHandler: ((e: MouseEvent) => void) | null = null\n private pageListener: PageNavigationListener | null = null\n private showAllPages = false\n\n constructor(\n private token: string,\n private shadowRoot: ShadowRoot,\n ) {\n this.pinManager = new PinManager()\n }\n\n async init(): Promise<void> {\n this.pinManager.mount()\n\n try {\n this.comments = await fetchComments(this.token)\n for (const c of this.comments) {\n if (c.pinNumber != null && c.pinData) {\n this.pinManager.addPin(c.pinNumber, c.pinData.pinX, c.pinData.pinY, true, c.pageUrl ?? '')\n }\n }\n } catch {\n // Show error state\n }\n\n this.pinManager.filterByPage(getCurrentPageId())\n\n this.renderToolbar()\n\n this.pageListener = new PageNavigationListener((pageId) => {\n if (!this.showAllPages) {\n this.pinManager.filterByPage(pageId)\n }\n this.updateToolbar()\n })\n this.pageListener.start()\n\n this.pinClickHandler = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n if (target.classList?.contains('review-pin')) {\n const num = Number(target.dataset.pinNumber)\n if (num) this.handlePinClick(num, e)\n }\n }\n document.addEventListener('click', this.pinClickHandler, true)\n\n this.autoFocusPin()\n }\n\n private renderToolbar(): void {\n this.toolbarEl = document.createElement('div')\n this.toolbarEl.className = 'review-toolbar'\n this.updateToolbar()\n this.shadowRoot.appendChild(this.toolbarEl)\n }\n\n private updateToolbar(): void {\n if (!this.toolbarEl) return\n\n const totalCount = this.comments.filter((c) => c.pinNumber != null).length\n const currentPageId = getCurrentPageId()\n const pageCount = this.pinManager.countForPage(currentPageId)\n // Show pathname for path-routed apps, or pathname#hash for hash-routed apps\n const url = new URL(currentPageId, window.location.origin)\n const pagePath = url.hash ? `${url.pathname}${url.hash.split('?')[0]}` : (url.pathname || '/')\n\n this.toolbarEl.innerHTML = ''\n\n const label = document.createElement('span')\n label.style.fontWeight = '500'\n label.textContent = 'Triage Mode'\n this.toolbarEl.appendChild(label)\n\n const count = document.createElement('span')\n count.style.opacity = '0.7'\n if (this.showAllPages) {\n count.textContent = `${totalCount} pin${totalCount !== 1 ? 's' : ''}`\n } else {\n count.textContent = `${pageCount} pin${pageCount !== 1 ? 's' : ''} on ${pagePath} (${totalCount} total)`\n }\n this.toolbarEl.appendChild(count)\n\n const toggleBtn = document.createElement('button')\n toggleBtn.className = 'review-btn review-btn--submit'\n toggleBtn.style.cssText = 'margin-left:auto;padding:6px 12px;font-size:13px;'\n toggleBtn.textContent = this.showAllPages ? 'This page' : 'All pages'\n toggleBtn.addEventListener('click', (e) => {\n e.stopPropagation()\n this.togglePageFilter()\n })\n this.toolbarEl.appendChild(toggleBtn)\n }\n\n private togglePageFilter(): void {\n this.showAllPages = !this.showAllPages\n if (this.showAllPages) {\n this.pinManager.showAll()\n } else {\n this.pinManager.filterByPage(getCurrentPageId())\n }\n this.updateToolbar()\n }\n\n private handlePinClick(pinNumber: number, e: MouseEvent): void {\n this.hideTooltip()\n this.pinManager.highlightPin(pinNumber)\n this.showTooltipForPin(pinNumber, e.clientX + 16, e.clientY - 10)\n }\n\n private showTooltipForPin(pinNumber: number, x?: number, y?: number): void {\n this.hideTooltip()\n\n const comment = this.comments.find((c) => c.pinNumber === pinNumber)\n if (!comment) return\n\n this.tooltipEl = document.createElement('div')\n this.tooltipEl.className = 'review-tooltip'\n\n const time = new Date(comment.createdAt).toLocaleString()\n\n const header = document.createElement('div')\n header.style.cssText = 'font-weight:500;margin-bottom:4px;'\n header.textContent = `Pin #${pinNumber}`\n this.tooltipEl.appendChild(header)\n\n if (comment.reviewerName) {\n const name = document.createElement('div')\n name.style.cssText = 'font-size:11px;opacity:0.7;margin-bottom:2px;'\n name.textContent = comment.reviewerName\n this.tooltipEl.appendChild(name)\n }\n\n const text = document.createElement('div')\n text.style.cssText = 'margin-bottom:4px;'\n text.textContent = comment.commentText || '(no text)'\n this.tooltipEl.appendChild(text)\n\n const timeEl = document.createElement('div')\n timeEl.style.cssText = 'font-size:11px;opacity:0.7;'\n timeEl.textContent = time\n this.tooltipEl.appendChild(timeEl)\n\n const pinPageUrl = comment.pageUrl ?? ''\n if (pinPageUrl && pinPageUrl !== getCurrentPageId()) {\n const navEl = document.createElement('div')\n navEl.style.cssText = 'margin-top:6px;padding-top:6px;border-top:1px solid rgba(255,255,255,0.2);font-size:12px;'\n\n const pageLabel = document.createElement('span')\n pageLabel.style.opacity = '0.7'\n pageLabel.textContent = `Page: ${pinPageUrl.split('?')[0].split('#')[0] || '/'} \\u2014 `\n navEl.appendChild(pageLabel)\n\n const navLink = document.createElement('a')\n navLink.style.cssText = 'color:#a78bfa;cursor:pointer;text-decoration:underline;pointer-events:auto;'\n navLink.textContent = 'Navigate there?'\n navLink.addEventListener('click', (e) => {\n e.stopPropagation()\n this.navigateToPin(pinPageUrl, pinNumber)\n })\n navEl.appendChild(navLink)\n\n this.tooltipEl.appendChild(navEl)\n this.tooltipEl.style.pointerEvents = 'auto'\n }\n\n const posX = x ?? window.innerWidth / 2\n const posY = y ?? window.innerHeight / 3\n this.tooltipEl.style.position = 'fixed'\n this.tooltipEl.style.left = `${Math.min(posX, window.innerWidth - 300)}px`\n this.tooltipEl.style.top = `${Math.min(posY, window.innerHeight - 150)}px`\n this.shadowRoot.appendChild(this.tooltipEl)\n\n const dismiss = (ev: MouseEvent) => {\n if (ev.target !== this.tooltipEl && !this.tooltipEl?.contains(ev.target as Node)) {\n this.hideTooltip()\n this.pinManager.clearHighlight()\n document.removeEventListener('click', dismiss, true)\n }\n }\n setTimeout(() => document.addEventListener('click', dismiss, true), 0)\n }\n\n private navigateToPin(pageUrl: string, pinNumber: number): void {\n this.hideTooltip()\n this.pinManager.clearHighlight()\n\n const url = new URL(pageUrl, window.location.origin)\n url.searchParams.set('pin', String(pinNumber))\n window.location.href = url.toString()\n }\n\n private autoFocusPin(): void {\n const params = new URLSearchParams(window.location.search)\n const pinParam = params.get('pin')\n if (!pinParam) return\n\n const pinNumber = Number(pinParam)\n if (!pinNumber) return\n\n const comment = this.comments.find((c) => c.pinNumber === pinNumber)\n if (!comment?.pinData) return\n\n const pinPageUrl = comment.pageUrl ?? ''\n if (pinPageUrl) {\n // Strip ?pin=N from current URL before comparing — navigateToPin adds it,\n // so after redirect getCurrentPageId() includes it but comment.pageUrl doesn't\n const currentUrl = new URL(window.location.href)\n currentUrl.searchParams.delete('pin')\n const currentPageWithoutPin = currentUrl.pathname + currentUrl.search + currentUrl.hash\n if (pinPageUrl !== currentPageWithoutPin) {\n this.navigateToPin(pinPageUrl, pinNumber)\n return\n }\n }\n\n this.pinManager.showAll()\n this.showAllPages = true\n this.updateToolbar()\n\n const docEl = document.documentElement\n const scrollX = (comment.pinData.pinX / 100) * docEl.scrollWidth\n const scrollY = (comment.pinData.pinY / 100) * docEl.scrollHeight\n\n window.scrollTo({\n left: scrollX - window.innerWidth / 2,\n top: scrollY - window.innerHeight / 2,\n behavior: 'smooth',\n })\n\n setTimeout(() => {\n this.pinManager.highlightPin(pinNumber)\n this.showTooltipForPin(pinNumber)\n }, 500)\n }\n\n private hideTooltip(): void {\n this.tooltipEl?.remove()\n this.tooltipEl = null\n }\n\n destroy(): void {\n if (this.pinClickHandler) {\n document.removeEventListener('click', this.pinClickHandler, true)\n }\n this.pageListener?.destroy()\n this.hideTooltip()\n this.toolbarEl?.remove()\n this.pinManager.destroy()\n }\n}\n","import { validateToken, ReviewError } from './api'\nimport { ReviewMode } from './ReviewMode'\nimport { clearStoredToken } from './TokenStorage'\nimport { TriageMode } from './TriageMode'\nimport { REVIEW_STYLES } from './styles'\nimport type { ReviewOptions } from './types'\n\nexport class Review {\n private root: HTMLElement\n private shadow: ShadowRoot\n private mode: ReviewMode | TriageMode | null = null\n private _isDestroyed = false\n\n constructor(_options: ReviewOptions = {}) {\n this.root = document.createElement('div')\n this.root.id = 'ourroadmaps-review'\n this.shadow = this.root.attachShadow({ mode: 'open' })\n\n const styleEl = document.createElement('style')\n styleEl.textContent = REVIEW_STYLES\n this.shadow.appendChild(styleEl)\n\n document.body.appendChild(this.root)\n }\n\n async init(tokenType?: 'review' | 'triage', token?: string): Promise<void> {\n // Backward compat: if no args, read from URL params (old inline script pattern)\n if (!tokenType || !token) {\n const params = new URLSearchParams(window.location.search)\n const reviewToken = params.get('review')\n const triageToken = params.get('triage')\n if (reviewToken) {\n tokenType = 'review'\n token = reviewToken\n } else if (triageToken) {\n tokenType = 'triage'\n token = triageToken\n } else {\n return\n }\n }\n\n if (tokenType === 'review') {\n try {\n const data = await validateToken(token)\n this.mode = new ReviewMode(token, this.shadow, data)\n await this.mode.init()\n } catch (err) {\n if (err instanceof ReviewError) {\n clearStoredToken()\n this.showErrorOverlay(\n err.code === 'expired'\n ? 'This feedback session has expired'\n : 'This review link is no longer valid',\n )\n }\n }\n } else if (tokenType === 'triage') {\n try {\n await validateToken(token)\n this.mode = new TriageMode(token, this.shadow)\n await this.mode.init()\n } catch (err) {\n if (err instanceof ReviewError) {\n clearStoredToken()\n this.showErrorOverlay(\n err.code === 'expired'\n ? 'This feedback session has expired'\n : 'This review link is no longer valid',\n )\n }\n }\n }\n }\n\n private showErrorOverlay(message: string): void {\n const overlay = document.createElement('div')\n overlay.className = 'review-expired-overlay'\n overlay.innerHTML = `\n <div class=\"review-expired-card\">\n <h2 style=\"margin:0 0 8px;font-size:18px;\">Session Unavailable</h2>\n <p style=\"margin:0;color:#666;font-size:14px;\">${message}</p>\n <p style=\"margin:12px 0 0;color:#999;font-size:13px;\">Contact the prototype owner for a new link.</p>\n </div>\n `\n this.shadow.appendChild(overlay)\n\n // Apply grayscale to body\n document.body.style.filter = 'grayscale(0.8)'\n }\n\n destroy(): void {\n if (this._isDestroyed) return\n this._isDestroyed = true\n this.mode?.destroy()\n this.root.remove()\n document.body.style.filter = ''\n }\n}\n"]}