@papyrus-sdk/ui-react 0.2.19 → 0.2.21
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/dist/index.js +527 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +535 -57
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -46,6 +46,7 @@ var Topbar = ({
|
|
|
46
46
|
showUpload = true,
|
|
47
47
|
showSearch = true
|
|
48
48
|
}) => {
|
|
49
|
+
const viewerState = (0, import_core.useViewerStore)();
|
|
49
50
|
const {
|
|
50
51
|
currentPage,
|
|
51
52
|
pageCount,
|
|
@@ -58,13 +59,15 @@ var Topbar = ({
|
|
|
58
59
|
toggleSidebarLeft,
|
|
59
60
|
toggleSidebarRight,
|
|
60
61
|
triggerScrollToPage
|
|
61
|
-
} =
|
|
62
|
+
} = viewerState;
|
|
63
|
+
const mobileTopbarVisible = viewerState.mobileTopbarVisible ?? true;
|
|
62
64
|
const fileInputRef = (0, import_react.useRef)(null);
|
|
63
65
|
const zoomTimerRef = (0, import_react.useRef)(null);
|
|
64
66
|
const pendingZoomRef = (0, import_react.useRef)(null);
|
|
65
67
|
const [pageInput, setPageInput] = (0, import_react.useState)(currentPage.toString());
|
|
66
68
|
const [showPageThemes, setShowPageThemes] = (0, import_react.useState)(false);
|
|
67
69
|
const [showMobileMenu, setShowMobileMenu] = (0, import_react.useState)(false);
|
|
70
|
+
const [isMobileViewport, setIsMobileViewport] = (0, import_react.useState)(false);
|
|
68
71
|
const pageDigits = Math.max(2, String(pageCount || 1).length);
|
|
69
72
|
const isDark = uiTheme === "dark";
|
|
70
73
|
const canUseDOM = typeof document !== "undefined";
|
|
@@ -81,6 +84,18 @@ var Topbar = ({
|
|
|
81
84
|
(0, import_react.useEffect)(() => {
|
|
82
85
|
if (!hasMobileMenu) setShowMobileMenu(false);
|
|
83
86
|
}, [hasMobileMenu]);
|
|
87
|
+
(0, import_react.useEffect)(() => {
|
|
88
|
+
if (!canUseDOM || typeof window.matchMedia !== "function") return;
|
|
89
|
+
const mediaQuery = window.matchMedia("(max-width: 639px)");
|
|
90
|
+
const updateViewport = () => setIsMobileViewport(mediaQuery.matches);
|
|
91
|
+
updateViewport();
|
|
92
|
+
if (typeof mediaQuery.addEventListener === "function") {
|
|
93
|
+
mediaQuery.addEventListener("change", updateViewport);
|
|
94
|
+
return () => mediaQuery.removeEventListener("change", updateViewport);
|
|
95
|
+
}
|
|
96
|
+
mediaQuery.addListener(updateViewport);
|
|
97
|
+
return () => mediaQuery.removeListener(updateViewport);
|
|
98
|
+
}, [canUseDOM]);
|
|
84
99
|
(0, import_react.useEffect)(() => {
|
|
85
100
|
if (!showMobileMenu || !canUseDOM) return;
|
|
86
101
|
const previousOverflow = document.body.style.overflow;
|
|
@@ -94,6 +109,30 @@ var Topbar = ({
|
|
|
94
109
|
window.removeEventListener("keydown", handleKeyDown);
|
|
95
110
|
};
|
|
96
111
|
}, [showMobileMenu, canUseDOM]);
|
|
112
|
+
const topbarStyle = (0, import_react.useMemo)(() => {
|
|
113
|
+
const mergedStyle = { ...style ?? {} };
|
|
114
|
+
if (!isMobileViewport) {
|
|
115
|
+
mergedStyle.transition = "height 180ms ease, opacity 160ms ease, padding 180ms ease, border-width 180ms ease";
|
|
116
|
+
return mergedStyle;
|
|
117
|
+
}
|
|
118
|
+
mergedStyle.transition = "height 180ms ease, opacity 160ms ease, padding 180ms ease, border-width 180ms ease";
|
|
119
|
+
mergedStyle.overflow = "hidden";
|
|
120
|
+
if (!mobileTopbarVisible) {
|
|
121
|
+
mergedStyle.height = 0;
|
|
122
|
+
mergedStyle.minHeight = 0;
|
|
123
|
+
mergedStyle.paddingTop = 0;
|
|
124
|
+
mergedStyle.paddingBottom = 0;
|
|
125
|
+
mergedStyle.borderBottomWidth = 0;
|
|
126
|
+
mergedStyle.opacity = 0;
|
|
127
|
+
mergedStyle.pointerEvents = "none";
|
|
128
|
+
return mergedStyle;
|
|
129
|
+
}
|
|
130
|
+
mergedStyle.height = 56;
|
|
131
|
+
mergedStyle.minHeight = 56;
|
|
132
|
+
mergedStyle.opacity = 1;
|
|
133
|
+
mergedStyle.pointerEvents = "auto";
|
|
134
|
+
return mergedStyle;
|
|
135
|
+
}, [isMobileViewport, mobileTopbarVisible, style]);
|
|
97
136
|
const handleZoom = (delta) => {
|
|
98
137
|
const baseZoom = pendingZoomRef.current ?? zoom;
|
|
99
138
|
const nextZoom = Math.max(0.2, Math.min(5, baseZoom + delta));
|
|
@@ -384,7 +423,7 @@ var Topbar = ({
|
|
|
384
423
|
{
|
|
385
424
|
"data-papyrus-theme": uiTheme,
|
|
386
425
|
className: `papyrus-topbar papyrus-theme relative h-14 border-b flex items-center px-3 sm:px-4 z-50 transition-colors duration-200 ${isDark ? "bg-[#1a1a1a] border-[#333] text-white" : "bg-white border-gray-200 text-gray-800"}`,
|
|
387
|
-
style,
|
|
426
|
+
style: topbarStyle,
|
|
388
427
|
children: [
|
|
389
428
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 min-w-0 z-10", children: [
|
|
390
429
|
showSidebarLeftToggle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1092,10 +1131,15 @@ var SidebarRight = ({ engine, style }) => {
|
|
|
1092
1131
|
setDocumentState,
|
|
1093
1132
|
triggerScrollToPage,
|
|
1094
1133
|
annotations,
|
|
1095
|
-
accentColor
|
|
1134
|
+
accentColor,
|
|
1135
|
+
updateAnnotation,
|
|
1136
|
+
addAnnotationReply,
|
|
1137
|
+
setSelectedAnnotation
|
|
1096
1138
|
} = (0, import_core3.useViewerStore)();
|
|
1097
1139
|
const [query, setQuery] = (0, import_react3.useState)("");
|
|
1098
1140
|
const [isSearching, setIsSearching] = (0, import_react3.useState)(false);
|
|
1141
|
+
const [contentDrafts, setContentDrafts] = (0, import_react3.useState)({});
|
|
1142
|
+
const [replyDrafts, setReplyDrafts] = (0, import_react3.useState)({});
|
|
1099
1143
|
const searchService = new import_core3.SearchService(engine);
|
|
1100
1144
|
const isDark = uiTheme === "dark";
|
|
1101
1145
|
const accentSoft = withAlpha2(accentColor, 0.12);
|
|
@@ -1111,6 +1155,41 @@ var SidebarRight = ({ engine, style }) => {
|
|
|
1111
1155
|
setSearch(query, results);
|
|
1112
1156
|
setIsSearching(false);
|
|
1113
1157
|
};
|
|
1158
|
+
const jumpToAnnotation = (annotation) => {
|
|
1159
|
+
const page = annotation.pageIndex + 1;
|
|
1160
|
+
engine.goToPage(page);
|
|
1161
|
+
setDocumentState({ currentPage: page });
|
|
1162
|
+
setSelectedAnnotation(annotation.id);
|
|
1163
|
+
triggerScrollToPage(annotation.pageIndex);
|
|
1164
|
+
};
|
|
1165
|
+
const getContentDraft = (annotation) => {
|
|
1166
|
+
if (Object.prototype.hasOwnProperty.call(contentDrafts, annotation.id)) {
|
|
1167
|
+
return contentDrafts[annotation.id];
|
|
1168
|
+
}
|
|
1169
|
+
return annotation.content ?? "";
|
|
1170
|
+
};
|
|
1171
|
+
const updateContentDraft = (annotationId, nextValue) => {
|
|
1172
|
+
setContentDrafts((prev) => ({ ...prev, [annotationId]: nextValue }));
|
|
1173
|
+
};
|
|
1174
|
+
const submitContent = (annotation) => {
|
|
1175
|
+
const nextContent = getContentDraft(annotation).trim();
|
|
1176
|
+
const currentContent = (annotation.content ?? "").trim();
|
|
1177
|
+
if (nextContent === currentContent) return;
|
|
1178
|
+
updateAnnotation(annotation.id, {
|
|
1179
|
+
content: nextContent,
|
|
1180
|
+
updatedAt: Date.now()
|
|
1181
|
+
});
|
|
1182
|
+
};
|
|
1183
|
+
const getReplyDraft = (annotationId) => replyDrafts[annotationId] ?? "";
|
|
1184
|
+
const updateReplyDraft = (annotationId, nextValue) => {
|
|
1185
|
+
setReplyDrafts((prev) => ({ ...prev, [annotationId]: nextValue }));
|
|
1186
|
+
};
|
|
1187
|
+
const submitReply = (annotationId) => {
|
|
1188
|
+
const nextReply = getReplyDraft(annotationId).trim();
|
|
1189
|
+
if (!nextReply) return;
|
|
1190
|
+
addAnnotationReply(annotationId, nextReply);
|
|
1191
|
+
setReplyDrafts((prev) => ({ ...prev, [annotationId]: "" }));
|
|
1192
|
+
};
|
|
1114
1193
|
if (!sidebarRightOpen) return null;
|
|
1115
1194
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1116
1195
|
"div",
|
|
@@ -1312,48 +1391,152 @@ var SidebarRight = ({ engine, style }) => {
|
|
|
1312
1391
|
}
|
|
1313
1392
|
) }),
|
|
1314
1393
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-[10px] font-bold text-gray-400 uppercase tracking-widest", children: "Sem anota\xE7\xF5es" })
|
|
1315
|
-
] }) : annotations.
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1394
|
+
] }) : annotations.slice().sort(
|
|
1395
|
+
(a, b) => (b.updatedAt ?? b.createdAt) - (a.updatedAt ?? a.createdAt)
|
|
1396
|
+
).map((ann) => {
|
|
1397
|
+
const isCommentThread = ann.type === "comment" || ann.type === "text";
|
|
1398
|
+
const replies = ann.replies ?? [];
|
|
1399
|
+
const contentDraft = getContentDraft(ann);
|
|
1400
|
+
const replyDraft = getReplyDraft(ann.id);
|
|
1401
|
+
const hasExistingContent = Boolean((ann.content ?? "").trim());
|
|
1402
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1403
|
+
"div",
|
|
1404
|
+
{
|
|
1405
|
+
className: "rounded-xl border p-4 transition-colors",
|
|
1406
|
+
style: {
|
|
1407
|
+
background: "var(--papyrus-surface-2-resolved, var(--papyrus-surface-2, #1f2937))",
|
|
1408
|
+
borderColor: "var(--papyrus-border-resolved, var(--papyrus-border, #374151))",
|
|
1409
|
+
color: "var(--papyrus-text-resolved, var(--papyrus-text, #e5e7eb))"
|
|
1410
|
+
},
|
|
1411
|
+
children: [
|
|
1412
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mb-3 flex items-center justify-between", children: [
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center space-x-2", children: [
|
|
1414
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1415
|
+
"div",
|
|
1416
|
+
{
|
|
1417
|
+
className: "h-2.5 w-2.5 rounded-full",
|
|
1418
|
+
style: { backgroundColor: ann.color }
|
|
1419
|
+
}
|
|
1420
|
+
),
|
|
1421
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1422
|
+
"span",
|
|
1423
|
+
{
|
|
1424
|
+
className: "text-[10px] font-black uppercase tracking-wide",
|
|
1425
|
+
style: { color: accentColor },
|
|
1426
|
+
children: [
|
|
1427
|
+
"P",
|
|
1428
|
+
ann.pageIndex + 1
|
|
1429
|
+
]
|
|
1430
|
+
}
|
|
1431
|
+
),
|
|
1432
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-[10px] font-semibold opacity-70 uppercase tracking-wide", children: ann.type })
|
|
1433
|
+
] }),
|
|
1322
1434
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1323
|
-
"
|
|
1435
|
+
"button",
|
|
1436
|
+
{
|
|
1437
|
+
type: "button",
|
|
1438
|
+
className: "rounded-md border px-2 py-1 text-[10px] font-semibold uppercase tracking-wide",
|
|
1439
|
+
onClick: () => jumpToAnnotation(ann),
|
|
1440
|
+
style: {
|
|
1441
|
+
borderColor: accentColor,
|
|
1442
|
+
color: accentColor
|
|
1443
|
+
},
|
|
1444
|
+
children: "Ir para pagina"
|
|
1445
|
+
}
|
|
1446
|
+
)
|
|
1447
|
+
] }),
|
|
1448
|
+
isCommentThread ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "space-y-2", children: [
|
|
1449
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1450
|
+
"textarea",
|
|
1324
1451
|
{
|
|
1325
|
-
className: "w-
|
|
1326
|
-
style: {
|
|
1452
|
+
className: "w-full resize-none rounded-md border p-2 text-xs focus:outline-none",
|
|
1453
|
+
style: {
|
|
1454
|
+
background: "var(--papyrus-surface-resolved, var(--papyrus-surface, #111827))",
|
|
1455
|
+
borderColor: "var(--papyrus-border-resolved, var(--papyrus-border, #374151))",
|
|
1456
|
+
color: "var(--papyrus-text-resolved, var(--papyrus-text, #e5e7eb))"
|
|
1457
|
+
},
|
|
1458
|
+
rows: 3,
|
|
1459
|
+
placeholder: "Escreva seu comentario...",
|
|
1460
|
+
value: contentDraft,
|
|
1461
|
+
onChange: (event) => updateContentDraft(ann.id, event.target.value),
|
|
1462
|
+
onKeyDown: (event) => {
|
|
1463
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
1464
|
+
event.preventDefault();
|
|
1465
|
+
submitContent(ann);
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1327
1468
|
}
|
|
1328
1469
|
),
|
|
1329
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1330
|
-
"
|
|
1470
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1471
|
+
"button",
|
|
1331
1472
|
{
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1473
|
+
type: "button",
|
|
1474
|
+
className: "rounded-md px-3 py-1.5 text-[11px] font-semibold text-white",
|
|
1475
|
+
style: { backgroundColor: accentColor },
|
|
1476
|
+
onClick: () => submitContent(ann),
|
|
1477
|
+
children: hasExistingContent ? "Atualizar comentario" : "Enviar comentario"
|
|
1478
|
+
}
|
|
1479
|
+
) })
|
|
1480
|
+
] }) : null,
|
|
1481
|
+
replies.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mt-3 space-y-2", children: replies.map((reply) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1482
|
+
"div",
|
|
1483
|
+
{
|
|
1484
|
+
className: "rounded-md border p-2",
|
|
1485
|
+
style: {
|
|
1486
|
+
background: "var(--papyrus-surface-resolved, var(--papyrus-surface, #111827))",
|
|
1487
|
+
borderColor: "var(--papyrus-border-resolved, var(--papyrus-border, #374151))"
|
|
1488
|
+
},
|
|
1489
|
+
children: [
|
|
1490
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-xs leading-relaxed", children: reply.content }),
|
|
1491
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mt-1 text-[10px] opacity-70", children: new Date(reply.createdAt).toLocaleTimeString(
|
|
1492
|
+
[],
|
|
1493
|
+
{
|
|
1494
|
+
hour: "2-digit",
|
|
1495
|
+
minute: "2-digit"
|
|
1496
|
+
}
|
|
1497
|
+
) })
|
|
1498
|
+
]
|
|
1499
|
+
},
|
|
1500
|
+
reply.id
|
|
1501
|
+
)) }) : null,
|
|
1502
|
+
isCommentThread ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mt-3 flex items-center gap-2", children: [
|
|
1503
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1504
|
+
"input",
|
|
1505
|
+
{
|
|
1506
|
+
type: "text",
|
|
1507
|
+
className: "flex-1 rounded-md border px-2 py-1.5 text-xs focus:outline-none",
|
|
1508
|
+
style: {
|
|
1509
|
+
background: "var(--papyrus-surface-resolved, var(--papyrus-surface, #111827))",
|
|
1510
|
+
borderColor: "var(--papyrus-border-resolved, var(--papyrus-border, #374151))",
|
|
1511
|
+
color: "var(--papyrus-text-resolved, var(--papyrus-text, #e5e7eb))"
|
|
1512
|
+
},
|
|
1513
|
+
value: replyDraft,
|
|
1514
|
+
placeholder: "Responder...",
|
|
1515
|
+
onChange: (event) => updateReplyDraft(ann.id, event.target.value),
|
|
1516
|
+
onKeyDown: (event) => {
|
|
1517
|
+
if (event.key === "Enter") {
|
|
1518
|
+
event.preventDefault();
|
|
1519
|
+
submitReply(ann.id);
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
),
|
|
1524
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1525
|
+
"button",
|
|
1526
|
+
{
|
|
1527
|
+
type: "button",
|
|
1528
|
+
className: "rounded-md px-3 py-1.5 text-[11px] font-semibold text-white",
|
|
1529
|
+
style: { backgroundColor: accentColor },
|
|
1530
|
+
onClick: () => submitReply(ann.id),
|
|
1531
|
+
children: "Responder"
|
|
1338
1532
|
}
|
|
1339
1533
|
)
|
|
1340
|
-
] })
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1347
|
-
"p",
|
|
1348
|
-
{
|
|
1349
|
-
className: `text-[11px] font-bold uppercase tracking-tight ${isDark ? "text-gray-200" : "text-gray-700"}`,
|
|
1350
|
-
children: ann.type
|
|
1351
|
-
}
|
|
1352
|
-
)
|
|
1353
|
-
]
|
|
1354
|
-
},
|
|
1355
|
-
ann.id
|
|
1356
|
-
))
|
|
1534
|
+
] }) : null
|
|
1535
|
+
]
|
|
1536
|
+
},
|
|
1537
|
+
ann.id
|
|
1538
|
+
);
|
|
1539
|
+
})
|
|
1357
1540
|
] }) })
|
|
1358
1541
|
]
|
|
1359
1542
|
}
|
|
@@ -1381,6 +1564,10 @@ var PageRenderer = ({
|
|
|
1381
1564
|
const canvasRef = (0, import_react4.useRef)(null);
|
|
1382
1565
|
const htmlLayerRef = (0, import_react4.useRef)(null);
|
|
1383
1566
|
const textLayerRef = (0, import_react4.useRef)(null);
|
|
1567
|
+
const skipNextAnnotationSelectRef = (0, import_react4.useRef)(false);
|
|
1568
|
+
const skipSelectResetTimerRef = (0, import_react4.useRef)(
|
|
1569
|
+
null
|
|
1570
|
+
);
|
|
1384
1571
|
const [loading, setLoading] = (0, import_react4.useState)(true);
|
|
1385
1572
|
const [pageSize, setPageSize] = (0, import_react4.useState)(null);
|
|
1386
1573
|
const [isDragging, setIsDragging] = (0, import_react4.useState)(false);
|
|
@@ -1398,6 +1585,8 @@ var PageRenderer = ({
|
|
|
1398
1585
|
setDocumentState,
|
|
1399
1586
|
annotations,
|
|
1400
1587
|
addAnnotation,
|
|
1588
|
+
addAnnotationReply,
|
|
1589
|
+
updateAnnotation,
|
|
1401
1590
|
activeTool,
|
|
1402
1591
|
removeAnnotation,
|
|
1403
1592
|
selectedAnnotationId,
|
|
@@ -1421,6 +1610,24 @@ var PageRenderer = ({
|
|
|
1421
1610
|
() => Boolean(searchQuery?.trim()) && searchResults.some((res) => res.pageIndex === pageIndex),
|
|
1422
1611
|
[searchQuery, searchResults, pageIndex]
|
|
1423
1612
|
);
|
|
1613
|
+
const suppressNextAnnotationSelect = () => {
|
|
1614
|
+
skipNextAnnotationSelectRef.current = true;
|
|
1615
|
+
if (skipSelectResetTimerRef.current) {
|
|
1616
|
+
clearTimeout(skipSelectResetTimerRef.current);
|
|
1617
|
+
}
|
|
1618
|
+
skipSelectResetTimerRef.current = setTimeout(() => {
|
|
1619
|
+
skipNextAnnotationSelectRef.current = false;
|
|
1620
|
+
skipSelectResetTimerRef.current = null;
|
|
1621
|
+
}, 0);
|
|
1622
|
+
};
|
|
1623
|
+
(0, import_react4.useEffect)(
|
|
1624
|
+
() => () => {
|
|
1625
|
+
if (skipSelectResetTimerRef.current) {
|
|
1626
|
+
clearTimeout(skipSelectResetTimerRef.current);
|
|
1627
|
+
}
|
|
1628
|
+
},
|
|
1629
|
+
[]
|
|
1630
|
+
);
|
|
1424
1631
|
(0, import_react4.useEffect)(() => {
|
|
1425
1632
|
let active = true;
|
|
1426
1633
|
const loadSize = async () => {
|
|
@@ -1591,6 +1798,16 @@ var PageRenderer = ({
|
|
|
1591
1798
|
textLayerVersion
|
|
1592
1799
|
]);
|
|
1593
1800
|
const handleMouseDown = (e) => {
|
|
1801
|
+
const target = e.target;
|
|
1802
|
+
const clickedInsideAnnotation = Boolean(
|
|
1803
|
+
target?.closest("[data-papyrus-annotation-id]")
|
|
1804
|
+
);
|
|
1805
|
+
const clickedSelectionMenu = Boolean(
|
|
1806
|
+
target?.closest("[data-papyrus-selection-menu]")
|
|
1807
|
+
);
|
|
1808
|
+
if (!clickedInsideAnnotation && !clickedSelectionMenu) {
|
|
1809
|
+
setSelectedAnnotation(null);
|
|
1810
|
+
}
|
|
1594
1811
|
setSelectionMenu(null);
|
|
1595
1812
|
if (activeTool === "ink") {
|
|
1596
1813
|
const rect2 = containerRef.current?.getBoundingClientRect();
|
|
@@ -1647,6 +1864,7 @@ var PageRenderer = ({
|
|
|
1647
1864
|
x: Math.max(0, Math.min(1, p.x)),
|
|
1648
1865
|
y: Math.max(0, Math.min(1, p.y))
|
|
1649
1866
|
}));
|
|
1867
|
+
suppressNextAnnotationSelect();
|
|
1650
1868
|
addAnnotation({
|
|
1651
1869
|
id: Math.random().toString(36).substr(2, 9),
|
|
1652
1870
|
pageIndex,
|
|
@@ -1727,6 +1945,7 @@ var PageRenderer = ({
|
|
|
1727
1945
|
height: Math.max(...ye) - Math.min(...ys)
|
|
1728
1946
|
};
|
|
1729
1947
|
if (textMarkupTools.has(activeTool)) {
|
|
1948
|
+
suppressNextAnnotationSelect();
|
|
1730
1949
|
addAnnotation({
|
|
1731
1950
|
id: Math.random().toString(36).substr(2, 9),
|
|
1732
1951
|
pageIndex,
|
|
@@ -1762,6 +1981,9 @@ var PageRenderer = ({
|
|
|
1762
1981
|
if (currentRect.w > 5 && currentRect.h > 5) {
|
|
1763
1982
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
1764
1983
|
if (rect) {
|
|
1984
|
+
if (activeTool !== "text" && activeTool !== "comment") {
|
|
1985
|
+
suppressNextAnnotationSelect();
|
|
1986
|
+
}
|
|
1765
1987
|
addAnnotation({
|
|
1766
1988
|
id: Math.random().toString(36).substr(2, 9),
|
|
1767
1989
|
pageIndex,
|
|
@@ -1885,6 +2107,7 @@ var PageRenderer = ({
|
|
|
1885
2107
|
selectionMenu && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1886
2108
|
"div",
|
|
1887
2109
|
{
|
|
2110
|
+
"data-papyrus-selection-menu": "true",
|
|
1888
2111
|
className: "absolute z-[60] flex items-center gap-1 rounded-full border px-2 py-1 shadow-xl bg-white/95 backdrop-blur-md text-gray-700",
|
|
1889
2112
|
style: { left: selectionMenu.anchor.x, top: selectionMenu.anchor.y },
|
|
1890
2113
|
children: [
|
|
@@ -1897,6 +2120,7 @@ var PageRenderer = ({
|
|
|
1897
2120
|
{
|
|
1898
2121
|
className: "text-[10px] font-bold px-2 py-1 rounded-full hover:bg-gray-100",
|
|
1899
2122
|
onClick: () => {
|
|
2123
|
+
suppressNextAnnotationSelect();
|
|
1900
2124
|
addAnnotation({
|
|
1901
2125
|
id: Math.random().toString(36).substr(2, 9),
|
|
1902
2126
|
pageIndex,
|
|
@@ -1923,7 +2147,15 @@ var PageRenderer = ({
|
|
|
1923
2147
|
isSelected: selectedAnnotationId === ann.id,
|
|
1924
2148
|
accentColor,
|
|
1925
2149
|
onDelete: () => removeAnnotation(ann.id),
|
|
1926
|
-
onSelect: () =>
|
|
2150
|
+
onSelect: () => {
|
|
2151
|
+
if (skipNextAnnotationSelectRef.current) {
|
|
2152
|
+
skipNextAnnotationSelectRef.current = false;
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2155
|
+
setSelectedAnnotation(ann.id);
|
|
2156
|
+
},
|
|
2157
|
+
onUpdate: (updates) => updateAnnotation(ann.id, updates),
|
|
2158
|
+
onAddReply: (content) => addAnnotationReply(ann.id, content)
|
|
1927
2159
|
},
|
|
1928
2160
|
ann.id
|
|
1929
2161
|
)) })
|
|
@@ -1931,12 +2163,43 @@ var PageRenderer = ({
|
|
|
1931
2163
|
}
|
|
1932
2164
|
);
|
|
1933
2165
|
};
|
|
1934
|
-
var AnnotationItem = ({
|
|
2166
|
+
var AnnotationItem = ({
|
|
2167
|
+
ann,
|
|
2168
|
+
isSelected,
|
|
2169
|
+
accentColor,
|
|
2170
|
+
onDelete,
|
|
2171
|
+
onSelect,
|
|
2172
|
+
onUpdate,
|
|
2173
|
+
onAddReply
|
|
2174
|
+
}) => {
|
|
1935
2175
|
const isText = ann.type === "text" || ann.type === "comment";
|
|
1936
2176
|
const isHighlight = ann.type === "highlight";
|
|
1937
2177
|
const isMarkup = ann.type === "highlight" || ann.type === "underline" || ann.type === "squiggly" || ann.type === "strikeout";
|
|
1938
2178
|
const rects = ann.rects && ann.rects.length > 0 ? ann.rects : [ann.rect];
|
|
1939
2179
|
const isInk = ann.type === "ink" && ann.path && ann.path.length > 1;
|
|
2180
|
+
const [draftContent, setDraftContent] = (0, import_react4.useState)(ann.content ?? "");
|
|
2181
|
+
const [draftReply, setDraftReply] = (0, import_react4.useState)("");
|
|
2182
|
+
(0, import_react4.useEffect)(() => {
|
|
2183
|
+
setDraftContent(ann.content ?? "");
|
|
2184
|
+
}, [ann.id, ann.content]);
|
|
2185
|
+
(0, import_react4.useEffect)(() => {
|
|
2186
|
+
setDraftReply("");
|
|
2187
|
+
}, [ann.id]);
|
|
2188
|
+
const handleSaveContent = () => {
|
|
2189
|
+
const nextContent = draftContent.trim();
|
|
2190
|
+
const currentContent = (ann.content ?? "").trim();
|
|
2191
|
+
if (nextContent === currentContent) return;
|
|
2192
|
+
onUpdate({
|
|
2193
|
+
content: nextContent,
|
|
2194
|
+
updatedAt: Date.now()
|
|
2195
|
+
});
|
|
2196
|
+
};
|
|
2197
|
+
const handleReplySubmit = () => {
|
|
2198
|
+
const nextReply = draftReply.trim();
|
|
2199
|
+
if (!nextReply) return;
|
|
2200
|
+
onAddReply(nextReply);
|
|
2201
|
+
setDraftReply("");
|
|
2202
|
+
};
|
|
1940
2203
|
const renderMarkupRects = () => {
|
|
1941
2204
|
if (!isMarkup) return null;
|
|
1942
2205
|
return rects.map((r, idx) => {
|
|
@@ -2041,6 +2304,7 @@ var AnnotationItem = ({ ann, isSelected, accentColor, onDelete, onSelect }) => {
|
|
|
2041
2304
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2042
2305
|
"div",
|
|
2043
2306
|
{
|
|
2307
|
+
"data-papyrus-annotation-id": ann.id,
|
|
2044
2308
|
className: `absolute pointer-events-auto transition-all ${isSelected ? "shadow-xl z-30" : "z-10"}`,
|
|
2045
2309
|
style: {
|
|
2046
2310
|
left: `${ann.rect.x * 100}%`,
|
|
@@ -2059,16 +2323,151 @@ var AnnotationItem = ({ ann, isSelected, accentColor, onDelete, onSelect }) => {
|
|
|
2059
2323
|
children: [
|
|
2060
2324
|
renderMarkupRects(),
|
|
2061
2325
|
renderInk(),
|
|
2062
|
-
isText && isSelected && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2063
|
-
"
|
|
2326
|
+
isText && !isSelected && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2327
|
+
"button",
|
|
2064
2328
|
{
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2329
|
+
type: "button",
|
|
2330
|
+
className: "absolute -top-2 -right-2 h-6 w-6 rounded-full flex items-center justify-center shadow-lg",
|
|
2331
|
+
style: {
|
|
2332
|
+
background: "var(--papyrus-surface-2-resolved, var(--papyrus-surface-2, #1f2937))",
|
|
2333
|
+
border: "1px solid var(--papyrus-border-resolved, #374151)",
|
|
2334
|
+
color: "var(--papyrus-text-resolved, #e5e7eb)"
|
|
2335
|
+
},
|
|
2336
|
+
title: "Abrir comentario",
|
|
2337
|
+
"aria-label": "Abrir comentario",
|
|
2338
|
+
onClick: (event) => {
|
|
2339
|
+
event.stopPropagation();
|
|
2340
|
+
onSelect();
|
|
2341
|
+
},
|
|
2342
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2343
|
+
"svg",
|
|
2344
|
+
{
|
|
2345
|
+
className: "h-3.5 w-3.5",
|
|
2346
|
+
fill: "none",
|
|
2347
|
+
stroke: "currentColor",
|
|
2348
|
+
viewBox: "0 0 24 24",
|
|
2349
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2350
|
+
"path",
|
|
2351
|
+
{
|
|
2352
|
+
strokeLinecap: "round",
|
|
2353
|
+
strokeLinejoin: "round",
|
|
2354
|
+
strokeWidth: 2,
|
|
2355
|
+
d: "M8 10h.01M12 10h.01M16 10h.01M7 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-4l-4 4v-4z"
|
|
2356
|
+
}
|
|
2357
|
+
)
|
|
2358
|
+
}
|
|
2359
|
+
)
|
|
2070
2360
|
}
|
|
2071
|
-
)
|
|
2361
|
+
),
|
|
2362
|
+
isText && isSelected && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2363
|
+
"div",
|
|
2364
|
+
{
|
|
2365
|
+
className: "absolute top-full mt-2 w-72 rounded-xl p-3 z-50",
|
|
2366
|
+
style: {
|
|
2367
|
+
background: "var(--papyrus-popover-resolved, var(--papyrus-popover, #ffffff))",
|
|
2368
|
+
border: "1px solid var(--papyrus-border-resolved, #d1d5db)",
|
|
2369
|
+
color: "var(--papyrus-text-resolved, #111827)",
|
|
2370
|
+
boxShadow: "0 20px 40px var(--papyrus-shadow-resolved, rgba(0, 0, 0, 0.3))"
|
|
2371
|
+
},
|
|
2372
|
+
onClick: (event) => event.stopPropagation(),
|
|
2373
|
+
children: [
|
|
2374
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mb-2 flex items-center justify-between", children: [
|
|
2375
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-wider opacity-70", children: ann.type === "comment" ? "Comentario" : "Nota" }),
|
|
2376
|
+
ann.replies?.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "text-[10px] opacity-70", children: [
|
|
2377
|
+
ann.replies.length,
|
|
2378
|
+
" resposta",
|
|
2379
|
+
ann.replies.length > 1 ? "s" : ""
|
|
2380
|
+
] }) : null
|
|
2381
|
+
] }),
|
|
2382
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2383
|
+
"textarea",
|
|
2384
|
+
{
|
|
2385
|
+
className: "w-full rounded-md border p-2 text-xs font-medium resize-none focus:outline-none",
|
|
2386
|
+
style: {
|
|
2387
|
+
background: "var(--papyrus-surface-resolved, var(--papyrus-surface, #ffffff))",
|
|
2388
|
+
borderColor: "var(--papyrus-border-resolved, #d1d5db)",
|
|
2389
|
+
color: "var(--papyrus-text-resolved, #111827)"
|
|
2390
|
+
},
|
|
2391
|
+
placeholder: "Escreva seu comentario...",
|
|
2392
|
+
rows: 3,
|
|
2393
|
+
value: draftContent,
|
|
2394
|
+
onChange: (event) => setDraftContent(event.target.value),
|
|
2395
|
+
onKeyDown: (event) => {
|
|
2396
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
2397
|
+
event.preventDefault();
|
|
2398
|
+
handleSaveContent();
|
|
2399
|
+
}
|
|
2400
|
+
},
|
|
2401
|
+
autoFocus: true
|
|
2402
|
+
}
|
|
2403
|
+
),
|
|
2404
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2405
|
+
"button",
|
|
2406
|
+
{
|
|
2407
|
+
type: "button",
|
|
2408
|
+
className: "rounded-md px-3 py-1.5 text-[11px] font-semibold text-white",
|
|
2409
|
+
style: { backgroundColor: accentColor },
|
|
2410
|
+
onClick: (event) => {
|
|
2411
|
+
event.stopPropagation();
|
|
2412
|
+
handleSaveContent();
|
|
2413
|
+
},
|
|
2414
|
+
children: (ann.content ?? "").trim() ? "Atualizar" : "Enviar"
|
|
2415
|
+
}
|
|
2416
|
+
) }),
|
|
2417
|
+
ann.replies && ann.replies.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mt-3 space-y-2", children: ann.replies.map((reply) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2418
|
+
"div",
|
|
2419
|
+
{
|
|
2420
|
+
className: "rounded-md border p-2",
|
|
2421
|
+
style: {
|
|
2422
|
+
background: "var(--papyrus-surface-resolved, var(--papyrus-surface, #ffffff))",
|
|
2423
|
+
borderColor: "var(--papyrus-border-resolved, #d1d5db)"
|
|
2424
|
+
},
|
|
2425
|
+
children: [
|
|
2426
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-xs", children: reply.content }),
|
|
2427
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mt-1 text-[10px] opacity-70", children: new Date(reply.createdAt).toLocaleTimeString([], {
|
|
2428
|
+
hour: "2-digit",
|
|
2429
|
+
minute: "2-digit"
|
|
2430
|
+
}) })
|
|
2431
|
+
]
|
|
2432
|
+
},
|
|
2433
|
+
reply.id
|
|
2434
|
+
)) }) : null,
|
|
2435
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mt-3 flex items-center gap-2", children: [
|
|
2436
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2437
|
+
"input",
|
|
2438
|
+
{
|
|
2439
|
+
type: "text",
|
|
2440
|
+
className: "flex-1 rounded-md border px-2 py-1.5 text-xs focus:outline-none",
|
|
2441
|
+
style: {
|
|
2442
|
+
background: "var(--papyrus-surface-resolved, var(--papyrus-surface, #ffffff))",
|
|
2443
|
+
borderColor: "var(--papyrus-border-resolved, #d1d5db)",
|
|
2444
|
+
color: "var(--papyrus-text-resolved, #111827)"
|
|
2445
|
+
},
|
|
2446
|
+
placeholder: "Responder...",
|
|
2447
|
+
value: draftReply,
|
|
2448
|
+
onChange: (event) => setDraftReply(event.target.value),
|
|
2449
|
+
onKeyDown: (event) => {
|
|
2450
|
+
if (event.key === "Enter") {
|
|
2451
|
+
event.preventDefault();
|
|
2452
|
+
handleReplySubmit();
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
),
|
|
2457
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2458
|
+
"button",
|
|
2459
|
+
{
|
|
2460
|
+
type: "button",
|
|
2461
|
+
className: "rounded-md px-3 py-1.5 text-[11px] font-semibold text-white",
|
|
2462
|
+
style: { backgroundColor: accentColor },
|
|
2463
|
+
onClick: handleReplySubmit,
|
|
2464
|
+
children: "Responder"
|
|
2465
|
+
}
|
|
2466
|
+
)
|
|
2467
|
+
] })
|
|
2468
|
+
]
|
|
2469
|
+
}
|
|
2470
|
+
),
|
|
2072
2471
|
isSelected && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2073
2472
|
"button",
|
|
2074
2473
|
{
|
|
@@ -2110,7 +2509,11 @@ var MIN_ZOOM = 0.2;
|
|
|
2110
2509
|
var MAX_ZOOM = 5;
|
|
2111
2510
|
var WIDTH_SNAP_PX = 4;
|
|
2112
2511
|
var WIDTH_HYSTERESIS_PX = 6;
|
|
2512
|
+
var MOBILE_HEADER_HIDE_DELTA_PX = 28;
|
|
2513
|
+
var MOBILE_HEADER_SHOW_DELTA_PX = 16;
|
|
2514
|
+
var MOBILE_HEADER_TOP_RESET_PX = 12;
|
|
2113
2515
|
var Viewer = ({ engine, style }) => {
|
|
2516
|
+
const viewerState = (0, import_core5.useViewerStore)();
|
|
2114
2517
|
const {
|
|
2115
2518
|
pageCount,
|
|
2116
2519
|
currentPage,
|
|
@@ -2123,7 +2526,8 @@ var Viewer = ({ engine, style }) => {
|
|
|
2123
2526
|
annotationColor,
|
|
2124
2527
|
setAnnotationColor,
|
|
2125
2528
|
toolDockOpen
|
|
2126
|
-
} =
|
|
2529
|
+
} = viewerState;
|
|
2530
|
+
const mobileTopbarVisible = viewerState.mobileTopbarVisible ?? true;
|
|
2127
2531
|
const isDark = uiTheme === "dark";
|
|
2128
2532
|
const viewerRef = (0, import_react5.useRef)(null);
|
|
2129
2533
|
const colorPickerRef = (0, import_react5.useRef)(null);
|
|
@@ -2133,6 +2537,11 @@ var Viewer = ({ engine, style }) => {
|
|
|
2133
2537
|
const jumpRef = (0, import_react5.useRef)(false);
|
|
2134
2538
|
const jumpTimerRef = (0, import_react5.useRef)(null);
|
|
2135
2539
|
const lastWidthRef = (0, import_react5.useRef)(null);
|
|
2540
|
+
const lastScrollTopRef = (0, import_react5.useRef)(0);
|
|
2541
|
+
const scrollDownAccumulatorRef = (0, import_react5.useRef)(0);
|
|
2542
|
+
const scrollUpAccumulatorRef = (0, import_react5.useRef)(0);
|
|
2543
|
+
const previousCurrentPageRef = (0, import_react5.useRef)(currentPage);
|
|
2544
|
+
const mobileTopbarVisibleRef = (0, import_react5.useRef)(mobileTopbarVisible);
|
|
2136
2545
|
const pinchRef = (0, import_react5.useRef)({
|
|
2137
2546
|
active: false,
|
|
2138
2547
|
startDistance: 0,
|
|
@@ -2145,6 +2554,7 @@ var Viewer = ({ engine, style }) => {
|
|
|
2145
2554
|
const [pageSizes, setPageSizes] = (0, import_react5.useState)({});
|
|
2146
2555
|
const [colorPickerOpen, setColorPickerOpen] = (0, import_react5.useState)(false);
|
|
2147
2556
|
const isCompact = availableWidth !== null && availableWidth < 820;
|
|
2557
|
+
const isMobileViewport = availableWidth !== null && availableWidth < 640;
|
|
2148
2558
|
const paddingY = isCompact ? "py-10" : "py-16";
|
|
2149
2559
|
const toolDockPosition = isCompact ? "bottom-4" : "bottom-8";
|
|
2150
2560
|
const colorPalette = [
|
|
@@ -2157,6 +2567,13 @@ var Viewer = ({ engine, style }) => {
|
|
|
2157
2567
|
"#8b5cf6",
|
|
2158
2568
|
"#111827"
|
|
2159
2569
|
];
|
|
2570
|
+
const setMobileTopbarVisibility = (visible) => {
|
|
2571
|
+
if (mobileTopbarVisibleRef.current === visible) return;
|
|
2572
|
+
mobileTopbarVisibleRef.current = visible;
|
|
2573
|
+
setDocumentState({
|
|
2574
|
+
mobileTopbarVisible: visible
|
|
2575
|
+
});
|
|
2576
|
+
};
|
|
2160
2577
|
(0, import_react5.useEffect)(() => {
|
|
2161
2578
|
if (!colorPickerOpen) return;
|
|
2162
2579
|
const handleClick = (event) => {
|
|
@@ -2171,6 +2588,9 @@ var Viewer = ({ engine, style }) => {
|
|
|
2171
2588
|
(0, import_react5.useEffect)(() => {
|
|
2172
2589
|
if (!toolDockOpen && colorPickerOpen) setColorPickerOpen(false);
|
|
2173
2590
|
}, [toolDockOpen, colorPickerOpen]);
|
|
2591
|
+
(0, import_react5.useEffect)(() => {
|
|
2592
|
+
mobileTopbarVisibleRef.current = mobileTopbarVisible;
|
|
2593
|
+
}, [mobileTopbarVisible]);
|
|
2174
2594
|
(0, import_react5.useEffect)(
|
|
2175
2595
|
() => () => {
|
|
2176
2596
|
if (pinchRef.current.rafId != null) {
|
|
@@ -2222,6 +2642,64 @@ var Viewer = ({ engine, style }) => {
|
|
|
2222
2642
|
observer.disconnect();
|
|
2223
2643
|
};
|
|
2224
2644
|
}, []);
|
|
2645
|
+
(0, import_react5.useEffect)(() => {
|
|
2646
|
+
const root = viewerRef.current;
|
|
2647
|
+
if (!root) return;
|
|
2648
|
+
if (!isMobileViewport) {
|
|
2649
|
+
lastScrollTopRef.current = root.scrollTop;
|
|
2650
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2651
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2652
|
+
setMobileTopbarVisibility(true);
|
|
2653
|
+
return;
|
|
2654
|
+
}
|
|
2655
|
+
lastScrollTopRef.current = root.scrollTop;
|
|
2656
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2657
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2658
|
+
const handleScroll = () => {
|
|
2659
|
+
const nextScrollTop = root.scrollTop;
|
|
2660
|
+
const delta = nextScrollTop - lastScrollTopRef.current;
|
|
2661
|
+
lastScrollTopRef.current = nextScrollTop;
|
|
2662
|
+
if (Math.abs(delta) < 1) return;
|
|
2663
|
+
if (nextScrollTop <= MOBILE_HEADER_TOP_RESET_PX) {
|
|
2664
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2665
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2666
|
+
setMobileTopbarVisibility(true);
|
|
2667
|
+
return;
|
|
2668
|
+
}
|
|
2669
|
+
if (delta > 0) {
|
|
2670
|
+
scrollDownAccumulatorRef.current += delta;
|
|
2671
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2672
|
+
} else {
|
|
2673
|
+
scrollUpAccumulatorRef.current += -delta;
|
|
2674
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2675
|
+
}
|
|
2676
|
+
if (scrollDownAccumulatorRef.current >= MOBILE_HEADER_HIDE_DELTA_PX && mobileTopbarVisibleRef.current) {
|
|
2677
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2678
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2679
|
+
setMobileTopbarVisibility(false);
|
|
2680
|
+
return;
|
|
2681
|
+
}
|
|
2682
|
+
if (scrollUpAccumulatorRef.current >= MOBILE_HEADER_SHOW_DELTA_PX && !mobileTopbarVisibleRef.current) {
|
|
2683
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2684
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2685
|
+
setMobileTopbarVisibility(true);
|
|
2686
|
+
}
|
|
2687
|
+
};
|
|
2688
|
+
root.addEventListener("scroll", handleScroll, { passive: true });
|
|
2689
|
+
return () => {
|
|
2690
|
+
root.removeEventListener("scroll", handleScroll);
|
|
2691
|
+
};
|
|
2692
|
+
}, [isMobileViewport, setDocumentState]);
|
|
2693
|
+
(0, import_react5.useEffect)(() => {
|
|
2694
|
+
const previousPage = previousCurrentPageRef.current;
|
|
2695
|
+
previousCurrentPageRef.current = currentPage;
|
|
2696
|
+
if (!isMobileViewport) return;
|
|
2697
|
+
if (currentPage < previousPage && !mobileTopbarVisibleRef.current) {
|
|
2698
|
+
scrollDownAccumulatorRef.current = 0;
|
|
2699
|
+
scrollUpAccumulatorRef.current = 0;
|
|
2700
|
+
setMobileTopbarVisibility(true);
|
|
2701
|
+
}
|
|
2702
|
+
}, [currentPage, isMobileViewport, setDocumentState]);
|
|
2225
2703
|
(0, import_react5.useEffect)(() => {
|
|
2226
2704
|
let active = true;
|
|
2227
2705
|
if (!pageCount) return;
|