pdfjs-reader-core 0.1.4 → 0.2.0
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.cjs +1563 -243
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +642 -11
- package/dist/index.d.ts +642 -11
- package/dist/index.js +1504 -198
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -332,6 +332,9 @@ var init_highlight_storage = __esm({
|
|
|
332
332
|
});
|
|
333
333
|
|
|
334
334
|
// src/store/viewer-store.ts
|
|
335
|
+
function generateRequestId() {
|
|
336
|
+
return `scroll-${Date.now()}-${++requestCounter}`;
|
|
337
|
+
}
|
|
335
338
|
function createViewerStore(initialOverrides = {}) {
|
|
336
339
|
return (0, import_vanilla.createStore)()((set, get) => ({
|
|
337
340
|
...initialState,
|
|
@@ -384,6 +387,46 @@ function createViewerStore(initialOverrides = {}) {
|
|
|
384
387
|
set({ currentPage: currentPage - 1 });
|
|
385
388
|
}
|
|
386
389
|
},
|
|
390
|
+
// Scroll coordination actions
|
|
391
|
+
requestScrollToPage: (page, behavior = "smooth") => {
|
|
392
|
+
const { numPages } = get();
|
|
393
|
+
const validPage = Math.max(1, Math.min(page, numPages));
|
|
394
|
+
return new Promise((resolve) => {
|
|
395
|
+
const requestId = generateRequestId();
|
|
396
|
+
const timeoutId = setTimeout(() => {
|
|
397
|
+
const callback = scrollCallbacks.get(requestId);
|
|
398
|
+
if (callback) {
|
|
399
|
+
scrollCallbacks.delete(requestId);
|
|
400
|
+
callback.resolve();
|
|
401
|
+
}
|
|
402
|
+
const currentRequest = get().scrollToPageRequest;
|
|
403
|
+
if (currentRequest?.requestId === requestId) {
|
|
404
|
+
set({ scrollToPageRequest: null });
|
|
405
|
+
}
|
|
406
|
+
}, SCROLL_TIMEOUT_MS);
|
|
407
|
+
scrollCallbacks.set(requestId, { resolve, timeoutId });
|
|
408
|
+
set({
|
|
409
|
+
currentPage: validPage,
|
|
410
|
+
scrollToPageRequest: {
|
|
411
|
+
page: validPage,
|
|
412
|
+
requestId,
|
|
413
|
+
behavior
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
});
|
|
417
|
+
},
|
|
418
|
+
completeScrollRequest: (requestId) => {
|
|
419
|
+
const callback = scrollCallbacks.get(requestId);
|
|
420
|
+
if (callback) {
|
|
421
|
+
clearTimeout(callback.timeoutId);
|
|
422
|
+
scrollCallbacks.delete(requestId);
|
|
423
|
+
callback.resolve();
|
|
424
|
+
}
|
|
425
|
+
const currentRequest = get().scrollToPageRequest;
|
|
426
|
+
if (currentRequest?.requestId === requestId) {
|
|
427
|
+
set({ scrollToPageRequest: null });
|
|
428
|
+
}
|
|
429
|
+
},
|
|
387
430
|
// Zoom actions
|
|
388
431
|
setScale: (scale) => {
|
|
389
432
|
const clampedScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
|
|
@@ -450,7 +493,7 @@ function createViewerStore(initialOverrides = {}) {
|
|
|
450
493
|
}
|
|
451
494
|
}));
|
|
452
495
|
}
|
|
453
|
-
var import_vanilla, ZOOM_LEVELS, MIN_SCALE, MAX_SCALE, initialState;
|
|
496
|
+
var import_vanilla, ZOOM_LEVELS, MIN_SCALE, MAX_SCALE, SCROLL_TIMEOUT_MS, scrollCallbacks, requestCounter, initialState;
|
|
454
497
|
var init_viewer_store = __esm({
|
|
455
498
|
"src/store/viewer-store.ts"() {
|
|
456
499
|
"use strict";
|
|
@@ -458,6 +501,9 @@ var init_viewer_store = __esm({
|
|
|
458
501
|
ZOOM_LEVELS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 3, 4];
|
|
459
502
|
MIN_SCALE = 0.1;
|
|
460
503
|
MAX_SCALE = 10;
|
|
504
|
+
SCROLL_TIMEOUT_MS = 3e3;
|
|
505
|
+
scrollCallbacks = /* @__PURE__ */ new Map();
|
|
506
|
+
requestCounter = 0;
|
|
461
507
|
initialState = {
|
|
462
508
|
// Document state
|
|
463
509
|
document: null,
|
|
@@ -468,6 +514,8 @@ var init_viewer_store = __esm({
|
|
|
468
514
|
currentPage: 1,
|
|
469
515
|
scale: 1,
|
|
470
516
|
rotation: 0,
|
|
517
|
+
// Scroll coordination
|
|
518
|
+
scrollToPageRequest: null,
|
|
471
519
|
// UI state
|
|
472
520
|
viewMode: "single",
|
|
473
521
|
scrollMode: "single",
|
|
@@ -1277,6 +1325,252 @@ var init_agent_api = __esm({
|
|
|
1277
1325
|
}
|
|
1278
1326
|
});
|
|
1279
1327
|
|
|
1328
|
+
// src/utils/text-search.ts
|
|
1329
|
+
async function extractPageText(document2, pageNumber) {
|
|
1330
|
+
const page = await document2.getPage(pageNumber);
|
|
1331
|
+
const textContent = await page.getTextContent();
|
|
1332
|
+
const viewport = page.getViewport({ scale: 1 });
|
|
1333
|
+
let fullText = "";
|
|
1334
|
+
const charPositions = [];
|
|
1335
|
+
for (const item of textContent.items) {
|
|
1336
|
+
if ("str" in item && item.str) {
|
|
1337
|
+
const tx = item.transform;
|
|
1338
|
+
const x = tx[4];
|
|
1339
|
+
const y = viewport.height - tx[5];
|
|
1340
|
+
const width = item.width ?? 0;
|
|
1341
|
+
const height = item.height ?? 12;
|
|
1342
|
+
const charWidth = item.str.length > 0 ? width / item.str.length : width;
|
|
1343
|
+
for (let i = 0; i < item.str.length; i++) {
|
|
1344
|
+
charPositions.push({
|
|
1345
|
+
char: item.str[i],
|
|
1346
|
+
rect: {
|
|
1347
|
+
x: x + i * charWidth,
|
|
1348
|
+
y: y - height,
|
|
1349
|
+
width: charWidth,
|
|
1350
|
+
height
|
|
1351
|
+
}
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
fullText += item.str;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
return { fullText, charPositions };
|
|
1358
|
+
}
|
|
1359
|
+
async function findTextOnPage(document2, pageNumber, query, options = {}) {
|
|
1360
|
+
const { caseSensitive = false, wholeWord = false } = options;
|
|
1361
|
+
if (!query || pageNumber < 1 || pageNumber > document2.numPages) {
|
|
1362
|
+
return [];
|
|
1363
|
+
}
|
|
1364
|
+
const { fullText, charPositions } = await extractPageText(document2, pageNumber);
|
|
1365
|
+
const matches = [];
|
|
1366
|
+
const searchText = caseSensitive ? query : query.toLowerCase();
|
|
1367
|
+
const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();
|
|
1368
|
+
let startIndex = 0;
|
|
1369
|
+
while (true) {
|
|
1370
|
+
const matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
1371
|
+
if (matchIndex === -1) break;
|
|
1372
|
+
if (wholeWord) {
|
|
1373
|
+
const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : " ";
|
|
1374
|
+
const afterChar = matchIndex + query.length < textToSearch.length ? textToSearch[matchIndex + query.length] : " ";
|
|
1375
|
+
if (/\w/.test(beforeChar) || /\w/.test(afterChar)) {
|
|
1376
|
+
startIndex = matchIndex + 1;
|
|
1377
|
+
continue;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
const matchRects = [];
|
|
1381
|
+
for (let i = matchIndex; i < matchIndex + query.length && i < charPositions.length; i++) {
|
|
1382
|
+
matchRects.push(charPositions[i].rect);
|
|
1383
|
+
}
|
|
1384
|
+
const mergedRects = mergeAdjacentRects(matchRects);
|
|
1385
|
+
matches.push({
|
|
1386
|
+
text: fullText.substring(matchIndex, matchIndex + query.length),
|
|
1387
|
+
rects: mergedRects,
|
|
1388
|
+
pageNumber,
|
|
1389
|
+
startIndex: matchIndex
|
|
1390
|
+
});
|
|
1391
|
+
startIndex = matchIndex + 1;
|
|
1392
|
+
}
|
|
1393
|
+
return matches;
|
|
1394
|
+
}
|
|
1395
|
+
async function findTextInDocument(document2, query, options = {}) {
|
|
1396
|
+
const { pageRange, ...findOptions } = options;
|
|
1397
|
+
const pagesToSearch = pageRange ?? Array.from({ length: document2.numPages }, (_, i) => i + 1);
|
|
1398
|
+
const allMatches = [];
|
|
1399
|
+
for (const pageNum of pagesToSearch) {
|
|
1400
|
+
if (pageNum < 1 || pageNum > document2.numPages) continue;
|
|
1401
|
+
try {
|
|
1402
|
+
const matches = await findTextOnPage(document2, pageNum, query, findOptions);
|
|
1403
|
+
allMatches.push(...matches);
|
|
1404
|
+
} catch {
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
return allMatches;
|
|
1408
|
+
}
|
|
1409
|
+
function mergeAdjacentRects(rects) {
|
|
1410
|
+
if (rects.length === 0) return [];
|
|
1411
|
+
const sorted = [...rects].sort((a, b) => a.y - b.y || a.x - b.x);
|
|
1412
|
+
const merged = [];
|
|
1413
|
+
let current = { ...sorted[0] };
|
|
1414
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
1415
|
+
const rect = sorted[i];
|
|
1416
|
+
if (Math.abs(rect.y - current.y) < 2 && rect.x <= current.x + current.width + 2) {
|
|
1417
|
+
const newRight = Math.max(current.x + current.width, rect.x + rect.width);
|
|
1418
|
+
current.width = newRight - current.x;
|
|
1419
|
+
current.height = Math.max(current.height, rect.height);
|
|
1420
|
+
} else {
|
|
1421
|
+
merged.push(current);
|
|
1422
|
+
current = { ...rect };
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
merged.push(current);
|
|
1426
|
+
return merged;
|
|
1427
|
+
}
|
|
1428
|
+
async function getPageText(document2, pageNumber) {
|
|
1429
|
+
if (pageNumber < 1 || pageNumber > document2.numPages) {
|
|
1430
|
+
return "";
|
|
1431
|
+
}
|
|
1432
|
+
const page = await document2.getPage(pageNumber);
|
|
1433
|
+
const textContent = await page.getTextContent();
|
|
1434
|
+
return textContent.items.filter((item) => "str" in item).map((item) => item.str).join("");
|
|
1435
|
+
}
|
|
1436
|
+
async function countTextOnPage(document2, pageNumber, query, options = {}) {
|
|
1437
|
+
const { caseSensitive = false, wholeWord = false } = options;
|
|
1438
|
+
if (!query || pageNumber < 1 || pageNumber > document2.numPages) {
|
|
1439
|
+
return 0;
|
|
1440
|
+
}
|
|
1441
|
+
const text = await getPageText(document2, pageNumber);
|
|
1442
|
+
const searchText = caseSensitive ? query : query.toLowerCase();
|
|
1443
|
+
const textToSearch = caseSensitive ? text : text.toLowerCase();
|
|
1444
|
+
let count = 0;
|
|
1445
|
+
let startIndex = 0;
|
|
1446
|
+
while (true) {
|
|
1447
|
+
const matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
1448
|
+
if (matchIndex === -1) break;
|
|
1449
|
+
if (wholeWord) {
|
|
1450
|
+
const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : " ";
|
|
1451
|
+
const afterChar = matchIndex + query.length < textToSearch.length ? textToSearch[matchIndex + query.length] : " ";
|
|
1452
|
+
if (/\w/.test(beforeChar) || /\w/.test(afterChar)) {
|
|
1453
|
+
startIndex = matchIndex + 1;
|
|
1454
|
+
continue;
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
count++;
|
|
1458
|
+
startIndex = matchIndex + 1;
|
|
1459
|
+
}
|
|
1460
|
+
return count;
|
|
1461
|
+
}
|
|
1462
|
+
var init_text_search = __esm({
|
|
1463
|
+
"src/utils/text-search.ts"() {
|
|
1464
|
+
"use strict";
|
|
1465
|
+
}
|
|
1466
|
+
});
|
|
1467
|
+
|
|
1468
|
+
// src/utils/coordinates.ts
|
|
1469
|
+
function pdfToViewport(x, y, scale, pageHeight) {
|
|
1470
|
+
return {
|
|
1471
|
+
x: x * scale,
|
|
1472
|
+
y: (pageHeight - y) * scale
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function viewportToPDF(x, y, scale, pageHeight) {
|
|
1476
|
+
return {
|
|
1477
|
+
x: x / scale,
|
|
1478
|
+
y: pageHeight - y / scale
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
function percentToPDF(xPercent, yPercent, pageWidth, pageHeight) {
|
|
1482
|
+
return {
|
|
1483
|
+
x: xPercent / 100 * pageWidth,
|
|
1484
|
+
y: yPercent / 100 * pageHeight
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
1487
|
+
function pdfToPercent(x, y, pageWidth, pageHeight) {
|
|
1488
|
+
return {
|
|
1489
|
+
x: x / pageWidth * 100,
|
|
1490
|
+
y: y / pageHeight * 100
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
function percentToViewport(xPercent, yPercent, pageWidth, pageHeight, scale) {
|
|
1494
|
+
return {
|
|
1495
|
+
x: xPercent / 100 * pageWidth * scale,
|
|
1496
|
+
y: yPercent / 100 * pageHeight * scale
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
function viewportToPercent(x, y, pageWidth, pageHeight, scale) {
|
|
1500
|
+
return {
|
|
1501
|
+
x: x / (pageWidth * scale) * 100,
|
|
1502
|
+
y: y / (pageHeight * scale) * 100
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
function applyRotation(x, y, rotation, pageWidth, pageHeight) {
|
|
1506
|
+
const normalizedRotation = (rotation % 360 + 360) % 360;
|
|
1507
|
+
switch (normalizedRotation) {
|
|
1508
|
+
case 90:
|
|
1509
|
+
return { x: y, y: pageWidth - x };
|
|
1510
|
+
case 180:
|
|
1511
|
+
return { x: pageWidth - x, y: pageHeight - y };
|
|
1512
|
+
case 270:
|
|
1513
|
+
return { x: pageHeight - y, y: x };
|
|
1514
|
+
default:
|
|
1515
|
+
return { x, y };
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
function removeRotation(x, y, rotation, pageWidth, pageHeight) {
|
|
1519
|
+
const normalizedRotation = (rotation % 360 + 360) % 360;
|
|
1520
|
+
switch (normalizedRotation) {
|
|
1521
|
+
case 90:
|
|
1522
|
+
return { x: pageWidth - y, y: x };
|
|
1523
|
+
case 180:
|
|
1524
|
+
return { x: pageWidth - x, y: pageHeight - y };
|
|
1525
|
+
case 270:
|
|
1526
|
+
return { x: y, y: pageHeight - x };
|
|
1527
|
+
default:
|
|
1528
|
+
return { x, y };
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
function getRotatedDimensions(width, height, rotation) {
|
|
1532
|
+
const normalizedRotation = (rotation % 360 + 360) % 360;
|
|
1533
|
+
if (normalizedRotation === 90 || normalizedRotation === 270) {
|
|
1534
|
+
return { width: height, height: width };
|
|
1535
|
+
}
|
|
1536
|
+
return { width, height };
|
|
1537
|
+
}
|
|
1538
|
+
function scaleRect(rect, fromScale, toScale) {
|
|
1539
|
+
const ratio = toScale / fromScale;
|
|
1540
|
+
return {
|
|
1541
|
+
x: rect.x * ratio,
|
|
1542
|
+
y: rect.y * ratio,
|
|
1543
|
+
width: rect.width * ratio,
|
|
1544
|
+
height: rect.height * ratio
|
|
1545
|
+
};
|
|
1546
|
+
}
|
|
1547
|
+
function isPointInRect(point, rect) {
|
|
1548
|
+
return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
|
|
1549
|
+
}
|
|
1550
|
+
function doRectsIntersect(rectA, rectB) {
|
|
1551
|
+
return !(rectA.x + rectA.width < rectB.x || rectB.x + rectB.width < rectA.x || rectA.y + rectA.height < rectB.y || rectB.y + rectB.height < rectA.y);
|
|
1552
|
+
}
|
|
1553
|
+
function getRectIntersection(rectA, rectB) {
|
|
1554
|
+
const x = Math.max(rectA.x, rectB.x);
|
|
1555
|
+
const y = Math.max(rectA.y, rectB.y);
|
|
1556
|
+
const right = Math.min(rectA.x + rectA.width, rectB.x + rectB.width);
|
|
1557
|
+
const bottom = Math.min(rectA.y + rectA.height, rectB.y + rectB.height);
|
|
1558
|
+
if (right <= x || bottom <= y) {
|
|
1559
|
+
return null;
|
|
1560
|
+
}
|
|
1561
|
+
return {
|
|
1562
|
+
x,
|
|
1563
|
+
y,
|
|
1564
|
+
width: right - x,
|
|
1565
|
+
height: bottom - y
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
var init_coordinates = __esm({
|
|
1569
|
+
"src/utils/coordinates.ts"() {
|
|
1570
|
+
"use strict";
|
|
1571
|
+
}
|
|
1572
|
+
});
|
|
1573
|
+
|
|
1280
1574
|
// src/utils/index.ts
|
|
1281
1575
|
var init_utils = __esm({
|
|
1282
1576
|
"src/utils/index.ts"() {
|
|
@@ -1289,6 +1583,8 @@ var init_utils = __esm({
|
|
|
1289
1583
|
init_export_annotations();
|
|
1290
1584
|
init_student_storage();
|
|
1291
1585
|
init_agent_api();
|
|
1586
|
+
init_text_search();
|
|
1587
|
+
init_coordinates();
|
|
1292
1588
|
}
|
|
1293
1589
|
});
|
|
1294
1590
|
|
|
@@ -1384,6 +1680,12 @@ function createSearchStore(initialOverrides = {}) {
|
|
|
1384
1680
|
set({ currentResultIndex: index });
|
|
1385
1681
|
}
|
|
1386
1682
|
},
|
|
1683
|
+
setCaseSensitive: (value) => {
|
|
1684
|
+
set({ caseSensitive: value });
|
|
1685
|
+
},
|
|
1686
|
+
setWholeWord: (value) => {
|
|
1687
|
+
set({ wholeWord: value });
|
|
1688
|
+
},
|
|
1387
1689
|
toggleCaseSensitive: () => {
|
|
1388
1690
|
set((state) => ({ caseSensitive: !state.caseSensitive }));
|
|
1389
1691
|
},
|
|
@@ -7920,6 +8222,8 @@ var init_DocumentContainer = __esm({
|
|
|
7920
8222
|
nextPage,
|
|
7921
8223
|
previousPage
|
|
7922
8224
|
} = usePDFViewer();
|
|
8225
|
+
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
8226
|
+
const { viewerStore } = usePDFViewerStores();
|
|
7923
8227
|
const [currentPageObj, setCurrentPageObj] = (0, import_react35.useState)(null);
|
|
7924
8228
|
const [isLoadingPage, setIsLoadingPage] = (0, import_react35.useState)(false);
|
|
7925
8229
|
const containerRef = (0, import_react35.useRef)(null);
|
|
@@ -7985,6 +8289,11 @@ var init_DocumentContainer = __esm({
|
|
|
7985
8289
|
const page = await document2.getPage(currentPage);
|
|
7986
8290
|
if (!cancelled && document2 === documentRef.current) {
|
|
7987
8291
|
setCurrentPageObj(page);
|
|
8292
|
+
if (scrollToPageRequest && scrollToPageRequest.page === currentPage) {
|
|
8293
|
+
requestAnimationFrame(() => {
|
|
8294
|
+
viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);
|
|
8295
|
+
});
|
|
8296
|
+
}
|
|
7988
8297
|
}
|
|
7989
8298
|
} catch (error) {
|
|
7990
8299
|
if (!cancelled) {
|
|
@@ -8003,7 +8312,7 @@ var init_DocumentContainer = __esm({
|
|
|
8003
8312
|
return () => {
|
|
8004
8313
|
cancelled = true;
|
|
8005
8314
|
};
|
|
8006
|
-
}, [document2, currentPage]);
|
|
8315
|
+
}, [document2, currentPage, scrollToPageRequest, viewerStore]);
|
|
8007
8316
|
const getPageElement = (0, import_react35.useCallback)(() => {
|
|
8008
8317
|
return containerRef.current?.querySelector(`[data-page-number="${currentPage}"]`);
|
|
8009
8318
|
}, [currentPage]);
|
|
@@ -8145,6 +8454,8 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
8145
8454
|
nextPage,
|
|
8146
8455
|
previousPage
|
|
8147
8456
|
} = usePDFViewer();
|
|
8457
|
+
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
8458
|
+
const { viewerStore } = usePDFViewerStores();
|
|
8148
8459
|
const containerRef = (0, import_react36.useRef)(null);
|
|
8149
8460
|
const scrollContainerRef = (0, import_react36.useRef)(null);
|
|
8150
8461
|
const documentRef = (0, import_react36.useRef)(null);
|
|
@@ -8282,6 +8593,45 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
8282
8593
|
loadPages();
|
|
8283
8594
|
}, [document2, visiblePages, pageObjects]);
|
|
8284
8595
|
(0, import_react36.useEffect)(() => {
|
|
8596
|
+
if (!scrollToPageRequest || !scrollContainerRef.current || pageInfos.length === 0) return;
|
|
8597
|
+
const { page, requestId, behavior } = scrollToPageRequest;
|
|
8598
|
+
const pageInfo = pageInfos.find((p) => p.pageNumber === page);
|
|
8599
|
+
if (!pageInfo) {
|
|
8600
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8601
|
+
return;
|
|
8602
|
+
}
|
|
8603
|
+
const container = scrollContainerRef.current;
|
|
8604
|
+
const targetScroll = pageInfo.top - pageGap;
|
|
8605
|
+
const scrollTop = container.scrollTop;
|
|
8606
|
+
const viewportHeight = container.clientHeight;
|
|
8607
|
+
const isVisible = targetScroll >= scrollTop && pageInfo.top + pageInfo.height <= scrollTop + viewportHeight;
|
|
8608
|
+
if (isVisible) {
|
|
8609
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8610
|
+
return;
|
|
8611
|
+
}
|
|
8612
|
+
container.scrollTo({
|
|
8613
|
+
top: targetScroll,
|
|
8614
|
+
behavior
|
|
8615
|
+
});
|
|
8616
|
+
if (behavior === "instant") {
|
|
8617
|
+
requestAnimationFrame(() => {
|
|
8618
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8619
|
+
});
|
|
8620
|
+
} else {
|
|
8621
|
+
let scrollEndTimeout;
|
|
8622
|
+
const handleScrollEnd = () => {
|
|
8623
|
+
clearTimeout(scrollEndTimeout);
|
|
8624
|
+
scrollEndTimeout = setTimeout(() => {
|
|
8625
|
+
container.removeEventListener("scroll", handleScrollEnd);
|
|
8626
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8627
|
+
}, 100);
|
|
8628
|
+
};
|
|
8629
|
+
container.addEventListener("scroll", handleScrollEnd, { passive: true });
|
|
8630
|
+
handleScrollEnd();
|
|
8631
|
+
}
|
|
8632
|
+
}, [scrollToPageRequest, pageInfos, pageGap, viewerStore]);
|
|
8633
|
+
(0, import_react36.useEffect)(() => {
|
|
8634
|
+
if (scrollToPageRequest) return;
|
|
8285
8635
|
if (!scrollContainerRef.current || pageInfos.length === 0) return;
|
|
8286
8636
|
const pageInfo = pageInfos.find((p) => p.pageNumber === currentPage);
|
|
8287
8637
|
if (pageInfo) {
|
|
@@ -8296,7 +8646,7 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
8296
8646
|
});
|
|
8297
8647
|
}
|
|
8298
8648
|
}
|
|
8299
|
-
}, [currentPage, pageInfos, pageGap]);
|
|
8649
|
+
}, [currentPage, pageInfos, pageGap, scrollToPageRequest]);
|
|
8300
8650
|
const handlePinchZoom = (0, import_react36.useCallback)(
|
|
8301
8651
|
(pinchScale) => {
|
|
8302
8652
|
const newScale = Math.max(0.25, Math.min(4, baseScaleRef.current * pinchScale));
|
|
@@ -8503,6 +8853,8 @@ var init_DualPageContainer = __esm({
|
|
|
8503
8853
|
setScale,
|
|
8504
8854
|
goToPage
|
|
8505
8855
|
} = usePDFViewer();
|
|
8856
|
+
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
8857
|
+
const { viewerStore } = usePDFViewerStores();
|
|
8506
8858
|
const containerRef = (0, import_react38.useRef)(null);
|
|
8507
8859
|
const documentRef = (0, import_react38.useRef)(null);
|
|
8508
8860
|
const baseScaleRef = (0, import_react38.useRef)(scale);
|
|
@@ -8588,6 +8940,14 @@ var init_DualPageContainer = __esm({
|
|
|
8588
8940
|
if (!cancelled) {
|
|
8589
8941
|
setLeftPage(left);
|
|
8590
8942
|
setRightPage(right);
|
|
8943
|
+
if (scrollToPageRequest) {
|
|
8944
|
+
const requestedPage = scrollToPageRequest.page;
|
|
8945
|
+
if (requestedPage === spread2.left || requestedPage === spread2.right) {
|
|
8946
|
+
requestAnimationFrame(() => {
|
|
8947
|
+
viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);
|
|
8948
|
+
});
|
|
8949
|
+
}
|
|
8950
|
+
}
|
|
8591
8951
|
}
|
|
8592
8952
|
} catch (error) {
|
|
8593
8953
|
if (!cancelled) {
|
|
@@ -8603,7 +8963,7 @@ var init_DualPageContainer = __esm({
|
|
|
8603
8963
|
return () => {
|
|
8604
8964
|
cancelled = true;
|
|
8605
8965
|
};
|
|
8606
|
-
}, [document2, currentPage, getSpreadPages]);
|
|
8966
|
+
}, [document2, currentPage, getSpreadPages, scrollToPageRequest, viewerStore]);
|
|
8607
8967
|
const goToPreviousSpread = (0, import_react38.useCallback)(() => {
|
|
8608
8968
|
const spread2 = getSpreadPages(currentPage);
|
|
8609
8969
|
const leftmostPage = spread2.left || spread2.right || currentPage;
|
|
@@ -8780,6 +9140,145 @@ var init_DualPageContainer = __esm({
|
|
|
8780
9140
|
}
|
|
8781
9141
|
});
|
|
8782
9142
|
|
|
9143
|
+
// src/components/FloatingZoomControls/FloatingZoomControls.tsx
|
|
9144
|
+
var import_react39, import_jsx_runtime25, FloatingZoomControls;
|
|
9145
|
+
var init_FloatingZoomControls = __esm({
|
|
9146
|
+
"src/components/FloatingZoomControls/FloatingZoomControls.tsx"() {
|
|
9147
|
+
"use strict";
|
|
9148
|
+
import_react39 = require("react");
|
|
9149
|
+
init_hooks();
|
|
9150
|
+
init_utils();
|
|
9151
|
+
import_jsx_runtime25 = require("react/jsx-runtime");
|
|
9152
|
+
FloatingZoomControls = (0, import_react39.memo)(function FloatingZoomControls2({
|
|
9153
|
+
position = "bottom-right",
|
|
9154
|
+
className,
|
|
9155
|
+
showFitToWidth = true,
|
|
9156
|
+
showFitToPage = false,
|
|
9157
|
+
showZoomLevel = true
|
|
9158
|
+
}) {
|
|
9159
|
+
const { viewerStore } = usePDFViewerStores();
|
|
9160
|
+
const scale = useViewerStore((s) => s.scale);
|
|
9161
|
+
const document2 = useViewerStore((s) => s.document);
|
|
9162
|
+
const handleZoomIn = (0, import_react39.useCallback)(() => {
|
|
9163
|
+
const currentScale = viewerStore.getState().scale;
|
|
9164
|
+
const newScale = Math.min(4, currentScale + 0.05);
|
|
9165
|
+
viewerStore.getState().setScale(newScale);
|
|
9166
|
+
}, [viewerStore]);
|
|
9167
|
+
const handleZoomOut = (0, import_react39.useCallback)(() => {
|
|
9168
|
+
const currentScale = viewerStore.getState().scale;
|
|
9169
|
+
const newScale = Math.max(0.1, currentScale - 0.05);
|
|
9170
|
+
viewerStore.getState().setScale(newScale);
|
|
9171
|
+
}, [viewerStore]);
|
|
9172
|
+
const handleFitToWidth = (0, import_react39.useCallback)(() => {
|
|
9173
|
+
viewerStore.getState().setScale(1);
|
|
9174
|
+
}, [viewerStore]);
|
|
9175
|
+
const handleFitToPage = (0, import_react39.useCallback)(() => {
|
|
9176
|
+
viewerStore.getState().setScale(0.75);
|
|
9177
|
+
}, [viewerStore]);
|
|
9178
|
+
if (!document2) return null;
|
|
9179
|
+
const positionClasses = {
|
|
9180
|
+
"bottom-right": "bottom-4 right-4",
|
|
9181
|
+
"bottom-left": "bottom-4 left-4",
|
|
9182
|
+
"top-right": "top-4 right-4",
|
|
9183
|
+
"top-left": "top-4 left-4"
|
|
9184
|
+
};
|
|
9185
|
+
const zoomPercentage = Math.round(scale * 100);
|
|
9186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
9187
|
+
"div",
|
|
9188
|
+
{
|
|
9189
|
+
className: cn(
|
|
9190
|
+
"fixed z-50 flex items-center gap-1",
|
|
9191
|
+
"bg-white dark:bg-gray-800 rounded-lg shadow-lg",
|
|
9192
|
+
"border border-gray-200 dark:border-gray-700",
|
|
9193
|
+
"p-1",
|
|
9194
|
+
positionClasses[position],
|
|
9195
|
+
className
|
|
9196
|
+
),
|
|
9197
|
+
children: [
|
|
9198
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9199
|
+
"button",
|
|
9200
|
+
{
|
|
9201
|
+
onClick: handleZoomOut,
|
|
9202
|
+
className: cn(
|
|
9203
|
+
"w-8 h-8 flex items-center justify-center rounded",
|
|
9204
|
+
"text-gray-700 dark:text-gray-300",
|
|
9205
|
+
"hover:bg-gray-100 dark:hover:bg-gray-700",
|
|
9206
|
+
"transition-colors",
|
|
9207
|
+
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
9208
|
+
),
|
|
9209
|
+
disabled: scale <= 0.25,
|
|
9210
|
+
title: "Zoom Out",
|
|
9211
|
+
"aria-label": "Zoom Out",
|
|
9212
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20 12H4" }) })
|
|
9213
|
+
}
|
|
9214
|
+
),
|
|
9215
|
+
showZoomLevel && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "min-w-[48px] text-center text-sm font-medium text-gray-700 dark:text-gray-300", children: [
|
|
9216
|
+
zoomPercentage,
|
|
9217
|
+
"%"
|
|
9218
|
+
] }),
|
|
9219
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9220
|
+
"button",
|
|
9221
|
+
{
|
|
9222
|
+
onClick: handleZoomIn,
|
|
9223
|
+
className: cn(
|
|
9224
|
+
"w-8 h-8 flex items-center justify-center rounded",
|
|
9225
|
+
"text-gray-700 dark:text-gray-300",
|
|
9226
|
+
"hover:bg-gray-100 dark:hover:bg-gray-700",
|
|
9227
|
+
"transition-colors",
|
|
9228
|
+
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
9229
|
+
),
|
|
9230
|
+
disabled: scale >= 4,
|
|
9231
|
+
title: "Zoom In",
|
|
9232
|
+
"aria-label": "Zoom In",
|
|
9233
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) })
|
|
9234
|
+
}
|
|
9235
|
+
),
|
|
9236
|
+
(showFitToWidth || showFitToPage) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "w-px h-6 bg-gray-200 dark:bg-gray-700 mx-1" }),
|
|
9237
|
+
showFitToWidth && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9238
|
+
"button",
|
|
9239
|
+
{
|
|
9240
|
+
onClick: handleFitToWidth,
|
|
9241
|
+
className: cn(
|
|
9242
|
+
"w-8 h-8 flex items-center justify-center rounded",
|
|
9243
|
+
"text-gray-700 dark:text-gray-300",
|
|
9244
|
+
"hover:bg-gray-100 dark:hover:bg-gray-700",
|
|
9245
|
+
"transition-colors"
|
|
9246
|
+
),
|
|
9247
|
+
title: "Fit to Width",
|
|
9248
|
+
"aria-label": "Fit to Width",
|
|
9249
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" }) })
|
|
9250
|
+
}
|
|
9251
|
+
),
|
|
9252
|
+
showFitToPage && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9253
|
+
"button",
|
|
9254
|
+
{
|
|
9255
|
+
onClick: handleFitToPage,
|
|
9256
|
+
className: cn(
|
|
9257
|
+
"w-8 h-8 flex items-center justify-center rounded",
|
|
9258
|
+
"text-gray-700 dark:text-gray-300",
|
|
9259
|
+
"hover:bg-gray-100 dark:hover:bg-gray-700",
|
|
9260
|
+
"transition-colors"
|
|
9261
|
+
),
|
|
9262
|
+
title: "Fit to Page",
|
|
9263
|
+
"aria-label": "Fit to Page",
|
|
9264
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) })
|
|
9265
|
+
}
|
|
9266
|
+
)
|
|
9267
|
+
]
|
|
9268
|
+
}
|
|
9269
|
+
);
|
|
9270
|
+
});
|
|
9271
|
+
}
|
|
9272
|
+
});
|
|
9273
|
+
|
|
9274
|
+
// src/components/FloatingZoomControls/index.ts
|
|
9275
|
+
var init_FloatingZoomControls2 = __esm({
|
|
9276
|
+
"src/components/FloatingZoomControls/index.ts"() {
|
|
9277
|
+
"use strict";
|
|
9278
|
+
init_FloatingZoomControls();
|
|
9279
|
+
}
|
|
9280
|
+
});
|
|
9281
|
+
|
|
8783
9282
|
// src/components/PDFViewer/PDFViewerClient.tsx
|
|
8784
9283
|
var PDFViewerClient_exports = {};
|
|
8785
9284
|
__export(PDFViewerClient_exports, {
|
|
@@ -8796,11 +9295,30 @@ function getSrcIdentifier(src) {
|
|
|
8796
9295
|
const last = Array.from(data.slice(-4)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
8797
9296
|
return `binary:${len}:${first}:${last}`;
|
|
8798
9297
|
}
|
|
8799
|
-
|
|
9298
|
+
function mergeRects2(rects) {
|
|
9299
|
+
if (rects.length === 0) return [];
|
|
9300
|
+
const sorted = [...rects].sort((a, b) => a.y - b.y || a.x - b.x);
|
|
9301
|
+
const merged = [];
|
|
9302
|
+
let current = { ...sorted[0] };
|
|
9303
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
9304
|
+
const rect = sorted[i];
|
|
9305
|
+
if (Math.abs(rect.y - current.y) < 2 && rect.x <= current.x + current.width + 2) {
|
|
9306
|
+
const newRight = Math.max(current.x + current.width, rect.x + rect.width);
|
|
9307
|
+
current.width = newRight - current.x;
|
|
9308
|
+
current.height = Math.max(current.height, rect.height);
|
|
9309
|
+
} else {
|
|
9310
|
+
merged.push(current);
|
|
9311
|
+
current = { ...rect };
|
|
9312
|
+
}
|
|
9313
|
+
}
|
|
9314
|
+
merged.push(current);
|
|
9315
|
+
return merged;
|
|
9316
|
+
}
|
|
9317
|
+
var import_react40, import_jsx_runtime26, PDFViewerInner, PDFViewerInnerWithRef, PDFViewerClient;
|
|
8800
9318
|
var init_PDFViewerClient = __esm({
|
|
8801
9319
|
"src/components/PDFViewer/PDFViewerClient.tsx"() {
|
|
8802
9320
|
"use strict";
|
|
8803
|
-
|
|
9321
|
+
import_react40 = require("react");
|
|
8804
9322
|
init_hooks();
|
|
8805
9323
|
init_utils();
|
|
8806
9324
|
init_Toolbar2();
|
|
@@ -8809,35 +9327,63 @@ var init_PDFViewerClient = __esm({
|
|
|
8809
9327
|
init_DocumentContainer();
|
|
8810
9328
|
init_ContinuousScrollContainer();
|
|
8811
9329
|
init_DualPageContainer();
|
|
9330
|
+
init_FloatingZoomControls2();
|
|
8812
9331
|
init_utils();
|
|
8813
|
-
|
|
8814
|
-
PDFViewerInner = (0,
|
|
9332
|
+
import_jsx_runtime26 = require("react/jsx-runtime");
|
|
9333
|
+
PDFViewerInner = (0, import_react40.memo)(function PDFViewerInner2({
|
|
8815
9334
|
src,
|
|
8816
9335
|
initialPage = 1,
|
|
8817
|
-
|
|
9336
|
+
page: controlledPage,
|
|
9337
|
+
initialScale = "auto",
|
|
8818
9338
|
showToolbar = true,
|
|
8819
9339
|
showSidebar = true,
|
|
8820
9340
|
showAnnotationToolbar = false,
|
|
9341
|
+
showFloatingZoom = true,
|
|
8821
9342
|
viewMode = "single",
|
|
8822
9343
|
onDocumentLoad,
|
|
8823
9344
|
onPageChange,
|
|
8824
9345
|
onScaleChange,
|
|
9346
|
+
onZoomChange,
|
|
8825
9347
|
onError,
|
|
9348
|
+
onPageRenderStart,
|
|
9349
|
+
onPageRenderComplete,
|
|
9350
|
+
onHighlightAdded,
|
|
9351
|
+
onHighlightRemoved,
|
|
9352
|
+
onAnnotationAdded,
|
|
8826
9353
|
workerSrc,
|
|
8827
|
-
className
|
|
9354
|
+
className,
|
|
9355
|
+
loadingComponent,
|
|
9356
|
+
errorComponent,
|
|
9357
|
+
onReady
|
|
8828
9358
|
}) {
|
|
8829
|
-
const { viewerStore } = usePDFViewerStores();
|
|
8830
|
-
const mountedRef = (0,
|
|
8831
|
-
const [, setLoadState] = (0,
|
|
8832
|
-
const onDocumentLoadRef = (0,
|
|
8833
|
-
const onErrorRef = (0,
|
|
8834
|
-
const onPageChangeRef = (0,
|
|
8835
|
-
const onScaleChangeRef = (0,
|
|
9359
|
+
const { viewerStore, annotationStore, searchStore } = usePDFViewerStores();
|
|
9360
|
+
const mountedRef = (0, import_react40.useRef)(true);
|
|
9361
|
+
const [, setLoadState] = (0, import_react40.useState)("idle");
|
|
9362
|
+
const onDocumentLoadRef = (0, import_react40.useRef)(onDocumentLoad);
|
|
9363
|
+
const onErrorRef = (0, import_react40.useRef)(onError);
|
|
9364
|
+
const onPageChangeRef = (0, import_react40.useRef)(onPageChange);
|
|
9365
|
+
const onScaleChangeRef = (0, import_react40.useRef)(onScaleChange);
|
|
9366
|
+
const onZoomChangeRef = (0, import_react40.useRef)(onZoomChange);
|
|
9367
|
+
const onPageRenderStartRef = (0, import_react40.useRef)(onPageRenderStart);
|
|
9368
|
+
const onPageRenderCompleteRef = (0, import_react40.useRef)(onPageRenderComplete);
|
|
9369
|
+
const onHighlightAddedRef = (0, import_react40.useRef)(onHighlightAdded);
|
|
9370
|
+
const onHighlightRemovedRef = (0, import_react40.useRef)(onHighlightRemoved);
|
|
9371
|
+
const onAnnotationAddedRef = (0, import_react40.useRef)(onAnnotationAdded);
|
|
9372
|
+
const onReadyRef = (0, import_react40.useRef)(onReady);
|
|
8836
9373
|
onDocumentLoadRef.current = onDocumentLoad;
|
|
8837
9374
|
onErrorRef.current = onError;
|
|
8838
9375
|
onPageChangeRef.current = onPageChange;
|
|
8839
9376
|
onScaleChangeRef.current = onScaleChange;
|
|
8840
|
-
|
|
9377
|
+
onZoomChangeRef.current = onZoomChange;
|
|
9378
|
+
onPageRenderStartRef.current = onPageRenderStart;
|
|
9379
|
+
onPageRenderCompleteRef.current = onPageRenderComplete;
|
|
9380
|
+
onHighlightAddedRef.current = onHighlightAdded;
|
|
9381
|
+
onHighlightRemovedRef.current = onHighlightRemoved;
|
|
9382
|
+
onAnnotationAddedRef.current = onAnnotationAdded;
|
|
9383
|
+
onReadyRef.current = onReady;
|
|
9384
|
+
const isControlled = controlledPage !== void 0;
|
|
9385
|
+
const prevControlledPageRef = (0, import_react40.useRef)(controlledPage);
|
|
9386
|
+
const srcIdRef = (0, import_react40.useRef)(null);
|
|
8841
9387
|
const currentPage = useViewerStore((s) => s.currentPage);
|
|
8842
9388
|
const scale = useViewerStore((s) => s.scale);
|
|
8843
9389
|
const theme = useViewerStore((s) => s.theme);
|
|
@@ -8845,18 +9391,463 @@ var init_PDFViewerClient = __esm({
|
|
|
8845
9391
|
const error = useViewerStore((s) => s.error);
|
|
8846
9392
|
const sidebarOpen = useViewerStore((s) => s.sidebarOpen);
|
|
8847
9393
|
const srcId = getSrcIdentifier(src);
|
|
8848
|
-
const
|
|
9394
|
+
const handleRef = (0, import_react40.useRef)(null);
|
|
9395
|
+
(0, import_react40.useEffect)(() => {
|
|
9396
|
+
const handle = {
|
|
9397
|
+
// ==================== Text Highlighting ====================
|
|
9398
|
+
highlightText: async (text, options) => {
|
|
9399
|
+
const doc = viewerStore.getState().document;
|
|
9400
|
+
if (!doc) return [];
|
|
9401
|
+
const color = options?.color ?? "yellow";
|
|
9402
|
+
const targetPage = options?.page;
|
|
9403
|
+
const caseSensitive = options?.caseSensitive ?? false;
|
|
9404
|
+
const scrollTo = options?.scrollTo ?? true;
|
|
9405
|
+
const highlightIds = [];
|
|
9406
|
+
const searchText = caseSensitive ? text : text.toLowerCase();
|
|
9407
|
+
const pagesToSearch = targetPage ? [targetPage] : Array.from({ length: doc.numPages }, (_, i) => i + 1);
|
|
9408
|
+
for (const pageNum of pagesToSearch) {
|
|
9409
|
+
try {
|
|
9410
|
+
const page = await doc.getPage(pageNum);
|
|
9411
|
+
const textContent = await page.getTextContent();
|
|
9412
|
+
const viewport = page.getViewport({ scale: 1 });
|
|
9413
|
+
let fullText = "";
|
|
9414
|
+
const charPositions = [];
|
|
9415
|
+
for (const item of textContent.items) {
|
|
9416
|
+
if ("str" in item && item.str) {
|
|
9417
|
+
const tx = item.transform;
|
|
9418
|
+
const x = tx[4];
|
|
9419
|
+
const y = viewport.height - tx[5];
|
|
9420
|
+
const width = item.width ?? 0;
|
|
9421
|
+
const height = item.height ?? 12;
|
|
9422
|
+
const charWidth = item.str.length > 0 ? width / item.str.length : width;
|
|
9423
|
+
for (let i = 0; i < item.str.length; i++) {
|
|
9424
|
+
charPositions.push({
|
|
9425
|
+
char: item.str[i],
|
|
9426
|
+
rect: {
|
|
9427
|
+
x: x + i * charWidth,
|
|
9428
|
+
y: y - height,
|
|
9429
|
+
width: charWidth,
|
|
9430
|
+
height
|
|
9431
|
+
}
|
|
9432
|
+
});
|
|
9433
|
+
}
|
|
9434
|
+
fullText += item.str;
|
|
9435
|
+
}
|
|
9436
|
+
}
|
|
9437
|
+
const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();
|
|
9438
|
+
let startIndex = 0;
|
|
9439
|
+
while (true) {
|
|
9440
|
+
const matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
9441
|
+
if (matchIndex === -1) break;
|
|
9442
|
+
const matchRects = [];
|
|
9443
|
+
for (let i = matchIndex; i < matchIndex + text.length && i < charPositions.length; i++) {
|
|
9444
|
+
matchRects.push(charPositions[i].rect);
|
|
9445
|
+
}
|
|
9446
|
+
const mergedRects = mergeRects2(matchRects);
|
|
9447
|
+
const highlight = annotationStore.getState().addHighlight({
|
|
9448
|
+
pageNumber: pageNum,
|
|
9449
|
+
rects: mergedRects,
|
|
9450
|
+
color,
|
|
9451
|
+
text: fullText.substring(matchIndex, matchIndex + text.length)
|
|
9452
|
+
});
|
|
9453
|
+
highlightIds.push(highlight.id);
|
|
9454
|
+
startIndex = matchIndex + 1;
|
|
9455
|
+
}
|
|
9456
|
+
} catch {
|
|
9457
|
+
}
|
|
9458
|
+
}
|
|
9459
|
+
if (scrollTo && highlightIds.length > 0) {
|
|
9460
|
+
const firstHighlight = annotationStore.getState().highlights.find((h) => h.id === highlightIds[0]);
|
|
9461
|
+
if (firstHighlight) {
|
|
9462
|
+
viewerStore.getState().goToPage(firstHighlight.pageNumber);
|
|
9463
|
+
}
|
|
9464
|
+
}
|
|
9465
|
+
return highlightIds;
|
|
9466
|
+
},
|
|
9467
|
+
removeHighlight: (id) => {
|
|
9468
|
+
annotationStore.getState().removeHighlight(id);
|
|
9469
|
+
},
|
|
9470
|
+
clearHighlights: () => {
|
|
9471
|
+
const highlights = annotationStore.getState().highlights;
|
|
9472
|
+
for (const h of highlights) {
|
|
9473
|
+
annotationStore.getState().removeHighlight(h.id);
|
|
9474
|
+
}
|
|
9475
|
+
},
|
|
9476
|
+
// ==================== Annotations ====================
|
|
9477
|
+
drawRect: (options) => {
|
|
9478
|
+
const annotation = annotationStore.getState().addAnnotation({
|
|
9479
|
+
type: "shape",
|
|
9480
|
+
shapeType: "rect",
|
|
9481
|
+
pageNumber: options.page,
|
|
9482
|
+
x: options.x,
|
|
9483
|
+
y: options.y,
|
|
9484
|
+
width: options.width,
|
|
9485
|
+
height: options.height,
|
|
9486
|
+
color: options.color ?? "blue",
|
|
9487
|
+
strokeWidth: options.strokeWidth ?? 2
|
|
9488
|
+
});
|
|
9489
|
+
return annotation.id;
|
|
9490
|
+
},
|
|
9491
|
+
drawCircle: (options) => {
|
|
9492
|
+
const annotation = annotationStore.getState().addAnnotation({
|
|
9493
|
+
type: "shape",
|
|
9494
|
+
shapeType: "circle",
|
|
9495
|
+
pageNumber: options.page,
|
|
9496
|
+
x: options.x,
|
|
9497
|
+
y: options.y,
|
|
9498
|
+
width: options.radius * 2,
|
|
9499
|
+
height: options.radius * 2,
|
|
9500
|
+
color: options.color ?? "blue",
|
|
9501
|
+
strokeWidth: options.strokeWidth ?? 2
|
|
9502
|
+
});
|
|
9503
|
+
return annotation.id;
|
|
9504
|
+
},
|
|
9505
|
+
addNote: (options) => {
|
|
9506
|
+
const annotation = annotationStore.getState().addAnnotation({
|
|
9507
|
+
type: "note",
|
|
9508
|
+
pageNumber: options.page,
|
|
9509
|
+
x: options.x,
|
|
9510
|
+
y: options.y,
|
|
9511
|
+
content: options.content,
|
|
9512
|
+
color: options.color ?? "yellow"
|
|
9513
|
+
});
|
|
9514
|
+
return annotation.id;
|
|
9515
|
+
},
|
|
9516
|
+
removeAnnotation: (id) => {
|
|
9517
|
+
annotationStore.getState().removeAnnotation(id);
|
|
9518
|
+
},
|
|
9519
|
+
clearAnnotations: () => {
|
|
9520
|
+
const annotations = annotationStore.getState().annotations;
|
|
9521
|
+
for (const a of annotations) {
|
|
9522
|
+
annotationStore.getState().removeAnnotation(a.id);
|
|
9523
|
+
}
|
|
9524
|
+
},
|
|
9525
|
+
// ==================== Navigation ====================
|
|
9526
|
+
goToPage: async (page, options) => {
|
|
9527
|
+
const behavior = options?.behavior ?? "smooth";
|
|
9528
|
+
await viewerStore.getState().requestScrollToPage(page, behavior);
|
|
9529
|
+
},
|
|
9530
|
+
nextPage: () => {
|
|
9531
|
+
viewerStore.getState().nextPage();
|
|
9532
|
+
},
|
|
9533
|
+
previousPage: () => {
|
|
9534
|
+
viewerStore.getState().previousPage();
|
|
9535
|
+
},
|
|
9536
|
+
getCurrentPage: () => {
|
|
9537
|
+
return viewerStore.getState().currentPage;
|
|
9538
|
+
},
|
|
9539
|
+
getNumPages: () => {
|
|
9540
|
+
return viewerStore.getState().numPages;
|
|
9541
|
+
},
|
|
9542
|
+
// ==================== Zoom ====================
|
|
9543
|
+
setZoom: (scale2) => {
|
|
9544
|
+
viewerStore.getState().setScale(scale2);
|
|
9545
|
+
},
|
|
9546
|
+
getZoom: () => {
|
|
9547
|
+
return viewerStore.getState().scale;
|
|
9548
|
+
},
|
|
9549
|
+
zoomIn: () => {
|
|
9550
|
+
viewerStore.getState().zoomIn();
|
|
9551
|
+
},
|
|
9552
|
+
zoomOut: () => {
|
|
9553
|
+
viewerStore.getState().zoomOut();
|
|
9554
|
+
},
|
|
9555
|
+
// ==================== Search ====================
|
|
9556
|
+
search: async (query, options) => {
|
|
9557
|
+
const doc = viewerStore.getState().document;
|
|
9558
|
+
if (!doc) return [];
|
|
9559
|
+
searchStore.getState().setQuery(query);
|
|
9560
|
+
if (options?.caseSensitive !== void 0) {
|
|
9561
|
+
searchStore.getState().setCaseSensitive(options.caseSensitive);
|
|
9562
|
+
}
|
|
9563
|
+
if (options?.wholeWord !== void 0) {
|
|
9564
|
+
searchStore.getState().setWholeWord(options.wholeWord);
|
|
9565
|
+
}
|
|
9566
|
+
await searchStore.getState().search(doc);
|
|
9567
|
+
return searchStore.getState().results;
|
|
9568
|
+
},
|
|
9569
|
+
nextSearchResult: () => {
|
|
9570
|
+
searchStore.getState().nextResult();
|
|
9571
|
+
const results = searchStore.getState().results;
|
|
9572
|
+
const index = searchStore.getState().currentResultIndex;
|
|
9573
|
+
if (results[index]) {
|
|
9574
|
+
viewerStore.getState().goToPage(results[index].pageNumber);
|
|
9575
|
+
}
|
|
9576
|
+
},
|
|
9577
|
+
previousSearchResult: () => {
|
|
9578
|
+
searchStore.getState().previousResult();
|
|
9579
|
+
const results = searchStore.getState().results;
|
|
9580
|
+
const index = searchStore.getState().currentResultIndex;
|
|
9581
|
+
if (results[index]) {
|
|
9582
|
+
viewerStore.getState().goToPage(results[index].pageNumber);
|
|
9583
|
+
}
|
|
9584
|
+
},
|
|
9585
|
+
clearSearch: () => {
|
|
9586
|
+
searchStore.getState().clearSearch();
|
|
9587
|
+
},
|
|
9588
|
+
// ==================== Combined Search & Highlight ====================
|
|
9589
|
+
searchAndHighlight: async (query, options) => {
|
|
9590
|
+
const doc = viewerStore.getState().document;
|
|
9591
|
+
if (!doc) {
|
|
9592
|
+
return { matchCount: 0, highlightIds: [], matches: [] };
|
|
9593
|
+
}
|
|
9594
|
+
const color = options?.color ?? "yellow";
|
|
9595
|
+
const caseSensitive = options?.caseSensitive ?? false;
|
|
9596
|
+
const wholeWord = options?.wholeWord ?? false;
|
|
9597
|
+
const scrollToFirst = options?.scrollToFirst ?? true;
|
|
9598
|
+
const clearPrevious = options?.clearPrevious ?? true;
|
|
9599
|
+
if (clearPrevious) {
|
|
9600
|
+
const existingHighlights = annotationStore.getState().highlights;
|
|
9601
|
+
for (const h of existingHighlights) {
|
|
9602
|
+
if (h.source === "search") {
|
|
9603
|
+
annotationStore.getState().removeHighlight(h.id);
|
|
9604
|
+
}
|
|
9605
|
+
}
|
|
9606
|
+
}
|
|
9607
|
+
let pagesToSearch;
|
|
9608
|
+
if (options?.pageRange) {
|
|
9609
|
+
if (Array.isArray(options.pageRange)) {
|
|
9610
|
+
pagesToSearch = options.pageRange;
|
|
9611
|
+
} else {
|
|
9612
|
+
const { start, end } = options.pageRange;
|
|
9613
|
+
pagesToSearch = Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
|
9614
|
+
}
|
|
9615
|
+
} else {
|
|
9616
|
+
pagesToSearch = Array.from({ length: doc.numPages }, (_, i) => i + 1);
|
|
9617
|
+
}
|
|
9618
|
+
const result = {
|
|
9619
|
+
matchCount: 0,
|
|
9620
|
+
highlightIds: [],
|
|
9621
|
+
matches: []
|
|
9622
|
+
};
|
|
9623
|
+
const searchText = caseSensitive ? query : query.toLowerCase();
|
|
9624
|
+
for (const pageNum of pagesToSearch) {
|
|
9625
|
+
if (pageNum < 1 || pageNum > doc.numPages) continue;
|
|
9626
|
+
try {
|
|
9627
|
+
const page = await doc.getPage(pageNum);
|
|
9628
|
+
const textContent = await page.getTextContent();
|
|
9629
|
+
const viewport = page.getViewport({ scale: 1 });
|
|
9630
|
+
let fullText = "";
|
|
9631
|
+
const charPositions = [];
|
|
9632
|
+
for (const item of textContent.items) {
|
|
9633
|
+
if ("str" in item && item.str) {
|
|
9634
|
+
const tx = item.transform;
|
|
9635
|
+
const x = tx[4];
|
|
9636
|
+
const y = viewport.height - tx[5];
|
|
9637
|
+
const width = item.width ?? 0;
|
|
9638
|
+
const height = item.height ?? 12;
|
|
9639
|
+
const charWidth = item.str.length > 0 ? width / item.str.length : width;
|
|
9640
|
+
for (let i = 0; i < item.str.length; i++) {
|
|
9641
|
+
charPositions.push({
|
|
9642
|
+
char: item.str[i],
|
|
9643
|
+
rect: {
|
|
9644
|
+
x: x + i * charWidth,
|
|
9645
|
+
y: y - height,
|
|
9646
|
+
width: charWidth,
|
|
9647
|
+
height
|
|
9648
|
+
}
|
|
9649
|
+
});
|
|
9650
|
+
}
|
|
9651
|
+
fullText += item.str;
|
|
9652
|
+
}
|
|
9653
|
+
}
|
|
9654
|
+
const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();
|
|
9655
|
+
let startIndex = 0;
|
|
9656
|
+
while (true) {
|
|
9657
|
+
let matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
9658
|
+
if (matchIndex === -1) break;
|
|
9659
|
+
if (wholeWord) {
|
|
9660
|
+
const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : " ";
|
|
9661
|
+
const afterChar = matchIndex + query.length < textToSearch.length ? textToSearch[matchIndex + query.length] : " ";
|
|
9662
|
+
if (/\w/.test(beforeChar) || /\w/.test(afterChar)) {
|
|
9663
|
+
startIndex = matchIndex + 1;
|
|
9664
|
+
continue;
|
|
9665
|
+
}
|
|
9666
|
+
}
|
|
9667
|
+
const matchRects = [];
|
|
9668
|
+
for (let i = matchIndex; i < matchIndex + query.length && i < charPositions.length; i++) {
|
|
9669
|
+
matchRects.push(charPositions[i].rect);
|
|
9670
|
+
}
|
|
9671
|
+
const mergedRects = mergeRects2(matchRects);
|
|
9672
|
+
const highlight = annotationStore.getState().addHighlight({
|
|
9673
|
+
pageNumber: pageNum,
|
|
9674
|
+
rects: mergedRects,
|
|
9675
|
+
color,
|
|
9676
|
+
text: fullText.substring(matchIndex, matchIndex + query.length),
|
|
9677
|
+
source: "search"
|
|
9678
|
+
});
|
|
9679
|
+
result.matchCount++;
|
|
9680
|
+
result.highlightIds.push(highlight.id);
|
|
9681
|
+
result.matches.push({
|
|
9682
|
+
pageNumber: pageNum,
|
|
9683
|
+
text: fullText.substring(matchIndex, matchIndex + query.length),
|
|
9684
|
+
highlightId: highlight.id,
|
|
9685
|
+
rects: mergedRects
|
|
9686
|
+
});
|
|
9687
|
+
startIndex = matchIndex + 1;
|
|
9688
|
+
}
|
|
9689
|
+
} catch {
|
|
9690
|
+
}
|
|
9691
|
+
}
|
|
9692
|
+
if (scrollToFirst && result.matches.length > 0) {
|
|
9693
|
+
const firstMatch = result.matches[0];
|
|
9694
|
+
await viewerStore.getState().requestScrollToPage(firstMatch.pageNumber, "smooth");
|
|
9695
|
+
}
|
|
9696
|
+
return result;
|
|
9697
|
+
},
|
|
9698
|
+
// ==================== Agent Tools ====================
|
|
9699
|
+
agentTools: {
|
|
9700
|
+
navigateToPage: async (page) => {
|
|
9701
|
+
try {
|
|
9702
|
+
const { currentPage: currentPage2, numPages } = viewerStore.getState();
|
|
9703
|
+
if (numPages === 0) {
|
|
9704
|
+
return {
|
|
9705
|
+
success: false,
|
|
9706
|
+
error: { code: "NO_DOCUMENT", message: "No document is loaded" }
|
|
9707
|
+
};
|
|
9708
|
+
}
|
|
9709
|
+
if (page < 1 || page > numPages) {
|
|
9710
|
+
return {
|
|
9711
|
+
success: false,
|
|
9712
|
+
error: { code: "INVALID_PAGE", message: `Page ${page} is out of range (1-${numPages})` }
|
|
9713
|
+
};
|
|
9714
|
+
}
|
|
9715
|
+
const previousPage = currentPage2;
|
|
9716
|
+
await viewerStore.getState().requestScrollToPage(page, "smooth");
|
|
9717
|
+
return {
|
|
9718
|
+
success: true,
|
|
9719
|
+
data: { previousPage, currentPage: page }
|
|
9720
|
+
};
|
|
9721
|
+
} catch (err) {
|
|
9722
|
+
return {
|
|
9723
|
+
success: false,
|
|
9724
|
+
error: { code: "NAVIGATION_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9725
|
+
};
|
|
9726
|
+
}
|
|
9727
|
+
},
|
|
9728
|
+
highlightText: async (text, options) => {
|
|
9729
|
+
try {
|
|
9730
|
+
const highlightIds = await handle.highlightText(text, options);
|
|
9731
|
+
return {
|
|
9732
|
+
success: true,
|
|
9733
|
+
data: { matchCount: highlightIds.length, highlightIds }
|
|
9734
|
+
};
|
|
9735
|
+
} catch (err) {
|
|
9736
|
+
return {
|
|
9737
|
+
success: false,
|
|
9738
|
+
error: { code: "HIGHLIGHT_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9739
|
+
};
|
|
9740
|
+
}
|
|
9741
|
+
},
|
|
9742
|
+
getPageContent: async (page) => {
|
|
9743
|
+
try {
|
|
9744
|
+
const doc = viewerStore.getState().document;
|
|
9745
|
+
if (!doc) {
|
|
9746
|
+
return {
|
|
9747
|
+
success: false,
|
|
9748
|
+
error: { code: "NO_DOCUMENT", message: "No document is loaded" }
|
|
9749
|
+
};
|
|
9750
|
+
}
|
|
9751
|
+
if (page < 1 || page > doc.numPages) {
|
|
9752
|
+
return {
|
|
9753
|
+
success: false,
|
|
9754
|
+
error: { code: "INVALID_PAGE", message: `Page ${page} is out of range (1-${doc.numPages})` }
|
|
9755
|
+
};
|
|
9756
|
+
}
|
|
9757
|
+
const pageObj = await doc.getPage(page);
|
|
9758
|
+
const textContent = await pageObj.getTextContent();
|
|
9759
|
+
const text = textContent.items.filter((item) => "str" in item).map((item) => item.str).join("");
|
|
9760
|
+
return {
|
|
9761
|
+
success: true,
|
|
9762
|
+
data: { text }
|
|
9763
|
+
};
|
|
9764
|
+
} catch (err) {
|
|
9765
|
+
return {
|
|
9766
|
+
success: false,
|
|
9767
|
+
error: { code: "CONTENT_FETCH_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9768
|
+
};
|
|
9769
|
+
}
|
|
9770
|
+
},
|
|
9771
|
+
clearAllVisuals: async () => {
|
|
9772
|
+
try {
|
|
9773
|
+
const highlights = annotationStore.getState().highlights;
|
|
9774
|
+
for (const h of highlights) {
|
|
9775
|
+
annotationStore.getState().removeHighlight(h.id);
|
|
9776
|
+
}
|
|
9777
|
+
const annotations = annotationStore.getState().annotations;
|
|
9778
|
+
for (const a of annotations) {
|
|
9779
|
+
annotationStore.getState().removeAnnotation(a.id);
|
|
9780
|
+
}
|
|
9781
|
+
return { success: true };
|
|
9782
|
+
} catch (err) {
|
|
9783
|
+
return {
|
|
9784
|
+
success: false,
|
|
9785
|
+
error: { code: "CLEAR_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9786
|
+
};
|
|
9787
|
+
}
|
|
9788
|
+
}
|
|
9789
|
+
},
|
|
9790
|
+
// ==================== Coordinate Helpers ====================
|
|
9791
|
+
coordinates: {
|
|
9792
|
+
getPageDimensions: (page) => {
|
|
9793
|
+
const doc = viewerStore.getState().document;
|
|
9794
|
+
if (!doc || page < 1 || page > doc.numPages) {
|
|
9795
|
+
return null;
|
|
9796
|
+
}
|
|
9797
|
+
try {
|
|
9798
|
+
return {
|
|
9799
|
+
width: 612,
|
|
9800
|
+
// Default US Letter width
|
|
9801
|
+
height: 792,
|
|
9802
|
+
// Default US Letter height
|
|
9803
|
+
rotation: viewerStore.getState().rotation
|
|
9804
|
+
};
|
|
9805
|
+
} catch {
|
|
9806
|
+
return null;
|
|
9807
|
+
}
|
|
9808
|
+
},
|
|
9809
|
+
percentToPixels: (xPercent, yPercent, page) => {
|
|
9810
|
+
const dimensions = handle.coordinates.getPageDimensions(page);
|
|
9811
|
+
if (!dimensions) return null;
|
|
9812
|
+
const scale2 = viewerStore.getState().scale;
|
|
9813
|
+
return {
|
|
9814
|
+
x: xPercent / 100 * dimensions.width * scale2,
|
|
9815
|
+
y: yPercent / 100 * dimensions.height * scale2
|
|
9816
|
+
};
|
|
9817
|
+
},
|
|
9818
|
+
pixelsToPercent: (x, y, page) => {
|
|
9819
|
+
const dimensions = handle.coordinates.getPageDimensions(page);
|
|
9820
|
+
if (!dimensions) return null;
|
|
9821
|
+
const scale2 = viewerStore.getState().scale;
|
|
9822
|
+
return {
|
|
9823
|
+
x: x / (dimensions.width * scale2) * 100,
|
|
9824
|
+
y: y / (dimensions.height * scale2) * 100
|
|
9825
|
+
};
|
|
9826
|
+
}
|
|
9827
|
+
},
|
|
9828
|
+
// ==================== Document ====================
|
|
9829
|
+
getDocument: () => {
|
|
9830
|
+
return viewerStore.getState().document;
|
|
9831
|
+
},
|
|
9832
|
+
isLoaded: () => {
|
|
9833
|
+
return viewerStore.getState().document !== null;
|
|
9834
|
+
}
|
|
9835
|
+
};
|
|
9836
|
+
handleRef.current = handle;
|
|
9837
|
+
onReadyRef.current?.(handle);
|
|
9838
|
+
}, [viewerStore, annotationStore, searchStore]);
|
|
9839
|
+
const handleRetry = (0, import_react40.useCallback)(() => {
|
|
8849
9840
|
srcIdRef.current = null;
|
|
8850
9841
|
viewerStore.getState().setError(null);
|
|
8851
9842
|
setLoadState("idle");
|
|
8852
9843
|
}, [viewerStore]);
|
|
8853
|
-
(0,
|
|
9844
|
+
(0, import_react40.useEffect)(() => {
|
|
8854
9845
|
mountedRef.current = true;
|
|
8855
9846
|
return () => {
|
|
8856
9847
|
mountedRef.current = false;
|
|
8857
9848
|
};
|
|
8858
9849
|
}, []);
|
|
8859
|
-
(0,
|
|
9850
|
+
(0, import_react40.useEffect)(() => {
|
|
8860
9851
|
if (srcIdRef.current === srcId && viewerStore.getState().document) {
|
|
8861
9852
|
return;
|
|
8862
9853
|
}
|
|
@@ -8883,8 +9874,12 @@ var init_PDFViewerClient = __esm({
|
|
|
8883
9874
|
if (initialPage !== 1) {
|
|
8884
9875
|
viewerStore.getState().goToPage(initialPage);
|
|
8885
9876
|
}
|
|
8886
|
-
if (typeof initialScale === "number"
|
|
9877
|
+
if (typeof initialScale === "number") {
|
|
8887
9878
|
viewerStore.getState().setScale(initialScale);
|
|
9879
|
+
} else if (initialScale === "auto" || initialScale === "page-width") {
|
|
9880
|
+
viewerStore.getState().setScale(1);
|
|
9881
|
+
} else if (initialScale === "page-fit") {
|
|
9882
|
+
viewerStore.getState().setScale(0.75);
|
|
8888
9883
|
}
|
|
8889
9884
|
onDocumentLoadRef.current?.({ document: document2, numPages });
|
|
8890
9885
|
} else {
|
|
@@ -8904,23 +9899,49 @@ var init_PDFViewerClient = __esm({
|
|
|
8904
9899
|
return () => {
|
|
8905
9900
|
};
|
|
8906
9901
|
}, [srcId, src, workerSrc, initialPage, initialScale, viewerStore]);
|
|
8907
|
-
const prevPageRef = (0,
|
|
8908
|
-
(0,
|
|
9902
|
+
const prevPageRef = (0, import_react40.useRef)(currentPage);
|
|
9903
|
+
(0, import_react40.useEffect)(() => {
|
|
8909
9904
|
if (prevPageRef.current !== currentPage) {
|
|
8910
9905
|
prevPageRef.current = currentPage;
|
|
8911
9906
|
onPageChangeRef.current?.(currentPage);
|
|
8912
9907
|
}
|
|
8913
9908
|
}, [currentPage]);
|
|
8914
|
-
const prevScaleRef = (0,
|
|
8915
|
-
(0,
|
|
9909
|
+
const prevScaleRef = (0, import_react40.useRef)(scale);
|
|
9910
|
+
(0, import_react40.useEffect)(() => {
|
|
8916
9911
|
if (prevScaleRef.current !== scale) {
|
|
8917
9912
|
prevScaleRef.current = scale;
|
|
8918
9913
|
onScaleChangeRef.current?.(scale);
|
|
9914
|
+
onZoomChangeRef.current?.(scale);
|
|
8919
9915
|
}
|
|
8920
9916
|
}, [scale]);
|
|
9917
|
+
(0, import_react40.useEffect)(() => {
|
|
9918
|
+
if (!isControlled || controlledPage === void 0) return;
|
|
9919
|
+
if (prevControlledPageRef.current === controlledPage) return;
|
|
9920
|
+
prevControlledPageRef.current = controlledPage;
|
|
9921
|
+
const { numPages, currentPage: currentPage2 } = viewerStore.getState();
|
|
9922
|
+
if (numPages > 0 && controlledPage !== currentPage2) {
|
|
9923
|
+
viewerStore.getState().requestScrollToPage(controlledPage, "smooth");
|
|
9924
|
+
}
|
|
9925
|
+
}, [controlledPage, isControlled, viewerStore]);
|
|
8921
9926
|
const themeClass = theme === "dark" ? "dark" : "";
|
|
8922
9927
|
if (error) {
|
|
8923
|
-
|
|
9928
|
+
if (errorComponent) {
|
|
9929
|
+
const errorContent = typeof errorComponent === "function" ? errorComponent(error, handleRetry) : errorComponent;
|
|
9930
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
9931
|
+
"div",
|
|
9932
|
+
{
|
|
9933
|
+
className: cn(
|
|
9934
|
+
"pdf-viewer pdf-viewer-error",
|
|
9935
|
+
"flex flex-col h-full",
|
|
9936
|
+
"bg-white dark:bg-gray-900",
|
|
9937
|
+
themeClass,
|
|
9938
|
+
className
|
|
9939
|
+
),
|
|
9940
|
+
children: errorContent
|
|
9941
|
+
}
|
|
9942
|
+
);
|
|
9943
|
+
}
|
|
9944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
8924
9945
|
"div",
|
|
8925
9946
|
{
|
|
8926
9947
|
className: cn(
|
|
@@ -8930,10 +9951,10 @@ var init_PDFViewerClient = __esm({
|
|
|
8930
9951
|
themeClass,
|
|
8931
9952
|
className
|
|
8932
9953
|
),
|
|
8933
|
-
children: /* @__PURE__ */ (0,
|
|
8934
|
-
/* @__PURE__ */ (0,
|
|
8935
|
-
/* @__PURE__ */ (0,
|
|
8936
|
-
/* @__PURE__ */ (0,
|
|
9954
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "text-center p-8", children: [
|
|
9955
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "text-red-500 text-lg font-semibold mb-2", children: "Failed to load PDF" }),
|
|
9956
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "text-gray-500 text-sm", children: error.message }),
|
|
9957
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
8937
9958
|
"button",
|
|
8938
9959
|
{
|
|
8939
9960
|
onClick: handleRetry,
|
|
@@ -8948,68 +9969,85 @@ var init_PDFViewerClient = __esm({
|
|
|
8948
9969
|
const renderContainer = () => {
|
|
8949
9970
|
switch (viewMode) {
|
|
8950
9971
|
case "continuous":
|
|
8951
|
-
return /* @__PURE__ */ (0,
|
|
9972
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ContinuousScrollContainer, {});
|
|
8952
9973
|
case "dual":
|
|
8953
|
-
return /* @__PURE__ */ (0,
|
|
9974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DualPageContainer, {});
|
|
8954
9975
|
case "single":
|
|
8955
9976
|
default:
|
|
8956
|
-
return /* @__PURE__ */ (0,
|
|
9977
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DocumentContainer, {});
|
|
8957
9978
|
}
|
|
8958
9979
|
};
|
|
8959
|
-
return /* @__PURE__ */ (0,
|
|
9980
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
8960
9981
|
"div",
|
|
8961
9982
|
{
|
|
8962
9983
|
className: cn(
|
|
8963
9984
|
"pdf-viewer",
|
|
8964
|
-
"flex flex-col h-full",
|
|
9985
|
+
"flex flex-col h-full relative",
|
|
8965
9986
|
"bg-white dark:bg-gray-900",
|
|
8966
9987
|
"text-gray-900 dark:text-gray-100",
|
|
8967
9988
|
themeClass,
|
|
8968
9989
|
className
|
|
8969
9990
|
),
|
|
8970
9991
|
children: [
|
|
8971
|
-
showToolbar && /* @__PURE__ */ (0,
|
|
8972
|
-
showAnnotationToolbar && /* @__PURE__ */ (0,
|
|
8973
|
-
/* @__PURE__ */ (0,
|
|
8974
|
-
showSidebar && sidebarOpen && /* @__PURE__ */ (0,
|
|
9992
|
+
showToolbar && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Toolbar, {}),
|
|
9993
|
+
showAnnotationToolbar && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AnnotationToolbar, {}),
|
|
9994
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-1 overflow-hidden", children: [
|
|
9995
|
+
showSidebar && sidebarOpen && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Sidebar, {}),
|
|
8975
9996
|
renderContainer()
|
|
8976
9997
|
] }),
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
/* @__PURE__ */ (0,
|
|
9998
|
+
showFloatingZoom && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(FloatingZoomControls, { position: "bottom-right" }),
|
|
9999
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-900/80", children: loadingComponent ?? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col items-center", children: [
|
|
10000
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" }),
|
|
10001
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "mt-2 text-sm text-gray-500", children: "Loading PDF..." })
|
|
8980
10002
|
] }) })
|
|
8981
10003
|
]
|
|
8982
10004
|
}
|
|
8983
10005
|
);
|
|
8984
10006
|
});
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
{
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
|
|
8994
|
-
|
|
10007
|
+
PDFViewerInnerWithRef = (0, import_react40.forwardRef)(
|
|
10008
|
+
function PDFViewerInnerWithRef2(props, ref) {
|
|
10009
|
+
const handleRef = (0, import_react40.useRef)(null);
|
|
10010
|
+
const handleReady = (0, import_react40.useCallback)((handle) => {
|
|
10011
|
+
handleRef.current = handle;
|
|
10012
|
+
if (typeof ref === "function") {
|
|
10013
|
+
ref(handle);
|
|
10014
|
+
} else if (ref) {
|
|
10015
|
+
ref.current = handle;
|
|
10016
|
+
}
|
|
10017
|
+
}, [ref]);
|
|
10018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PDFViewerInner, { ...props, onReady: handleReady });
|
|
10019
|
+
}
|
|
10020
|
+
);
|
|
10021
|
+
PDFViewerClient = (0, import_react40.memo)(
|
|
10022
|
+
(0, import_react40.forwardRef)(function PDFViewerClient2(props, ref) {
|
|
10023
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10024
|
+
PDFViewerProvider,
|
|
10025
|
+
{
|
|
10026
|
+
theme: props.theme,
|
|
10027
|
+
defaultSidebarPanel: props.defaultSidebarPanel,
|
|
10028
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PDFViewerInnerWithRef, { ref, ...props })
|
|
10029
|
+
}
|
|
10030
|
+
);
|
|
10031
|
+
})
|
|
10032
|
+
);
|
|
8995
10033
|
}
|
|
8996
10034
|
});
|
|
8997
10035
|
|
|
8998
10036
|
// src/components/PDFViewer/PDFViewer.tsx
|
|
8999
|
-
var
|
|
10037
|
+
var import_react41, import_jsx_runtime27, PDFViewerClient3, PDFViewerLoading, PDFViewer;
|
|
9000
10038
|
var init_PDFViewer = __esm({
|
|
9001
10039
|
"src/components/PDFViewer/PDFViewer.tsx"() {
|
|
9002
10040
|
"use strict";
|
|
9003
|
-
|
|
10041
|
+
import_react41 = require("react");
|
|
9004
10042
|
init_utils();
|
|
9005
|
-
|
|
9006
|
-
PDFViewerClient3 = (0,
|
|
10043
|
+
import_jsx_runtime27 = require("react/jsx-runtime");
|
|
10044
|
+
PDFViewerClient3 = (0, import_react41.lazy)(
|
|
9007
10045
|
() => Promise.resolve().then(() => (init_PDFViewerClient(), PDFViewerClient_exports)).then((mod) => ({ default: mod.PDFViewerClient }))
|
|
9008
10046
|
);
|
|
9009
|
-
PDFViewerLoading = (0,
|
|
10047
|
+
PDFViewerLoading = (0, import_react41.memo)(function PDFViewerLoading2({
|
|
9010
10048
|
className
|
|
9011
10049
|
}) {
|
|
9012
|
-
return /* @__PURE__ */ (0,
|
|
10050
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
9013
10051
|
"div",
|
|
9014
10052
|
{
|
|
9015
10053
|
className: cn(
|
|
@@ -9018,18 +10056,18 @@ var init_PDFViewer = __esm({
|
|
|
9018
10056
|
"bg-white dark:bg-gray-900",
|
|
9019
10057
|
className
|
|
9020
10058
|
),
|
|
9021
|
-
children: /* @__PURE__ */ (0,
|
|
9022
|
-
/* @__PURE__ */ (0,
|
|
9023
|
-
/* @__PURE__ */ (0,
|
|
10059
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col items-center", children: [
|
|
10060
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" }),
|
|
10061
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "mt-2 text-sm text-gray-500", children: "Loading PDF viewer..." })
|
|
9024
10062
|
] }) })
|
|
9025
10063
|
}
|
|
9026
10064
|
);
|
|
9027
10065
|
});
|
|
9028
|
-
PDFViewer = (0,
|
|
10066
|
+
PDFViewer = (0, import_react41.memo)(function PDFViewer2(props) {
|
|
9029
10067
|
if (typeof window === "undefined") {
|
|
9030
|
-
return /* @__PURE__ */ (0,
|
|
10068
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PDFViewerLoading, { className: props.className });
|
|
9031
10069
|
}
|
|
9032
|
-
return /* @__PURE__ */ (0,
|
|
10070
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react41.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PDFViewerLoading, { className: props.className }), children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PDFViewerClient3, { ...props }) });
|
|
9033
10071
|
});
|
|
9034
10072
|
}
|
|
9035
10073
|
});
|
|
@@ -9060,6 +10098,7 @@ __export(index_exports, {
|
|
|
9060
10098
|
DocumentContainer: () => DocumentContainer,
|
|
9061
10099
|
DrawingCanvas: () => DrawingCanvas,
|
|
9062
10100
|
DualPageContainer: () => DualPageContainer,
|
|
10101
|
+
FloatingZoomControls: () => FloatingZoomControls,
|
|
9063
10102
|
FocusRegionLayer: () => FocusRegionLayer,
|
|
9064
10103
|
HighlightLayer: () => HighlightLayer,
|
|
9065
10104
|
HighlightPopover: () => HighlightPopover,
|
|
@@ -9070,6 +10109,7 @@ __export(index_exports, {
|
|
|
9070
10109
|
OutlinePanel: () => OutlinePanel,
|
|
9071
10110
|
PDFErrorBoundary: () => PDFErrorBoundary,
|
|
9072
10111
|
PDFPage: () => PDFPage,
|
|
10112
|
+
PDFThumbnailNav: () => PDFThumbnailNav,
|
|
9073
10113
|
PDFViewer: () => PDFViewer,
|
|
9074
10114
|
PDFViewerClient: () => PDFViewerClient,
|
|
9075
10115
|
PDFViewerContext: () => PDFViewerContext,
|
|
@@ -9088,9 +10128,11 @@ __export(index_exports, {
|
|
|
9088
10128
|
ThumbnailPanel: () => ThumbnailPanel,
|
|
9089
10129
|
Toolbar: () => Toolbar,
|
|
9090
10130
|
VirtualizedDocumentContainer: () => VirtualizedDocumentContainer,
|
|
10131
|
+
applyRotation: () => applyRotation,
|
|
9091
10132
|
clearHighlights: () => clearHighlights,
|
|
9092
10133
|
clearStudentData: () => clearStudentData,
|
|
9093
10134
|
cn: () => cn,
|
|
10135
|
+
countTextOnPage: () => countTextOnPage,
|
|
9094
10136
|
createAgentAPI: () => createAgentAPI,
|
|
9095
10137
|
createAgentStore: () => createAgentStore,
|
|
9096
10138
|
createAnnotationStore: () => createAnnotationStore,
|
|
@@ -9099,6 +10141,7 @@ __export(index_exports, {
|
|
|
9099
10141
|
createSearchStore: () => createSearchStore,
|
|
9100
10142
|
createStudentStore: () => createStudentStore,
|
|
9101
10143
|
createViewerStore: () => createViewerStore,
|
|
10144
|
+
doRectsIntersect: () => doRectsIntersect,
|
|
9102
10145
|
downloadAnnotationsAsJSON: () => downloadAnnotationsAsJSON,
|
|
9103
10146
|
downloadAnnotationsAsMarkdown: () => downloadAnnotationsAsMarkdown,
|
|
9104
10147
|
downloadFile: () => downloadFile,
|
|
@@ -9106,25 +10149,39 @@ __export(index_exports, {
|
|
|
9106
10149
|
exportAnnotationsAsMarkdown: () => exportAnnotationsAsMarkdown,
|
|
9107
10150
|
exportHighlightsAsJSON: () => exportHighlightsAsJSON,
|
|
9108
10151
|
exportHighlightsAsMarkdown: () => exportHighlightsAsMarkdown,
|
|
10152
|
+
extractPageText: () => extractPageText,
|
|
10153
|
+
findTextInDocument: () => findTextInDocument,
|
|
10154
|
+
findTextOnPage: () => findTextOnPage,
|
|
9109
10155
|
generateDocumentId: () => generateDocumentId,
|
|
9110
10156
|
getAllDocumentIds: () => getAllDocumentIds,
|
|
9111
10157
|
getAllStudentDataDocumentIds: () => getAllStudentDataDocumentIds,
|
|
9112
10158
|
getMetadata: () => getMetadata,
|
|
9113
10159
|
getOutline: () => getOutline,
|
|
9114
10160
|
getPage: () => getPage,
|
|
10161
|
+
getPageText: () => getPageText,
|
|
9115
10162
|
getPageTextContent: () => getPageTextContent,
|
|
9116
10163
|
getPluginManager: () => getPluginManager,
|
|
10164
|
+
getRectIntersection: () => getRectIntersection,
|
|
10165
|
+
getRotatedDimensions: () => getRotatedDimensions,
|
|
9117
10166
|
getStorageStats: () => getStorageStats,
|
|
9118
10167
|
importHighlightsFromJSON: () => importHighlightsFromJSON,
|
|
9119
10168
|
initializePDFJS: () => initializePDFJS,
|
|
9120
10169
|
isPDFJSInitialized: () => isPDFJSInitialized,
|
|
10170
|
+
isPointInRect: () => isPointInRect,
|
|
9121
10171
|
loadDocument: () => loadDocument,
|
|
9122
10172
|
loadHighlights: () => loadHighlights,
|
|
9123
10173
|
loadStudentData: () => loadStudentData,
|
|
10174
|
+
mergeAdjacentRects: () => mergeAdjacentRects,
|
|
10175
|
+
pdfToPercent: () => pdfToPercent,
|
|
10176
|
+
pdfToViewport: () => pdfToViewport,
|
|
9124
10177
|
pdfjsLib: () => pdfjsLib,
|
|
10178
|
+
percentToPDF: () => percentToPDF,
|
|
10179
|
+
percentToViewport: () => percentToViewport,
|
|
9125
10180
|
quickViewer: () => quickViewer,
|
|
10181
|
+
removeRotation: () => removeRotation,
|
|
9126
10182
|
saveHighlights: () => saveHighlights,
|
|
9127
10183
|
saveStudentData: () => saveStudentData,
|
|
10184
|
+
scaleRect: () => scaleRect,
|
|
9128
10185
|
useAgentContext: () => useAgentContext,
|
|
9129
10186
|
useAgentStore: () => useAgentStore,
|
|
9130
10187
|
useAnnotationStore: () => useAnnotationStore,
|
|
@@ -9146,6 +10203,8 @@ __export(index_exports, {
|
|
|
9146
10203
|
useTouchGestures: () => useTouchGestures,
|
|
9147
10204
|
useViewerStore: () => useViewerStore,
|
|
9148
10205
|
useZoom: () => useZoom,
|
|
10206
|
+
viewportToPDF: () => viewportToPDF,
|
|
10207
|
+
viewportToPercent: () => viewportToPercent,
|
|
9149
10208
|
withErrorBoundary: () => withErrorBoundary
|
|
9150
10209
|
});
|
|
9151
10210
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -9160,9 +10219,9 @@ init_HighlightPopover2();
|
|
|
9160
10219
|
init_AnnotationToolbar2();
|
|
9161
10220
|
|
|
9162
10221
|
// src/components/Annotations/StickyNote.tsx
|
|
9163
|
-
var
|
|
10222
|
+
var import_react42 = require("react");
|
|
9164
10223
|
init_utils();
|
|
9165
|
-
var
|
|
10224
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
9166
10225
|
var NOTE_COLORS = [
|
|
9167
10226
|
"#fef08a",
|
|
9168
10227
|
// yellow
|
|
@@ -9175,7 +10234,7 @@ var NOTE_COLORS = [
|
|
|
9175
10234
|
"#fed7aa"
|
|
9176
10235
|
// orange
|
|
9177
10236
|
];
|
|
9178
|
-
var StickyNote = (0,
|
|
10237
|
+
var StickyNote = (0, import_react42.memo)(function StickyNote2({
|
|
9179
10238
|
note,
|
|
9180
10239
|
scale,
|
|
9181
10240
|
isSelected,
|
|
@@ -9188,37 +10247,37 @@ var StickyNote = (0, import_react41.memo)(function StickyNote2({
|
|
|
9188
10247
|
onDragStart,
|
|
9189
10248
|
className
|
|
9190
10249
|
}) {
|
|
9191
|
-
const [isExpanded, setIsExpanded] = (0,
|
|
9192
|
-
const [localContent, setLocalContent] = (0,
|
|
9193
|
-
const textareaRef = (0,
|
|
9194
|
-
const noteRef = (0,
|
|
9195
|
-
(0,
|
|
10250
|
+
const [isExpanded, setIsExpanded] = (0, import_react42.useState)(false);
|
|
10251
|
+
const [localContent, setLocalContent] = (0, import_react42.useState)(note.content);
|
|
10252
|
+
const textareaRef = (0, import_react42.useRef)(null);
|
|
10253
|
+
const noteRef = (0, import_react42.useRef)(null);
|
|
10254
|
+
(0, import_react42.useEffect)(() => {
|
|
9196
10255
|
setLocalContent(note.content);
|
|
9197
10256
|
}, [note.content]);
|
|
9198
|
-
(0,
|
|
10257
|
+
(0, import_react42.useEffect)(() => {
|
|
9199
10258
|
if (isEditing && textareaRef.current) {
|
|
9200
10259
|
textareaRef.current.focus();
|
|
9201
10260
|
textareaRef.current.select();
|
|
9202
10261
|
}
|
|
9203
10262
|
}, [isEditing]);
|
|
9204
|
-
const handleClick = (0,
|
|
10263
|
+
const handleClick = (0, import_react42.useCallback)((e) => {
|
|
9205
10264
|
e.stopPropagation();
|
|
9206
10265
|
onSelect?.();
|
|
9207
10266
|
if (!isExpanded) {
|
|
9208
10267
|
setIsExpanded(true);
|
|
9209
10268
|
}
|
|
9210
10269
|
}, [isExpanded, onSelect]);
|
|
9211
|
-
const handleDoubleClick = (0,
|
|
10270
|
+
const handleDoubleClick = (0, import_react42.useCallback)((e) => {
|
|
9212
10271
|
e.stopPropagation();
|
|
9213
10272
|
onStartEdit?.();
|
|
9214
10273
|
}, [onStartEdit]);
|
|
9215
|
-
const handleBlur = (0,
|
|
10274
|
+
const handleBlur = (0, import_react42.useCallback)(() => {
|
|
9216
10275
|
if (isEditing && localContent !== note.content) {
|
|
9217
10276
|
onUpdate?.({ content: localContent });
|
|
9218
10277
|
}
|
|
9219
10278
|
onEndEdit?.();
|
|
9220
10279
|
}, [isEditing, localContent, note.content, onUpdate, onEndEdit]);
|
|
9221
|
-
const handleKeyDown = (0,
|
|
10280
|
+
const handleKeyDown = (0, import_react42.useCallback)((e) => {
|
|
9222
10281
|
if (e.key === "Escape") {
|
|
9223
10282
|
setLocalContent(note.content);
|
|
9224
10283
|
onEndEdit?.();
|
|
@@ -9226,16 +10285,16 @@ var StickyNote = (0, import_react41.memo)(function StickyNote2({
|
|
|
9226
10285
|
handleBlur();
|
|
9227
10286
|
}
|
|
9228
10287
|
}, [note.content, onEndEdit, handleBlur]);
|
|
9229
|
-
const handleColorChange = (0,
|
|
10288
|
+
const handleColorChange = (0, import_react42.useCallback)((color) => {
|
|
9230
10289
|
onUpdate?.({ color });
|
|
9231
10290
|
}, [onUpdate]);
|
|
9232
|
-
const handleCollapse = (0,
|
|
10291
|
+
const handleCollapse = (0, import_react42.useCallback)((e) => {
|
|
9233
10292
|
e.stopPropagation();
|
|
9234
10293
|
setIsExpanded(false);
|
|
9235
10294
|
onEndEdit?.();
|
|
9236
10295
|
}, [onEndEdit]);
|
|
9237
10296
|
if (!isExpanded) {
|
|
9238
|
-
return /* @__PURE__ */ (0,
|
|
10297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9239
10298
|
"div",
|
|
9240
10299
|
{
|
|
9241
10300
|
ref: noteRef,
|
|
@@ -9256,14 +10315,14 @@ var StickyNote = (0, import_react41.memo)(function StickyNote2({
|
|
|
9256
10315
|
onMouseDown: onDragStart,
|
|
9257
10316
|
onTouchStart: onDragStart,
|
|
9258
10317
|
title: note.content || "Empty note",
|
|
9259
|
-
children: /* @__PURE__ */ (0,
|
|
10318
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9260
10319
|
"svg",
|
|
9261
10320
|
{
|
|
9262
10321
|
className: "w-4 h-4 opacity-70",
|
|
9263
10322
|
fill: "currentColor",
|
|
9264
10323
|
viewBox: "0 0 20 20",
|
|
9265
10324
|
style: { color: "#333" },
|
|
9266
|
-
children: /* @__PURE__ */ (0,
|
|
10325
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9267
10326
|
"path",
|
|
9268
10327
|
{
|
|
9269
10328
|
fillRule: "evenodd",
|
|
@@ -9276,7 +10335,7 @@ var StickyNote = (0, import_react41.memo)(function StickyNote2({
|
|
|
9276
10335
|
}
|
|
9277
10336
|
);
|
|
9278
10337
|
}
|
|
9279
|
-
return /* @__PURE__ */ (0,
|
|
10338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
9280
10339
|
"div",
|
|
9281
10340
|
{
|
|
9282
10341
|
ref: noteRef,
|
|
@@ -9294,14 +10353,14 @@ var StickyNote = (0, import_react41.memo)(function StickyNote2({
|
|
|
9294
10353
|
},
|
|
9295
10354
|
onClick: handleClick,
|
|
9296
10355
|
children: [
|
|
9297
|
-
/* @__PURE__ */ (0,
|
|
10356
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
9298
10357
|
"div",
|
|
9299
10358
|
{
|
|
9300
10359
|
className: "flex items-center justify-between px-2 py-1 border-b border-black/10 cursor-move",
|
|
9301
10360
|
onMouseDown: onDragStart,
|
|
9302
10361
|
onTouchStart: onDragStart,
|
|
9303
10362
|
children: [
|
|
9304
|
-
/* @__PURE__ */ (0,
|
|
10363
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex gap-1", children: NOTE_COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9305
10364
|
"button",
|
|
9306
10365
|
{
|
|
9307
10366
|
className: cn(
|
|
@@ -9318,8 +10377,8 @@ var StickyNote = (0, import_react41.memo)(function StickyNote2({
|
|
|
9318
10377
|
},
|
|
9319
10378
|
color
|
|
9320
10379
|
)) }),
|
|
9321
|
-
/* @__PURE__ */ (0,
|
|
9322
|
-
/* @__PURE__ */ (0,
|
|
10380
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex gap-1", children: [
|
|
10381
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9323
10382
|
"button",
|
|
9324
10383
|
{
|
|
9325
10384
|
className: "p-0.5 hover:bg-black/10 rounded",
|
|
@@ -9328,23 +10387,23 @@ var StickyNote = (0, import_react41.memo)(function StickyNote2({
|
|
|
9328
10387
|
onDelete?.();
|
|
9329
10388
|
},
|
|
9330
10389
|
title: "Delete note",
|
|
9331
|
-
children: /* @__PURE__ */ (0,
|
|
10390
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) })
|
|
9332
10391
|
}
|
|
9333
10392
|
),
|
|
9334
|
-
/* @__PURE__ */ (0,
|
|
10393
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9335
10394
|
"button",
|
|
9336
10395
|
{
|
|
9337
10396
|
className: "p-0.5 hover:bg-black/10 rounded",
|
|
9338
10397
|
onClick: handleCollapse,
|
|
9339
10398
|
title: "Collapse note",
|
|
9340
|
-
children: /* @__PURE__ */ (0,
|
|
10399
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
9341
10400
|
}
|
|
9342
10401
|
)
|
|
9343
10402
|
] })
|
|
9344
10403
|
]
|
|
9345
10404
|
}
|
|
9346
10405
|
),
|
|
9347
|
-
/* @__PURE__ */ (0,
|
|
10406
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "p-2", children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9348
10407
|
"textarea",
|
|
9349
10408
|
{
|
|
9350
10409
|
ref: textareaRef,
|
|
@@ -9359,7 +10418,7 @@ var StickyNote = (0, import_react41.memo)(function StickyNote2({
|
|
|
9359
10418
|
onKeyDown: handleKeyDown,
|
|
9360
10419
|
placeholder: "Enter note..."
|
|
9361
10420
|
}
|
|
9362
|
-
) : /* @__PURE__ */ (0,
|
|
10421
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9363
10422
|
"div",
|
|
9364
10423
|
{
|
|
9365
10424
|
className: cn(
|
|
@@ -9370,16 +10429,16 @@ var StickyNote = (0, import_react41.memo)(function StickyNote2({
|
|
|
9370
10429
|
children: note.content || "Double-click to edit..."
|
|
9371
10430
|
}
|
|
9372
10431
|
) }),
|
|
9373
|
-
/* @__PURE__ */ (0,
|
|
10432
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "px-2 pb-1 text-[10px] text-gray-500", children: new Date(note.updatedAt).toLocaleDateString() })
|
|
9374
10433
|
]
|
|
9375
10434
|
}
|
|
9376
10435
|
);
|
|
9377
10436
|
});
|
|
9378
10437
|
|
|
9379
10438
|
// src/components/Annotations/DrawingCanvas.tsx
|
|
9380
|
-
var
|
|
10439
|
+
var import_react43 = require("react");
|
|
9381
10440
|
init_utils();
|
|
9382
|
-
var
|
|
10441
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
9383
10442
|
function pointsToSvgPath(points) {
|
|
9384
10443
|
if (points.length === 0) return "";
|
|
9385
10444
|
if (points.length === 1) {
|
|
@@ -9417,7 +10476,7 @@ function simplifyPath(points, tolerance = 1) {
|
|
|
9417
10476
|
result.push(points[points.length - 1]);
|
|
9418
10477
|
return result;
|
|
9419
10478
|
}
|
|
9420
|
-
var DrawingCanvas = (0,
|
|
10479
|
+
var DrawingCanvas = (0, import_react43.memo)(function DrawingCanvas2({
|
|
9421
10480
|
width,
|
|
9422
10481
|
height,
|
|
9423
10482
|
scale,
|
|
@@ -9427,10 +10486,10 @@ var DrawingCanvas = (0, import_react42.memo)(function DrawingCanvas2({
|
|
|
9427
10486
|
onDrawingComplete,
|
|
9428
10487
|
className
|
|
9429
10488
|
}) {
|
|
9430
|
-
const svgRef = (0,
|
|
9431
|
-
const [isDrawing, setIsDrawing] = (0,
|
|
9432
|
-
const [currentPath, setCurrentPath] = (0,
|
|
9433
|
-
const getPoint = (0,
|
|
10489
|
+
const svgRef = (0, import_react43.useRef)(null);
|
|
10490
|
+
const [isDrawing, setIsDrawing] = (0, import_react43.useState)(false);
|
|
10491
|
+
const [currentPath, setCurrentPath] = (0, import_react43.useState)([]);
|
|
10492
|
+
const getPoint = (0, import_react43.useCallback)((e) => {
|
|
9434
10493
|
if (!svgRef.current) return null;
|
|
9435
10494
|
const svg = svgRef.current;
|
|
9436
10495
|
const rect = svg.getBoundingClientRect();
|
|
@@ -9450,7 +10509,7 @@ var DrawingCanvas = (0, import_react42.memo)(function DrawingCanvas2({
|
|
|
9450
10509
|
y: (clientY - rect.top) / scale
|
|
9451
10510
|
};
|
|
9452
10511
|
}, [scale]);
|
|
9453
|
-
const handleStart = (0,
|
|
10512
|
+
const handleStart = (0, import_react43.useCallback)((e) => {
|
|
9454
10513
|
if (!isActive) return;
|
|
9455
10514
|
const point = getPoint(e);
|
|
9456
10515
|
if (point) {
|
|
@@ -9458,14 +10517,14 @@ var DrawingCanvas = (0, import_react42.memo)(function DrawingCanvas2({
|
|
|
9458
10517
|
setCurrentPath([point]);
|
|
9459
10518
|
}
|
|
9460
10519
|
}, [isActive, getPoint]);
|
|
9461
|
-
const handleMove = (0,
|
|
10520
|
+
const handleMove = (0, import_react43.useCallback)((e) => {
|
|
9462
10521
|
if (!isDrawing || !isActive) return;
|
|
9463
10522
|
const point = getPoint(e);
|
|
9464
10523
|
if (point) {
|
|
9465
10524
|
setCurrentPath((prev) => [...prev, point]);
|
|
9466
10525
|
}
|
|
9467
10526
|
}, [isDrawing, isActive, getPoint]);
|
|
9468
|
-
const handleEnd = (0,
|
|
10527
|
+
const handleEnd = (0, import_react43.useCallback)(() => {
|
|
9469
10528
|
if (!isDrawing) return;
|
|
9470
10529
|
setIsDrawing(false);
|
|
9471
10530
|
if (currentPath.length >= 2) {
|
|
@@ -9474,7 +10533,7 @@ var DrawingCanvas = (0, import_react42.memo)(function DrawingCanvas2({
|
|
|
9474
10533
|
}
|
|
9475
10534
|
setCurrentPath([]);
|
|
9476
10535
|
}, [isDrawing, currentPath, onDrawingComplete]);
|
|
9477
|
-
return /* @__PURE__ */ (0,
|
|
10536
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
9478
10537
|
"svg",
|
|
9479
10538
|
{
|
|
9480
10539
|
ref: svgRef,
|
|
@@ -9494,7 +10553,7 @@ var DrawingCanvas = (0, import_react42.memo)(function DrawingCanvas2({
|
|
|
9494
10553
|
onTouchStart: handleStart,
|
|
9495
10554
|
onTouchMove: handleMove,
|
|
9496
10555
|
onTouchEnd: handleEnd,
|
|
9497
|
-
children: isDrawing && currentPath.length > 0 && /* @__PURE__ */ (0,
|
|
10556
|
+
children: isDrawing && currentPath.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
9498
10557
|
"path",
|
|
9499
10558
|
{
|
|
9500
10559
|
d: pointsToSvgPath(currentPath),
|
|
@@ -9511,10 +10570,10 @@ var DrawingCanvas = (0, import_react42.memo)(function DrawingCanvas2({
|
|
|
9511
10570
|
});
|
|
9512
10571
|
|
|
9513
10572
|
// src/components/Annotations/ShapeRenderer.tsx
|
|
9514
|
-
var
|
|
10573
|
+
var import_react44 = require("react");
|
|
9515
10574
|
init_utils();
|
|
9516
|
-
var
|
|
9517
|
-
var ShapeRenderer = (0,
|
|
10575
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
10576
|
+
var ShapeRenderer = (0, import_react44.memo)(function ShapeRenderer2({
|
|
9518
10577
|
shape,
|
|
9519
10578
|
scale,
|
|
9520
10579
|
isSelected,
|
|
@@ -9524,18 +10583,18 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9524
10583
|
onDelete: _onDelete,
|
|
9525
10584
|
className
|
|
9526
10585
|
}) {
|
|
9527
|
-
const [_isDragging, setIsDragging] = (0,
|
|
9528
|
-
const [_isResizing, setIsResizing] = (0,
|
|
9529
|
-
const [activeHandle, setActiveHandle] = (0,
|
|
9530
|
-
const startPosRef = (0,
|
|
9531
|
-
const startShapeRef = (0,
|
|
10586
|
+
const [_isDragging, setIsDragging] = (0, import_react44.useState)(false);
|
|
10587
|
+
const [_isResizing, setIsResizing] = (0, import_react44.useState)(false);
|
|
10588
|
+
const [activeHandle, setActiveHandle] = (0, import_react44.useState)(null);
|
|
10589
|
+
const startPosRef = (0, import_react44.useRef)({ x: 0, y: 0 });
|
|
10590
|
+
const startShapeRef = (0, import_react44.useRef)({ x: 0, y: 0, width: 0, height: 0 });
|
|
9532
10591
|
const { shapeType, x, y, width, height, color, strokeWidth, id: _id } = shape;
|
|
9533
10592
|
const scaledX = x * scale;
|
|
9534
10593
|
const scaledY = y * scale;
|
|
9535
10594
|
const scaledWidth = width * scale;
|
|
9536
10595
|
const scaledHeight = height * scale;
|
|
9537
10596
|
const scaledStroke = strokeWidth * scale;
|
|
9538
|
-
const getResizeHandles = (0,
|
|
10597
|
+
const getResizeHandles = (0, import_react44.useCallback)(() => {
|
|
9539
10598
|
const handleSize = 8;
|
|
9540
10599
|
const half = handleSize / 2;
|
|
9541
10600
|
return [
|
|
@@ -9549,7 +10608,7 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9549
10608
|
{ position: "w", cursor: "ew-resize", x: scaledX - half, y: scaledY + scaledHeight / 2 - half }
|
|
9550
10609
|
];
|
|
9551
10610
|
}, [scaledX, scaledY, scaledWidth, scaledHeight]);
|
|
9552
|
-
const handleMouseDown = (0,
|
|
10611
|
+
const handleMouseDown = (0, import_react44.useCallback)((e, handle) => {
|
|
9553
10612
|
e.stopPropagation();
|
|
9554
10613
|
onSelect?.();
|
|
9555
10614
|
if (!isEditing) return;
|
|
@@ -9625,7 +10684,7 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9625
10684
|
document.addEventListener("mousemove", handleMouseMove);
|
|
9626
10685
|
document.addEventListener("mouseup", handleMouseUp);
|
|
9627
10686
|
}, [isEditing, x, y, width, height, scale, onSelect, onUpdate]);
|
|
9628
|
-
const renderShape2 = (0,
|
|
10687
|
+
const renderShape2 = (0, import_react44.useCallback)(() => {
|
|
9629
10688
|
const commonProps = {
|
|
9630
10689
|
stroke: color,
|
|
9631
10690
|
strokeWidth: scaledStroke,
|
|
@@ -9637,7 +10696,7 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9637
10696
|
};
|
|
9638
10697
|
switch (shapeType) {
|
|
9639
10698
|
case "rect":
|
|
9640
|
-
return /* @__PURE__ */ (0,
|
|
10699
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
9641
10700
|
"rect",
|
|
9642
10701
|
{
|
|
9643
10702
|
x: scaledX,
|
|
@@ -9648,7 +10707,7 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9648
10707
|
}
|
|
9649
10708
|
);
|
|
9650
10709
|
case "circle":
|
|
9651
|
-
return /* @__PURE__ */ (0,
|
|
10710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
9652
10711
|
"ellipse",
|
|
9653
10712
|
{
|
|
9654
10713
|
cx: scaledX + scaledWidth / 2,
|
|
@@ -9659,7 +10718,7 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9659
10718
|
}
|
|
9660
10719
|
);
|
|
9661
10720
|
case "line":
|
|
9662
|
-
return /* @__PURE__ */ (0,
|
|
10721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
9663
10722
|
"line",
|
|
9664
10723
|
{
|
|
9665
10724
|
x1: scaledX,
|
|
@@ -9679,22 +10738,22 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9679
10738
|
const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);
|
|
9680
10739
|
const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);
|
|
9681
10740
|
const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);
|
|
9682
|
-
return /* @__PURE__ */ (0,
|
|
9683
|
-
/* @__PURE__ */ (0,
|
|
9684
|
-
/* @__PURE__ */ (0,
|
|
9685
|
-
/* @__PURE__ */ (0,
|
|
10741
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("g", { children: [
|
|
10742
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("line", { x1: scaledX, y1: scaledY, x2: endX, y2: endY, ...commonProps }),
|
|
10743
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
|
|
10744
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
|
|
9686
10745
|
] });
|
|
9687
10746
|
default:
|
|
9688
10747
|
return null;
|
|
9689
10748
|
}
|
|
9690
10749
|
}, [shapeType, scaledX, scaledY, scaledWidth, scaledHeight, color, scaledStroke, isSelected]);
|
|
9691
|
-
return /* @__PURE__ */ (0,
|
|
10750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
9692
10751
|
"g",
|
|
9693
10752
|
{
|
|
9694
10753
|
className: cn("shape-renderer", className),
|
|
9695
10754
|
onMouseDown: (e) => handleMouseDown(e),
|
|
9696
10755
|
children: [
|
|
9697
|
-
/* @__PURE__ */ (0,
|
|
10756
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
9698
10757
|
"rect",
|
|
9699
10758
|
{
|
|
9700
10759
|
x: scaledX - 5,
|
|
@@ -9707,7 +10766,7 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9707
10766
|
}
|
|
9708
10767
|
),
|
|
9709
10768
|
renderShape2(),
|
|
9710
|
-
isSelected && /* @__PURE__ */ (0,
|
|
10769
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
9711
10770
|
"rect",
|
|
9712
10771
|
{
|
|
9713
10772
|
x: scaledX - 2,
|
|
@@ -9720,7 +10779,7 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9720
10779
|
strokeDasharray: "4 2"
|
|
9721
10780
|
}
|
|
9722
10781
|
),
|
|
9723
|
-
isSelected && isEditing && getResizeHandles().map((handle) => /* @__PURE__ */ (0,
|
|
10782
|
+
isSelected && isEditing && getResizeHandles().map((handle) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
9724
10783
|
"rect",
|
|
9725
10784
|
{
|
|
9726
10785
|
x: handle.x,
|
|
@@ -9740,7 +10799,7 @@ var ShapeRenderer = (0, import_react43.memo)(function ShapeRenderer2({
|
|
|
9740
10799
|
}
|
|
9741
10800
|
);
|
|
9742
10801
|
});
|
|
9743
|
-
var ShapePreview = (0,
|
|
10802
|
+
var ShapePreview = (0, import_react44.memo)(function ShapePreview2({
|
|
9744
10803
|
shapeType,
|
|
9745
10804
|
startPoint,
|
|
9746
10805
|
endPoint,
|
|
@@ -9761,9 +10820,9 @@ var ShapePreview = (0, import_react43.memo)(function ShapePreview2({
|
|
|
9761
10820
|
};
|
|
9762
10821
|
switch (shapeType) {
|
|
9763
10822
|
case "rect":
|
|
9764
|
-
return /* @__PURE__ */ (0,
|
|
10823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("rect", { x, y, width, height, ...commonProps });
|
|
9765
10824
|
case "circle":
|
|
9766
|
-
return /* @__PURE__ */ (0,
|
|
10825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
9767
10826
|
"ellipse",
|
|
9768
10827
|
{
|
|
9769
10828
|
cx: x + width / 2,
|
|
@@ -9774,7 +10833,7 @@ var ShapePreview = (0, import_react43.memo)(function ShapePreview2({
|
|
|
9774
10833
|
}
|
|
9775
10834
|
);
|
|
9776
10835
|
case "line":
|
|
9777
|
-
return /* @__PURE__ */ (0,
|
|
10836
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
9778
10837
|
"line",
|
|
9779
10838
|
{
|
|
9780
10839
|
x1: startPoint.x * scale,
|
|
@@ -9796,8 +10855,8 @@ var ShapePreview = (0, import_react43.memo)(function ShapePreview2({
|
|
|
9796
10855
|
const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);
|
|
9797
10856
|
const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);
|
|
9798
10857
|
const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);
|
|
9799
|
-
return /* @__PURE__ */ (0,
|
|
9800
|
-
/* @__PURE__ */ (0,
|
|
10858
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("g", { children: [
|
|
10859
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
9801
10860
|
"line",
|
|
9802
10861
|
{
|
|
9803
10862
|
x1: startPoint.x * scale,
|
|
@@ -9807,8 +10866,8 @@ var ShapePreview = (0, import_react43.memo)(function ShapePreview2({
|
|
|
9807
10866
|
...commonProps
|
|
9808
10867
|
}
|
|
9809
10868
|
),
|
|
9810
|
-
/* @__PURE__ */ (0,
|
|
9811
|
-
/* @__PURE__ */ (0,
|
|
10869
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
|
|
10870
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
|
|
9812
10871
|
] });
|
|
9813
10872
|
default:
|
|
9814
10873
|
return null;
|
|
@@ -9816,10 +10875,10 @@ var ShapePreview = (0, import_react43.memo)(function ShapePreview2({
|
|
|
9816
10875
|
});
|
|
9817
10876
|
|
|
9818
10877
|
// src/components/Annotations/QuickNoteButton.tsx
|
|
9819
|
-
var
|
|
10878
|
+
var import_react45 = require("react");
|
|
9820
10879
|
init_utils();
|
|
9821
|
-
var
|
|
9822
|
-
var QuickNoteButton = (0,
|
|
10880
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
10881
|
+
var QuickNoteButton = (0, import_react45.memo)(function QuickNoteButton2({
|
|
9823
10882
|
pageNumber,
|
|
9824
10883
|
scale,
|
|
9825
10884
|
position = "top-right",
|
|
@@ -9827,8 +10886,8 @@ var QuickNoteButton = (0, import_react44.memo)(function QuickNoteButton2({
|
|
|
9827
10886
|
className,
|
|
9828
10887
|
visible = true
|
|
9829
10888
|
}) {
|
|
9830
|
-
const [isHovered, setIsHovered] = (0,
|
|
9831
|
-
const handleClick = (0,
|
|
10889
|
+
const [isHovered, setIsHovered] = (0, import_react45.useState)(false);
|
|
10890
|
+
const handleClick = (0, import_react45.useCallback)(
|
|
9832
10891
|
(e) => {
|
|
9833
10892
|
e.stopPropagation();
|
|
9834
10893
|
const x = position === "top-right" ? 80 : 80;
|
|
@@ -9840,7 +10899,7 @@ var QuickNoteButton = (0, import_react44.memo)(function QuickNoteButton2({
|
|
|
9840
10899
|
if (!visible) {
|
|
9841
10900
|
return null;
|
|
9842
10901
|
}
|
|
9843
|
-
return /* @__PURE__ */ (0,
|
|
10902
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
9844
10903
|
"button",
|
|
9845
10904
|
{
|
|
9846
10905
|
onClick: handleClick,
|
|
@@ -9862,7 +10921,7 @@ var QuickNoteButton = (0, import_react44.memo)(function QuickNoteButton2({
|
|
|
9862
10921
|
),
|
|
9863
10922
|
title: "Add quick note",
|
|
9864
10923
|
"aria-label": "Add quick note",
|
|
9865
|
-
children: /* @__PURE__ */ (0,
|
|
10924
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
9866
10925
|
"svg",
|
|
9867
10926
|
{
|
|
9868
10927
|
className: "w-4 h-4 text-yellow-900",
|
|
@@ -9870,7 +10929,7 @@ var QuickNoteButton = (0, import_react44.memo)(function QuickNoteButton2({
|
|
|
9870
10929
|
viewBox: "0 0 24 24",
|
|
9871
10930
|
stroke: "currentColor",
|
|
9872
10931
|
strokeWidth: 2,
|
|
9873
|
-
children: /* @__PURE__ */ (0,
|
|
10932
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4v16m8-8H4" })
|
|
9874
10933
|
}
|
|
9875
10934
|
)
|
|
9876
10935
|
}
|
|
@@ -9878,10 +10937,10 @@ var QuickNoteButton = (0, import_react44.memo)(function QuickNoteButton2({
|
|
|
9878
10937
|
});
|
|
9879
10938
|
|
|
9880
10939
|
// src/components/Annotations/QuickNotePopover.tsx
|
|
9881
|
-
var
|
|
10940
|
+
var import_react46 = require("react");
|
|
9882
10941
|
init_utils();
|
|
9883
|
-
var
|
|
9884
|
-
var QuickNotePopover = (0,
|
|
10942
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
10943
|
+
var QuickNotePopover = (0, import_react46.memo)(function QuickNotePopover2({
|
|
9885
10944
|
visible,
|
|
9886
10945
|
position,
|
|
9887
10946
|
initialContent = "",
|
|
@@ -9890,21 +10949,21 @@ var QuickNotePopover = (0, import_react45.memo)(function QuickNotePopover2({
|
|
|
9890
10949
|
onCancel,
|
|
9891
10950
|
className
|
|
9892
10951
|
}) {
|
|
9893
|
-
const [content, setContent] = (0,
|
|
9894
|
-
const textareaRef = (0,
|
|
9895
|
-
const popoverRef = (0,
|
|
9896
|
-
const [adjustedPosition, setAdjustedPosition] = (0,
|
|
9897
|
-
(0,
|
|
10952
|
+
const [content, setContent] = (0, import_react46.useState)(initialContent);
|
|
10953
|
+
const textareaRef = (0, import_react46.useRef)(null);
|
|
10954
|
+
const popoverRef = (0, import_react46.useRef)(null);
|
|
10955
|
+
const [adjustedPosition, setAdjustedPosition] = (0, import_react46.useState)(position);
|
|
10956
|
+
(0, import_react46.useEffect)(() => {
|
|
9898
10957
|
if (visible && textareaRef.current) {
|
|
9899
10958
|
textareaRef.current.focus();
|
|
9900
10959
|
}
|
|
9901
10960
|
}, [visible]);
|
|
9902
|
-
(0,
|
|
10961
|
+
(0, import_react46.useEffect)(() => {
|
|
9903
10962
|
if (visible) {
|
|
9904
10963
|
setContent(initialContent);
|
|
9905
10964
|
}
|
|
9906
10965
|
}, [visible, initialContent]);
|
|
9907
|
-
(0,
|
|
10966
|
+
(0, import_react46.useEffect)(() => {
|
|
9908
10967
|
if (!visible || !popoverRef.current) return;
|
|
9909
10968
|
const rect = popoverRef.current.getBoundingClientRect();
|
|
9910
10969
|
const padding = 10;
|
|
@@ -9923,14 +10982,14 @@ var QuickNotePopover = (0, import_react45.memo)(function QuickNotePopover2({
|
|
|
9923
10982
|
}
|
|
9924
10983
|
setAdjustedPosition({ x, y });
|
|
9925
10984
|
}, [position, visible]);
|
|
9926
|
-
const handleSave = (0,
|
|
10985
|
+
const handleSave = (0, import_react46.useCallback)(() => {
|
|
9927
10986
|
if (content.trim()) {
|
|
9928
10987
|
onSave(content.trim());
|
|
9929
10988
|
} else {
|
|
9930
10989
|
onCancel();
|
|
9931
10990
|
}
|
|
9932
10991
|
}, [content, onSave, onCancel]);
|
|
9933
|
-
const handleKeyDown = (0,
|
|
10992
|
+
const handleKeyDown = (0, import_react46.useCallback)(
|
|
9934
10993
|
(e) => {
|
|
9935
10994
|
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
|
9936
10995
|
e.preventDefault();
|
|
@@ -9945,7 +11004,7 @@ var QuickNotePopover = (0, import_react45.memo)(function QuickNotePopover2({
|
|
|
9945
11004
|
if (!visible) {
|
|
9946
11005
|
return null;
|
|
9947
11006
|
}
|
|
9948
|
-
return /* @__PURE__ */ (0,
|
|
11007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
9949
11008
|
"div",
|
|
9950
11009
|
{
|
|
9951
11010
|
ref: popoverRef,
|
|
@@ -9964,15 +11023,15 @@ var QuickNotePopover = (0, import_react45.memo)(function QuickNotePopover2({
|
|
|
9964
11023
|
top: adjustedPosition.y
|
|
9965
11024
|
},
|
|
9966
11025
|
children: [
|
|
9967
|
-
agentLastStatement && /* @__PURE__ */ (0,
|
|
9968
|
-
/* @__PURE__ */ (0,
|
|
9969
|
-
/* @__PURE__ */ (0,
|
|
11026
|
+
agentLastStatement && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "mb-2 p-2 bg-blue-50 dark:bg-blue-900/50 rounded text-xs text-blue-600 dark:text-blue-300 border border-blue-100 dark:border-blue-800", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-start gap-1", children: [
|
|
11027
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("svg", { className: "w-3 h-3 mt-0.5 flex-shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }),
|
|
11028
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "line-clamp-2", children: [
|
|
9970
11029
|
"AI discussed: \u201C",
|
|
9971
11030
|
agentLastStatement,
|
|
9972
11031
|
"\u201D"
|
|
9973
11032
|
] })
|
|
9974
11033
|
] }) }),
|
|
9975
|
-
/* @__PURE__ */ (0,
|
|
11034
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
9976
11035
|
"textarea",
|
|
9977
11036
|
{
|
|
9978
11037
|
ref: textareaRef,
|
|
@@ -9991,13 +11050,13 @@ var QuickNotePopover = (0, import_react45.memo)(function QuickNotePopover2({
|
|
|
9991
11050
|
)
|
|
9992
11051
|
}
|
|
9993
11052
|
),
|
|
9994
|
-
/* @__PURE__ */ (0,
|
|
9995
|
-
/* @__PURE__ */ (0,
|
|
11053
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between mt-2", children: [
|
|
11054
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
|
|
9996
11055
|
navigator.platform.includes("Mac") ? "\u2318" : "Ctrl",
|
|
9997
11056
|
"+Enter to save"
|
|
9998
11057
|
] }),
|
|
9999
|
-
/* @__PURE__ */ (0,
|
|
10000
|
-
/* @__PURE__ */ (0,
|
|
11058
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex gap-2", children: [
|
|
11059
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
10001
11060
|
"button",
|
|
10002
11061
|
{
|
|
10003
11062
|
onClick: onCancel,
|
|
@@ -10010,7 +11069,7 @@ var QuickNotePopover = (0, import_react45.memo)(function QuickNotePopover2({
|
|
|
10010
11069
|
children: "Cancel"
|
|
10011
11070
|
}
|
|
10012
11071
|
),
|
|
10013
|
-
/* @__PURE__ */ (0,
|
|
11072
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
10014
11073
|
"button",
|
|
10015
11074
|
{
|
|
10016
11075
|
onClick: handleSave,
|
|
@@ -10033,10 +11092,10 @@ var QuickNotePopover = (0, import_react45.memo)(function QuickNotePopover2({
|
|
|
10033
11092
|
});
|
|
10034
11093
|
|
|
10035
11094
|
// src/components/AskAbout/AskAboutOverlay.tsx
|
|
10036
|
-
var
|
|
11095
|
+
var import_react47 = require("react");
|
|
10037
11096
|
init_utils();
|
|
10038
|
-
var
|
|
10039
|
-
var AskAboutOverlay = (0,
|
|
11097
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
11098
|
+
var AskAboutOverlay = (0, import_react47.memo)(function AskAboutOverlay2({
|
|
10040
11099
|
visible,
|
|
10041
11100
|
progress,
|
|
10042
11101
|
position,
|
|
@@ -10050,7 +11109,7 @@ var AskAboutOverlay = (0, import_react46.memo)(function AskAboutOverlay2({
|
|
|
10050
11109
|
const radius = (size - strokeWidth) / 2;
|
|
10051
11110
|
const circumference = 2 * Math.PI * radius;
|
|
10052
11111
|
const strokeDashoffset = circumference * (1 - progress);
|
|
10053
|
-
return /* @__PURE__ */ (0,
|
|
11112
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
10054
11113
|
"div",
|
|
10055
11114
|
{
|
|
10056
11115
|
className: cn(
|
|
@@ -10063,7 +11122,7 @@ var AskAboutOverlay = (0, import_react46.memo)(function AskAboutOverlay2({
|
|
|
10063
11122
|
top: position.y - size / 2
|
|
10064
11123
|
},
|
|
10065
11124
|
children: [
|
|
10066
|
-
/* @__PURE__ */ (0,
|
|
11125
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
10067
11126
|
"svg",
|
|
10068
11127
|
{
|
|
10069
11128
|
width: size,
|
|
@@ -10071,7 +11130,7 @@ var AskAboutOverlay = (0, import_react46.memo)(function AskAboutOverlay2({
|
|
|
10071
11130
|
viewBox: `0 0 ${size} ${size}`,
|
|
10072
11131
|
className: "transform -rotate-90",
|
|
10073
11132
|
children: [
|
|
10074
|
-
/* @__PURE__ */ (0,
|
|
11133
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10075
11134
|
"circle",
|
|
10076
11135
|
{
|
|
10077
11136
|
cx: size / 2,
|
|
@@ -10082,7 +11141,7 @@ var AskAboutOverlay = (0, import_react46.memo)(function AskAboutOverlay2({
|
|
|
10082
11141
|
strokeWidth
|
|
10083
11142
|
}
|
|
10084
11143
|
),
|
|
10085
|
-
/* @__PURE__ */ (0,
|
|
11144
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10086
11145
|
"circle",
|
|
10087
11146
|
{
|
|
10088
11147
|
cx: size / 2,
|
|
@@ -10100,12 +11159,12 @@ var AskAboutOverlay = (0, import_react46.memo)(function AskAboutOverlay2({
|
|
|
10100
11159
|
]
|
|
10101
11160
|
}
|
|
10102
11161
|
),
|
|
10103
|
-
/* @__PURE__ */ (0,
|
|
11162
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10104
11163
|
"div",
|
|
10105
11164
|
{
|
|
10106
11165
|
className: "absolute inset-0 flex items-center justify-center",
|
|
10107
11166
|
style: { color: progress >= 1 ? "#22c55e" : "white" },
|
|
10108
|
-
children: progress >= 1 ? /* @__PURE__ */ (0,
|
|
11167
|
+
children: progress >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10109
11168
|
"svg",
|
|
10110
11169
|
{
|
|
10111
11170
|
width: "24",
|
|
@@ -10116,9 +11175,9 @@ var AskAboutOverlay = (0, import_react46.memo)(function AskAboutOverlay2({
|
|
|
10116
11175
|
strokeWidth: "2",
|
|
10117
11176
|
strokeLinecap: "round",
|
|
10118
11177
|
strokeLinejoin: "round",
|
|
10119
|
-
children: /* @__PURE__ */ (0,
|
|
11178
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("polyline", { points: "20 6 9 17 4 12" })
|
|
10120
11179
|
}
|
|
10121
|
-
) : /* @__PURE__ */ (0,
|
|
11180
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
10122
11181
|
"svg",
|
|
10123
11182
|
{
|
|
10124
11183
|
width: "20",
|
|
@@ -10130,9 +11189,9 @@ var AskAboutOverlay = (0, import_react46.memo)(function AskAboutOverlay2({
|
|
|
10130
11189
|
strokeLinecap: "round",
|
|
10131
11190
|
strokeLinejoin: "round",
|
|
10132
11191
|
children: [
|
|
10133
|
-
/* @__PURE__ */ (0,
|
|
10134
|
-
/* @__PURE__ */ (0,
|
|
10135
|
-
/* @__PURE__ */ (0,
|
|
11192
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
11193
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
|
|
11194
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
|
|
10136
11195
|
]
|
|
10137
11196
|
}
|
|
10138
11197
|
)
|
|
@@ -10144,10 +11203,10 @@ var AskAboutOverlay = (0, import_react46.memo)(function AskAboutOverlay2({
|
|
|
10144
11203
|
});
|
|
10145
11204
|
|
|
10146
11205
|
// src/components/AskAbout/AskAboutTrigger.tsx
|
|
10147
|
-
var
|
|
11206
|
+
var import_react48 = require("react");
|
|
10148
11207
|
init_utils();
|
|
10149
|
-
var
|
|
10150
|
-
var AskAboutTrigger = (0,
|
|
11208
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
11209
|
+
var AskAboutTrigger = (0, import_react48.memo)(function AskAboutTrigger2({
|
|
10151
11210
|
position,
|
|
10152
11211
|
onConfirm,
|
|
10153
11212
|
onCancel,
|
|
@@ -10155,9 +11214,9 @@ var AskAboutTrigger = (0, import_react47.memo)(function AskAboutTrigger2({
|
|
|
10155
11214
|
autoHideDelay = 5e3,
|
|
10156
11215
|
className
|
|
10157
11216
|
}) {
|
|
10158
|
-
const [adjustedPosition, setAdjustedPosition] = (0,
|
|
10159
|
-
const triggerRef = (0,
|
|
10160
|
-
(0,
|
|
11217
|
+
const [adjustedPosition, setAdjustedPosition] = (0, import_react48.useState)(position);
|
|
11218
|
+
const triggerRef = (0, import_react48.useRef)(null);
|
|
11219
|
+
(0, import_react48.useEffect)(() => {
|
|
10161
11220
|
if (!visible || !triggerRef.current) return;
|
|
10162
11221
|
const rect = triggerRef.current.getBoundingClientRect();
|
|
10163
11222
|
const padding = 10;
|
|
@@ -10173,19 +11232,19 @@ var AskAboutTrigger = (0, import_react47.memo)(function AskAboutTrigger2({
|
|
|
10173
11232
|
}
|
|
10174
11233
|
setAdjustedPosition({ x, y });
|
|
10175
11234
|
}, [position, visible]);
|
|
10176
|
-
(0,
|
|
11235
|
+
(0, import_react48.useEffect)(() => {
|
|
10177
11236
|
if (!visible || autoHideDelay === 0) return;
|
|
10178
11237
|
const timer = setTimeout(onCancel, autoHideDelay);
|
|
10179
11238
|
return () => clearTimeout(timer);
|
|
10180
11239
|
}, [visible, autoHideDelay, onCancel]);
|
|
10181
|
-
const handleConfirm = (0,
|
|
11240
|
+
const handleConfirm = (0, import_react48.useCallback)(
|
|
10182
11241
|
(e) => {
|
|
10183
11242
|
e.stopPropagation();
|
|
10184
11243
|
onConfirm();
|
|
10185
11244
|
},
|
|
10186
11245
|
[onConfirm]
|
|
10187
11246
|
);
|
|
10188
|
-
const handleCancel = (0,
|
|
11247
|
+
const handleCancel = (0, import_react48.useCallback)(
|
|
10189
11248
|
(e) => {
|
|
10190
11249
|
e.stopPropagation();
|
|
10191
11250
|
onCancel();
|
|
@@ -10195,7 +11254,7 @@ var AskAboutTrigger = (0, import_react47.memo)(function AskAboutTrigger2({
|
|
|
10195
11254
|
if (!visible) {
|
|
10196
11255
|
return null;
|
|
10197
11256
|
}
|
|
10198
|
-
return /* @__PURE__ */ (0,
|
|
11257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
10199
11258
|
"div",
|
|
10200
11259
|
{
|
|
10201
11260
|
ref: triggerRef,
|
|
@@ -10214,8 +11273,8 @@ var AskAboutTrigger = (0, import_react47.memo)(function AskAboutTrigger2({
|
|
|
10214
11273
|
transform: "translate(-50%, 0)"
|
|
10215
11274
|
},
|
|
10216
11275
|
children: [
|
|
10217
|
-
/* @__PURE__ */ (0,
|
|
10218
|
-
/* @__PURE__ */ (0,
|
|
11276
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-sm text-gray-600 dark:text-gray-300 px-2", children: "Ask about this?" }),
|
|
11277
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
10219
11278
|
"button",
|
|
10220
11279
|
{
|
|
10221
11280
|
onClick: handleConfirm,
|
|
@@ -10228,7 +11287,7 @@ var AskAboutTrigger = (0, import_react47.memo)(function AskAboutTrigger2({
|
|
|
10228
11287
|
children: "Ask"
|
|
10229
11288
|
}
|
|
10230
11289
|
),
|
|
10231
|
-
/* @__PURE__ */ (0,
|
|
11290
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
10232
11291
|
"button",
|
|
10233
11292
|
{
|
|
10234
11293
|
onClick: handleCancel,
|
|
@@ -10248,11 +11307,11 @@ var AskAboutTrigger = (0, import_react47.memo)(function AskAboutTrigger2({
|
|
|
10248
11307
|
});
|
|
10249
11308
|
|
|
10250
11309
|
// src/components/Minimap/Minimap.tsx
|
|
10251
|
-
var
|
|
11310
|
+
var import_react49 = require("react");
|
|
10252
11311
|
init_hooks();
|
|
10253
11312
|
init_utils();
|
|
10254
|
-
var
|
|
10255
|
-
var PageIndicator = (0,
|
|
11313
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
11314
|
+
var PageIndicator = (0, import_react49.memo)(function PageIndicator2({
|
|
10256
11315
|
pageNumber,
|
|
10257
11316
|
status,
|
|
10258
11317
|
isBookmarked,
|
|
@@ -10266,7 +11325,7 @@ var PageIndicator = (0, import_react48.memo)(function PageIndicator2({
|
|
|
10266
11325
|
if (status === "visited") return "bg-green-400";
|
|
10267
11326
|
return "bg-gray-200 dark:bg-gray-700";
|
|
10268
11327
|
};
|
|
10269
|
-
return /* @__PURE__ */ (0,
|
|
11328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
10270
11329
|
"button",
|
|
10271
11330
|
{
|
|
10272
11331
|
onClick,
|
|
@@ -10282,13 +11341,13 @@ var PageIndicator = (0, import_react48.memo)(function PageIndicator2({
|
|
|
10282
11341
|
title: `Page ${pageNumber}${isBookmarked ? " (bookmarked)" : ""}`,
|
|
10283
11342
|
"aria-label": `Go to page ${pageNumber}`,
|
|
10284
11343
|
children: [
|
|
10285
|
-
isBookmarked && !compact && /* @__PURE__ */ (0,
|
|
10286
|
-
showNumber && !compact && /* @__PURE__ */ (0,
|
|
11344
|
+
isBookmarked && !compact && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "absolute -top-1 -right-1 w-2 h-2 bg-yellow-500 rounded-full border border-white" }),
|
|
11345
|
+
showNumber && !compact && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "absolute inset-0 flex items-center justify-center text-[8px] font-medium text-white", children: pageNumber })
|
|
10287
11346
|
]
|
|
10288
11347
|
}
|
|
10289
11348
|
);
|
|
10290
11349
|
});
|
|
10291
|
-
var Minimap = (0,
|
|
11350
|
+
var Minimap = (0, import_react49.memo)(function Minimap2({
|
|
10292
11351
|
variant = "sidebar",
|
|
10293
11352
|
floatingPosition = "right",
|
|
10294
11353
|
maxHeight = 300,
|
|
@@ -10301,18 +11360,18 @@ var Minimap = (0, import_react48.memo)(function Minimap2({
|
|
|
10301
11360
|
const currentPage = useViewerStore((s) => s.currentPage);
|
|
10302
11361
|
const numPages = useViewerStore((s) => s.numPages);
|
|
10303
11362
|
const goToPage = useViewerStore((s) => s.goToPage);
|
|
10304
|
-
const bookmarkedPages = (0,
|
|
11363
|
+
const bookmarkedPages = (0, import_react49.useMemo)(() => {
|
|
10305
11364
|
return new Set(bookmarks.map((b) => b.pageNumber));
|
|
10306
11365
|
}, [bookmarks]);
|
|
10307
11366
|
const compact = numPages > 50;
|
|
10308
|
-
const handlePageClick = (0,
|
|
11367
|
+
const handlePageClick = (0, import_react49.useCallback)(
|
|
10309
11368
|
(pageNumber) => {
|
|
10310
11369
|
goToPage(pageNumber);
|
|
10311
11370
|
onPageClick?.(pageNumber);
|
|
10312
11371
|
},
|
|
10313
11372
|
[goToPage, onPageClick]
|
|
10314
11373
|
);
|
|
10315
|
-
const getPageStatus = (0,
|
|
11374
|
+
const getPageStatus = (0, import_react49.useCallback)(
|
|
10316
11375
|
(pageNumber) => {
|
|
10317
11376
|
if (pageNumber === currentPage) return "current";
|
|
10318
11377
|
if (bookmarkedPages.has(pageNumber)) return "bookmarked";
|
|
@@ -10321,11 +11380,11 @@ var Minimap = (0, import_react48.memo)(function Minimap2({
|
|
|
10321
11380
|
},
|
|
10322
11381
|
[currentPage, visitedPages, bookmarkedPages]
|
|
10323
11382
|
);
|
|
10324
|
-
const pageIndicators = (0,
|
|
11383
|
+
const pageIndicators = (0, import_react49.useMemo)(() => {
|
|
10325
11384
|
const pages = [];
|
|
10326
11385
|
for (let i = 1; i <= numPages; i++) {
|
|
10327
11386
|
pages.push(
|
|
10328
|
-
/* @__PURE__ */ (0,
|
|
11387
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
10329
11388
|
PageIndicator,
|
|
10330
11389
|
{
|
|
10331
11390
|
pageNumber: i,
|
|
@@ -10346,16 +11405,16 @@ var Minimap = (0, import_react48.memo)(function Minimap2({
|
|
|
10346
11405
|
if (numPages === 0) {
|
|
10347
11406
|
return null;
|
|
10348
11407
|
}
|
|
10349
|
-
const content = /* @__PURE__ */ (0,
|
|
10350
|
-
/* @__PURE__ */ (0,
|
|
10351
|
-
/* @__PURE__ */ (0,
|
|
10352
|
-
/* @__PURE__ */ (0,
|
|
10353
|
-
/* @__PURE__ */ (0,
|
|
11408
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
11409
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "mb-3", children: [
|
|
11410
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 mb-1", children: [
|
|
11411
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: "Progress" }),
|
|
11412
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { children: [
|
|
10354
11413
|
progressPercentage,
|
|
10355
11414
|
"%"
|
|
10356
11415
|
] })
|
|
10357
11416
|
] }),
|
|
10358
|
-
/* @__PURE__ */ (0,
|
|
11417
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
10359
11418
|
"div",
|
|
10360
11419
|
{
|
|
10361
11420
|
className: "h-full bg-green-500 rounded-full transition-all duration-300",
|
|
@@ -10363,7 +11422,7 @@ var Minimap = (0, import_react48.memo)(function Minimap2({
|
|
|
10363
11422
|
}
|
|
10364
11423
|
) })
|
|
10365
11424
|
] }),
|
|
10366
|
-
/* @__PURE__ */ (0,
|
|
11425
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
10367
11426
|
"div",
|
|
10368
11427
|
{
|
|
10369
11428
|
className: cn(
|
|
@@ -10374,21 +11433,21 @@ var Minimap = (0, import_react48.memo)(function Minimap2({
|
|
|
10374
11433
|
children: pageIndicators
|
|
10375
11434
|
}
|
|
10376
11435
|
),
|
|
10377
|
-
/* @__PURE__ */ (0,
|
|
10378
|
-
/* @__PURE__ */ (0,
|
|
10379
|
-
/* @__PURE__ */ (0,
|
|
10380
|
-
/* @__PURE__ */ (0,
|
|
11436
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "mt-3 pt-2 border-t border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400", children: [
|
|
11437
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
11438
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "w-2 h-2 rounded-sm bg-blue-500" }),
|
|
11439
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: "Current" })
|
|
10381
11440
|
] }),
|
|
10382
|
-
/* @__PURE__ */ (0,
|
|
10383
|
-
/* @__PURE__ */ (0,
|
|
10384
|
-
/* @__PURE__ */ (0,
|
|
11441
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
11442
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "w-2 h-2 rounded-sm bg-green-400" }),
|
|
11443
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: "Visited" })
|
|
10385
11444
|
] }),
|
|
10386
|
-
/* @__PURE__ */ (0,
|
|
10387
|
-
/* @__PURE__ */ (0,
|
|
10388
|
-
/* @__PURE__ */ (0,
|
|
11445
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
11446
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "w-2 h-2 rounded-sm bg-yellow-400" }),
|
|
11447
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: "Bookmarked" })
|
|
10389
11448
|
] })
|
|
10390
11449
|
] }) }),
|
|
10391
|
-
/* @__PURE__ */ (0,
|
|
11450
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "mt-2 text-xs text-gray-500 dark:text-gray-400", children: [
|
|
10392
11451
|
visitedCount,
|
|
10393
11452
|
" of ",
|
|
10394
11453
|
numPages,
|
|
@@ -10396,7 +11455,7 @@ var Minimap = (0, import_react48.memo)(function Minimap2({
|
|
|
10396
11455
|
] })
|
|
10397
11456
|
] });
|
|
10398
11457
|
if (variant === "floating") {
|
|
10399
|
-
return /* @__PURE__ */ (0,
|
|
11458
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
10400
11459
|
"div",
|
|
10401
11460
|
{
|
|
10402
11461
|
className: cn(
|
|
@@ -10412,13 +11471,13 @@ var Minimap = (0, import_react48.memo)(function Minimap2({
|
|
|
10412
11471
|
),
|
|
10413
11472
|
style: { maxHeight },
|
|
10414
11473
|
children: [
|
|
10415
|
-
/* @__PURE__ */ (0,
|
|
11474
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h3", { className: "text-sm font-semibold text-gray-700 dark:text-gray-200 mb-2", children: "Reading Progress" }),
|
|
10416
11475
|
content
|
|
10417
11476
|
]
|
|
10418
11477
|
}
|
|
10419
11478
|
);
|
|
10420
11479
|
}
|
|
10421
|
-
return /* @__PURE__ */ (0,
|
|
11480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
10422
11481
|
"div",
|
|
10423
11482
|
{
|
|
10424
11483
|
className: cn(
|
|
@@ -10432,11 +11491,251 @@ var Minimap = (0, import_react48.memo)(function Minimap2({
|
|
|
10432
11491
|
);
|
|
10433
11492
|
});
|
|
10434
11493
|
|
|
11494
|
+
// src/components/index.ts
|
|
11495
|
+
init_FloatingZoomControls2();
|
|
11496
|
+
|
|
11497
|
+
// src/components/PDFThumbnailNav/PDFThumbnailNav.tsx
|
|
11498
|
+
var import_react50 = require("react");
|
|
11499
|
+
init_hooks();
|
|
11500
|
+
init_utils();
|
|
11501
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
11502
|
+
var DEFAULT_WIDTH = 612;
|
|
11503
|
+
var DEFAULT_HEIGHT = 792;
|
|
11504
|
+
var PDFThumbnailNav = (0, import_react50.memo)(function PDFThumbnailNav2({
|
|
11505
|
+
thumbnailScale = 0.15,
|
|
11506
|
+
orientation = "vertical",
|
|
11507
|
+
maxVisible = 10,
|
|
11508
|
+
className,
|
|
11509
|
+
onThumbnailClick,
|
|
11510
|
+
gap = 8,
|
|
11511
|
+
showPageNumbers = true
|
|
11512
|
+
}) {
|
|
11513
|
+
const { document: document2, numPages, currentPage } = usePDFViewer();
|
|
11514
|
+
const { viewerStore } = usePDFViewerStores();
|
|
11515
|
+
const containerRef = (0, import_react50.useRef)(null);
|
|
11516
|
+
const [thumbnails, setThumbnails] = (0, import_react50.useState)(/* @__PURE__ */ new Map());
|
|
11517
|
+
const [visibleRange, setVisibleRange] = (0, import_react50.useState)({ start: 1, end: maxVisible });
|
|
11518
|
+
const renderQueueRef = (0, import_react50.useRef)(/* @__PURE__ */ new Set());
|
|
11519
|
+
const pageCache = (0, import_react50.useRef)(/* @__PURE__ */ new Map());
|
|
11520
|
+
const thumbnailWidth = Math.floor(DEFAULT_WIDTH * thumbnailScale);
|
|
11521
|
+
const thumbnailHeight = Math.floor(DEFAULT_HEIGHT * thumbnailScale);
|
|
11522
|
+
const updateVisibleRange = (0, import_react50.useCallback)(() => {
|
|
11523
|
+
if (!containerRef.current || numPages === 0) return;
|
|
11524
|
+
const container = containerRef.current;
|
|
11525
|
+
const isHorizontal2 = orientation === "horizontal";
|
|
11526
|
+
const scrollPosition = isHorizontal2 ? container.scrollLeft : container.scrollTop;
|
|
11527
|
+
const viewportSize = isHorizontal2 ? container.clientWidth : container.clientHeight;
|
|
11528
|
+
const itemSize = (isHorizontal2 ? thumbnailWidth : thumbnailHeight) + gap;
|
|
11529
|
+
const firstVisible = Math.max(1, Math.floor(scrollPosition / itemSize) + 1);
|
|
11530
|
+
const visibleCount = Math.ceil(viewportSize / itemSize) + 2;
|
|
11531
|
+
const lastVisible = Math.min(numPages, firstVisible + visibleCount);
|
|
11532
|
+
setVisibleRange({ start: firstVisible, end: lastVisible });
|
|
11533
|
+
}, [numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
|
|
11534
|
+
(0, import_react50.useEffect)(() => {
|
|
11535
|
+
const container = containerRef.current;
|
|
11536
|
+
if (!container) return;
|
|
11537
|
+
const handleScroll = () => {
|
|
11538
|
+
requestAnimationFrame(updateVisibleRange);
|
|
11539
|
+
};
|
|
11540
|
+
container.addEventListener("scroll", handleScroll, { passive: true });
|
|
11541
|
+
updateVisibleRange();
|
|
11542
|
+
return () => container.removeEventListener("scroll", handleScroll);
|
|
11543
|
+
}, [updateVisibleRange]);
|
|
11544
|
+
(0, import_react50.useEffect)(() => {
|
|
11545
|
+
if (!document2) {
|
|
11546
|
+
setThumbnails(/* @__PURE__ */ new Map());
|
|
11547
|
+
pageCache.current.clear();
|
|
11548
|
+
return;
|
|
11549
|
+
}
|
|
11550
|
+
const renderThumbnails = async () => {
|
|
11551
|
+
const newThumbnails = new Map(thumbnails);
|
|
11552
|
+
const pagesToRender = [];
|
|
11553
|
+
for (let i = visibleRange.start; i <= visibleRange.end; i++) {
|
|
11554
|
+
if (!newThumbnails.has(i) && !renderQueueRef.current.has(i)) {
|
|
11555
|
+
pagesToRender.push(i);
|
|
11556
|
+
renderQueueRef.current.add(i);
|
|
11557
|
+
}
|
|
11558
|
+
}
|
|
11559
|
+
for (const pageNum of pagesToRender) {
|
|
11560
|
+
try {
|
|
11561
|
+
let page = pageCache.current.get(pageNum);
|
|
11562
|
+
if (!page) {
|
|
11563
|
+
page = await document2.getPage(pageNum);
|
|
11564
|
+
pageCache.current.set(pageNum, page);
|
|
11565
|
+
}
|
|
11566
|
+
const viewport = page.getViewport({ scale: thumbnailScale });
|
|
11567
|
+
const canvas = window.document.createElement("canvas");
|
|
11568
|
+
canvas.width = Math.floor(viewport.width);
|
|
11569
|
+
canvas.height = Math.floor(viewport.height);
|
|
11570
|
+
const ctx = canvas.getContext("2d");
|
|
11571
|
+
if (ctx) {
|
|
11572
|
+
await page.render({
|
|
11573
|
+
canvasContext: ctx,
|
|
11574
|
+
viewport
|
|
11575
|
+
}).promise;
|
|
11576
|
+
newThumbnails.set(pageNum, {
|
|
11577
|
+
pageNumber: pageNum,
|
|
11578
|
+
canvas,
|
|
11579
|
+
width: canvas.width,
|
|
11580
|
+
height: canvas.height
|
|
11581
|
+
});
|
|
11582
|
+
}
|
|
11583
|
+
} catch (error) {
|
|
11584
|
+
console.error(`Failed to render thumbnail for page ${pageNum}:`, error);
|
|
11585
|
+
} finally {
|
|
11586
|
+
renderQueueRef.current.delete(pageNum);
|
|
11587
|
+
}
|
|
11588
|
+
}
|
|
11589
|
+
if (pagesToRender.length > 0) {
|
|
11590
|
+
setThumbnails(newThumbnails);
|
|
11591
|
+
}
|
|
11592
|
+
};
|
|
11593
|
+
renderThumbnails();
|
|
11594
|
+
}, [document2, visibleRange, thumbnailScale, thumbnails]);
|
|
11595
|
+
(0, import_react50.useEffect)(() => {
|
|
11596
|
+
if (!containerRef.current || numPages === 0) return;
|
|
11597
|
+
const container = containerRef.current;
|
|
11598
|
+
const isHorizontal2 = orientation === "horizontal";
|
|
11599
|
+
const itemSize = (isHorizontal2 ? thumbnailWidth : thumbnailHeight) + gap;
|
|
11600
|
+
const targetPosition = (currentPage - 1) * itemSize;
|
|
11601
|
+
const scrollPosition = isHorizontal2 ? container.scrollLeft : container.scrollTop;
|
|
11602
|
+
const viewportSize = isHorizontal2 ? container.clientWidth : container.clientHeight;
|
|
11603
|
+
if (targetPosition < scrollPosition || targetPosition + itemSize > scrollPosition + viewportSize) {
|
|
11604
|
+
const targetScroll = targetPosition - (viewportSize - itemSize) / 2;
|
|
11605
|
+
container.scrollTo({
|
|
11606
|
+
[isHorizontal2 ? "left" : "top"]: Math.max(0, targetScroll),
|
|
11607
|
+
behavior: "smooth"
|
|
11608
|
+
});
|
|
11609
|
+
}
|
|
11610
|
+
}, [currentPage, numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
|
|
11611
|
+
const handleThumbnailClick = (0, import_react50.useCallback)((pageNum) => {
|
|
11612
|
+
onThumbnailClick?.(pageNum);
|
|
11613
|
+
viewerStore.getState().requestScrollToPage(pageNum, "smooth");
|
|
11614
|
+
}, [onThumbnailClick, viewerStore]);
|
|
11615
|
+
if (!document2 || numPages === 0) {
|
|
11616
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
11617
|
+
"div",
|
|
11618
|
+
{
|
|
11619
|
+
className: cn(
|
|
11620
|
+
"pdf-thumbnail-nav",
|
|
11621
|
+
"flex items-center justify-center",
|
|
11622
|
+
"bg-gray-100 dark:bg-gray-800",
|
|
11623
|
+
"text-gray-500 dark:text-gray-400",
|
|
11624
|
+
"text-sm",
|
|
11625
|
+
className
|
|
11626
|
+
),
|
|
11627
|
+
style: {
|
|
11628
|
+
width: orientation === "vertical" ? thumbnailWidth + 24 : "100%",
|
|
11629
|
+
height: orientation === "horizontal" ? thumbnailHeight + 40 : "100%"
|
|
11630
|
+
},
|
|
11631
|
+
children: "No document"
|
|
11632
|
+
}
|
|
11633
|
+
);
|
|
11634
|
+
}
|
|
11635
|
+
const isHorizontal = orientation === "horizontal";
|
|
11636
|
+
const totalSize = numPages * ((isHorizontal ? thumbnailWidth : thumbnailHeight) + gap) - gap;
|
|
11637
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
11638
|
+
"div",
|
|
11639
|
+
{
|
|
11640
|
+
ref: containerRef,
|
|
11641
|
+
className: cn(
|
|
11642
|
+
"pdf-thumbnail-nav",
|
|
11643
|
+
"overflow-auto",
|
|
11644
|
+
"bg-gray-100 dark:bg-gray-800",
|
|
11645
|
+
isHorizontal ? "flex-row" : "flex-col",
|
|
11646
|
+
className
|
|
11647
|
+
),
|
|
11648
|
+
style: {
|
|
11649
|
+
...isHorizontal ? { overflowX: "auto", overflowY: "hidden" } : { overflowX: "hidden", overflowY: "auto" }
|
|
11650
|
+
},
|
|
11651
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
11652
|
+
"div",
|
|
11653
|
+
{
|
|
11654
|
+
className: cn(
|
|
11655
|
+
"relative",
|
|
11656
|
+
isHorizontal ? "flex flex-row items-center" : "flex flex-col items-center"
|
|
11657
|
+
),
|
|
11658
|
+
style: {
|
|
11659
|
+
[isHorizontal ? "width" : "height"]: totalSize,
|
|
11660
|
+
[isHorizontal ? "minWidth" : "minHeight"]: totalSize,
|
|
11661
|
+
padding: gap / 2,
|
|
11662
|
+
gap
|
|
11663
|
+
},
|
|
11664
|
+
children: Array.from({ length: numPages }, (_, i) => i + 1).map((pageNum) => {
|
|
11665
|
+
const thumbnail = thumbnails.get(pageNum);
|
|
11666
|
+
const isActive = pageNum === currentPage;
|
|
11667
|
+
const isVisible = pageNum >= visibleRange.start && pageNum <= visibleRange.end;
|
|
11668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
11669
|
+
"div",
|
|
11670
|
+
{
|
|
11671
|
+
className: cn(
|
|
11672
|
+
"pdf-thumbnail",
|
|
11673
|
+
"flex-shrink-0 cursor-pointer transition-all duration-200",
|
|
11674
|
+
"border-2 rounded shadow-sm hover:shadow-md",
|
|
11675
|
+
isActive ? "border-blue-500 ring-2 ring-blue-200 dark:ring-blue-800" : "border-gray-300 dark:border-gray-600 hover:border-blue-400"
|
|
11676
|
+
),
|
|
11677
|
+
style: {
|
|
11678
|
+
width: thumbnailWidth,
|
|
11679
|
+
height: thumbnailHeight + (showPageNumbers ? 24 : 0)
|
|
11680
|
+
},
|
|
11681
|
+
onClick: () => handleThumbnailClick(pageNum),
|
|
11682
|
+
role: "button",
|
|
11683
|
+
tabIndex: 0,
|
|
11684
|
+
"aria-label": `Go to page ${pageNum}`,
|
|
11685
|
+
"aria-current": isActive ? "page" : void 0,
|
|
11686
|
+
onKeyDown: (e) => {
|
|
11687
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
11688
|
+
e.preventDefault();
|
|
11689
|
+
handleThumbnailClick(pageNum);
|
|
11690
|
+
}
|
|
11691
|
+
},
|
|
11692
|
+
children: [
|
|
11693
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
11694
|
+
"div",
|
|
11695
|
+
{
|
|
11696
|
+
className: "relative bg-white dark:bg-gray-700",
|
|
11697
|
+
style: {
|
|
11698
|
+
width: thumbnailWidth,
|
|
11699
|
+
height: thumbnailHeight
|
|
11700
|
+
},
|
|
11701
|
+
children: isVisible && thumbnail?.canvas ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
11702
|
+
"img",
|
|
11703
|
+
{
|
|
11704
|
+
src: thumbnail.canvas.toDataURL(),
|
|
11705
|
+
alt: `Page ${pageNum}`,
|
|
11706
|
+
className: "w-full h-full object-contain",
|
|
11707
|
+
loading: "lazy"
|
|
11708
|
+
}
|
|
11709
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "absolute inset-0 flex items-center justify-center text-gray-400 dark:text-gray-500 text-xs", children: pageNum })
|
|
11710
|
+
}
|
|
11711
|
+
),
|
|
11712
|
+
showPageNumbers && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
11713
|
+
"div",
|
|
11714
|
+
{
|
|
11715
|
+
className: cn(
|
|
11716
|
+
"text-center text-xs py-1",
|
|
11717
|
+
"bg-gray-50 dark:bg-gray-700",
|
|
11718
|
+
isActive ? "text-blue-600 dark:text-blue-400 font-medium" : "text-gray-600 dark:text-gray-400"
|
|
11719
|
+
),
|
|
11720
|
+
children: pageNum
|
|
11721
|
+
}
|
|
11722
|
+
)
|
|
11723
|
+
]
|
|
11724
|
+
},
|
|
11725
|
+
pageNum
|
|
11726
|
+
);
|
|
11727
|
+
})
|
|
11728
|
+
}
|
|
11729
|
+
)
|
|
11730
|
+
}
|
|
11731
|
+
);
|
|
11732
|
+
});
|
|
11733
|
+
|
|
10435
11734
|
// src/components/ErrorBoundary/PDFErrorBoundary.tsx
|
|
10436
|
-
var
|
|
11735
|
+
var import_react51 = require("react");
|
|
10437
11736
|
init_utils();
|
|
10438
|
-
var
|
|
10439
|
-
var PDFErrorBoundary = class extends
|
|
11737
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
11738
|
+
var PDFErrorBoundary = class extends import_react51.Component {
|
|
10440
11739
|
constructor(props) {
|
|
10441
11740
|
super(props);
|
|
10442
11741
|
this.handleReset = () => {
|
|
@@ -10463,7 +11762,7 @@ var PDFErrorBoundary = class extends import_react49.Component {
|
|
|
10463
11762
|
return fallback;
|
|
10464
11763
|
}
|
|
10465
11764
|
if (showDefaultUI) {
|
|
10466
|
-
return /* @__PURE__ */ (0,
|
|
11765
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
10467
11766
|
DefaultErrorUI,
|
|
10468
11767
|
{
|
|
10469
11768
|
error,
|
|
@@ -10482,7 +11781,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10482
11781
|
const isNetworkError = error.message.includes("fetch") || error.message.includes("network") || error.message.includes("Failed to load");
|
|
10483
11782
|
let title = "Something went wrong";
|
|
10484
11783
|
let description = error.message;
|
|
10485
|
-
let icon = /* @__PURE__ */ (0,
|
|
11784
|
+
let icon = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
10486
11785
|
"path",
|
|
10487
11786
|
{
|
|
10488
11787
|
strokeLinecap: "round",
|
|
@@ -10494,7 +11793,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10494
11793
|
if (isPDFError) {
|
|
10495
11794
|
title = "Unable to load PDF";
|
|
10496
11795
|
description = "The PDF file could not be loaded. It may be corrupted or in an unsupported format.";
|
|
10497
|
-
icon = /* @__PURE__ */ (0,
|
|
11796
|
+
icon = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
10498
11797
|
"path",
|
|
10499
11798
|
{
|
|
10500
11799
|
strokeLinecap: "round",
|
|
@@ -10506,7 +11805,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10506
11805
|
} else if (isNetworkError) {
|
|
10507
11806
|
title = "Network error";
|
|
10508
11807
|
description = "Unable to fetch the PDF file. Please check your internet connection and try again.";
|
|
10509
|
-
icon = /* @__PURE__ */ (0,
|
|
11808
|
+
icon = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
10510
11809
|
"path",
|
|
10511
11810
|
{
|
|
10512
11811
|
strokeLinecap: "round",
|
|
@@ -10516,7 +11815,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10516
11815
|
}
|
|
10517
11816
|
) });
|
|
10518
11817
|
}
|
|
10519
|
-
return /* @__PURE__ */ (0,
|
|
11818
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
10520
11819
|
"div",
|
|
10521
11820
|
{
|
|
10522
11821
|
className: cn(
|
|
@@ -10529,14 +11828,14 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10529
11828
|
),
|
|
10530
11829
|
children: [
|
|
10531
11830
|
icon,
|
|
10532
|
-
/* @__PURE__ */ (0,
|
|
10533
|
-
/* @__PURE__ */ (0,
|
|
10534
|
-
/* @__PURE__ */ (0,
|
|
10535
|
-
/* @__PURE__ */ (0,
|
|
10536
|
-
/* @__PURE__ */ (0,
|
|
11831
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("h2", { className: "mt-4 text-xl font-semibold text-gray-900 dark:text-gray-100", children: title }),
|
|
11832
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 max-w-md", children: description }),
|
|
11833
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("details", { className: "mt-4 text-left max-w-md w-full", children: [
|
|
11834
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("summary", { className: "cursor-pointer text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200", children: "Technical details" }),
|
|
11835
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("pre", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto", children: error.stack || error.message })
|
|
10537
11836
|
] }),
|
|
10538
|
-
/* @__PURE__ */ (0,
|
|
10539
|
-
/* @__PURE__ */ (0,
|
|
11837
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "mt-6 flex gap-3", children: [
|
|
11838
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
10540
11839
|
"button",
|
|
10541
11840
|
{
|
|
10542
11841
|
onClick: onReset,
|
|
@@ -10550,7 +11849,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10550
11849
|
children: "Try again"
|
|
10551
11850
|
}
|
|
10552
11851
|
),
|
|
10553
|
-
/* @__PURE__ */ (0,
|
|
11852
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
10554
11853
|
"button",
|
|
10555
11854
|
{
|
|
10556
11855
|
onClick: () => window.location.reload(),
|
|
@@ -10570,7 +11869,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10570
11869
|
);
|
|
10571
11870
|
}
|
|
10572
11871
|
function withErrorBoundary({ component, ...props }) {
|
|
10573
|
-
return /* @__PURE__ */ (0,
|
|
11872
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(PDFErrorBoundary, { ...props, children: component });
|
|
10574
11873
|
}
|
|
10575
11874
|
|
|
10576
11875
|
// src/index.ts
|
|
@@ -10594,6 +11893,7 @@ init_utils();
|
|
|
10594
11893
|
DocumentContainer,
|
|
10595
11894
|
DrawingCanvas,
|
|
10596
11895
|
DualPageContainer,
|
|
11896
|
+
FloatingZoomControls,
|
|
10597
11897
|
FocusRegionLayer,
|
|
10598
11898
|
HighlightLayer,
|
|
10599
11899
|
HighlightPopover,
|
|
@@ -10604,6 +11904,7 @@ init_utils();
|
|
|
10604
11904
|
OutlinePanel,
|
|
10605
11905
|
PDFErrorBoundary,
|
|
10606
11906
|
PDFPage,
|
|
11907
|
+
PDFThumbnailNav,
|
|
10607
11908
|
PDFViewer,
|
|
10608
11909
|
PDFViewerClient,
|
|
10609
11910
|
PDFViewerContext,
|
|
@@ -10622,9 +11923,11 @@ init_utils();
|
|
|
10622
11923
|
ThumbnailPanel,
|
|
10623
11924
|
Toolbar,
|
|
10624
11925
|
VirtualizedDocumentContainer,
|
|
11926
|
+
applyRotation,
|
|
10625
11927
|
clearHighlights,
|
|
10626
11928
|
clearStudentData,
|
|
10627
11929
|
cn,
|
|
11930
|
+
countTextOnPage,
|
|
10628
11931
|
createAgentAPI,
|
|
10629
11932
|
createAgentStore,
|
|
10630
11933
|
createAnnotationStore,
|
|
@@ -10633,6 +11936,7 @@ init_utils();
|
|
|
10633
11936
|
createSearchStore,
|
|
10634
11937
|
createStudentStore,
|
|
10635
11938
|
createViewerStore,
|
|
11939
|
+
doRectsIntersect,
|
|
10636
11940
|
downloadAnnotationsAsJSON,
|
|
10637
11941
|
downloadAnnotationsAsMarkdown,
|
|
10638
11942
|
downloadFile,
|
|
@@ -10640,25 +11944,39 @@ init_utils();
|
|
|
10640
11944
|
exportAnnotationsAsMarkdown,
|
|
10641
11945
|
exportHighlightsAsJSON,
|
|
10642
11946
|
exportHighlightsAsMarkdown,
|
|
11947
|
+
extractPageText,
|
|
11948
|
+
findTextInDocument,
|
|
11949
|
+
findTextOnPage,
|
|
10643
11950
|
generateDocumentId,
|
|
10644
11951
|
getAllDocumentIds,
|
|
10645
11952
|
getAllStudentDataDocumentIds,
|
|
10646
11953
|
getMetadata,
|
|
10647
11954
|
getOutline,
|
|
10648
11955
|
getPage,
|
|
11956
|
+
getPageText,
|
|
10649
11957
|
getPageTextContent,
|
|
10650
11958
|
getPluginManager,
|
|
11959
|
+
getRectIntersection,
|
|
11960
|
+
getRotatedDimensions,
|
|
10651
11961
|
getStorageStats,
|
|
10652
11962
|
importHighlightsFromJSON,
|
|
10653
11963
|
initializePDFJS,
|
|
10654
11964
|
isPDFJSInitialized,
|
|
11965
|
+
isPointInRect,
|
|
10655
11966
|
loadDocument,
|
|
10656
11967
|
loadHighlights,
|
|
10657
11968
|
loadStudentData,
|
|
11969
|
+
mergeAdjacentRects,
|
|
11970
|
+
pdfToPercent,
|
|
11971
|
+
pdfToViewport,
|
|
10658
11972
|
pdfjsLib,
|
|
11973
|
+
percentToPDF,
|
|
11974
|
+
percentToViewport,
|
|
10659
11975
|
quickViewer,
|
|
11976
|
+
removeRotation,
|
|
10660
11977
|
saveHighlights,
|
|
10661
11978
|
saveStudentData,
|
|
11979
|
+
scaleRect,
|
|
10662
11980
|
useAgentContext,
|
|
10663
11981
|
useAgentStore,
|
|
10664
11982
|
useAnnotationStore,
|
|
@@ -10680,6 +11998,8 @@ init_utils();
|
|
|
10680
11998
|
useTouchGestures,
|
|
10681
11999
|
useViewerStore,
|
|
10682
12000
|
useZoom,
|
|
12001
|
+
viewportToPDF,
|
|
12002
|
+
viewportToPercent,
|
|
10683
12003
|
withErrorBoundary
|
|
10684
12004
|
});
|
|
10685
12005
|
//# sourceMappingURL=index.cjs.map
|