@nuasite/notes 0.22.2 → 0.22.3
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.
- package/README.md +79 -41
- package/dist/overlay.js +227 -65
- package/package.json +1 -1
- package/src/dev/api-handlers.ts +82 -28
- package/src/dev/middleware.ts +9 -4
- package/src/integration.ts +2 -1
- package/src/overlay/App.tsx +88 -21
- package/src/overlay/components/Sidebar.tsx +41 -8
- package/src/overlay/components/SidebarItem.tsx +57 -16
- package/src/overlay/components/Toolbar.tsx +15 -3
- package/src/overlay/index.tsx +3 -1
- package/src/overlay/lib/cms-bridge.ts +61 -11
- package/src/overlay/lib/notes-fetch.ts +27 -5
- package/src/overlay/lib/url-mode.ts +46 -9
- package/src/overlay/styles.css +388 -138
- package/src/overlay/types.ts +11 -1
- package/src/storage/json-store.ts +57 -13
- package/src/storage/types.ts +54 -4
- package/src/types.ts +11 -0
package/dist/overlay.js
CHANGED
|
@@ -523,21 +523,23 @@ function formatTime(iso) {
|
|
|
523
523
|
return iso;
|
|
524
524
|
}
|
|
525
525
|
}
|
|
526
|
-
function SidebarItem({ item, active, stale, applying, onFocus, onResolve, onReopen, onDelete, onApply }) {
|
|
526
|
+
function SidebarItem({ item, active, stale, applying, isAgency, onFocus, onResolve, onReopen, onDelete, onPurge, onApply }) {
|
|
527
527
|
const isResolved = item.status === "resolved" || item.status === "applied";
|
|
528
528
|
const isApplied = item.status === "applied";
|
|
529
|
+
const isDeleted = item.status === "deleted";
|
|
529
530
|
const isSuggestion = item.type === "suggestion" && item.range;
|
|
530
|
-
const canApply = isSuggestion && !isApplied && !stale;
|
|
531
|
+
const canApply = isAgency && isSuggestion && !isApplied && !isDeleted && !stale;
|
|
531
532
|
return /* @__PURE__ */ u$1(
|
|
532
533
|
"div",
|
|
533
534
|
{
|
|
534
|
-
class: `notes-item ${active ? "notes-item--active" : ""} ${isResolved ? "notes-item--resolved" : ""}`,
|
|
535
|
+
class: `notes-item ${active ? "notes-item--active" : ""} ${isResolved ? "notes-item--resolved" : ""} ${isDeleted ? "notes-item--deleted" : ""}`,
|
|
535
536
|
onMouseEnter: onFocus,
|
|
536
537
|
children: [
|
|
537
538
|
/* @__PURE__ */ u$1("div", { class: "notes-item__head", children: [
|
|
538
539
|
/* @__PURE__ */ u$1("div", { children: [
|
|
539
540
|
/* @__PURE__ */ u$1("span", { class: `notes-item__badge notes-item__badge--${item.type}`, children: item.type }),
|
|
540
541
|
isResolved ? /* @__PURE__ */ u$1("span", { class: "notes-item__badge notes-item__badge--resolved", children: item.status }) : null,
|
|
542
|
+
isDeleted ? /* @__PURE__ */ u$1("span", { class: "notes-item__badge notes-item__badge--deleted", children: "deleted" }) : null,
|
|
541
543
|
/* @__PURE__ */ u$1("span", { class: "notes-item__author", children: item.author })
|
|
542
544
|
] }),
|
|
543
545
|
/* @__PURE__ */ u$1("span", { class: "notes-item__time", children: formatTime(item.createdAt) })
|
|
@@ -555,18 +557,51 @@ function SidebarItem({ item, active, stale, applying, onFocus, onResolve, onReop
|
|
|
555
557
|
item.targetSnippet ? /* @__PURE__ */ u$1("div", { class: "notes-item__snippet", children: item.targetSnippet }) : null,
|
|
556
558
|
/* @__PURE__ */ u$1("div", { class: "notes-item__body", children: item.body })
|
|
557
559
|
] }),
|
|
558
|
-
/* @__PURE__ */ u$1("
|
|
560
|
+
isAgency && item.history.length > 1 ? /* @__PURE__ */ u$1("details", { class: "notes-item__history", children: [
|
|
561
|
+
/* @__PURE__ */ u$1("summary", { children: [
|
|
562
|
+
"History (",
|
|
563
|
+
item.history.length,
|
|
564
|
+
")"
|
|
565
|
+
] }),
|
|
566
|
+
/* @__PURE__ */ u$1("ul", { children: item.history.map((h2, i2) => /* @__PURE__ */ u$1("li", { children: [
|
|
567
|
+
/* @__PURE__ */ u$1("span", { class: "notes-item__history-action", children: h2.action }),
|
|
568
|
+
/* @__PURE__ */ u$1("span", { class: "notes-item__history-meta", children: [
|
|
569
|
+
h2.role ? ` · ${h2.role}` : "",
|
|
570
|
+
" · ",
|
|
571
|
+
formatTime(h2.at)
|
|
572
|
+
] }),
|
|
573
|
+
h2.note ? /* @__PURE__ */ u$1("div", { class: "notes-item__history-note", children: h2.note }) : null
|
|
574
|
+
] }, i2)) })
|
|
575
|
+
] }) : null,
|
|
576
|
+
isAgency ? /* @__PURE__ */ u$1("div", { class: "notes-item__actions", children: [
|
|
559
577
|
canApply ? /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--primary", onClick: onApply, disabled: applying, children: applying ? "Applying..." : "Apply" }) : null,
|
|
560
|
-
isResolved ? /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost", onClick: onReopen, children: "Reopen" }) : /* @__PURE__ */ u$1("button", { class: "notes-btn", onClick: onResolve, children: "Resolve" }),
|
|
561
|
-
/* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost notes-btn--danger", onClick: onDelete, children: "Delete" })
|
|
562
|
-
] })
|
|
578
|
+
isDeleted ? /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost notes-btn--danger", onClick: onPurge, children: "Purge" }) : isResolved ? /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost", onClick: onReopen, children: "Reopen" }) : /* @__PURE__ */ u$1("button", { class: "notes-btn", onClick: onResolve, children: "Resolve" }),
|
|
579
|
+
!isDeleted ? /* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost notes-btn--danger", onClick: onDelete, children: "Delete" }) : null
|
|
580
|
+
] }) : null
|
|
563
581
|
]
|
|
564
582
|
}
|
|
565
583
|
);
|
|
566
584
|
}
|
|
567
|
-
function Sidebar({
|
|
568
|
-
|
|
569
|
-
|
|
585
|
+
function Sidebar({
|
|
586
|
+
page,
|
|
587
|
+
items,
|
|
588
|
+
activeId,
|
|
589
|
+
picking,
|
|
590
|
+
error,
|
|
591
|
+
staleIds,
|
|
592
|
+
applyingId,
|
|
593
|
+
isAgency,
|
|
594
|
+
onFocus,
|
|
595
|
+
onResolve,
|
|
596
|
+
onReopen,
|
|
597
|
+
onDelete,
|
|
598
|
+
onPurge,
|
|
599
|
+
onApply
|
|
600
|
+
}) {
|
|
601
|
+
const open = items.filter((i2) => i2.status === "open" || i2.status === "stale" || i2.status === "rejected");
|
|
602
|
+
const resolved = items.filter((i2) => i2.status === "resolved" || i2.status === "applied");
|
|
603
|
+
const deleted = isAgency ? items.filter((i2) => i2.status === "deleted") : [];
|
|
604
|
+
const visible = [...open, ...resolved, ...deleted];
|
|
570
605
|
const renderItem = (item) => /* @__PURE__ */ u$1(
|
|
571
606
|
SidebarItem,
|
|
572
607
|
{
|
|
@@ -574,10 +609,12 @@ function Sidebar({ page, items, activeId, picking, error, staleIds, applyingId,
|
|
|
574
609
|
active: item.id === activeId,
|
|
575
610
|
stale: staleIds.has(item.id),
|
|
576
611
|
applying: applyingId === item.id,
|
|
612
|
+
isAgency,
|
|
577
613
|
onFocus: () => onFocus(item.id),
|
|
578
614
|
onResolve: () => onResolve(item.id),
|
|
579
615
|
onReopen: () => onReopen(item.id),
|
|
580
616
|
onDelete: () => onDelete(item.id),
|
|
617
|
+
onPurge: () => onPurge(item.id),
|
|
581
618
|
onApply: () => onApply(item.id)
|
|
582
619
|
},
|
|
583
620
|
item.id
|
|
@@ -588,18 +625,28 @@ function Sidebar({ page, items, activeId, picking, error, staleIds, applyingId,
|
|
|
588
625
|
/* @__PURE__ */ u$1("div", { class: "notes-sidebar__meta", children: [
|
|
589
626
|
open.length,
|
|
590
627
|
" open · ",
|
|
591
|
-
|
|
592
|
-
" resolved
|
|
628
|
+
resolved.length,
|
|
629
|
+
" resolved",
|
|
630
|
+
isAgency && deleted.length > 0 ? ` · ${deleted.length} deleted` : "",
|
|
631
|
+
" · ",
|
|
593
632
|
/* @__PURE__ */ u$1("code", { children: page })
|
|
594
633
|
] })
|
|
595
634
|
] }),
|
|
596
635
|
/* @__PURE__ */ u$1("div", { class: "notes-sidebar__list", children: [
|
|
597
636
|
error ? /* @__PURE__ */ u$1("div", { class: "notes-banner", children: error }) : null,
|
|
598
|
-
|
|
637
|
+
visible.length === 0 ? /* @__PURE__ */ u$1("div", { class: "notes-sidebar__empty", children: picking ? "Click any text or element on the page to add a comment." : 'Select text on the page to suggest an edit, or click "Pick element" to comment.' }) : null,
|
|
599
638
|
open.map(renderItem),
|
|
600
|
-
|
|
601
|
-
/* @__PURE__ */ u$1("div", { class: "notes-
|
|
602
|
-
|
|
639
|
+
resolved.length > 0 ? /* @__PURE__ */ u$1(S, { children: [
|
|
640
|
+
/* @__PURE__ */ u$1("div", { class: "notes-sidebar__section", children: "Resolved" }),
|
|
641
|
+
resolved.map(renderItem)
|
|
642
|
+
] }) : null,
|
|
643
|
+
isAgency && deleted.length > 0 ? /* @__PURE__ */ u$1("details", { class: "notes-sidebar__deleted", children: [
|
|
644
|
+
/* @__PURE__ */ u$1("summary", { children: [
|
|
645
|
+
"Deleted (",
|
|
646
|
+
deleted.length,
|
|
647
|
+
")"
|
|
648
|
+
] }),
|
|
649
|
+
deleted.map(renderItem)
|
|
603
650
|
] }) : null
|
|
604
651
|
] })
|
|
605
652
|
] });
|
|
@@ -732,11 +779,12 @@ function SuggestPopover({ rect, originalText, defaultAuthor, onCancel, onSubmit
|
|
|
732
779
|
}
|
|
733
780
|
);
|
|
734
781
|
}
|
|
735
|
-
function Toolbar({ page, count, picking, onTogglePick, onExit }) {
|
|
782
|
+
function Toolbar({ page, count, picking, role, collapsed, onTogglePick, onToggleCollapse, onExit }) {
|
|
736
783
|
return /* @__PURE__ */ u$1("div", { class: "notes-toolbar", children: [
|
|
737
784
|
/* @__PURE__ */ u$1("div", { class: "notes-toolbar__brand", children: [
|
|
738
785
|
/* @__PURE__ */ u$1("span", { class: "notes-toolbar__dot" }),
|
|
739
786
|
/* @__PURE__ */ u$1("span", { children: "Notes" }),
|
|
787
|
+
/* @__PURE__ */ u$1("span", { class: `notes-toolbar__role notes-toolbar__role--${role}`, children: role }),
|
|
740
788
|
/* @__PURE__ */ u$1("span", { class: "notes-toolbar__page", children: [
|
|
741
789
|
page,
|
|
742
790
|
" · ",
|
|
@@ -755,10 +803,65 @@ function Toolbar({ page, count, picking, onTogglePick, onExit }) {
|
|
|
755
803
|
children: picking ? "Cancel pick" : "Pick element"
|
|
756
804
|
}
|
|
757
805
|
),
|
|
806
|
+
/* @__PURE__ */ u$1(
|
|
807
|
+
"button",
|
|
808
|
+
{
|
|
809
|
+
class: "notes-btn notes-btn--ghost",
|
|
810
|
+
onClick: onToggleCollapse,
|
|
811
|
+
title: collapsed ? "Show notes sidebar" : "Hide notes sidebar to see the full page",
|
|
812
|
+
children: collapsed ? "Show sidebar" : "Hide sidebar"
|
|
813
|
+
}
|
|
814
|
+
),
|
|
758
815
|
/* @__PURE__ */ u$1("button", { class: "notes-btn notes-btn--ghost", onClick: onExit, title: "Leave review mode", children: "Exit" })
|
|
759
816
|
] })
|
|
760
817
|
] });
|
|
761
818
|
}
|
|
819
|
+
const STYLE_ID = "nua-notes-cms-bridge";
|
|
820
|
+
const COLLAPSE_ATTR = "data-nua-notes-collapsed";
|
|
821
|
+
const STYLES = `
|
|
822
|
+
#cms-app-host { display: none !important; }
|
|
823
|
+
[data-nuasite-cms] { display: none !important; }
|
|
824
|
+
|
|
825
|
+
/* Reserve space for the notes toolbar + sidebar so they don't sit on top
|
|
826
|
+
* of host page content. Padding the body lets the page reflow into the
|
|
827
|
+
* visible area instead of being clipped under fixed-position chrome. */
|
|
828
|
+
html:not([${COLLAPSE_ATTR}]) body {
|
|
829
|
+
box-sizing: border-box;
|
|
830
|
+
padding-top: 40px !important;
|
|
831
|
+
padding-right: 340px !important;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/* When the sidebar is collapsed, only reserve the toolbar height. */
|
|
835
|
+
html[${COLLAPSE_ATTR}] body {
|
|
836
|
+
box-sizing: border-box;
|
|
837
|
+
padding-top: 40px !important;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/* Page-fixed elements (sticky headers, fixed nav) don't get pushed by
|
|
841
|
+
* body padding because they're positioned against the viewport. Offset
|
|
842
|
+
* them via top/right so they slot into the same chrome-free area. We
|
|
843
|
+
* scope this to elements the host page declared as fixed/sticky to
|
|
844
|
+
* avoid touching the notes UI itself (which lives in a shadow DOM). */
|
|
845
|
+
html:not([${COLLAPSE_ATTR}]) body > header[class*="fixed"],
|
|
846
|
+
html:not([${COLLAPSE_ATTR}]) body > nav[class*="fixed"],
|
|
847
|
+
html:not([${COLLAPSE_ATTR}]) body > [class*="sticky"] {
|
|
848
|
+
right: 340px !important;
|
|
849
|
+
}
|
|
850
|
+
`;
|
|
851
|
+
function enableCmsBridge() {
|
|
852
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
853
|
+
const style = document.createElement("style");
|
|
854
|
+
style.id = STYLE_ID;
|
|
855
|
+
style.textContent = STYLES;
|
|
856
|
+
document.head.appendChild(style);
|
|
857
|
+
}
|
|
858
|
+
function setSidebarCollapsed(collapsed) {
|
|
859
|
+
if (collapsed) {
|
|
860
|
+
document.documentElement.setAttribute(COLLAPSE_ATTR, "");
|
|
861
|
+
} else {
|
|
862
|
+
document.documentElement.removeAttribute(COLLAPSE_ATTR);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
762
865
|
function manifestUrlForPage(page) {
|
|
763
866
|
if (page === "" || page === "/") return "/index.json";
|
|
764
867
|
const trimmed = page.replace(/^\/+|\/+$/g, "");
|
|
@@ -776,12 +879,64 @@ async function fetchPageManifest(page) {
|
|
|
776
879
|
return null;
|
|
777
880
|
}
|
|
778
881
|
}
|
|
882
|
+
const MODE_COOKIE = "nua-notes-mode";
|
|
883
|
+
const ROLE_COOKIE = "nua-notes-role";
|
|
884
|
+
function readCookie(name) {
|
|
885
|
+
if (typeof document === "undefined") return null;
|
|
886
|
+
for (const part of document.cookie.split("; ")) {
|
|
887
|
+
const eq = part.indexOf("=");
|
|
888
|
+
if (eq < 0) continue;
|
|
889
|
+
if (part.slice(0, eq) === name) return decodeURIComponent(part.slice(eq + 1));
|
|
890
|
+
}
|
|
891
|
+
return null;
|
|
892
|
+
}
|
|
893
|
+
function isReviewMode(urlFlag) {
|
|
894
|
+
if (typeof window === "undefined") return false;
|
|
895
|
+
const url = new URL(window.location.href);
|
|
896
|
+
if (url.searchParams.has(urlFlag)) return true;
|
|
897
|
+
return readCookie(MODE_COOKIE) === "1";
|
|
898
|
+
}
|
|
899
|
+
function setReviewModeCookie() {
|
|
900
|
+
document.cookie = `${MODE_COOKIE}=1; path=/; SameSite=Lax`;
|
|
901
|
+
}
|
|
902
|
+
function clearReviewModeCookie() {
|
|
903
|
+
document.cookie = `${MODE_COOKIE}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax`;
|
|
904
|
+
}
|
|
905
|
+
function resolveRole(agencyFlag) {
|
|
906
|
+
if (typeof window === "undefined") return "client";
|
|
907
|
+
const url = new URL(window.location.href);
|
|
908
|
+
if (url.searchParams.has(agencyFlag)) {
|
|
909
|
+
document.cookie = `${ROLE_COOKIE}=agency; path=/; SameSite=Lax`;
|
|
910
|
+
return "agency";
|
|
911
|
+
}
|
|
912
|
+
return readCookie(ROLE_COOKIE) === "agency" ? "agency" : "client";
|
|
913
|
+
}
|
|
914
|
+
function clearRoleCookie() {
|
|
915
|
+
document.cookie = `${ROLE_COOKIE}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax`;
|
|
916
|
+
}
|
|
917
|
+
function exitReviewMode(urlFlag, agencyFlag) {
|
|
918
|
+
clearReviewModeCookie();
|
|
919
|
+
clearRoleCookie();
|
|
920
|
+
const url = new URL(window.location.href);
|
|
921
|
+
url.searchParams.delete(urlFlag);
|
|
922
|
+
url.searchParams.delete(agencyFlag);
|
|
923
|
+
window.location.href = url.pathname + (url.search || "") + url.hash;
|
|
924
|
+
}
|
|
925
|
+
function getCurrentPagePath() {
|
|
926
|
+
if (typeof window === "undefined") return "/";
|
|
927
|
+
const p2 = window.location.pathname;
|
|
928
|
+
if (p2 === "" || p2 === "/") return "/";
|
|
929
|
+
return p2.endsWith("/") ? p2.slice(0, -1) : p2;
|
|
930
|
+
}
|
|
779
931
|
const BASE = "/_nua/notes";
|
|
780
932
|
const TIMEOUT_MS = 1e4;
|
|
933
|
+
function authHeaders() {
|
|
934
|
+
return { "x-nua-role": resolveRole("nua-agency") };
|
|
935
|
+
}
|
|
781
936
|
async function postJson(path, body) {
|
|
782
937
|
const res = await fetch(`${BASE}${path}`, {
|
|
783
938
|
method: "POST",
|
|
784
|
-
headers: { "Content-Type": "application/json" },
|
|
939
|
+
headers: { "Content-Type": "application/json", ...authHeaders() },
|
|
785
940
|
body: JSON.stringify(body),
|
|
786
941
|
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
787
942
|
});
|
|
@@ -799,7 +954,7 @@ async function postJson(path, body) {
|
|
|
799
954
|
}
|
|
800
955
|
async function listNotes(page) {
|
|
801
956
|
const res = await fetch(`${BASE}/list?page=${encodeURIComponent(page)}`, {
|
|
802
|
-
headers: { Accept: "application/json" },
|
|
957
|
+
headers: { Accept: "application/json", ...authHeaders() },
|
|
803
958
|
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
804
959
|
});
|
|
805
960
|
if (!res.ok) throw new Error(`notes: list failed (${res.status})`);
|
|
@@ -825,12 +980,16 @@ async function setNoteStatus(page, id, status) {
|
|
|
825
980
|
return updateNote(page, id, { status });
|
|
826
981
|
}
|
|
827
982
|
async function deleteNote(page, id) {
|
|
828
|
-
await postJson("/delete", { page, id });
|
|
983
|
+
const res = await postJson("/delete", { page, id });
|
|
984
|
+
return res.item;
|
|
985
|
+
}
|
|
986
|
+
async function purgeNote(page, id) {
|
|
987
|
+
await postJson("/purge", { page, id });
|
|
829
988
|
}
|
|
830
989
|
async function applyNote(page, id) {
|
|
831
990
|
const res = await fetch(`${BASE}/apply`, {
|
|
832
991
|
method: "POST",
|
|
833
|
-
headers: { "Content-Type": "application/json" },
|
|
992
|
+
headers: { "Content-Type": "application/json", ...authHeaders() },
|
|
834
993
|
body: JSON.stringify({ page, id }),
|
|
835
994
|
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
836
995
|
});
|
|
@@ -932,30 +1091,19 @@ function selectionInsideElement(el, selection) {
|
|
|
932
1091
|
if (!text.trim()) return null;
|
|
933
1092
|
return { text, rect: range.getBoundingClientRect() };
|
|
934
1093
|
}
|
|
935
|
-
const
|
|
936
|
-
function
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
}
|
|
942
|
-
function setReviewModeCookie() {
|
|
943
|
-
document.cookie = `${COOKIE}=1; path=/; SameSite=Lax`;
|
|
944
|
-
}
|
|
945
|
-
function clearReviewModeCookie() {
|
|
946
|
-
document.cookie = `${COOKIE}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax`;
|
|
947
|
-
}
|
|
948
|
-
function exitReviewMode(urlFlag) {
|
|
949
|
-
clearReviewModeCookie();
|
|
950
|
-
const url = new URL(window.location.href);
|
|
951
|
-
url.searchParams.delete(urlFlag);
|
|
952
|
-
window.location.href = url.pathname + (url.search || "") + url.hash;
|
|
1094
|
+
const COLLAPSED_KEY = "nua-notes-sidebar-collapsed";
|
|
1095
|
+
function loadCollapsed() {
|
|
1096
|
+
try {
|
|
1097
|
+
return localStorage.getItem(COLLAPSED_KEY) === "1";
|
|
1098
|
+
} catch {
|
|
1099
|
+
return false;
|
|
1100
|
+
}
|
|
953
1101
|
}
|
|
954
|
-
function
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1102
|
+
function saveCollapsed(value) {
|
|
1103
|
+
try {
|
|
1104
|
+
localStorage.setItem(COLLAPSED_KEY, value ? "1" : "0");
|
|
1105
|
+
} catch {
|
|
1106
|
+
}
|
|
959
1107
|
}
|
|
960
1108
|
const AUTHOR_KEY = "nua-notes-author";
|
|
961
1109
|
function loadAuthor() {
|
|
@@ -986,8 +1134,10 @@ function findCmsAncestor(target) {
|
|
|
986
1134
|
}
|
|
987
1135
|
return null;
|
|
988
1136
|
}
|
|
989
|
-
function App({ urlFlag }) {
|
|
1137
|
+
function App({ urlFlag, agencyFlag }) {
|
|
990
1138
|
const page = T(() => getCurrentPagePath(), []);
|
|
1139
|
+
const role = T(() => resolveRole(agencyFlag), [agencyFlag]);
|
|
1140
|
+
const isAgency = role === "agency";
|
|
991
1141
|
const [items, setItems] = d([]);
|
|
992
1142
|
const [manifest, setManifest] = d(null);
|
|
993
1143
|
const [picking, setPicking] = d(false);
|
|
@@ -1001,6 +1151,17 @@ function App({ urlFlag }) {
|
|
|
1001
1151
|
const [author, setAuthor] = d(() => loadAuthor());
|
|
1002
1152
|
const [staleIds, setStaleIds] = d(/* @__PURE__ */ new Set());
|
|
1003
1153
|
const [applyingId, setApplyingId] = d(null);
|
|
1154
|
+
const [collapsed, setCollapsedState] = d(() => loadCollapsed());
|
|
1155
|
+
y(() => {
|
|
1156
|
+
setSidebarCollapsed(collapsed);
|
|
1157
|
+
saveCollapsed(collapsed);
|
|
1158
|
+
}, [collapsed]);
|
|
1159
|
+
y(() => {
|
|
1160
|
+
setSidebarCollapsed(loadCollapsed());
|
|
1161
|
+
}, []);
|
|
1162
|
+
const toggleCollapsed = q(() => {
|
|
1163
|
+
setCollapsedState((c2) => !c2);
|
|
1164
|
+
}, []);
|
|
1004
1165
|
y(() => {
|
|
1005
1166
|
let alive = true;
|
|
1006
1167
|
Promise.all([listNotes(page), fetchPageManifest(page)]).then(([file, mf]) => {
|
|
@@ -1214,7 +1375,16 @@ function App({ urlFlag }) {
|
|
|
1214
1375
|
}, [page]);
|
|
1215
1376
|
const handleDelete = q(async (id) => {
|
|
1216
1377
|
try {
|
|
1217
|
-
await deleteNote(page, id);
|
|
1378
|
+
const item = await deleteNote(page, id);
|
|
1379
|
+
setItems((prev) => prev.map((i2) => i2.id === id ? item : i2));
|
|
1380
|
+
if (activeId === id) setActiveId(null);
|
|
1381
|
+
} catch (err) {
|
|
1382
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
1383
|
+
}
|
|
1384
|
+
}, [page, activeId]);
|
|
1385
|
+
const handlePurge = q(async (id) => {
|
|
1386
|
+
try {
|
|
1387
|
+
await purgeNote(page, id);
|
|
1218
1388
|
setItems((prev) => prev.filter((i2) => i2.id !== id));
|
|
1219
1389
|
if (activeId === id) setActiveId(null);
|
|
1220
1390
|
} catch (err) {
|
|
@@ -1256,17 +1426,20 @@ function App({ urlFlag }) {
|
|
|
1256
1426
|
Toolbar,
|
|
1257
1427
|
{
|
|
1258
1428
|
page,
|
|
1259
|
-
count: items.length,
|
|
1429
|
+
count: items.filter((i2) => i2.status !== "deleted").length,
|
|
1260
1430
|
picking,
|
|
1431
|
+
role,
|
|
1432
|
+
collapsed,
|
|
1261
1433
|
onTogglePick: () => {
|
|
1262
1434
|
setPicking((p2) => !p2);
|
|
1263
1435
|
setPendingPick(null);
|
|
1264
1436
|
setPendingSuggest(null);
|
|
1265
1437
|
},
|
|
1266
|
-
|
|
1438
|
+
onToggleCollapse: toggleCollapsed,
|
|
1439
|
+
onExit: () => exitReviewMode(urlFlag, agencyFlag)
|
|
1267
1440
|
}
|
|
1268
1441
|
),
|
|
1269
|
-
/* @__PURE__ */ u$1(
|
|
1442
|
+
collapsed ? null : /* @__PURE__ */ u$1(
|
|
1270
1443
|
Sidebar,
|
|
1271
1444
|
{
|
|
1272
1445
|
page,
|
|
@@ -1276,10 +1449,12 @@ function App({ urlFlag }) {
|
|
|
1276
1449
|
error,
|
|
1277
1450
|
staleIds,
|
|
1278
1451
|
applyingId,
|
|
1452
|
+
isAgency,
|
|
1279
1453
|
onFocus: setActiveId,
|
|
1280
1454
|
onResolve: handleResolve,
|
|
1281
1455
|
onReopen: handleReopen,
|
|
1282
1456
|
onDelete: handleDelete,
|
|
1457
|
+
onPurge: handlePurge,
|
|
1283
1458
|
onApply: handleApply
|
|
1284
1459
|
}
|
|
1285
1460
|
),
|
|
@@ -1321,25 +1496,12 @@ function App({ urlFlag }) {
|
|
|
1321
1496
|
) : null
|
|
1322
1497
|
] });
|
|
1323
1498
|
}
|
|
1324
|
-
const STYLE_ID = "nua-notes-cms-bridge";
|
|
1325
|
-
const HIDE_CMS_CSS = `
|
|
1326
|
-
#cms-app-host { display: none !important; }
|
|
1327
|
-
[data-nuasite-cms] { display: none !important; }
|
|
1328
|
-
/* Allow notes to handle clicks on annotated elements without CMS interfering */
|
|
1329
|
-
[data-cms-id] { cursor: default !important; }
|
|
1330
|
-
`;
|
|
1331
|
-
function enableCmsBridge() {
|
|
1332
|
-
if (document.getElementById(STYLE_ID)) return;
|
|
1333
|
-
const style = document.createElement("style");
|
|
1334
|
-
style.id = STYLE_ID;
|
|
1335
|
-
style.textContent = HIDE_CMS_CSS;
|
|
1336
|
-
document.head.appendChild(style);
|
|
1337
|
-
}
|
|
1338
|
-
const OVERLAY_STYLES = "/**\n * @nuasite/notes overlay styles.\n *\n * Imported via Vite's `?inline` query and injected into a shadow root, so\n * these styles never leak into the host page (and the host page can't\n * accidentally style notes UI). Variables on `:host` are the only knobs.\n */\n\n:host {\n --notes-bg: #ffffff;\n --notes-fg: #0f172a;\n --notes-muted: #64748b;\n --notes-border: #e2e8f0;\n --notes-accent: #f59e0b;\n --notes-accent-fg: #1f2937;\n --notes-danger: #dc2626;\n --notes-success: #16a34a;\n --notes-shadow: 0 10px 30px rgba(15, 23, 42, 0.18);\n --notes-radius: 10px;\n --notes-sidebar-w: 360px;\n --notes-z: 2147483600;\n\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n line-height: 1.45;\n color: var(--notes-fg);\n -webkit-font-smoothing: antialiased;\n}\n\n* {\n box-sizing: border-box;\n}\n\nbutton {\n font: inherit;\n cursor: pointer;\n border: none;\n background: none;\n color: inherit;\n padding: 0;\n}\n\ninput,\ntextarea {\n font: inherit;\n color: inherit;\n}\n\n.notes-root {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: var(--notes-z);\n}\n\n/* Toolbar (top, full width) */\n.notes-toolbar {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 44px;\n background: var(--notes-bg);\n border-bottom: 1px solid var(--notes-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 16px;\n box-shadow: var(--notes-shadow);\n pointer-events: auto;\n}\n\n.notes-toolbar__brand {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n}\n\n.notes-toolbar__dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--notes-accent);\n box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.2);\n}\n\n.notes-toolbar__page {\n color: var(--notes-muted);\n font-weight: 400;\n margin-left: 12px;\n font-size: 13px;\n}\n\n.notes-toolbar__actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.notes-btn {\n padding: 6px 12px;\n border-radius: 6px;\n background: #f1f5f9;\n color: var(--notes-fg);\n font-size: 13px;\n font-weight: 500;\n transition: background 0.15s;\n}\n\n.notes-btn:hover {\n background: #e2e8f0;\n}\n\n.notes-btn--primary {\n background: var(--notes-accent);\n color: var(--notes-accent-fg);\n}\n\n.notes-btn--primary:hover {\n background: #d97706;\n color: #ffffff;\n}\n\n.notes-btn--ghost {\n background: transparent;\n color: var(--notes-muted);\n}\n\n.notes-btn--ghost:hover {\n color: var(--notes-fg);\n background: #f1f5f9;\n}\n\n.notes-btn--danger {\n color: var(--notes-danger);\n}\n\n/* Sidebar (right side) */\n.notes-sidebar {\n position: fixed;\n top: 44px;\n right: 0;\n bottom: 0;\n width: var(--notes-sidebar-w);\n background: var(--notes-bg);\n border-left: 1px solid var(--notes-border);\n box-shadow: var(--notes-shadow);\n display: flex;\n flex-direction: column;\n pointer-events: auto;\n}\n\n.notes-sidebar__header {\n padding: 16px 16px 12px;\n border-bottom: 1px solid var(--notes-border);\n}\n\n.notes-sidebar__title {\n font-size: 16px;\n font-weight: 600;\n margin: 0 0 4px;\n}\n\n.notes-sidebar__meta {\n font-size: 12px;\n color: var(--notes-muted);\n}\n\n.notes-sidebar__list {\n flex: 1;\n overflow-y: auto;\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.notes-sidebar__empty {\n padding: 24px 16px;\n text-align: center;\n color: var(--notes-muted);\n font-size: 13px;\n line-height: 1.5;\n}\n\n.notes-sidebar__hint {\n font-size: 12px;\n color: var(--notes-muted);\n margin-top: 6px;\n}\n\n/* Item card */\n.notes-item {\n border: 1px solid var(--notes-border);\n border-radius: var(--notes-radius);\n padding: 12px;\n background: #ffffff;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.notes-item:hover {\n border-color: #cbd5e1;\n}\n\n.notes-item--active {\n border-color: var(--notes-accent);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.12);\n}\n\n.notes-item--resolved {\n opacity: 0.55;\n}\n\n.notes-item__head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 6px;\n}\n\n.notes-item__author {\n font-weight: 600;\n font-size: 13px;\n}\n\n.notes-item__time {\n font-size: 11px;\n color: var(--notes-muted);\n}\n\n.notes-item__snippet {\n font-size: 12px;\n color: var(--notes-muted);\n background: #f8fafc;\n border-left: 3px solid var(--notes-border);\n padding: 6px 8px;\n margin-bottom: 6px;\n border-radius: 0 4px 4px 0;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.notes-item__body {\n font-size: 13px;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.notes-item__actions {\n display: flex;\n gap: 6px;\n margin-top: 10px;\n padding-top: 10px;\n border-top: 1px solid #f1f5f9;\n}\n\n.notes-item__badge {\n display: inline-block;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 2px 6px;\n border-radius: 4px;\n margin-right: 6px;\n}\n\n.notes-item__badge--comment {\n background: #dbeafe;\n color: #1e40af;\n}\n\n.notes-item__badge--suggestion {\n background: #fef3c7;\n color: #92400e;\n}\n\n.notes-item__badge--resolved {\n background: #dcfce7;\n color: #166534;\n}\n\n/* Element highlight ring */\n.notes-highlight {\n position: fixed;\n pointer-events: none;\n border: 2px solid var(--notes-accent);\n border-radius: 4px;\n box-shadow: 0 0 0 4px rgba(245, 158, 11, 0.18);\n transition: all 0.08s ease-out;\n}\n\n.notes-highlight--persistent {\n border-color: rgba(245, 158, 11, 0.6);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.12);\n}\n\n/* Comment popover */\n.notes-popover {\n position: fixed;\n width: 320px;\n background: var(--notes-bg);\n border: 1px solid var(--notes-border);\n border-radius: var(--notes-radius);\n box-shadow: var(--notes-shadow);\n padding: 14px;\n pointer-events: auto;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.notes-popover__title {\n font-size: 13px;\n font-weight: 600;\n margin: 0;\n}\n\n.notes-popover__snippet {\n font-size: 12px;\n color: var(--notes-muted);\n background: #f8fafc;\n border-left: 3px solid var(--notes-border);\n padding: 6px 8px;\n border-radius: 0 4px 4px 0;\n max-height: 60px;\n overflow: hidden;\n}\n\n.notes-popover textarea {\n width: 100%;\n min-height: 80px;\n resize: vertical;\n border: 1px solid var(--notes-border);\n border-radius: 6px;\n padding: 8px 10px;\n background: #ffffff;\n outline: none;\n}\n\n.notes-popover textarea:focus {\n border-color: var(--notes-accent);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.15);\n}\n\n.notes-popover input[type='text'] {\n border: 1px solid var(--notes-border);\n border-radius: 6px;\n padding: 6px 10px;\n background: #ffffff;\n outline: none;\n}\n\n.notes-popover input[type='text']:focus {\n border-color: var(--notes-accent);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.15);\n}\n\n.notes-popover__row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 8px;\n}\n\n/* Selection tooltip */\n.notes-selection-tooltip {\n position: fixed;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n background: #0f172a;\n color: #ffffff;\n border-radius: 8px;\n box-shadow: var(--notes-shadow);\n pointer-events: auto;\n z-index: calc(var(--notes-z) + 5);\n}\n\n.notes-selection-tooltip .notes-btn {\n background: rgba(255, 255, 255, 0.08);\n color: #ffffff;\n font-size: 12px;\n padding: 4px 8px;\n}\n\n.notes-selection-tooltip .notes-btn--primary {\n background: var(--notes-accent);\n color: var(--notes-accent-fg);\n}\n\n.notes-selection-tooltip .notes-btn--ghost {\n color: #e2e8f0;\n}\n\n.notes-selection-tooltip .notes-btn--ghost:hover {\n background: rgba(255, 255, 255, 0.16);\n color: #ffffff;\n}\n\n/* Suggest popover variations */\n.notes-popover--suggest {\n width: 360px;\n}\n\n.notes-popover__label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--notes-muted);\n margin-bottom: 4px;\n}\n\n.notes-popover__original {\n background: #fef3c7;\n border: 1px solid #fde68a;\n border-radius: 6px;\n padding: 8px 10px;\n font-size: 13px;\n color: #78350f;\n max-height: 80px;\n overflow-y: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.notes-strikethrough {\n text-decoration: line-through;\n text-decoration-color: rgba(220, 38, 38, 0.6);\n text-decoration-thickness: 2px;\n}\n\n/* Diff preview in sidebar */\n.notes-diff {\n font-size: 13px;\n border-radius: 6px;\n background: #f8fafc;\n border: 1px solid var(--notes-border);\n overflow: hidden;\n margin-bottom: 8px;\n}\n\n.notes-diff__row {\n padding: 6px 10px;\n display: flex;\n gap: 6px;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.notes-diff__row--del {\n background: #fef2f2;\n color: #7f1d1d;\n border-bottom: 1px solid #fee2e2;\n}\n\n.notes-diff__row--ins {\n background: #f0fdf4;\n color: #14532d;\n}\n\n.notes-diff__marker {\n font-weight: 700;\n font-family: ui-monospace, SFMono-Regular, monospace;\n width: 12px;\n flex-shrink: 0;\n text-align: center;\n}\n\n.notes-item__rationale {\n font-size: 12px;\n color: var(--notes-muted);\n margin-bottom: 6px;\n font-style: italic;\n}\n\n.notes-item__rationale-label {\n font-style: normal;\n font-weight: 600;\n color: var(--notes-fg);\n margin-right: 4px;\n}\n\n/* Stale warning */\n.notes-stale {\n display: flex;\n align-items: center;\n gap: 6px;\n background: #fef3c7;\n border: 1px solid #fde68a;\n color: #92400e;\n font-size: 12px;\n padding: 6px 8px;\n border-radius: 6px;\n margin-bottom: 8px;\n}\n\n.notes-stale__icon {\n font-size: 14px;\n}\n\n/* Persistent highlight variant for suggestion ranges */\n.notes-highlight--suggestion {\n border-color: rgba(250, 204, 21, 0.9);\n box-shadow: 0 0 0 3px rgba(250, 204, 21, 0.18);\n background: rgba(254, 243, 199, 0.25);\n}\n\n/* Banner shown when notes API fails to load */\n.notes-banner {\n position: fixed;\n top: 56px;\n left: 16px;\n right: calc(var(--notes-sidebar-w) + 16px);\n padding: 10px 14px;\n background: #fef2f2;\n border: 1px solid #fecaca;\n color: #991b1b;\n border-radius: var(--notes-radius);\n font-size: 13px;\n pointer-events: auto;\n}\n";
|
|
1499
|
+
const OVERLAY_STYLES = "/**\n * @nuasite/notes overlay styles.\n *\n * Imported via Vite's `?inline` query and injected into a shadow root, so\n * these styles never leak into the host page (and the host page can't\n * accidentally style notes UI). Variables on `:host` are the only knobs.\n *\n * Design language: cool neutrals (slate / zinc) with a single muted blue\n * accent. No bright primaries, no rounded-blob corners. Typography sticks\n * to the system stack. The goal is to feel like a real product, not a\n * Pastel-style demo.\n */\n\n:host {\n /* Surfaces */\n --notes-bg: #ffffff;\n --notes-bg-soft: #f8fafc;\n --notes-bg-sunken: #f1f5f9;\n\n /* Text */\n --notes-fg: #0f172a;\n --notes-fg-muted: #64748b;\n --notes-fg-subtle: #94a3b8;\n\n /* Lines */\n --notes-border: #e2e8f0;\n --notes-border-strong: #cbd5e1;\n\n /* Accent — single muted blue used for primary actions and active state */\n --notes-accent: #2563eb;\n --notes-accent-hover: #1d4ed8;\n --notes-accent-fg: #ffffff;\n --notes-accent-soft: rgba(37, 99, 235, 0.08);\n --notes-accent-ring: rgba(37, 99, 235, 0.2);\n\n /* Status colors — used sparingly */\n --notes-danger: #dc2626;\n --notes-danger-soft: #fef2f2;\n --notes-success: #16a34a;\n --notes-warn: #d97706;\n --notes-warn-soft: #fffbeb;\n --notes-warn-border: #fde68a;\n\n /* Geometry */\n --notes-shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);\n --notes-shadow: 0 8px 24px -8px rgba(15, 23, 42, 0.16), 0 2px 4px -2px rgba(15, 23, 42, 0.06);\n --notes-shadow-lg: 0 24px 48px -16px rgba(15, 23, 42, 0.22);\n --notes-radius: 8px;\n --notes-radius-sm: 5px;\n --notes-sidebar-w: 340px;\n --notes-z: 2147483600;\n\n font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.5;\n color: var(--notes-fg);\n -webkit-font-smoothing: antialiased;\n font-feature-settings: 'cv11', 'ss01';\n}\n\n* {\n box-sizing: border-box;\n}\n\nbutton {\n font: inherit;\n cursor: pointer;\n border: none;\n background: none;\n color: inherit;\n padding: 0;\n}\n\ninput,\ntextarea {\n font: inherit;\n color: inherit;\n}\n\ncode {\n font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;\n font-size: 0.92em;\n background: var(--notes-bg-sunken);\n padding: 1px 5px;\n border-radius: 3px;\n color: var(--notes-fg);\n}\n\n.notes-root {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: var(--notes-z);\n}\n\n/* ──────────────────────────────────────────────────────────────────\n * Toolbar\n * ────────────────────────────────────────────────────────────────── */\n.notes-toolbar {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 40px;\n background: var(--notes-bg);\n border-bottom: 1px solid var(--notes-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 14px;\n pointer-events: auto;\n}\n\n.notes-toolbar__brand {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n letter-spacing: -0.01em;\n}\n\n.notes-toolbar__dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--notes-accent);\n box-shadow: 0 0 0 3px var(--notes-accent-soft);\n}\n\n.notes-toolbar__role {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n padding: 2px 6px;\n border-radius: 3px;\n background: var(--notes-bg-sunken);\n color: var(--notes-fg-muted);\n}\n\n.notes-toolbar__role--agency {\n background: var(--notes-accent-soft);\n color: var(--notes-accent);\n}\n\n.notes-toolbar__page {\n color: var(--notes-fg-subtle);\n font-weight: 400;\n margin-left: 4px;\n font-size: 12px;\n}\n\n.notes-toolbar__actions {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n/* ──────────────────────────────────────────────────────────────────\n * Buttons\n * ────────────────────────────────────────────────────────────────── */\n.notes-btn {\n padding: 5px 11px;\n border-radius: var(--notes-radius-sm);\n background: var(--notes-bg-sunken);\n color: var(--notes-fg);\n font-size: 12px;\n font-weight: 500;\n border: 1px solid transparent;\n transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;\n white-space: nowrap;\n}\n\n.notes-btn:hover {\n background: var(--notes-border);\n}\n\n.notes-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.notes-btn--primary {\n background: var(--notes-accent);\n color: var(--notes-accent-fg);\n}\n\n.notes-btn--primary:hover {\n background: var(--notes-accent-hover);\n}\n\n.notes-btn--primary:disabled:hover {\n background: var(--notes-accent);\n}\n\n.notes-btn--ghost {\n background: transparent;\n color: var(--notes-fg-muted);\n}\n\n.notes-btn--ghost:hover {\n color: var(--notes-fg);\n background: var(--notes-bg-sunken);\n}\n\n.notes-btn--danger {\n color: var(--notes-danger);\n}\n\n.notes-btn--danger:hover {\n background: var(--notes-danger-soft);\n color: var(--notes-danger);\n}\n\n/* ──────────────────────────────────────────────────────────────────\n * Sidebar\n * ────────────────────────────────────────────────────────────────── */\n.notes-sidebar {\n position: fixed;\n top: 40px;\n right: 0;\n bottom: 0;\n width: var(--notes-sidebar-w);\n background: var(--notes-bg);\n border-left: 1px solid var(--notes-border);\n display: flex;\n flex-direction: column;\n pointer-events: auto;\n}\n\n.notes-sidebar__header {\n padding: 14px 16px 12px;\n border-bottom: 1px solid var(--notes-border);\n background: var(--notes-bg);\n}\n\n.notes-sidebar__title {\n font-size: 13px;\n font-weight: 600;\n margin: 0 0 3px;\n color: var(--notes-fg);\n letter-spacing: -0.01em;\n}\n\n.notes-sidebar__meta {\n font-size: 11px;\n color: var(--notes-fg-subtle);\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.notes-sidebar__list {\n flex: 1;\n overflow-y: auto;\n padding: 10px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.notes-sidebar__list::-webkit-scrollbar {\n width: 8px;\n}\n\n.notes-sidebar__list::-webkit-scrollbar-thumb {\n background: var(--notes-border);\n border-radius: 4px;\n}\n\n.notes-sidebar__list::-webkit-scrollbar-thumb:hover {\n background: var(--notes-border-strong);\n}\n\n.notes-sidebar__empty {\n padding: 32px 16px;\n text-align: center;\n color: var(--notes-fg-subtle);\n font-size: 12px;\n line-height: 1.6;\n}\n\n.notes-sidebar__hint {\n font-size: 11px;\n color: var(--notes-fg-subtle);\n}\n\n.notes-sidebar__section {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--notes-fg-subtle);\n margin: 6px 4px 2px;\n}\n\n.notes-sidebar__deleted {\n margin-top: 4px;\n border-top: 1px solid var(--notes-border);\n padding-top: 8px;\n}\n\n.notes-sidebar__deleted summary {\n font-size: 11px;\n font-weight: 500;\n color: var(--notes-fg-muted);\n cursor: pointer;\n padding: 4px 4px;\n user-select: none;\n list-style: none;\n}\n\n.notes-sidebar__deleted summary::-webkit-details-marker {\n display: none;\n}\n\n.notes-sidebar__deleted summary::before {\n content: '▸';\n display: inline-block;\n margin-right: 6px;\n transition: transform 0.15s;\n font-size: 9px;\n}\n\n.notes-sidebar__deleted[open] summary::before {\n transform: rotate(90deg);\n}\n\n.notes-sidebar__deleted summary:hover {\n color: var(--notes-fg);\n}\n\n.notes-sidebar__deleted[open] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* ──────────────────────────────────────────────────────────────────\n * Item card\n * ────────────────────────────────────────────────────────────────── */\n.notes-item {\n border: 1px solid var(--notes-border);\n border-radius: var(--notes-radius);\n padding: 11px 12px;\n background: var(--notes-bg);\n transition: border-color 0.12s, box-shadow 0.12s;\n}\n\n.notes-item:hover {\n border-color: var(--notes-border-strong);\n}\n\n.notes-item--active {\n border-color: var(--notes-accent);\n box-shadow: 0 0 0 3px var(--notes-accent-ring);\n}\n\n.notes-item--resolved {\n opacity: 0.6;\n}\n\n.notes-item--deleted {\n opacity: 0.45;\n background: var(--notes-bg-soft);\n}\n\n.notes-item__head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 7px;\n gap: 8px;\n}\n\n.notes-item__author {\n font-weight: 600;\n font-size: 12px;\n color: var(--notes-fg);\n}\n\n.notes-item__time {\n font-size: 10px;\n color: var(--notes-fg-subtle);\n white-space: nowrap;\n}\n\n.notes-item__snippet {\n font-size: 11px;\n color: var(--notes-fg-muted);\n background: var(--notes-bg-soft);\n border-left: 2px solid var(--notes-border);\n padding: 5px 8px;\n margin-bottom: 7px;\n border-radius: 0 3px 3px 0;\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 48px;\n overflow: hidden;\n}\n\n.notes-item__body {\n font-size: 12.5px;\n white-space: pre-wrap;\n word-break: break-word;\n color: var(--notes-fg);\n}\n\n.notes-item__actions {\n display: flex;\n gap: 5px;\n margin-top: 10px;\n padding-top: 9px;\n border-top: 1px solid var(--notes-border);\n}\n\n.notes-item__badge {\n display: inline-block;\n font-size: 9px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n padding: 2px 6px;\n border-radius: 3px;\n margin-right: 6px;\n vertical-align: 1px;\n}\n\n.notes-item__badge--comment {\n background: var(--notes-accent-soft);\n color: var(--notes-accent);\n}\n\n.notes-item__badge--suggestion {\n background: rgba(217, 119, 6, 0.1);\n color: var(--notes-warn);\n}\n\n.notes-item__badge--resolved {\n background: rgba(22, 163, 74, 0.1);\n color: var(--notes-success);\n}\n\n.notes-item__badge--deleted {\n background: var(--notes-bg-sunken);\n color: var(--notes-fg-subtle);\n}\n\n.notes-item__history {\n margin-top: 8px;\n font-size: 11px;\n}\n\n.notes-item__history summary {\n cursor: pointer;\n color: var(--notes-fg-subtle);\n user-select: none;\n font-weight: 500;\n list-style: none;\n}\n\n.notes-item__history summary::-webkit-details-marker {\n display: none;\n}\n\n.notes-item__history summary::before {\n content: '▸';\n display: inline-block;\n margin-right: 5px;\n transition: transform 0.15s;\n font-size: 8px;\n}\n\n.notes-item__history[open] summary::before {\n transform: rotate(90deg);\n}\n\n.notes-item__history summary:hover {\n color: var(--notes-fg-muted);\n}\n\n.notes-item__history ul {\n list-style: none;\n padding: 6px 0 0 14px;\n margin: 0;\n}\n\n.notes-item__history li {\n padding: 3px 0;\n color: var(--notes-fg-muted);\n}\n\n.notes-item__history-action {\n font-weight: 600;\n color: var(--notes-fg);\n text-transform: capitalize;\n}\n\n.notes-item__history-meta {\n color: var(--notes-fg-subtle);\n}\n\n.notes-item__history-note {\n color: var(--notes-fg-subtle);\n font-style: italic;\n padding-left: 8px;\n margin-top: 1px;\n font-size: 10px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* ──────────────────────────────────────────────────────────────────\n * Element highlight ring\n * ────────────────────────────────────────────────────────────────── */\n.notes-highlight {\n position: fixed;\n pointer-events: none;\n border: 2px solid var(--notes-accent);\n border-radius: 3px;\n box-shadow: 0 0 0 3px var(--notes-accent-ring);\n transition: all 0.08s ease-out;\n}\n\n.notes-highlight--persistent {\n border-color: rgba(37, 99, 235, 0.55);\n box-shadow: 0 0 0 3px var(--notes-accent-soft);\n}\n\n/* ──────────────────────────────────────────────────────────────────\n * Popover (comment + suggest)\n * ────────────────────────────────────────────────────────────────── */\n.notes-popover {\n position: fixed;\n width: 320px;\n background: var(--notes-bg);\n border: 1px solid var(--notes-border);\n border-radius: var(--notes-radius);\n box-shadow: var(--notes-shadow-lg);\n padding: 14px;\n pointer-events: auto;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.notes-popover__title {\n font-size: 12px;\n font-weight: 600;\n margin: 0;\n color: var(--notes-fg);\n letter-spacing: -0.01em;\n}\n\n.notes-popover__snippet {\n font-size: 11px;\n color: var(--notes-fg-muted);\n background: var(--notes-bg-soft);\n border-left: 2px solid var(--notes-border);\n padding: 6px 8px;\n border-radius: 0 3px 3px 0;\n max-height: 60px;\n overflow: hidden;\n}\n\n.notes-popover textarea {\n width: 100%;\n min-height: 78px;\n resize: vertical;\n border: 1px solid var(--notes-border);\n border-radius: var(--notes-radius-sm);\n padding: 8px 10px;\n background: var(--notes-bg);\n outline: none;\n font-size: 12.5px;\n line-height: 1.5;\n}\n\n.notes-popover textarea:focus {\n border-color: var(--notes-accent);\n box-shadow: 0 0 0 3px var(--notes-accent-ring);\n}\n\n.notes-popover input[type='text'] {\n border: 1px solid var(--notes-border);\n border-radius: var(--notes-radius-sm);\n padding: 6px 10px;\n background: var(--notes-bg);\n outline: none;\n font-size: 12px;\n width: 100%;\n}\n\n.notes-popover input[type='text']:focus {\n border-color: var(--notes-accent);\n box-shadow: 0 0 0 3px var(--notes-accent-ring);\n}\n\n.notes-popover__row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 8px;\n}\n\n/* Selection tooltip */\n.notes-selection-tooltip {\n position: fixed;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 5px;\n background: #0f172a;\n color: #ffffff;\n border-radius: 6px;\n box-shadow: var(--notes-shadow);\n pointer-events: auto;\n z-index: calc(var(--notes-z) + 5);\n}\n\n.notes-selection-tooltip .notes-btn {\n background: rgba(255, 255, 255, 0.06);\n color: #ffffff;\n font-size: 11px;\n padding: 4px 9px;\n}\n\n.notes-selection-tooltip .notes-btn:hover {\n background: rgba(255, 255, 255, 0.14);\n}\n\n.notes-selection-tooltip .notes-btn--primary {\n background: var(--notes-accent);\n color: var(--notes-accent-fg);\n}\n\n.notes-selection-tooltip .notes-btn--primary:hover {\n background: var(--notes-accent-hover);\n}\n\n.notes-selection-tooltip .notes-btn--ghost {\n color: #e2e8f0;\n}\n\n.notes-selection-tooltip .notes-btn--ghost:hover {\n background: rgba(255, 255, 255, 0.14);\n color: #ffffff;\n}\n\n/* Suggest popover variations */\n.notes-popover--suggest {\n width: 360px;\n}\n\n.notes-popover__label {\n display: block;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--notes-fg-subtle);\n margin-bottom: 4px;\n}\n\n.notes-popover__original {\n background: var(--notes-warn-soft);\n border: 1px solid var(--notes-warn-border);\n border-radius: var(--notes-radius-sm);\n padding: 8px 10px;\n font-size: 12px;\n color: #78350f;\n max-height: 80px;\n overflow-y: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.notes-strikethrough {\n text-decoration: line-through;\n text-decoration-color: rgba(220, 38, 38, 0.55);\n text-decoration-thickness: 1.5px;\n}\n\n/* ──────────────────────────────────────────────────────────────────\n * Diff preview\n * ────────────────────────────────────────────────────────────────── */\n.notes-diff {\n font-size: 12px;\n border-radius: var(--notes-radius-sm);\n background: var(--notes-bg-soft);\n border: 1px solid var(--notes-border);\n overflow: hidden;\n margin-bottom: 8px;\n}\n\n.notes-diff__row {\n padding: 6px 10px;\n display: flex;\n gap: 6px;\n white-space: pre-wrap;\n word-break: break-word;\n line-height: 1.5;\n}\n\n.notes-diff__row--del {\n background: #fef2f2;\n color: #7f1d1d;\n border-bottom: 1px solid #fee2e2;\n}\n\n.notes-diff__row--ins {\n background: #f0fdf4;\n color: #14532d;\n}\n\n.notes-diff__marker {\n font-weight: 700;\n font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;\n width: 11px;\n flex-shrink: 0;\n text-align: center;\n font-size: 11px;\n}\n\n.notes-item__rationale {\n font-size: 11px;\n color: var(--notes-fg-muted);\n margin-bottom: 6px;\n font-style: italic;\n}\n\n.notes-item__rationale-label {\n font-style: normal;\n font-weight: 600;\n color: var(--notes-fg);\n margin-right: 4px;\n}\n\n/* Stale warning */\n.notes-stale {\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--notes-warn-soft);\n border: 1px solid var(--notes-warn-border);\n color: #92400e;\n font-size: 11px;\n padding: 5px 8px;\n border-radius: var(--notes-radius-sm);\n margin-bottom: 8px;\n}\n\n.notes-stale__icon {\n font-size: 12px;\n}\n\n/* Persistent highlight variant for suggestion ranges */\n.notes-highlight--suggestion {\n border-color: rgba(217, 119, 6, 0.85);\n box-shadow: 0 0 0 3px rgba(217, 119, 6, 0.18);\n background: rgba(254, 243, 199, 0.25);\n}\n\n/* Banner shown when notes API fails to load */\n.notes-banner {\n padding: 9px 12px;\n background: var(--notes-danger-soft);\n border: 1px solid #fecaca;\n color: #991b1b;\n border-radius: var(--notes-radius-sm);\n font-size: 12px;\n pointer-events: auto;\n}\n";
|
|
1339
1500
|
function init() {
|
|
1340
1501
|
if (window.__nuasiteNotesMounted) return;
|
|
1341
1502
|
const config = window.__NuaNotesConfig ?? {};
|
|
1342
1503
|
const urlFlag = config.urlFlag ?? "nua-notes";
|
|
1504
|
+
const agencyFlag = config.agencyFlag ?? "nua-agency";
|
|
1343
1505
|
if (!isReviewMode(urlFlag)) return;
|
|
1344
1506
|
window.__nuasiteNotesMounted = true;
|
|
1345
1507
|
setReviewModeCookie();
|
|
@@ -1356,7 +1518,7 @@ function init() {
|
|
|
1356
1518
|
const root = document.createElement("div");
|
|
1357
1519
|
root.id = "nua-notes-root";
|
|
1358
1520
|
shadow.appendChild(root);
|
|
1359
|
-
R(/* @__PURE__ */ u$1(App, { urlFlag }), root);
|
|
1521
|
+
R(/* @__PURE__ */ u$1(App, { urlFlag, agencyFlag }), root);
|
|
1360
1522
|
}
|
|
1361
1523
|
if (typeof window !== "undefined") {
|
|
1362
1524
|
if (document.readyState === "loading") {
|