apostil 0.1.4 → 0.1.6
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 +11 -2
- package/dist/cli/index.cjs +1 -0
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +96 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +96 -37
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -0
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -93,6 +93,7 @@ var ApostilContext = createContext(null);
|
|
|
93
93
|
function ApostilProvider({
|
|
94
94
|
pageId,
|
|
95
95
|
storage,
|
|
96
|
+
brandColor = "#171717",
|
|
96
97
|
children
|
|
97
98
|
}) {
|
|
98
99
|
const adapter = storage ?? defaultAdapter;
|
|
@@ -110,6 +111,7 @@ function ApostilProvider({
|
|
|
110
111
|
useEffect(() => {
|
|
111
112
|
pageIdRef.current = pageId;
|
|
112
113
|
setLoaded(false);
|
|
114
|
+
hadThreadsRef.current = false;
|
|
113
115
|
debug.log("loading threads for pageId:", pageId);
|
|
114
116
|
adapter.load(pageId).then((t) => {
|
|
115
117
|
if (pageIdRef.current === pageId) {
|
|
@@ -119,10 +121,17 @@ function ApostilProvider({
|
|
|
119
121
|
}
|
|
120
122
|
});
|
|
121
123
|
}, [pageId]);
|
|
124
|
+
const hadThreadsRef = useRef(false);
|
|
122
125
|
useEffect(() => {
|
|
123
|
-
if (loaded
|
|
126
|
+
if (!loaded || pageIdRef.current !== pageId) return;
|
|
127
|
+
if (threads.length > 0) {
|
|
128
|
+
hadThreadsRef.current = true;
|
|
124
129
|
debug.log("saving", threads.length, "threads for pageId:", pageId);
|
|
125
130
|
adapter.save(pageId, threads);
|
|
131
|
+
} else if (hadThreadsRef.current) {
|
|
132
|
+
debug.log("saving empty threads for pageId:", pageId);
|
|
133
|
+
adapter.save(pageId, threads);
|
|
134
|
+
hadThreadsRef.current = false;
|
|
126
135
|
}
|
|
127
136
|
}, [threads, pageId, loaded]);
|
|
128
137
|
const setUser = useCallback((name) => {
|
|
@@ -184,6 +193,7 @@ function ApostilProvider({
|
|
|
184
193
|
commentMode,
|
|
185
194
|
activeThreadId,
|
|
186
195
|
sidebarOpen,
|
|
196
|
+
brandColor,
|
|
187
197
|
setCommentMode,
|
|
188
198
|
setActiveThreadId,
|
|
189
199
|
setSidebarOpen,
|
|
@@ -529,11 +539,14 @@ function CommentComposer({
|
|
|
529
539
|
placeholder = "Add a comment...",
|
|
530
540
|
autoFocus = false
|
|
531
541
|
}) {
|
|
542
|
+
const { brandColor } = useApostil();
|
|
532
543
|
const [value, setValue] = useState3("");
|
|
533
544
|
const inputRef = useRef3(null);
|
|
534
545
|
useEffect3(() => {
|
|
535
546
|
if (autoFocus) {
|
|
536
|
-
|
|
547
|
+
requestAnimationFrame(() => {
|
|
548
|
+
inputRef.current?.focus();
|
|
549
|
+
});
|
|
537
550
|
}
|
|
538
551
|
}, [autoFocus]);
|
|
539
552
|
const handleSubmit = () => {
|
|
@@ -565,7 +578,8 @@ function CommentComposer({
|
|
|
565
578
|
{
|
|
566
579
|
onClick: handleSubmit,
|
|
567
580
|
disabled: !value.trim(),
|
|
568
|
-
className: "flex items-center justify-center w-8 h-8 rounded-lg\n
|
|
581
|
+
className: "flex items-center justify-center w-8 h-8 rounded-lg\n text-white disabled:opacity-30\n transition-colors shrink-0",
|
|
582
|
+
style: { backgroundColor: brandColor },
|
|
569
583
|
children: /* @__PURE__ */ jsx4(Send, { className: "w-3.5 h-3.5" })
|
|
570
584
|
}
|
|
571
585
|
)
|
|
@@ -592,9 +606,17 @@ function ApostilThreadPopover({
|
|
|
592
606
|
const ref = useRef4(null);
|
|
593
607
|
const isOpen = activeThreadId === thread.id;
|
|
594
608
|
const [pos, setPos] = useState4(null);
|
|
609
|
+
const [flip, setFlip] = useState4({ x: false, y: false });
|
|
595
610
|
const updatePos = useCallback3(() => {
|
|
596
611
|
setPos(resolvePosition(thread, overlayRef.current));
|
|
597
612
|
}, [thread, overlayRef]);
|
|
613
|
+
useEffect4(() => {
|
|
614
|
+
if (!isOpen || !pos || !ref.current) return;
|
|
615
|
+
const rect = ref.current.getBoundingClientRect();
|
|
616
|
+
const flipX = rect.right > window.innerWidth;
|
|
617
|
+
const flipY = rect.bottom > window.innerHeight;
|
|
618
|
+
setFlip({ x: flipX, y: flipY });
|
|
619
|
+
}, [isOpen, pos]);
|
|
598
620
|
useEffect4(() => {
|
|
599
621
|
if (!isOpen) return;
|
|
600
622
|
updatePos();
|
|
@@ -623,8 +645,14 @@ function ApostilThreadPopover({
|
|
|
623
645
|
"div",
|
|
624
646
|
{
|
|
625
647
|
ref,
|
|
626
|
-
className: "absolute z-[70]
|
|
627
|
-
style: {
|
|
648
|
+
className: "absolute z-[70]",
|
|
649
|
+
style: {
|
|
650
|
+
left: pos.left,
|
|
651
|
+
top: pos.top,
|
|
652
|
+
marginLeft: flip.x ? -340 : 20,
|
|
653
|
+
marginTop: flip.y ? -12 : -12,
|
|
654
|
+
...flip.y ? { transform: "translateY(-100%)" } : {}
|
|
655
|
+
},
|
|
628
656
|
onClick: (e) => e.stopPropagation(),
|
|
629
657
|
children: /* @__PURE__ */ jsxs4("div", { className: "w-80 bg-white rounded-xl shadow-2xl border border-neutral-200 overflow-hidden", children: [
|
|
630
658
|
/* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between px-4 py-2.5 border-b border-neutral-100 bg-neutral-50", children: [
|
|
@@ -690,7 +718,7 @@ function ApostilThreadPopover({
|
|
|
690
718
|
import { useState as useState5 } from "react";
|
|
691
719
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
692
720
|
function UserPrompt() {
|
|
693
|
-
const { user, setUser, commentMode } = useApostil();
|
|
721
|
+
const { user, setUser, commentMode, brandColor } = useApostil();
|
|
694
722
|
const [name, setName] = useState5("");
|
|
695
723
|
if (user || !commentMode) return null;
|
|
696
724
|
const handleSubmit = () => {
|
|
@@ -726,7 +754,8 @@ function UserPrompt() {
|
|
|
726
754
|
{
|
|
727
755
|
onClick: handleSubmit,
|
|
728
756
|
disabled: !name.trim(),
|
|
729
|
-
className: "w-full py-2 rounded-lg
|
|
757
|
+
className: "w-full py-2 rounded-lg text-white text-sm font-medium\n disabled:opacity-30 transition-colors",
|
|
758
|
+
style: { backgroundColor: brandColor },
|
|
730
759
|
children: "Continue"
|
|
731
760
|
}
|
|
732
761
|
)
|
|
@@ -877,10 +906,12 @@ function findCommentTarget(el, boundary) {
|
|
|
877
906
|
};
|
|
878
907
|
}
|
|
879
908
|
function CommentOverlay() {
|
|
880
|
-
const { threads, commentMode, setCommentMode, user, addThread, setActiveThreadId } = useApostil();
|
|
909
|
+
const { threads, commentMode, setCommentMode, user, addThread, setActiveThreadId, brandColor } = useApostil();
|
|
881
910
|
const overlayRef = useRef5(null);
|
|
882
911
|
const [pendingPin, setPendingPin] = useState6(null);
|
|
883
912
|
const [pendingPixel, setPendingPixel] = useState6(null);
|
|
913
|
+
const pendingRef = useRef5(null);
|
|
914
|
+
const [pendingFlip, setPendingFlip] = useState6({ x: false, y: false });
|
|
884
915
|
const handleClick = useCallback4(
|
|
885
916
|
(e) => {
|
|
886
917
|
if (!commentMode || !overlayRef.current) return;
|
|
@@ -957,6 +988,17 @@ function CommentOverlay() {
|
|
|
957
988
|
setPendingPixel(null);
|
|
958
989
|
setCommentMode(false);
|
|
959
990
|
}, [setCommentMode]);
|
|
991
|
+
useEffect5(() => {
|
|
992
|
+
if (!pendingPin || !pendingRef.current) return;
|
|
993
|
+
requestAnimationFrame(() => {
|
|
994
|
+
if (!pendingRef.current) return;
|
|
995
|
+
const rect = pendingRef.current.getBoundingClientRect();
|
|
996
|
+
setPendingFlip({
|
|
997
|
+
x: rect.right > window.innerWidth,
|
|
998
|
+
y: rect.bottom > window.innerHeight
|
|
999
|
+
});
|
|
1000
|
+
});
|
|
1001
|
+
}, [pendingPin]);
|
|
960
1002
|
useEffect5(() => {
|
|
961
1003
|
const hash = window.location.hash;
|
|
962
1004
|
console.log("[apostil] hash check:", hash, "threads:", threads.length, threads.map((t) => t.id));
|
|
@@ -1041,35 +1083,46 @@ function CommentOverlay() {
|
|
|
1041
1083
|
children: "+"
|
|
1042
1084
|
}
|
|
1043
1085
|
),
|
|
1044
|
-
/* @__PURE__ */ jsx7(
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1086
|
+
/* @__PURE__ */ jsx7(
|
|
1087
|
+
"div",
|
|
1088
|
+
{
|
|
1089
|
+
ref: pendingRef,
|
|
1090
|
+
className: "absolute w-72",
|
|
1091
|
+
style: {
|
|
1092
|
+
marginLeft: pendingFlip.x ? -308 : 20,
|
|
1093
|
+
marginTop: pendingFlip.y ? void 0 : -12,
|
|
1094
|
+
...pendingFlip.y ? { bottom: 0 } : {}
|
|
1095
|
+
},
|
|
1096
|
+
children: /* @__PURE__ */ jsxs6("div", { className: "bg-white rounded-xl shadow-2xl border border-neutral-200 p-3", children: [
|
|
1097
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
1098
|
+
/* @__PURE__ */ jsx7("p", { className: "text-xs text-neutral-500", children: "New comment" }),
|
|
1099
|
+
pendingPin.targetLabel && /* @__PURE__ */ jsx7("span", { className: "text-[10px] bg-blue-50 text-blue-600 px-1.5 py-0.5 rounded font-medium", children: pendingPin.targetLabel })
|
|
1100
|
+
] }),
|
|
1101
|
+
/* @__PURE__ */ jsx7(
|
|
1102
|
+
CommentComposer,
|
|
1103
|
+
{
|
|
1104
|
+
onSubmit: handleNewComment,
|
|
1105
|
+
placeholder: "What's on your mind?",
|
|
1106
|
+
autoFocus: true
|
|
1107
|
+
}
|
|
1108
|
+
)
|
|
1109
|
+
] })
|
|
1110
|
+
}
|
|
1111
|
+
)
|
|
1066
1112
|
]
|
|
1067
1113
|
}
|
|
1068
1114
|
)
|
|
1069
1115
|
]
|
|
1070
1116
|
}
|
|
1071
1117
|
),
|
|
1072
|
-
commentMode && !pendingPin && !showingUserPrompt && /* @__PURE__ */ jsx7("div", { className: "absolute bottom-6 left-1/2 -translate-x-1/2 z-[60] pointer-events-none", children: /* @__PURE__ */ jsx7(
|
|
1118
|
+
commentMode && !pendingPin && !showingUserPrompt && /* @__PURE__ */ jsx7("div", { className: "absolute bottom-6 left-1/2 -translate-x-1/2 z-[60] pointer-events-none", children: /* @__PURE__ */ jsx7(
|
|
1119
|
+
"div",
|
|
1120
|
+
{
|
|
1121
|
+
className: "text-white text-sm px-4 py-2 rounded-full backdrop-blur-sm",
|
|
1122
|
+
style: { backgroundColor: `color-mix(in oklab, ${brandColor} 80%, transparent)` },
|
|
1123
|
+
children: "Click anywhere to add a comment"
|
|
1124
|
+
}
|
|
1125
|
+
) }),
|
|
1073
1126
|
/* @__PURE__ */ jsx7(UserPrompt, {})
|
|
1074
1127
|
] });
|
|
1075
1128
|
}
|
|
@@ -1083,7 +1136,8 @@ function CommentToggle() {
|
|
|
1083
1136
|
sidebarOpen,
|
|
1084
1137
|
setSidebarOpen,
|
|
1085
1138
|
unresolvedCount,
|
|
1086
|
-
setActiveThreadId
|
|
1139
|
+
setActiveThreadId,
|
|
1140
|
+
brandColor
|
|
1087
1141
|
} = useApostil();
|
|
1088
1142
|
return /* @__PURE__ */ jsxs7("div", { className: "absolute bottom-5 right-5 z-[65] flex flex-col gap-2 items-end", children: [
|
|
1089
1143
|
/* @__PURE__ */ jsx8(
|
|
@@ -1092,7 +1146,8 @@ function CommentToggle() {
|
|
|
1092
1146
|
onClick: () => setSidebarOpen(!sidebarOpen),
|
|
1093
1147
|
className: `flex items-center justify-center w-10 h-10 rounded-full shadow-lg
|
|
1094
1148
|
transition-all duration-200 hover:scale-105
|
|
1095
|
-
${sidebarOpen ? "
|
|
1149
|
+
${sidebarOpen ? "text-white" : "bg-white text-neutral-600 hover:bg-neutral-50 border border-neutral-200"}`,
|
|
1150
|
+
style: sidebarOpen ? { backgroundColor: brandColor } : void 0,
|
|
1096
1151
|
title: "Toggle comment list",
|
|
1097
1152
|
children: /* @__PURE__ */ jsx8(List, { className: "w-4 h-4" })
|
|
1098
1153
|
}
|
|
@@ -1110,7 +1165,8 @@ function CommentToggle() {
|
|
|
1110
1165
|
},
|
|
1111
1166
|
className: `relative flex items-center justify-center w-12 h-12 rounded-full shadow-lg
|
|
1112
1167
|
transition-all duration-200 hover:scale-105
|
|
1113
|
-
${commentMode ? "
|
|
1168
|
+
${commentMode ? "text-white ring-2 ring-neutral-400" : "bg-white text-neutral-700 hover:bg-neutral-50 border border-neutral-200"}`,
|
|
1169
|
+
style: commentMode ? { backgroundColor: brandColor } : void 0,
|
|
1114
1170
|
title: commentMode ? "Exit comment mode" : "Add comment",
|
|
1115
1171
|
children: [
|
|
1116
1172
|
commentMode ? /* @__PURE__ */ jsx8(X, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx8(MessageSquare, { className: "w-5 h-5" }),
|
|
@@ -1143,7 +1199,8 @@ function CommentSidebar() {
|
|
|
1143
1199
|
sidebarOpen,
|
|
1144
1200
|
setSidebarOpen,
|
|
1145
1201
|
setActiveThreadId,
|
|
1146
|
-
resolveThread
|
|
1202
|
+
resolveThread,
|
|
1203
|
+
brandColor
|
|
1147
1204
|
} = useApostil();
|
|
1148
1205
|
const [tab, setTab] = useState7("page");
|
|
1149
1206
|
const [allPages, setAllPages] = useState7([]);
|
|
@@ -1187,7 +1244,8 @@ function CommentSidebar() {
|
|
|
1187
1244
|
"button",
|
|
1188
1245
|
{
|
|
1189
1246
|
onClick: () => setTab("page"),
|
|
1190
|
-
className: `flex-1 flex items-center justify-center gap-1.5 py-2 text-xs font-medium transition-colors ${tab === "page" ? "
|
|
1247
|
+
className: `flex-1 flex items-center justify-center gap-1.5 py-2 text-xs font-medium transition-colors ${tab === "page" ? "border-b-2" : "text-neutral-400 hover:text-neutral-600"}`,
|
|
1248
|
+
style: tab === "page" ? { color: brandColor, borderColor: brandColor } : void 0,
|
|
1191
1249
|
children: [
|
|
1192
1250
|
/* @__PURE__ */ jsx9(FileText, { className: "w-3 h-3" }),
|
|
1193
1251
|
"This Page",
|
|
@@ -1199,7 +1257,8 @@ function CommentSidebar() {
|
|
|
1199
1257
|
"button",
|
|
1200
1258
|
{
|
|
1201
1259
|
onClick: () => setTab("all"),
|
|
1202
|
-
className: `flex-1 flex items-center justify-center gap-1.5 py-2 text-xs font-medium transition-colors ${tab === "all" ? "
|
|
1260
|
+
className: `flex-1 flex items-center justify-center gap-1.5 py-2 text-xs font-medium transition-colors ${tab === "all" ? "border-b-2" : "text-neutral-400 hover:text-neutral-600"}`,
|
|
1261
|
+
style: tab === "all" ? { color: brandColor, borderColor: brandColor } : void 0,
|
|
1203
1262
|
children: [
|
|
1204
1263
|
/* @__PURE__ */ jsx9(Globe, { className: "w-3 h-3" }),
|
|
1205
1264
|
"All Pages"
|