@papyrus-sdk/ui-react 0.2.20 → 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 +406 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +406 -46
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1131,10 +1131,15 @@ var SidebarRight = ({ engine, style }) => {
|
|
|
1131
1131
|
setDocumentState,
|
|
1132
1132
|
triggerScrollToPage,
|
|
1133
1133
|
annotations,
|
|
1134
|
-
accentColor
|
|
1134
|
+
accentColor,
|
|
1135
|
+
updateAnnotation,
|
|
1136
|
+
addAnnotationReply,
|
|
1137
|
+
setSelectedAnnotation
|
|
1135
1138
|
} = (0, import_core3.useViewerStore)();
|
|
1136
1139
|
const [query, setQuery] = (0, import_react3.useState)("");
|
|
1137
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)({});
|
|
1138
1143
|
const searchService = new import_core3.SearchService(engine);
|
|
1139
1144
|
const isDark = uiTheme === "dark";
|
|
1140
1145
|
const accentSoft = withAlpha2(accentColor, 0.12);
|
|
@@ -1150,6 +1155,41 @@ var SidebarRight = ({ engine, style }) => {
|
|
|
1150
1155
|
setSearch(query, results);
|
|
1151
1156
|
setIsSearching(false);
|
|
1152
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
|
+
};
|
|
1153
1193
|
if (!sidebarRightOpen) return null;
|
|
1154
1194
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1155
1195
|
"div",
|
|
@@ -1351,48 +1391,152 @@ var SidebarRight = ({ engine, style }) => {
|
|
|
1351
1391
|
}
|
|
1352
1392
|
) }),
|
|
1353
1393
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-[10px] font-bold text-gray-400 uppercase tracking-widest", children: "Sem anota\xE7\xF5es" })
|
|
1354
|
-
] }) : annotations.
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
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
|
+
] }),
|
|
1361
1434
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1362
|
-
"
|
|
1435
|
+
"button",
|
|
1363
1436
|
{
|
|
1364
|
-
|
|
1365
|
-
|
|
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",
|
|
1451
|
+
{
|
|
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
|
+
}
|
|
1366
1468
|
}
|
|
1367
1469
|
),
|
|
1368
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1369
|
-
"
|
|
1470
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1471
|
+
"button",
|
|
1370
1472
|
{
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
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"
|
|
1377
1532
|
}
|
|
1378
1533
|
)
|
|
1379
|
-
] })
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1386
|
-
"p",
|
|
1387
|
-
{
|
|
1388
|
-
className: `text-[11px] font-bold uppercase tracking-tight ${isDark ? "text-gray-200" : "text-gray-700"}`,
|
|
1389
|
-
children: ann.type
|
|
1390
|
-
}
|
|
1391
|
-
)
|
|
1392
|
-
]
|
|
1393
|
-
},
|
|
1394
|
-
ann.id
|
|
1395
|
-
))
|
|
1534
|
+
] }) : null
|
|
1535
|
+
]
|
|
1536
|
+
},
|
|
1537
|
+
ann.id
|
|
1538
|
+
);
|
|
1539
|
+
})
|
|
1396
1540
|
] }) })
|
|
1397
1541
|
]
|
|
1398
1542
|
}
|
|
@@ -1420,6 +1564,10 @@ var PageRenderer = ({
|
|
|
1420
1564
|
const canvasRef = (0, import_react4.useRef)(null);
|
|
1421
1565
|
const htmlLayerRef = (0, import_react4.useRef)(null);
|
|
1422
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
|
+
);
|
|
1423
1571
|
const [loading, setLoading] = (0, import_react4.useState)(true);
|
|
1424
1572
|
const [pageSize, setPageSize] = (0, import_react4.useState)(null);
|
|
1425
1573
|
const [isDragging, setIsDragging] = (0, import_react4.useState)(false);
|
|
@@ -1437,6 +1585,8 @@ var PageRenderer = ({
|
|
|
1437
1585
|
setDocumentState,
|
|
1438
1586
|
annotations,
|
|
1439
1587
|
addAnnotation,
|
|
1588
|
+
addAnnotationReply,
|
|
1589
|
+
updateAnnotation,
|
|
1440
1590
|
activeTool,
|
|
1441
1591
|
removeAnnotation,
|
|
1442
1592
|
selectedAnnotationId,
|
|
@@ -1460,6 +1610,24 @@ var PageRenderer = ({
|
|
|
1460
1610
|
() => Boolean(searchQuery?.trim()) && searchResults.some((res) => res.pageIndex === pageIndex),
|
|
1461
1611
|
[searchQuery, searchResults, pageIndex]
|
|
1462
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
|
+
);
|
|
1463
1631
|
(0, import_react4.useEffect)(() => {
|
|
1464
1632
|
let active = true;
|
|
1465
1633
|
const loadSize = async () => {
|
|
@@ -1630,6 +1798,16 @@ var PageRenderer = ({
|
|
|
1630
1798
|
textLayerVersion
|
|
1631
1799
|
]);
|
|
1632
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
|
+
}
|
|
1633
1811
|
setSelectionMenu(null);
|
|
1634
1812
|
if (activeTool === "ink") {
|
|
1635
1813
|
const rect2 = containerRef.current?.getBoundingClientRect();
|
|
@@ -1686,6 +1864,7 @@ var PageRenderer = ({
|
|
|
1686
1864
|
x: Math.max(0, Math.min(1, p.x)),
|
|
1687
1865
|
y: Math.max(0, Math.min(1, p.y))
|
|
1688
1866
|
}));
|
|
1867
|
+
suppressNextAnnotationSelect();
|
|
1689
1868
|
addAnnotation({
|
|
1690
1869
|
id: Math.random().toString(36).substr(2, 9),
|
|
1691
1870
|
pageIndex,
|
|
@@ -1766,6 +1945,7 @@ var PageRenderer = ({
|
|
|
1766
1945
|
height: Math.max(...ye) - Math.min(...ys)
|
|
1767
1946
|
};
|
|
1768
1947
|
if (textMarkupTools.has(activeTool)) {
|
|
1948
|
+
suppressNextAnnotationSelect();
|
|
1769
1949
|
addAnnotation({
|
|
1770
1950
|
id: Math.random().toString(36).substr(2, 9),
|
|
1771
1951
|
pageIndex,
|
|
@@ -1801,6 +1981,9 @@ var PageRenderer = ({
|
|
|
1801
1981
|
if (currentRect.w > 5 && currentRect.h > 5) {
|
|
1802
1982
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
1803
1983
|
if (rect) {
|
|
1984
|
+
if (activeTool !== "text" && activeTool !== "comment") {
|
|
1985
|
+
suppressNextAnnotationSelect();
|
|
1986
|
+
}
|
|
1804
1987
|
addAnnotation({
|
|
1805
1988
|
id: Math.random().toString(36).substr(2, 9),
|
|
1806
1989
|
pageIndex,
|
|
@@ -1924,6 +2107,7 @@ var PageRenderer = ({
|
|
|
1924
2107
|
selectionMenu && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1925
2108
|
"div",
|
|
1926
2109
|
{
|
|
2110
|
+
"data-papyrus-selection-menu": "true",
|
|
1927
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",
|
|
1928
2112
|
style: { left: selectionMenu.anchor.x, top: selectionMenu.anchor.y },
|
|
1929
2113
|
children: [
|
|
@@ -1936,6 +2120,7 @@ var PageRenderer = ({
|
|
|
1936
2120
|
{
|
|
1937
2121
|
className: "text-[10px] font-bold px-2 py-1 rounded-full hover:bg-gray-100",
|
|
1938
2122
|
onClick: () => {
|
|
2123
|
+
suppressNextAnnotationSelect();
|
|
1939
2124
|
addAnnotation({
|
|
1940
2125
|
id: Math.random().toString(36).substr(2, 9),
|
|
1941
2126
|
pageIndex,
|
|
@@ -1962,7 +2147,15 @@ var PageRenderer = ({
|
|
|
1962
2147
|
isSelected: selectedAnnotationId === ann.id,
|
|
1963
2148
|
accentColor,
|
|
1964
2149
|
onDelete: () => removeAnnotation(ann.id),
|
|
1965
|
-
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)
|
|
1966
2159
|
},
|
|
1967
2160
|
ann.id
|
|
1968
2161
|
)) })
|
|
@@ -1970,12 +2163,43 @@ var PageRenderer = ({
|
|
|
1970
2163
|
}
|
|
1971
2164
|
);
|
|
1972
2165
|
};
|
|
1973
|
-
var AnnotationItem = ({
|
|
2166
|
+
var AnnotationItem = ({
|
|
2167
|
+
ann,
|
|
2168
|
+
isSelected,
|
|
2169
|
+
accentColor,
|
|
2170
|
+
onDelete,
|
|
2171
|
+
onSelect,
|
|
2172
|
+
onUpdate,
|
|
2173
|
+
onAddReply
|
|
2174
|
+
}) => {
|
|
1974
2175
|
const isText = ann.type === "text" || ann.type === "comment";
|
|
1975
2176
|
const isHighlight = ann.type === "highlight";
|
|
1976
2177
|
const isMarkup = ann.type === "highlight" || ann.type === "underline" || ann.type === "squiggly" || ann.type === "strikeout";
|
|
1977
2178
|
const rects = ann.rects && ann.rects.length > 0 ? ann.rects : [ann.rect];
|
|
1978
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
|
+
};
|
|
1979
2203
|
const renderMarkupRects = () => {
|
|
1980
2204
|
if (!isMarkup) return null;
|
|
1981
2205
|
return rects.map((r, idx) => {
|
|
@@ -2080,6 +2304,7 @@ var AnnotationItem = ({ ann, isSelected, accentColor, onDelete, onSelect }) => {
|
|
|
2080
2304
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2081
2305
|
"div",
|
|
2082
2306
|
{
|
|
2307
|
+
"data-papyrus-annotation-id": ann.id,
|
|
2083
2308
|
className: `absolute pointer-events-auto transition-all ${isSelected ? "shadow-xl z-30" : "z-10"}`,
|
|
2084
2309
|
style: {
|
|
2085
2310
|
left: `${ann.rect.x * 100}%`,
|
|
@@ -2098,16 +2323,151 @@ var AnnotationItem = ({ ann, isSelected, accentColor, onDelete, onSelect }) => {
|
|
|
2098
2323
|
children: [
|
|
2099
2324
|
renderMarkupRects(),
|
|
2100
2325
|
renderInk(),
|
|
2101
|
-
isText && isSelected && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2102
|
-
"
|
|
2326
|
+
isText && !isSelected && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2327
|
+
"button",
|
|
2103
2328
|
{
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
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
|
+
)
|
|
2109
2360
|
}
|
|
2110
|
-
)
|
|
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
|
+
),
|
|
2111
2471
|
isSelected && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2112
2472
|
"button",
|
|
2113
2473
|
{
|