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.js
CHANGED
|
@@ -310,6 +310,9 @@ var init_highlight_storage = __esm({
|
|
|
310
310
|
|
|
311
311
|
// src/store/viewer-store.ts
|
|
312
312
|
import { createStore } from "zustand/vanilla";
|
|
313
|
+
function generateRequestId() {
|
|
314
|
+
return `scroll-${Date.now()}-${++requestCounter}`;
|
|
315
|
+
}
|
|
313
316
|
function createViewerStore(initialOverrides = {}) {
|
|
314
317
|
return createStore()((set, get) => ({
|
|
315
318
|
...initialState,
|
|
@@ -362,6 +365,46 @@ function createViewerStore(initialOverrides = {}) {
|
|
|
362
365
|
set({ currentPage: currentPage - 1 });
|
|
363
366
|
}
|
|
364
367
|
},
|
|
368
|
+
// Scroll coordination actions
|
|
369
|
+
requestScrollToPage: (page, behavior = "smooth") => {
|
|
370
|
+
const { numPages } = get();
|
|
371
|
+
const validPage = Math.max(1, Math.min(page, numPages));
|
|
372
|
+
return new Promise((resolve) => {
|
|
373
|
+
const requestId = generateRequestId();
|
|
374
|
+
const timeoutId = setTimeout(() => {
|
|
375
|
+
const callback = scrollCallbacks.get(requestId);
|
|
376
|
+
if (callback) {
|
|
377
|
+
scrollCallbacks.delete(requestId);
|
|
378
|
+
callback.resolve();
|
|
379
|
+
}
|
|
380
|
+
const currentRequest = get().scrollToPageRequest;
|
|
381
|
+
if (currentRequest?.requestId === requestId) {
|
|
382
|
+
set({ scrollToPageRequest: null });
|
|
383
|
+
}
|
|
384
|
+
}, SCROLL_TIMEOUT_MS);
|
|
385
|
+
scrollCallbacks.set(requestId, { resolve, timeoutId });
|
|
386
|
+
set({
|
|
387
|
+
currentPage: validPage,
|
|
388
|
+
scrollToPageRequest: {
|
|
389
|
+
page: validPage,
|
|
390
|
+
requestId,
|
|
391
|
+
behavior
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
},
|
|
396
|
+
completeScrollRequest: (requestId) => {
|
|
397
|
+
const callback = scrollCallbacks.get(requestId);
|
|
398
|
+
if (callback) {
|
|
399
|
+
clearTimeout(callback.timeoutId);
|
|
400
|
+
scrollCallbacks.delete(requestId);
|
|
401
|
+
callback.resolve();
|
|
402
|
+
}
|
|
403
|
+
const currentRequest = get().scrollToPageRequest;
|
|
404
|
+
if (currentRequest?.requestId === requestId) {
|
|
405
|
+
set({ scrollToPageRequest: null });
|
|
406
|
+
}
|
|
407
|
+
},
|
|
365
408
|
// Zoom actions
|
|
366
409
|
setScale: (scale) => {
|
|
367
410
|
const clampedScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
|
|
@@ -428,13 +471,16 @@ function createViewerStore(initialOverrides = {}) {
|
|
|
428
471
|
}
|
|
429
472
|
}));
|
|
430
473
|
}
|
|
431
|
-
var ZOOM_LEVELS, MIN_SCALE, MAX_SCALE, initialState;
|
|
474
|
+
var ZOOM_LEVELS, MIN_SCALE, MAX_SCALE, SCROLL_TIMEOUT_MS, scrollCallbacks, requestCounter, initialState;
|
|
432
475
|
var init_viewer_store = __esm({
|
|
433
476
|
"src/store/viewer-store.ts"() {
|
|
434
477
|
"use strict";
|
|
435
478
|
ZOOM_LEVELS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 3, 4];
|
|
436
479
|
MIN_SCALE = 0.1;
|
|
437
480
|
MAX_SCALE = 10;
|
|
481
|
+
SCROLL_TIMEOUT_MS = 3e3;
|
|
482
|
+
scrollCallbacks = /* @__PURE__ */ new Map();
|
|
483
|
+
requestCounter = 0;
|
|
438
484
|
initialState = {
|
|
439
485
|
// Document state
|
|
440
486
|
document: null,
|
|
@@ -445,6 +491,8 @@ var init_viewer_store = __esm({
|
|
|
445
491
|
currentPage: 1,
|
|
446
492
|
scale: 1,
|
|
447
493
|
rotation: 0,
|
|
494
|
+
// Scroll coordination
|
|
495
|
+
scrollToPageRequest: null,
|
|
448
496
|
// UI state
|
|
449
497
|
viewMode: "single",
|
|
450
498
|
scrollMode: "single",
|
|
@@ -1253,6 +1301,252 @@ var init_agent_api = __esm({
|
|
|
1253
1301
|
}
|
|
1254
1302
|
});
|
|
1255
1303
|
|
|
1304
|
+
// src/utils/text-search.ts
|
|
1305
|
+
async function extractPageText(document2, pageNumber) {
|
|
1306
|
+
const page = await document2.getPage(pageNumber);
|
|
1307
|
+
const textContent = await page.getTextContent();
|
|
1308
|
+
const viewport = page.getViewport({ scale: 1 });
|
|
1309
|
+
let fullText = "";
|
|
1310
|
+
const charPositions = [];
|
|
1311
|
+
for (const item of textContent.items) {
|
|
1312
|
+
if ("str" in item && item.str) {
|
|
1313
|
+
const tx = item.transform;
|
|
1314
|
+
const x = tx[4];
|
|
1315
|
+
const y = viewport.height - tx[5];
|
|
1316
|
+
const width = item.width ?? 0;
|
|
1317
|
+
const height = item.height ?? 12;
|
|
1318
|
+
const charWidth = item.str.length > 0 ? width / item.str.length : width;
|
|
1319
|
+
for (let i = 0; i < item.str.length; i++) {
|
|
1320
|
+
charPositions.push({
|
|
1321
|
+
char: item.str[i],
|
|
1322
|
+
rect: {
|
|
1323
|
+
x: x + i * charWidth,
|
|
1324
|
+
y: y - height,
|
|
1325
|
+
width: charWidth,
|
|
1326
|
+
height
|
|
1327
|
+
}
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
fullText += item.str;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
return { fullText, charPositions };
|
|
1334
|
+
}
|
|
1335
|
+
async function findTextOnPage(document2, pageNumber, query, options = {}) {
|
|
1336
|
+
const { caseSensitive = false, wholeWord = false } = options;
|
|
1337
|
+
if (!query || pageNumber < 1 || pageNumber > document2.numPages) {
|
|
1338
|
+
return [];
|
|
1339
|
+
}
|
|
1340
|
+
const { fullText, charPositions } = await extractPageText(document2, pageNumber);
|
|
1341
|
+
const matches = [];
|
|
1342
|
+
const searchText = caseSensitive ? query : query.toLowerCase();
|
|
1343
|
+
const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();
|
|
1344
|
+
let startIndex = 0;
|
|
1345
|
+
while (true) {
|
|
1346
|
+
const matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
1347
|
+
if (matchIndex === -1) break;
|
|
1348
|
+
if (wholeWord) {
|
|
1349
|
+
const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : " ";
|
|
1350
|
+
const afterChar = matchIndex + query.length < textToSearch.length ? textToSearch[matchIndex + query.length] : " ";
|
|
1351
|
+
if (/\w/.test(beforeChar) || /\w/.test(afterChar)) {
|
|
1352
|
+
startIndex = matchIndex + 1;
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
const matchRects = [];
|
|
1357
|
+
for (let i = matchIndex; i < matchIndex + query.length && i < charPositions.length; i++) {
|
|
1358
|
+
matchRects.push(charPositions[i].rect);
|
|
1359
|
+
}
|
|
1360
|
+
const mergedRects = mergeAdjacentRects(matchRects);
|
|
1361
|
+
matches.push({
|
|
1362
|
+
text: fullText.substring(matchIndex, matchIndex + query.length),
|
|
1363
|
+
rects: mergedRects,
|
|
1364
|
+
pageNumber,
|
|
1365
|
+
startIndex: matchIndex
|
|
1366
|
+
});
|
|
1367
|
+
startIndex = matchIndex + 1;
|
|
1368
|
+
}
|
|
1369
|
+
return matches;
|
|
1370
|
+
}
|
|
1371
|
+
async function findTextInDocument(document2, query, options = {}) {
|
|
1372
|
+
const { pageRange, ...findOptions } = options;
|
|
1373
|
+
const pagesToSearch = pageRange ?? Array.from({ length: document2.numPages }, (_, i) => i + 1);
|
|
1374
|
+
const allMatches = [];
|
|
1375
|
+
for (const pageNum of pagesToSearch) {
|
|
1376
|
+
if (pageNum < 1 || pageNum > document2.numPages) continue;
|
|
1377
|
+
try {
|
|
1378
|
+
const matches = await findTextOnPage(document2, pageNum, query, findOptions);
|
|
1379
|
+
allMatches.push(...matches);
|
|
1380
|
+
} catch {
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
return allMatches;
|
|
1384
|
+
}
|
|
1385
|
+
function mergeAdjacentRects(rects) {
|
|
1386
|
+
if (rects.length === 0) return [];
|
|
1387
|
+
const sorted = [...rects].sort((a, b) => a.y - b.y || a.x - b.x);
|
|
1388
|
+
const merged = [];
|
|
1389
|
+
let current = { ...sorted[0] };
|
|
1390
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
1391
|
+
const rect = sorted[i];
|
|
1392
|
+
if (Math.abs(rect.y - current.y) < 2 && rect.x <= current.x + current.width + 2) {
|
|
1393
|
+
const newRight = Math.max(current.x + current.width, rect.x + rect.width);
|
|
1394
|
+
current.width = newRight - current.x;
|
|
1395
|
+
current.height = Math.max(current.height, rect.height);
|
|
1396
|
+
} else {
|
|
1397
|
+
merged.push(current);
|
|
1398
|
+
current = { ...rect };
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
merged.push(current);
|
|
1402
|
+
return merged;
|
|
1403
|
+
}
|
|
1404
|
+
async function getPageText(document2, pageNumber) {
|
|
1405
|
+
if (pageNumber < 1 || pageNumber > document2.numPages) {
|
|
1406
|
+
return "";
|
|
1407
|
+
}
|
|
1408
|
+
const page = await document2.getPage(pageNumber);
|
|
1409
|
+
const textContent = await page.getTextContent();
|
|
1410
|
+
return textContent.items.filter((item) => "str" in item).map((item) => item.str).join("");
|
|
1411
|
+
}
|
|
1412
|
+
async function countTextOnPage(document2, pageNumber, query, options = {}) {
|
|
1413
|
+
const { caseSensitive = false, wholeWord = false } = options;
|
|
1414
|
+
if (!query || pageNumber < 1 || pageNumber > document2.numPages) {
|
|
1415
|
+
return 0;
|
|
1416
|
+
}
|
|
1417
|
+
const text = await getPageText(document2, pageNumber);
|
|
1418
|
+
const searchText = caseSensitive ? query : query.toLowerCase();
|
|
1419
|
+
const textToSearch = caseSensitive ? text : text.toLowerCase();
|
|
1420
|
+
let count = 0;
|
|
1421
|
+
let startIndex = 0;
|
|
1422
|
+
while (true) {
|
|
1423
|
+
const matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
1424
|
+
if (matchIndex === -1) break;
|
|
1425
|
+
if (wholeWord) {
|
|
1426
|
+
const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : " ";
|
|
1427
|
+
const afterChar = matchIndex + query.length < textToSearch.length ? textToSearch[matchIndex + query.length] : " ";
|
|
1428
|
+
if (/\w/.test(beforeChar) || /\w/.test(afterChar)) {
|
|
1429
|
+
startIndex = matchIndex + 1;
|
|
1430
|
+
continue;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
count++;
|
|
1434
|
+
startIndex = matchIndex + 1;
|
|
1435
|
+
}
|
|
1436
|
+
return count;
|
|
1437
|
+
}
|
|
1438
|
+
var init_text_search = __esm({
|
|
1439
|
+
"src/utils/text-search.ts"() {
|
|
1440
|
+
"use strict";
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
|
|
1444
|
+
// src/utils/coordinates.ts
|
|
1445
|
+
function pdfToViewport(x, y, scale, pageHeight) {
|
|
1446
|
+
return {
|
|
1447
|
+
x: x * scale,
|
|
1448
|
+
y: (pageHeight - y) * scale
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
function viewportToPDF(x, y, scale, pageHeight) {
|
|
1452
|
+
return {
|
|
1453
|
+
x: x / scale,
|
|
1454
|
+
y: pageHeight - y / scale
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
function percentToPDF(xPercent, yPercent, pageWidth, pageHeight) {
|
|
1458
|
+
return {
|
|
1459
|
+
x: xPercent / 100 * pageWidth,
|
|
1460
|
+
y: yPercent / 100 * pageHeight
|
|
1461
|
+
};
|
|
1462
|
+
}
|
|
1463
|
+
function pdfToPercent(x, y, pageWidth, pageHeight) {
|
|
1464
|
+
return {
|
|
1465
|
+
x: x / pageWidth * 100,
|
|
1466
|
+
y: y / pageHeight * 100
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
function percentToViewport(xPercent, yPercent, pageWidth, pageHeight, scale) {
|
|
1470
|
+
return {
|
|
1471
|
+
x: xPercent / 100 * pageWidth * scale,
|
|
1472
|
+
y: yPercent / 100 * pageHeight * scale
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function viewportToPercent(x, y, pageWidth, pageHeight, scale) {
|
|
1476
|
+
return {
|
|
1477
|
+
x: x / (pageWidth * scale) * 100,
|
|
1478
|
+
y: y / (pageHeight * scale) * 100
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
function applyRotation(x, y, rotation, pageWidth, pageHeight) {
|
|
1482
|
+
const normalizedRotation = (rotation % 360 + 360) % 360;
|
|
1483
|
+
switch (normalizedRotation) {
|
|
1484
|
+
case 90:
|
|
1485
|
+
return { x: y, y: pageWidth - x };
|
|
1486
|
+
case 180:
|
|
1487
|
+
return { x: pageWidth - x, y: pageHeight - y };
|
|
1488
|
+
case 270:
|
|
1489
|
+
return { x: pageHeight - y, y: x };
|
|
1490
|
+
default:
|
|
1491
|
+
return { x, y };
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
function removeRotation(x, y, rotation, pageWidth, pageHeight) {
|
|
1495
|
+
const normalizedRotation = (rotation % 360 + 360) % 360;
|
|
1496
|
+
switch (normalizedRotation) {
|
|
1497
|
+
case 90:
|
|
1498
|
+
return { x: pageWidth - y, y: x };
|
|
1499
|
+
case 180:
|
|
1500
|
+
return { x: pageWidth - x, y: pageHeight - y };
|
|
1501
|
+
case 270:
|
|
1502
|
+
return { x: y, y: pageHeight - x };
|
|
1503
|
+
default:
|
|
1504
|
+
return { x, y };
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
function getRotatedDimensions(width, height, rotation) {
|
|
1508
|
+
const normalizedRotation = (rotation % 360 + 360) % 360;
|
|
1509
|
+
if (normalizedRotation === 90 || normalizedRotation === 270) {
|
|
1510
|
+
return { width: height, height: width };
|
|
1511
|
+
}
|
|
1512
|
+
return { width, height };
|
|
1513
|
+
}
|
|
1514
|
+
function scaleRect(rect, fromScale, toScale) {
|
|
1515
|
+
const ratio = toScale / fromScale;
|
|
1516
|
+
return {
|
|
1517
|
+
x: rect.x * ratio,
|
|
1518
|
+
y: rect.y * ratio,
|
|
1519
|
+
width: rect.width * ratio,
|
|
1520
|
+
height: rect.height * ratio
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
function isPointInRect(point, rect) {
|
|
1524
|
+
return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
|
|
1525
|
+
}
|
|
1526
|
+
function doRectsIntersect(rectA, rectB) {
|
|
1527
|
+
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);
|
|
1528
|
+
}
|
|
1529
|
+
function getRectIntersection(rectA, rectB) {
|
|
1530
|
+
const x = Math.max(rectA.x, rectB.x);
|
|
1531
|
+
const y = Math.max(rectA.y, rectB.y);
|
|
1532
|
+
const right = Math.min(rectA.x + rectA.width, rectB.x + rectB.width);
|
|
1533
|
+
const bottom = Math.min(rectA.y + rectA.height, rectB.y + rectB.height);
|
|
1534
|
+
if (right <= x || bottom <= y) {
|
|
1535
|
+
return null;
|
|
1536
|
+
}
|
|
1537
|
+
return {
|
|
1538
|
+
x,
|
|
1539
|
+
y,
|
|
1540
|
+
width: right - x,
|
|
1541
|
+
height: bottom - y
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
var init_coordinates = __esm({
|
|
1545
|
+
"src/utils/coordinates.ts"() {
|
|
1546
|
+
"use strict";
|
|
1547
|
+
}
|
|
1548
|
+
});
|
|
1549
|
+
|
|
1256
1550
|
// src/utils/index.ts
|
|
1257
1551
|
var init_utils = __esm({
|
|
1258
1552
|
"src/utils/index.ts"() {
|
|
@@ -1265,6 +1559,8 @@ var init_utils = __esm({
|
|
|
1265
1559
|
init_export_annotations();
|
|
1266
1560
|
init_student_storage();
|
|
1267
1561
|
init_agent_api();
|
|
1562
|
+
init_text_search();
|
|
1563
|
+
init_coordinates();
|
|
1268
1564
|
}
|
|
1269
1565
|
});
|
|
1270
1566
|
|
|
@@ -1361,6 +1657,12 @@ function createSearchStore(initialOverrides = {}) {
|
|
|
1361
1657
|
set({ currentResultIndex: index });
|
|
1362
1658
|
}
|
|
1363
1659
|
},
|
|
1660
|
+
setCaseSensitive: (value) => {
|
|
1661
|
+
set({ caseSensitive: value });
|
|
1662
|
+
},
|
|
1663
|
+
setWholeWord: (value) => {
|
|
1664
|
+
set({ wholeWord: value });
|
|
1665
|
+
},
|
|
1364
1666
|
toggleCaseSensitive: () => {
|
|
1365
1667
|
set((state) => ({ caseSensitive: !state.caseSensitive }));
|
|
1366
1668
|
},
|
|
@@ -7883,6 +8185,8 @@ var init_DocumentContainer = __esm({
|
|
|
7883
8185
|
nextPage,
|
|
7884
8186
|
previousPage
|
|
7885
8187
|
} = usePDFViewer();
|
|
8188
|
+
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
8189
|
+
const { viewerStore } = usePDFViewerStores();
|
|
7886
8190
|
const [currentPageObj, setCurrentPageObj] = useState18(null);
|
|
7887
8191
|
const [isLoadingPage, setIsLoadingPage] = useState18(false);
|
|
7888
8192
|
const containerRef = useRef16(null);
|
|
@@ -7948,6 +8252,11 @@ var init_DocumentContainer = __esm({
|
|
|
7948
8252
|
const page = await document2.getPage(currentPage);
|
|
7949
8253
|
if (!cancelled && document2 === documentRef.current) {
|
|
7950
8254
|
setCurrentPageObj(page);
|
|
8255
|
+
if (scrollToPageRequest && scrollToPageRequest.page === currentPage) {
|
|
8256
|
+
requestAnimationFrame(() => {
|
|
8257
|
+
viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);
|
|
8258
|
+
});
|
|
8259
|
+
}
|
|
7951
8260
|
}
|
|
7952
8261
|
} catch (error) {
|
|
7953
8262
|
if (!cancelled) {
|
|
@@ -7966,7 +8275,7 @@ var init_DocumentContainer = __esm({
|
|
|
7966
8275
|
return () => {
|
|
7967
8276
|
cancelled = true;
|
|
7968
8277
|
};
|
|
7969
|
-
}, [document2, currentPage]);
|
|
8278
|
+
}, [document2, currentPage, scrollToPageRequest, viewerStore]);
|
|
7970
8279
|
const getPageElement = useCallback29(() => {
|
|
7971
8280
|
return containerRef.current?.querySelector(`[data-page-number="${currentPage}"]`);
|
|
7972
8281
|
}, [currentPage]);
|
|
@@ -8108,6 +8417,8 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
8108
8417
|
nextPage,
|
|
8109
8418
|
previousPage
|
|
8110
8419
|
} = usePDFViewer();
|
|
8420
|
+
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
8421
|
+
const { viewerStore } = usePDFViewerStores();
|
|
8111
8422
|
const containerRef = useRef17(null);
|
|
8112
8423
|
const scrollContainerRef = useRef17(null);
|
|
8113
8424
|
const documentRef = useRef17(null);
|
|
@@ -8245,6 +8556,45 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
8245
8556
|
loadPages();
|
|
8246
8557
|
}, [document2, visiblePages, pageObjects]);
|
|
8247
8558
|
useEffect20(() => {
|
|
8559
|
+
if (!scrollToPageRequest || !scrollContainerRef.current || pageInfos.length === 0) return;
|
|
8560
|
+
const { page, requestId, behavior } = scrollToPageRequest;
|
|
8561
|
+
const pageInfo = pageInfos.find((p) => p.pageNumber === page);
|
|
8562
|
+
if (!pageInfo) {
|
|
8563
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8564
|
+
return;
|
|
8565
|
+
}
|
|
8566
|
+
const container = scrollContainerRef.current;
|
|
8567
|
+
const targetScroll = pageInfo.top - pageGap;
|
|
8568
|
+
const scrollTop = container.scrollTop;
|
|
8569
|
+
const viewportHeight = container.clientHeight;
|
|
8570
|
+
const isVisible = targetScroll >= scrollTop && pageInfo.top + pageInfo.height <= scrollTop + viewportHeight;
|
|
8571
|
+
if (isVisible) {
|
|
8572
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8573
|
+
return;
|
|
8574
|
+
}
|
|
8575
|
+
container.scrollTo({
|
|
8576
|
+
top: targetScroll,
|
|
8577
|
+
behavior
|
|
8578
|
+
});
|
|
8579
|
+
if (behavior === "instant") {
|
|
8580
|
+
requestAnimationFrame(() => {
|
|
8581
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8582
|
+
});
|
|
8583
|
+
} else {
|
|
8584
|
+
let scrollEndTimeout;
|
|
8585
|
+
const handleScrollEnd = () => {
|
|
8586
|
+
clearTimeout(scrollEndTimeout);
|
|
8587
|
+
scrollEndTimeout = setTimeout(() => {
|
|
8588
|
+
container.removeEventListener("scroll", handleScrollEnd);
|
|
8589
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8590
|
+
}, 100);
|
|
8591
|
+
};
|
|
8592
|
+
container.addEventListener("scroll", handleScrollEnd, { passive: true });
|
|
8593
|
+
handleScrollEnd();
|
|
8594
|
+
}
|
|
8595
|
+
}, [scrollToPageRequest, pageInfos, pageGap, viewerStore]);
|
|
8596
|
+
useEffect20(() => {
|
|
8597
|
+
if (scrollToPageRequest) return;
|
|
8248
8598
|
if (!scrollContainerRef.current || pageInfos.length === 0) return;
|
|
8249
8599
|
const pageInfo = pageInfos.find((p) => p.pageNumber === currentPage);
|
|
8250
8600
|
if (pageInfo) {
|
|
@@ -8259,7 +8609,7 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
8259
8609
|
});
|
|
8260
8610
|
}
|
|
8261
8611
|
}
|
|
8262
|
-
}, [currentPage, pageInfos, pageGap]);
|
|
8612
|
+
}, [currentPage, pageInfos, pageGap, scrollToPageRequest]);
|
|
8263
8613
|
const handlePinchZoom = useCallback30(
|
|
8264
8614
|
(pinchScale) => {
|
|
8265
8615
|
const newScale = Math.max(0.25, Math.min(4, baseScaleRef.current * pinchScale));
|
|
@@ -8466,6 +8816,8 @@ var init_DualPageContainer = __esm({
|
|
|
8466
8816
|
setScale,
|
|
8467
8817
|
goToPage
|
|
8468
8818
|
} = usePDFViewer();
|
|
8819
|
+
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
8820
|
+
const { viewerStore } = usePDFViewerStores();
|
|
8469
8821
|
const containerRef = useRef18(null);
|
|
8470
8822
|
const documentRef = useRef18(null);
|
|
8471
8823
|
const baseScaleRef = useRef18(scale);
|
|
@@ -8551,6 +8903,14 @@ var init_DualPageContainer = __esm({
|
|
|
8551
8903
|
if (!cancelled) {
|
|
8552
8904
|
setLeftPage(left);
|
|
8553
8905
|
setRightPage(right);
|
|
8906
|
+
if (scrollToPageRequest) {
|
|
8907
|
+
const requestedPage = scrollToPageRequest.page;
|
|
8908
|
+
if (requestedPage === spread2.left || requestedPage === spread2.right) {
|
|
8909
|
+
requestAnimationFrame(() => {
|
|
8910
|
+
viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);
|
|
8911
|
+
});
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8554
8914
|
}
|
|
8555
8915
|
} catch (error) {
|
|
8556
8916
|
if (!cancelled) {
|
|
@@ -8566,7 +8926,7 @@ var init_DualPageContainer = __esm({
|
|
|
8566
8926
|
return () => {
|
|
8567
8927
|
cancelled = true;
|
|
8568
8928
|
};
|
|
8569
|
-
}, [document2, currentPage, getSpreadPages]);
|
|
8929
|
+
}, [document2, currentPage, getSpreadPages, scrollToPageRequest, viewerStore]);
|
|
8570
8930
|
const goToPreviousSpread = useCallback31(() => {
|
|
8571
8931
|
const spread2 = getSpreadPages(currentPage);
|
|
8572
8932
|
const leftmostPage = spread2.left || spread2.right || currentPage;
|
|
@@ -8743,13 +9103,159 @@ var init_DualPageContainer = __esm({
|
|
|
8743
9103
|
}
|
|
8744
9104
|
});
|
|
8745
9105
|
|
|
9106
|
+
// src/components/FloatingZoomControls/FloatingZoomControls.tsx
|
|
9107
|
+
import { memo as memo24, useCallback as useCallback32 } from "react";
|
|
9108
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
9109
|
+
var FloatingZoomControls;
|
|
9110
|
+
var init_FloatingZoomControls = __esm({
|
|
9111
|
+
"src/components/FloatingZoomControls/FloatingZoomControls.tsx"() {
|
|
9112
|
+
"use strict";
|
|
9113
|
+
init_hooks();
|
|
9114
|
+
init_utils();
|
|
9115
|
+
FloatingZoomControls = memo24(function FloatingZoomControls2({
|
|
9116
|
+
position = "bottom-right",
|
|
9117
|
+
className,
|
|
9118
|
+
showFitToWidth = true,
|
|
9119
|
+
showFitToPage = false,
|
|
9120
|
+
showZoomLevel = true
|
|
9121
|
+
}) {
|
|
9122
|
+
const { viewerStore } = usePDFViewerStores();
|
|
9123
|
+
const scale = useViewerStore((s) => s.scale);
|
|
9124
|
+
const document2 = useViewerStore((s) => s.document);
|
|
9125
|
+
const handleZoomIn = useCallback32(() => {
|
|
9126
|
+
const currentScale = viewerStore.getState().scale;
|
|
9127
|
+
const newScale = Math.min(4, currentScale + 0.05);
|
|
9128
|
+
viewerStore.getState().setScale(newScale);
|
|
9129
|
+
}, [viewerStore]);
|
|
9130
|
+
const handleZoomOut = useCallback32(() => {
|
|
9131
|
+
const currentScale = viewerStore.getState().scale;
|
|
9132
|
+
const newScale = Math.max(0.1, currentScale - 0.05);
|
|
9133
|
+
viewerStore.getState().setScale(newScale);
|
|
9134
|
+
}, [viewerStore]);
|
|
9135
|
+
const handleFitToWidth = useCallback32(() => {
|
|
9136
|
+
viewerStore.getState().setScale(1);
|
|
9137
|
+
}, [viewerStore]);
|
|
9138
|
+
const handleFitToPage = useCallback32(() => {
|
|
9139
|
+
viewerStore.getState().setScale(0.75);
|
|
9140
|
+
}, [viewerStore]);
|
|
9141
|
+
if (!document2) return null;
|
|
9142
|
+
const positionClasses = {
|
|
9143
|
+
"bottom-right": "bottom-4 right-4",
|
|
9144
|
+
"bottom-left": "bottom-4 left-4",
|
|
9145
|
+
"top-right": "top-4 right-4",
|
|
9146
|
+
"top-left": "top-4 left-4"
|
|
9147
|
+
};
|
|
9148
|
+
const zoomPercentage = Math.round(scale * 100);
|
|
9149
|
+
return /* @__PURE__ */ jsxs21(
|
|
9150
|
+
"div",
|
|
9151
|
+
{
|
|
9152
|
+
className: cn(
|
|
9153
|
+
"fixed z-50 flex items-center gap-1",
|
|
9154
|
+
"bg-white dark:bg-gray-800 rounded-lg shadow-lg",
|
|
9155
|
+
"border border-gray-200 dark:border-gray-700",
|
|
9156
|
+
"p-1",
|
|
9157
|
+
positionClasses[position],
|
|
9158
|
+
className
|
|
9159
|
+
),
|
|
9160
|
+
children: [
|
|
9161
|
+
/* @__PURE__ */ jsx25(
|
|
9162
|
+
"button",
|
|
9163
|
+
{
|
|
9164
|
+
onClick: handleZoomOut,
|
|
9165
|
+
className: cn(
|
|
9166
|
+
"w-8 h-8 flex items-center justify-center rounded",
|
|
9167
|
+
"text-gray-700 dark:text-gray-300",
|
|
9168
|
+
"hover:bg-gray-100 dark:hover:bg-gray-700",
|
|
9169
|
+
"transition-colors",
|
|
9170
|
+
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
9171
|
+
),
|
|
9172
|
+
disabled: scale <= 0.25,
|
|
9173
|
+
title: "Zoom Out",
|
|
9174
|
+
"aria-label": "Zoom Out",
|
|
9175
|
+
children: /* @__PURE__ */ jsx25("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx25("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20 12H4" }) })
|
|
9176
|
+
}
|
|
9177
|
+
),
|
|
9178
|
+
showZoomLevel && /* @__PURE__ */ jsxs21("span", { className: "min-w-[48px] text-center text-sm font-medium text-gray-700 dark:text-gray-300", children: [
|
|
9179
|
+
zoomPercentage,
|
|
9180
|
+
"%"
|
|
9181
|
+
] }),
|
|
9182
|
+
/* @__PURE__ */ jsx25(
|
|
9183
|
+
"button",
|
|
9184
|
+
{
|
|
9185
|
+
onClick: handleZoomIn,
|
|
9186
|
+
className: cn(
|
|
9187
|
+
"w-8 h-8 flex items-center justify-center rounded",
|
|
9188
|
+
"text-gray-700 dark:text-gray-300",
|
|
9189
|
+
"hover:bg-gray-100 dark:hover:bg-gray-700",
|
|
9190
|
+
"transition-colors",
|
|
9191
|
+
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
9192
|
+
),
|
|
9193
|
+
disabled: scale >= 4,
|
|
9194
|
+
title: "Zoom In",
|
|
9195
|
+
"aria-label": "Zoom In",
|
|
9196
|
+
children: /* @__PURE__ */ jsx25("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx25("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) })
|
|
9197
|
+
}
|
|
9198
|
+
),
|
|
9199
|
+
(showFitToWidth || showFitToPage) && /* @__PURE__ */ jsx25("div", { className: "w-px h-6 bg-gray-200 dark:bg-gray-700 mx-1" }),
|
|
9200
|
+
showFitToWidth && /* @__PURE__ */ jsx25(
|
|
9201
|
+
"button",
|
|
9202
|
+
{
|
|
9203
|
+
onClick: handleFitToWidth,
|
|
9204
|
+
className: cn(
|
|
9205
|
+
"w-8 h-8 flex items-center justify-center rounded",
|
|
9206
|
+
"text-gray-700 dark:text-gray-300",
|
|
9207
|
+
"hover:bg-gray-100 dark:hover:bg-gray-700",
|
|
9208
|
+
"transition-colors"
|
|
9209
|
+
),
|
|
9210
|
+
title: "Fit to Width",
|
|
9211
|
+
"aria-label": "Fit to Width",
|
|
9212
|
+
children: /* @__PURE__ */ jsx25("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx25("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" }) })
|
|
9213
|
+
}
|
|
9214
|
+
),
|
|
9215
|
+
showFitToPage && /* @__PURE__ */ jsx25(
|
|
9216
|
+
"button",
|
|
9217
|
+
{
|
|
9218
|
+
onClick: handleFitToPage,
|
|
9219
|
+
className: cn(
|
|
9220
|
+
"w-8 h-8 flex items-center justify-center rounded",
|
|
9221
|
+
"text-gray-700 dark:text-gray-300",
|
|
9222
|
+
"hover:bg-gray-100 dark:hover:bg-gray-700",
|
|
9223
|
+
"transition-colors"
|
|
9224
|
+
),
|
|
9225
|
+
title: "Fit to Page",
|
|
9226
|
+
"aria-label": "Fit to Page",
|
|
9227
|
+
children: /* @__PURE__ */ jsx25("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx25("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" }) })
|
|
9228
|
+
}
|
|
9229
|
+
)
|
|
9230
|
+
]
|
|
9231
|
+
}
|
|
9232
|
+
);
|
|
9233
|
+
});
|
|
9234
|
+
}
|
|
9235
|
+
});
|
|
9236
|
+
|
|
9237
|
+
// src/components/FloatingZoomControls/index.ts
|
|
9238
|
+
var init_FloatingZoomControls2 = __esm({
|
|
9239
|
+
"src/components/FloatingZoomControls/index.ts"() {
|
|
9240
|
+
"use strict";
|
|
9241
|
+
init_FloatingZoomControls();
|
|
9242
|
+
}
|
|
9243
|
+
});
|
|
9244
|
+
|
|
8746
9245
|
// src/components/PDFViewer/PDFViewerClient.tsx
|
|
8747
9246
|
var PDFViewerClient_exports = {};
|
|
8748
9247
|
__export(PDFViewerClient_exports, {
|
|
8749
9248
|
PDFViewerClient: () => PDFViewerClient
|
|
8750
9249
|
});
|
|
8751
|
-
import {
|
|
8752
|
-
|
|
9250
|
+
import {
|
|
9251
|
+
useEffect as useEffect22,
|
|
9252
|
+
useCallback as useCallback33,
|
|
9253
|
+
memo as memo25,
|
|
9254
|
+
useRef as useRef19,
|
|
9255
|
+
useState as useState21,
|
|
9256
|
+
forwardRef
|
|
9257
|
+
} from "react";
|
|
9258
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
8753
9259
|
function getSrcIdentifier(src) {
|
|
8754
9260
|
if (typeof src === "string") {
|
|
8755
9261
|
return src;
|
|
@@ -8761,7 +9267,26 @@ function getSrcIdentifier(src) {
|
|
|
8761
9267
|
const last = Array.from(data.slice(-4)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
8762
9268
|
return `binary:${len}:${first}:${last}`;
|
|
8763
9269
|
}
|
|
8764
|
-
|
|
9270
|
+
function mergeRects2(rects) {
|
|
9271
|
+
if (rects.length === 0) return [];
|
|
9272
|
+
const sorted = [...rects].sort((a, b) => a.y - b.y || a.x - b.x);
|
|
9273
|
+
const merged = [];
|
|
9274
|
+
let current = { ...sorted[0] };
|
|
9275
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
9276
|
+
const rect = sorted[i];
|
|
9277
|
+
if (Math.abs(rect.y - current.y) < 2 && rect.x <= current.x + current.width + 2) {
|
|
9278
|
+
const newRight = Math.max(current.x + current.width, rect.x + rect.width);
|
|
9279
|
+
current.width = newRight - current.x;
|
|
9280
|
+
current.height = Math.max(current.height, rect.height);
|
|
9281
|
+
} else {
|
|
9282
|
+
merged.push(current);
|
|
9283
|
+
current = { ...rect };
|
|
9284
|
+
}
|
|
9285
|
+
}
|
|
9286
|
+
merged.push(current);
|
|
9287
|
+
return merged;
|
|
9288
|
+
}
|
|
9289
|
+
var PDFViewerInner, PDFViewerInnerWithRef, PDFViewerClient;
|
|
8765
9290
|
var init_PDFViewerClient = __esm({
|
|
8766
9291
|
"src/components/PDFViewer/PDFViewerClient.tsx"() {
|
|
8767
9292
|
"use strict";
|
|
@@ -8773,33 +9298,61 @@ var init_PDFViewerClient = __esm({
|
|
|
8773
9298
|
init_DocumentContainer();
|
|
8774
9299
|
init_ContinuousScrollContainer();
|
|
8775
9300
|
init_DualPageContainer();
|
|
9301
|
+
init_FloatingZoomControls2();
|
|
8776
9302
|
init_utils();
|
|
8777
|
-
PDFViewerInner =
|
|
9303
|
+
PDFViewerInner = memo25(function PDFViewerInner2({
|
|
8778
9304
|
src,
|
|
8779
9305
|
initialPage = 1,
|
|
8780
|
-
|
|
9306
|
+
page: controlledPage,
|
|
9307
|
+
initialScale = "auto",
|
|
8781
9308
|
showToolbar = true,
|
|
8782
9309
|
showSidebar = true,
|
|
8783
9310
|
showAnnotationToolbar = false,
|
|
9311
|
+
showFloatingZoom = true,
|
|
8784
9312
|
viewMode = "single",
|
|
8785
9313
|
onDocumentLoad,
|
|
8786
9314
|
onPageChange,
|
|
8787
9315
|
onScaleChange,
|
|
9316
|
+
onZoomChange,
|
|
8788
9317
|
onError,
|
|
9318
|
+
onPageRenderStart,
|
|
9319
|
+
onPageRenderComplete,
|
|
9320
|
+
onHighlightAdded,
|
|
9321
|
+
onHighlightRemoved,
|
|
9322
|
+
onAnnotationAdded,
|
|
8789
9323
|
workerSrc,
|
|
8790
|
-
className
|
|
9324
|
+
className,
|
|
9325
|
+
loadingComponent,
|
|
9326
|
+
errorComponent,
|
|
9327
|
+
onReady
|
|
8791
9328
|
}) {
|
|
8792
|
-
const { viewerStore } = usePDFViewerStores();
|
|
9329
|
+
const { viewerStore, annotationStore, searchStore } = usePDFViewerStores();
|
|
8793
9330
|
const mountedRef = useRef19(true);
|
|
8794
9331
|
const [, setLoadState] = useState21("idle");
|
|
8795
9332
|
const onDocumentLoadRef = useRef19(onDocumentLoad);
|
|
8796
9333
|
const onErrorRef = useRef19(onError);
|
|
8797
9334
|
const onPageChangeRef = useRef19(onPageChange);
|
|
8798
9335
|
const onScaleChangeRef = useRef19(onScaleChange);
|
|
9336
|
+
const onZoomChangeRef = useRef19(onZoomChange);
|
|
9337
|
+
const onPageRenderStartRef = useRef19(onPageRenderStart);
|
|
9338
|
+
const onPageRenderCompleteRef = useRef19(onPageRenderComplete);
|
|
9339
|
+
const onHighlightAddedRef = useRef19(onHighlightAdded);
|
|
9340
|
+
const onHighlightRemovedRef = useRef19(onHighlightRemoved);
|
|
9341
|
+
const onAnnotationAddedRef = useRef19(onAnnotationAdded);
|
|
9342
|
+
const onReadyRef = useRef19(onReady);
|
|
8799
9343
|
onDocumentLoadRef.current = onDocumentLoad;
|
|
8800
9344
|
onErrorRef.current = onError;
|
|
8801
9345
|
onPageChangeRef.current = onPageChange;
|
|
8802
9346
|
onScaleChangeRef.current = onScaleChange;
|
|
9347
|
+
onZoomChangeRef.current = onZoomChange;
|
|
9348
|
+
onPageRenderStartRef.current = onPageRenderStart;
|
|
9349
|
+
onPageRenderCompleteRef.current = onPageRenderComplete;
|
|
9350
|
+
onHighlightAddedRef.current = onHighlightAdded;
|
|
9351
|
+
onHighlightRemovedRef.current = onHighlightRemoved;
|
|
9352
|
+
onAnnotationAddedRef.current = onAnnotationAdded;
|
|
9353
|
+
onReadyRef.current = onReady;
|
|
9354
|
+
const isControlled = controlledPage !== void 0;
|
|
9355
|
+
const prevControlledPageRef = useRef19(controlledPage);
|
|
8803
9356
|
const srcIdRef = useRef19(null);
|
|
8804
9357
|
const currentPage = useViewerStore((s) => s.currentPage);
|
|
8805
9358
|
const scale = useViewerStore((s) => s.scale);
|
|
@@ -8808,7 +9361,452 @@ var init_PDFViewerClient = __esm({
|
|
|
8808
9361
|
const error = useViewerStore((s) => s.error);
|
|
8809
9362
|
const sidebarOpen = useViewerStore((s) => s.sidebarOpen);
|
|
8810
9363
|
const srcId = getSrcIdentifier(src);
|
|
8811
|
-
const
|
|
9364
|
+
const handleRef = useRef19(null);
|
|
9365
|
+
useEffect22(() => {
|
|
9366
|
+
const handle = {
|
|
9367
|
+
// ==================== Text Highlighting ====================
|
|
9368
|
+
highlightText: async (text, options) => {
|
|
9369
|
+
const doc = viewerStore.getState().document;
|
|
9370
|
+
if (!doc) return [];
|
|
9371
|
+
const color = options?.color ?? "yellow";
|
|
9372
|
+
const targetPage = options?.page;
|
|
9373
|
+
const caseSensitive = options?.caseSensitive ?? false;
|
|
9374
|
+
const scrollTo = options?.scrollTo ?? true;
|
|
9375
|
+
const highlightIds = [];
|
|
9376
|
+
const searchText = caseSensitive ? text : text.toLowerCase();
|
|
9377
|
+
const pagesToSearch = targetPage ? [targetPage] : Array.from({ length: doc.numPages }, (_, i) => i + 1);
|
|
9378
|
+
for (const pageNum of pagesToSearch) {
|
|
9379
|
+
try {
|
|
9380
|
+
const page = await doc.getPage(pageNum);
|
|
9381
|
+
const textContent = await page.getTextContent();
|
|
9382
|
+
const viewport = page.getViewport({ scale: 1 });
|
|
9383
|
+
let fullText = "";
|
|
9384
|
+
const charPositions = [];
|
|
9385
|
+
for (const item of textContent.items) {
|
|
9386
|
+
if ("str" in item && item.str) {
|
|
9387
|
+
const tx = item.transform;
|
|
9388
|
+
const x = tx[4];
|
|
9389
|
+
const y = viewport.height - tx[5];
|
|
9390
|
+
const width = item.width ?? 0;
|
|
9391
|
+
const height = item.height ?? 12;
|
|
9392
|
+
const charWidth = item.str.length > 0 ? width / item.str.length : width;
|
|
9393
|
+
for (let i = 0; i < item.str.length; i++) {
|
|
9394
|
+
charPositions.push({
|
|
9395
|
+
char: item.str[i],
|
|
9396
|
+
rect: {
|
|
9397
|
+
x: x + i * charWidth,
|
|
9398
|
+
y: y - height,
|
|
9399
|
+
width: charWidth,
|
|
9400
|
+
height
|
|
9401
|
+
}
|
|
9402
|
+
});
|
|
9403
|
+
}
|
|
9404
|
+
fullText += item.str;
|
|
9405
|
+
}
|
|
9406
|
+
}
|
|
9407
|
+
const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();
|
|
9408
|
+
let startIndex = 0;
|
|
9409
|
+
while (true) {
|
|
9410
|
+
const matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
9411
|
+
if (matchIndex === -1) break;
|
|
9412
|
+
const matchRects = [];
|
|
9413
|
+
for (let i = matchIndex; i < matchIndex + text.length && i < charPositions.length; i++) {
|
|
9414
|
+
matchRects.push(charPositions[i].rect);
|
|
9415
|
+
}
|
|
9416
|
+
const mergedRects = mergeRects2(matchRects);
|
|
9417
|
+
const highlight = annotationStore.getState().addHighlight({
|
|
9418
|
+
pageNumber: pageNum,
|
|
9419
|
+
rects: mergedRects,
|
|
9420
|
+
color,
|
|
9421
|
+
text: fullText.substring(matchIndex, matchIndex + text.length)
|
|
9422
|
+
});
|
|
9423
|
+
highlightIds.push(highlight.id);
|
|
9424
|
+
startIndex = matchIndex + 1;
|
|
9425
|
+
}
|
|
9426
|
+
} catch {
|
|
9427
|
+
}
|
|
9428
|
+
}
|
|
9429
|
+
if (scrollTo && highlightIds.length > 0) {
|
|
9430
|
+
const firstHighlight = annotationStore.getState().highlights.find((h) => h.id === highlightIds[0]);
|
|
9431
|
+
if (firstHighlight) {
|
|
9432
|
+
viewerStore.getState().goToPage(firstHighlight.pageNumber);
|
|
9433
|
+
}
|
|
9434
|
+
}
|
|
9435
|
+
return highlightIds;
|
|
9436
|
+
},
|
|
9437
|
+
removeHighlight: (id) => {
|
|
9438
|
+
annotationStore.getState().removeHighlight(id);
|
|
9439
|
+
},
|
|
9440
|
+
clearHighlights: () => {
|
|
9441
|
+
const highlights = annotationStore.getState().highlights;
|
|
9442
|
+
for (const h of highlights) {
|
|
9443
|
+
annotationStore.getState().removeHighlight(h.id);
|
|
9444
|
+
}
|
|
9445
|
+
},
|
|
9446
|
+
// ==================== Annotations ====================
|
|
9447
|
+
drawRect: (options) => {
|
|
9448
|
+
const annotation = annotationStore.getState().addAnnotation({
|
|
9449
|
+
type: "shape",
|
|
9450
|
+
shapeType: "rect",
|
|
9451
|
+
pageNumber: options.page,
|
|
9452
|
+
x: options.x,
|
|
9453
|
+
y: options.y,
|
|
9454
|
+
width: options.width,
|
|
9455
|
+
height: options.height,
|
|
9456
|
+
color: options.color ?? "blue",
|
|
9457
|
+
strokeWidth: options.strokeWidth ?? 2
|
|
9458
|
+
});
|
|
9459
|
+
return annotation.id;
|
|
9460
|
+
},
|
|
9461
|
+
drawCircle: (options) => {
|
|
9462
|
+
const annotation = annotationStore.getState().addAnnotation({
|
|
9463
|
+
type: "shape",
|
|
9464
|
+
shapeType: "circle",
|
|
9465
|
+
pageNumber: options.page,
|
|
9466
|
+
x: options.x,
|
|
9467
|
+
y: options.y,
|
|
9468
|
+
width: options.radius * 2,
|
|
9469
|
+
height: options.radius * 2,
|
|
9470
|
+
color: options.color ?? "blue",
|
|
9471
|
+
strokeWidth: options.strokeWidth ?? 2
|
|
9472
|
+
});
|
|
9473
|
+
return annotation.id;
|
|
9474
|
+
},
|
|
9475
|
+
addNote: (options) => {
|
|
9476
|
+
const annotation = annotationStore.getState().addAnnotation({
|
|
9477
|
+
type: "note",
|
|
9478
|
+
pageNumber: options.page,
|
|
9479
|
+
x: options.x,
|
|
9480
|
+
y: options.y,
|
|
9481
|
+
content: options.content,
|
|
9482
|
+
color: options.color ?? "yellow"
|
|
9483
|
+
});
|
|
9484
|
+
return annotation.id;
|
|
9485
|
+
},
|
|
9486
|
+
removeAnnotation: (id) => {
|
|
9487
|
+
annotationStore.getState().removeAnnotation(id);
|
|
9488
|
+
},
|
|
9489
|
+
clearAnnotations: () => {
|
|
9490
|
+
const annotations = annotationStore.getState().annotations;
|
|
9491
|
+
for (const a of annotations) {
|
|
9492
|
+
annotationStore.getState().removeAnnotation(a.id);
|
|
9493
|
+
}
|
|
9494
|
+
},
|
|
9495
|
+
// ==================== Navigation ====================
|
|
9496
|
+
goToPage: async (page, options) => {
|
|
9497
|
+
const behavior = options?.behavior ?? "smooth";
|
|
9498
|
+
await viewerStore.getState().requestScrollToPage(page, behavior);
|
|
9499
|
+
},
|
|
9500
|
+
nextPage: () => {
|
|
9501
|
+
viewerStore.getState().nextPage();
|
|
9502
|
+
},
|
|
9503
|
+
previousPage: () => {
|
|
9504
|
+
viewerStore.getState().previousPage();
|
|
9505
|
+
},
|
|
9506
|
+
getCurrentPage: () => {
|
|
9507
|
+
return viewerStore.getState().currentPage;
|
|
9508
|
+
},
|
|
9509
|
+
getNumPages: () => {
|
|
9510
|
+
return viewerStore.getState().numPages;
|
|
9511
|
+
},
|
|
9512
|
+
// ==================== Zoom ====================
|
|
9513
|
+
setZoom: (scale2) => {
|
|
9514
|
+
viewerStore.getState().setScale(scale2);
|
|
9515
|
+
},
|
|
9516
|
+
getZoom: () => {
|
|
9517
|
+
return viewerStore.getState().scale;
|
|
9518
|
+
},
|
|
9519
|
+
zoomIn: () => {
|
|
9520
|
+
viewerStore.getState().zoomIn();
|
|
9521
|
+
},
|
|
9522
|
+
zoomOut: () => {
|
|
9523
|
+
viewerStore.getState().zoomOut();
|
|
9524
|
+
},
|
|
9525
|
+
// ==================== Search ====================
|
|
9526
|
+
search: async (query, options) => {
|
|
9527
|
+
const doc = viewerStore.getState().document;
|
|
9528
|
+
if (!doc) return [];
|
|
9529
|
+
searchStore.getState().setQuery(query);
|
|
9530
|
+
if (options?.caseSensitive !== void 0) {
|
|
9531
|
+
searchStore.getState().setCaseSensitive(options.caseSensitive);
|
|
9532
|
+
}
|
|
9533
|
+
if (options?.wholeWord !== void 0) {
|
|
9534
|
+
searchStore.getState().setWholeWord(options.wholeWord);
|
|
9535
|
+
}
|
|
9536
|
+
await searchStore.getState().search(doc);
|
|
9537
|
+
return searchStore.getState().results;
|
|
9538
|
+
},
|
|
9539
|
+
nextSearchResult: () => {
|
|
9540
|
+
searchStore.getState().nextResult();
|
|
9541
|
+
const results = searchStore.getState().results;
|
|
9542
|
+
const index = searchStore.getState().currentResultIndex;
|
|
9543
|
+
if (results[index]) {
|
|
9544
|
+
viewerStore.getState().goToPage(results[index].pageNumber);
|
|
9545
|
+
}
|
|
9546
|
+
},
|
|
9547
|
+
previousSearchResult: () => {
|
|
9548
|
+
searchStore.getState().previousResult();
|
|
9549
|
+
const results = searchStore.getState().results;
|
|
9550
|
+
const index = searchStore.getState().currentResultIndex;
|
|
9551
|
+
if (results[index]) {
|
|
9552
|
+
viewerStore.getState().goToPage(results[index].pageNumber);
|
|
9553
|
+
}
|
|
9554
|
+
},
|
|
9555
|
+
clearSearch: () => {
|
|
9556
|
+
searchStore.getState().clearSearch();
|
|
9557
|
+
},
|
|
9558
|
+
// ==================== Combined Search & Highlight ====================
|
|
9559
|
+
searchAndHighlight: async (query, options) => {
|
|
9560
|
+
const doc = viewerStore.getState().document;
|
|
9561
|
+
if (!doc) {
|
|
9562
|
+
return { matchCount: 0, highlightIds: [], matches: [] };
|
|
9563
|
+
}
|
|
9564
|
+
const color = options?.color ?? "yellow";
|
|
9565
|
+
const caseSensitive = options?.caseSensitive ?? false;
|
|
9566
|
+
const wholeWord = options?.wholeWord ?? false;
|
|
9567
|
+
const scrollToFirst = options?.scrollToFirst ?? true;
|
|
9568
|
+
const clearPrevious = options?.clearPrevious ?? true;
|
|
9569
|
+
if (clearPrevious) {
|
|
9570
|
+
const existingHighlights = annotationStore.getState().highlights;
|
|
9571
|
+
for (const h of existingHighlights) {
|
|
9572
|
+
if (h.source === "search") {
|
|
9573
|
+
annotationStore.getState().removeHighlight(h.id);
|
|
9574
|
+
}
|
|
9575
|
+
}
|
|
9576
|
+
}
|
|
9577
|
+
let pagesToSearch;
|
|
9578
|
+
if (options?.pageRange) {
|
|
9579
|
+
if (Array.isArray(options.pageRange)) {
|
|
9580
|
+
pagesToSearch = options.pageRange;
|
|
9581
|
+
} else {
|
|
9582
|
+
const { start, end } = options.pageRange;
|
|
9583
|
+
pagesToSearch = Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
|
9584
|
+
}
|
|
9585
|
+
} else {
|
|
9586
|
+
pagesToSearch = Array.from({ length: doc.numPages }, (_, i) => i + 1);
|
|
9587
|
+
}
|
|
9588
|
+
const result = {
|
|
9589
|
+
matchCount: 0,
|
|
9590
|
+
highlightIds: [],
|
|
9591
|
+
matches: []
|
|
9592
|
+
};
|
|
9593
|
+
const searchText = caseSensitive ? query : query.toLowerCase();
|
|
9594
|
+
for (const pageNum of pagesToSearch) {
|
|
9595
|
+
if (pageNum < 1 || pageNum > doc.numPages) continue;
|
|
9596
|
+
try {
|
|
9597
|
+
const page = await doc.getPage(pageNum);
|
|
9598
|
+
const textContent = await page.getTextContent();
|
|
9599
|
+
const viewport = page.getViewport({ scale: 1 });
|
|
9600
|
+
let fullText = "";
|
|
9601
|
+
const charPositions = [];
|
|
9602
|
+
for (const item of textContent.items) {
|
|
9603
|
+
if ("str" in item && item.str) {
|
|
9604
|
+
const tx = item.transform;
|
|
9605
|
+
const x = tx[4];
|
|
9606
|
+
const y = viewport.height - tx[5];
|
|
9607
|
+
const width = item.width ?? 0;
|
|
9608
|
+
const height = item.height ?? 12;
|
|
9609
|
+
const charWidth = item.str.length > 0 ? width / item.str.length : width;
|
|
9610
|
+
for (let i = 0; i < item.str.length; i++) {
|
|
9611
|
+
charPositions.push({
|
|
9612
|
+
char: item.str[i],
|
|
9613
|
+
rect: {
|
|
9614
|
+
x: x + i * charWidth,
|
|
9615
|
+
y: y - height,
|
|
9616
|
+
width: charWidth,
|
|
9617
|
+
height
|
|
9618
|
+
}
|
|
9619
|
+
});
|
|
9620
|
+
}
|
|
9621
|
+
fullText += item.str;
|
|
9622
|
+
}
|
|
9623
|
+
}
|
|
9624
|
+
const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();
|
|
9625
|
+
let startIndex = 0;
|
|
9626
|
+
while (true) {
|
|
9627
|
+
let matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
9628
|
+
if (matchIndex === -1) break;
|
|
9629
|
+
if (wholeWord) {
|
|
9630
|
+
const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : " ";
|
|
9631
|
+
const afterChar = matchIndex + query.length < textToSearch.length ? textToSearch[matchIndex + query.length] : " ";
|
|
9632
|
+
if (/\w/.test(beforeChar) || /\w/.test(afterChar)) {
|
|
9633
|
+
startIndex = matchIndex + 1;
|
|
9634
|
+
continue;
|
|
9635
|
+
}
|
|
9636
|
+
}
|
|
9637
|
+
const matchRects = [];
|
|
9638
|
+
for (let i = matchIndex; i < matchIndex + query.length && i < charPositions.length; i++) {
|
|
9639
|
+
matchRects.push(charPositions[i].rect);
|
|
9640
|
+
}
|
|
9641
|
+
const mergedRects = mergeRects2(matchRects);
|
|
9642
|
+
const highlight = annotationStore.getState().addHighlight({
|
|
9643
|
+
pageNumber: pageNum,
|
|
9644
|
+
rects: mergedRects,
|
|
9645
|
+
color,
|
|
9646
|
+
text: fullText.substring(matchIndex, matchIndex + query.length),
|
|
9647
|
+
source: "search"
|
|
9648
|
+
});
|
|
9649
|
+
result.matchCount++;
|
|
9650
|
+
result.highlightIds.push(highlight.id);
|
|
9651
|
+
result.matches.push({
|
|
9652
|
+
pageNumber: pageNum,
|
|
9653
|
+
text: fullText.substring(matchIndex, matchIndex + query.length),
|
|
9654
|
+
highlightId: highlight.id,
|
|
9655
|
+
rects: mergedRects
|
|
9656
|
+
});
|
|
9657
|
+
startIndex = matchIndex + 1;
|
|
9658
|
+
}
|
|
9659
|
+
} catch {
|
|
9660
|
+
}
|
|
9661
|
+
}
|
|
9662
|
+
if (scrollToFirst && result.matches.length > 0) {
|
|
9663
|
+
const firstMatch = result.matches[0];
|
|
9664
|
+
await viewerStore.getState().requestScrollToPage(firstMatch.pageNumber, "smooth");
|
|
9665
|
+
}
|
|
9666
|
+
return result;
|
|
9667
|
+
},
|
|
9668
|
+
// ==================== Agent Tools ====================
|
|
9669
|
+
agentTools: {
|
|
9670
|
+
navigateToPage: async (page) => {
|
|
9671
|
+
try {
|
|
9672
|
+
const { currentPage: currentPage2, numPages } = viewerStore.getState();
|
|
9673
|
+
if (numPages === 0) {
|
|
9674
|
+
return {
|
|
9675
|
+
success: false,
|
|
9676
|
+
error: { code: "NO_DOCUMENT", message: "No document is loaded" }
|
|
9677
|
+
};
|
|
9678
|
+
}
|
|
9679
|
+
if (page < 1 || page > numPages) {
|
|
9680
|
+
return {
|
|
9681
|
+
success: false,
|
|
9682
|
+
error: { code: "INVALID_PAGE", message: `Page ${page} is out of range (1-${numPages})` }
|
|
9683
|
+
};
|
|
9684
|
+
}
|
|
9685
|
+
const previousPage = currentPage2;
|
|
9686
|
+
await viewerStore.getState().requestScrollToPage(page, "smooth");
|
|
9687
|
+
return {
|
|
9688
|
+
success: true,
|
|
9689
|
+
data: { previousPage, currentPage: page }
|
|
9690
|
+
};
|
|
9691
|
+
} catch (err) {
|
|
9692
|
+
return {
|
|
9693
|
+
success: false,
|
|
9694
|
+
error: { code: "NAVIGATION_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9695
|
+
};
|
|
9696
|
+
}
|
|
9697
|
+
},
|
|
9698
|
+
highlightText: async (text, options) => {
|
|
9699
|
+
try {
|
|
9700
|
+
const highlightIds = await handle.highlightText(text, options);
|
|
9701
|
+
return {
|
|
9702
|
+
success: true,
|
|
9703
|
+
data: { matchCount: highlightIds.length, highlightIds }
|
|
9704
|
+
};
|
|
9705
|
+
} catch (err) {
|
|
9706
|
+
return {
|
|
9707
|
+
success: false,
|
|
9708
|
+
error: { code: "HIGHLIGHT_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9709
|
+
};
|
|
9710
|
+
}
|
|
9711
|
+
},
|
|
9712
|
+
getPageContent: async (page) => {
|
|
9713
|
+
try {
|
|
9714
|
+
const doc = viewerStore.getState().document;
|
|
9715
|
+
if (!doc) {
|
|
9716
|
+
return {
|
|
9717
|
+
success: false,
|
|
9718
|
+
error: { code: "NO_DOCUMENT", message: "No document is loaded" }
|
|
9719
|
+
};
|
|
9720
|
+
}
|
|
9721
|
+
if (page < 1 || page > doc.numPages) {
|
|
9722
|
+
return {
|
|
9723
|
+
success: false,
|
|
9724
|
+
error: { code: "INVALID_PAGE", message: `Page ${page} is out of range (1-${doc.numPages})` }
|
|
9725
|
+
};
|
|
9726
|
+
}
|
|
9727
|
+
const pageObj = await doc.getPage(page);
|
|
9728
|
+
const textContent = await pageObj.getTextContent();
|
|
9729
|
+
const text = textContent.items.filter((item) => "str" in item).map((item) => item.str).join("");
|
|
9730
|
+
return {
|
|
9731
|
+
success: true,
|
|
9732
|
+
data: { text }
|
|
9733
|
+
};
|
|
9734
|
+
} catch (err) {
|
|
9735
|
+
return {
|
|
9736
|
+
success: false,
|
|
9737
|
+
error: { code: "CONTENT_FETCH_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9738
|
+
};
|
|
9739
|
+
}
|
|
9740
|
+
},
|
|
9741
|
+
clearAllVisuals: async () => {
|
|
9742
|
+
try {
|
|
9743
|
+
const highlights = annotationStore.getState().highlights;
|
|
9744
|
+
for (const h of highlights) {
|
|
9745
|
+
annotationStore.getState().removeHighlight(h.id);
|
|
9746
|
+
}
|
|
9747
|
+
const annotations = annotationStore.getState().annotations;
|
|
9748
|
+
for (const a of annotations) {
|
|
9749
|
+
annotationStore.getState().removeAnnotation(a.id);
|
|
9750
|
+
}
|
|
9751
|
+
return { success: true };
|
|
9752
|
+
} catch (err) {
|
|
9753
|
+
return {
|
|
9754
|
+
success: false,
|
|
9755
|
+
error: { code: "CLEAR_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9756
|
+
};
|
|
9757
|
+
}
|
|
9758
|
+
}
|
|
9759
|
+
},
|
|
9760
|
+
// ==================== Coordinate Helpers ====================
|
|
9761
|
+
coordinates: {
|
|
9762
|
+
getPageDimensions: (page) => {
|
|
9763
|
+
const doc = viewerStore.getState().document;
|
|
9764
|
+
if (!doc || page < 1 || page > doc.numPages) {
|
|
9765
|
+
return null;
|
|
9766
|
+
}
|
|
9767
|
+
try {
|
|
9768
|
+
return {
|
|
9769
|
+
width: 612,
|
|
9770
|
+
// Default US Letter width
|
|
9771
|
+
height: 792,
|
|
9772
|
+
// Default US Letter height
|
|
9773
|
+
rotation: viewerStore.getState().rotation
|
|
9774
|
+
};
|
|
9775
|
+
} catch {
|
|
9776
|
+
return null;
|
|
9777
|
+
}
|
|
9778
|
+
},
|
|
9779
|
+
percentToPixels: (xPercent, yPercent, page) => {
|
|
9780
|
+
const dimensions = handle.coordinates.getPageDimensions(page);
|
|
9781
|
+
if (!dimensions) return null;
|
|
9782
|
+
const scale2 = viewerStore.getState().scale;
|
|
9783
|
+
return {
|
|
9784
|
+
x: xPercent / 100 * dimensions.width * scale2,
|
|
9785
|
+
y: yPercent / 100 * dimensions.height * scale2
|
|
9786
|
+
};
|
|
9787
|
+
},
|
|
9788
|
+
pixelsToPercent: (x, y, page) => {
|
|
9789
|
+
const dimensions = handle.coordinates.getPageDimensions(page);
|
|
9790
|
+
if (!dimensions) return null;
|
|
9791
|
+
const scale2 = viewerStore.getState().scale;
|
|
9792
|
+
return {
|
|
9793
|
+
x: x / (dimensions.width * scale2) * 100,
|
|
9794
|
+
y: y / (dimensions.height * scale2) * 100
|
|
9795
|
+
};
|
|
9796
|
+
}
|
|
9797
|
+
},
|
|
9798
|
+
// ==================== Document ====================
|
|
9799
|
+
getDocument: () => {
|
|
9800
|
+
return viewerStore.getState().document;
|
|
9801
|
+
},
|
|
9802
|
+
isLoaded: () => {
|
|
9803
|
+
return viewerStore.getState().document !== null;
|
|
9804
|
+
}
|
|
9805
|
+
};
|
|
9806
|
+
handleRef.current = handle;
|
|
9807
|
+
onReadyRef.current?.(handle);
|
|
9808
|
+
}, [viewerStore, annotationStore, searchStore]);
|
|
9809
|
+
const handleRetry = useCallback33(() => {
|
|
8812
9810
|
srcIdRef.current = null;
|
|
8813
9811
|
viewerStore.getState().setError(null);
|
|
8814
9812
|
setLoadState("idle");
|
|
@@ -8846,8 +9844,12 @@ var init_PDFViewerClient = __esm({
|
|
|
8846
9844
|
if (initialPage !== 1) {
|
|
8847
9845
|
viewerStore.getState().goToPage(initialPage);
|
|
8848
9846
|
}
|
|
8849
|
-
if (typeof initialScale === "number"
|
|
9847
|
+
if (typeof initialScale === "number") {
|
|
8850
9848
|
viewerStore.getState().setScale(initialScale);
|
|
9849
|
+
} else if (initialScale === "auto" || initialScale === "page-width") {
|
|
9850
|
+
viewerStore.getState().setScale(1);
|
|
9851
|
+
} else if (initialScale === "page-fit") {
|
|
9852
|
+
viewerStore.getState().setScale(0.75);
|
|
8851
9853
|
}
|
|
8852
9854
|
onDocumentLoadRef.current?.({ document: document2, numPages });
|
|
8853
9855
|
} else {
|
|
@@ -8879,11 +9881,37 @@ var init_PDFViewerClient = __esm({
|
|
|
8879
9881
|
if (prevScaleRef.current !== scale) {
|
|
8880
9882
|
prevScaleRef.current = scale;
|
|
8881
9883
|
onScaleChangeRef.current?.(scale);
|
|
9884
|
+
onZoomChangeRef.current?.(scale);
|
|
8882
9885
|
}
|
|
8883
9886
|
}, [scale]);
|
|
9887
|
+
useEffect22(() => {
|
|
9888
|
+
if (!isControlled || controlledPage === void 0) return;
|
|
9889
|
+
if (prevControlledPageRef.current === controlledPage) return;
|
|
9890
|
+
prevControlledPageRef.current = controlledPage;
|
|
9891
|
+
const { numPages, currentPage: currentPage2 } = viewerStore.getState();
|
|
9892
|
+
if (numPages > 0 && controlledPage !== currentPage2) {
|
|
9893
|
+
viewerStore.getState().requestScrollToPage(controlledPage, "smooth");
|
|
9894
|
+
}
|
|
9895
|
+
}, [controlledPage, isControlled, viewerStore]);
|
|
8884
9896
|
const themeClass = theme === "dark" ? "dark" : "";
|
|
8885
9897
|
if (error) {
|
|
8886
|
-
|
|
9898
|
+
if (errorComponent) {
|
|
9899
|
+
const errorContent = typeof errorComponent === "function" ? errorComponent(error, handleRetry) : errorComponent;
|
|
9900
|
+
return /* @__PURE__ */ jsx26(
|
|
9901
|
+
"div",
|
|
9902
|
+
{
|
|
9903
|
+
className: cn(
|
|
9904
|
+
"pdf-viewer pdf-viewer-error",
|
|
9905
|
+
"flex flex-col h-full",
|
|
9906
|
+
"bg-white dark:bg-gray-900",
|
|
9907
|
+
themeClass,
|
|
9908
|
+
className
|
|
9909
|
+
),
|
|
9910
|
+
children: errorContent
|
|
9911
|
+
}
|
|
9912
|
+
);
|
|
9913
|
+
}
|
|
9914
|
+
return /* @__PURE__ */ jsx26(
|
|
8887
9915
|
"div",
|
|
8888
9916
|
{
|
|
8889
9917
|
className: cn(
|
|
@@ -8893,10 +9921,10 @@ var init_PDFViewerClient = __esm({
|
|
|
8893
9921
|
themeClass,
|
|
8894
9922
|
className
|
|
8895
9923
|
),
|
|
8896
|
-
children: /* @__PURE__ */
|
|
8897
|
-
/* @__PURE__ */
|
|
8898
|
-
/* @__PURE__ */
|
|
8899
|
-
/* @__PURE__ */
|
|
9924
|
+
children: /* @__PURE__ */ jsx26("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs22("div", { className: "text-center p-8", children: [
|
|
9925
|
+
/* @__PURE__ */ jsx26("div", { className: "text-red-500 text-lg font-semibold mb-2", children: "Failed to load PDF" }),
|
|
9926
|
+
/* @__PURE__ */ jsx26("div", { className: "text-gray-500 text-sm", children: error.message }),
|
|
9927
|
+
/* @__PURE__ */ jsx26(
|
|
8900
9928
|
"button",
|
|
8901
9929
|
{
|
|
8902
9930
|
onClick: handleRetry,
|
|
@@ -8911,56 +9939,73 @@ var init_PDFViewerClient = __esm({
|
|
|
8911
9939
|
const renderContainer = () => {
|
|
8912
9940
|
switch (viewMode) {
|
|
8913
9941
|
case "continuous":
|
|
8914
|
-
return /* @__PURE__ */
|
|
9942
|
+
return /* @__PURE__ */ jsx26(ContinuousScrollContainer, {});
|
|
8915
9943
|
case "dual":
|
|
8916
|
-
return /* @__PURE__ */
|
|
9944
|
+
return /* @__PURE__ */ jsx26(DualPageContainer, {});
|
|
8917
9945
|
case "single":
|
|
8918
9946
|
default:
|
|
8919
|
-
return /* @__PURE__ */
|
|
9947
|
+
return /* @__PURE__ */ jsx26(DocumentContainer, {});
|
|
8920
9948
|
}
|
|
8921
9949
|
};
|
|
8922
|
-
return /* @__PURE__ */
|
|
9950
|
+
return /* @__PURE__ */ jsxs22(
|
|
8923
9951
|
"div",
|
|
8924
9952
|
{
|
|
8925
9953
|
className: cn(
|
|
8926
9954
|
"pdf-viewer",
|
|
8927
|
-
"flex flex-col h-full",
|
|
9955
|
+
"flex flex-col h-full relative",
|
|
8928
9956
|
"bg-white dark:bg-gray-900",
|
|
8929
9957
|
"text-gray-900 dark:text-gray-100",
|
|
8930
9958
|
themeClass,
|
|
8931
9959
|
className
|
|
8932
9960
|
),
|
|
8933
9961
|
children: [
|
|
8934
|
-
showToolbar && /* @__PURE__ */
|
|
8935
|
-
showAnnotationToolbar && /* @__PURE__ */
|
|
8936
|
-
/* @__PURE__ */
|
|
8937
|
-
showSidebar && sidebarOpen && /* @__PURE__ */
|
|
9962
|
+
showToolbar && /* @__PURE__ */ jsx26(Toolbar, {}),
|
|
9963
|
+
showAnnotationToolbar && /* @__PURE__ */ jsx26(AnnotationToolbar, {}),
|
|
9964
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex flex-1 overflow-hidden", children: [
|
|
9965
|
+
showSidebar && sidebarOpen && /* @__PURE__ */ jsx26(Sidebar, {}),
|
|
8938
9966
|
renderContainer()
|
|
8939
9967
|
] }),
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
/* @__PURE__ */
|
|
9968
|
+
showFloatingZoom && /* @__PURE__ */ jsx26(FloatingZoomControls, { position: "bottom-right" }),
|
|
9969
|
+
isLoading && /* @__PURE__ */ jsx26("div", { className: "absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-900/80", children: loadingComponent ?? /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-center", children: [
|
|
9970
|
+
/* @__PURE__ */ jsx26("div", { className: "w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" }),
|
|
9971
|
+
/* @__PURE__ */ jsx26("div", { className: "mt-2 text-sm text-gray-500", children: "Loading PDF..." })
|
|
8943
9972
|
] }) })
|
|
8944
9973
|
]
|
|
8945
9974
|
}
|
|
8946
9975
|
);
|
|
8947
9976
|
});
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
{
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
9977
|
+
PDFViewerInnerWithRef = forwardRef(
|
|
9978
|
+
function PDFViewerInnerWithRef2(props, ref) {
|
|
9979
|
+
const handleRef = useRef19(null);
|
|
9980
|
+
const handleReady = useCallback33((handle) => {
|
|
9981
|
+
handleRef.current = handle;
|
|
9982
|
+
if (typeof ref === "function") {
|
|
9983
|
+
ref(handle);
|
|
9984
|
+
} else if (ref) {
|
|
9985
|
+
ref.current = handle;
|
|
9986
|
+
}
|
|
9987
|
+
}, [ref]);
|
|
9988
|
+
return /* @__PURE__ */ jsx26(PDFViewerInner, { ...props, onReady: handleReady });
|
|
9989
|
+
}
|
|
9990
|
+
);
|
|
9991
|
+
PDFViewerClient = memo25(
|
|
9992
|
+
forwardRef(function PDFViewerClient2(props, ref) {
|
|
9993
|
+
return /* @__PURE__ */ jsx26(
|
|
9994
|
+
PDFViewerProvider,
|
|
9995
|
+
{
|
|
9996
|
+
theme: props.theme,
|
|
9997
|
+
defaultSidebarPanel: props.defaultSidebarPanel,
|
|
9998
|
+
children: /* @__PURE__ */ jsx26(PDFViewerInnerWithRef, { ref, ...props })
|
|
9999
|
+
}
|
|
10000
|
+
);
|
|
10001
|
+
})
|
|
10002
|
+
);
|
|
8958
10003
|
}
|
|
8959
10004
|
});
|
|
8960
10005
|
|
|
8961
10006
|
// src/components/PDFViewer/PDFViewer.tsx
|
|
8962
|
-
import { lazy, Suspense, memo as
|
|
8963
|
-
import { jsx as
|
|
10007
|
+
import { lazy, Suspense, memo as memo26 } from "react";
|
|
10008
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
8964
10009
|
var PDFViewerClient3, PDFViewerLoading, PDFViewer;
|
|
8965
10010
|
var init_PDFViewer = __esm({
|
|
8966
10011
|
"src/components/PDFViewer/PDFViewer.tsx"() {
|
|
@@ -8969,10 +10014,10 @@ var init_PDFViewer = __esm({
|
|
|
8969
10014
|
PDFViewerClient3 = lazy(
|
|
8970
10015
|
() => Promise.resolve().then(() => (init_PDFViewerClient(), PDFViewerClient_exports)).then((mod) => ({ default: mod.PDFViewerClient }))
|
|
8971
10016
|
);
|
|
8972
|
-
PDFViewerLoading =
|
|
10017
|
+
PDFViewerLoading = memo26(function PDFViewerLoading2({
|
|
8973
10018
|
className
|
|
8974
10019
|
}) {
|
|
8975
|
-
return /* @__PURE__ */
|
|
10020
|
+
return /* @__PURE__ */ jsx27(
|
|
8976
10021
|
"div",
|
|
8977
10022
|
{
|
|
8978
10023
|
className: cn(
|
|
@@ -8981,18 +10026,18 @@ var init_PDFViewer = __esm({
|
|
|
8981
10026
|
"bg-white dark:bg-gray-900",
|
|
8982
10027
|
className
|
|
8983
10028
|
),
|
|
8984
|
-
children: /* @__PURE__ */
|
|
8985
|
-
/* @__PURE__ */
|
|
8986
|
-
/* @__PURE__ */
|
|
10029
|
+
children: /* @__PURE__ */ jsx27("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs23("div", { className: "flex flex-col items-center", children: [
|
|
10030
|
+
/* @__PURE__ */ jsx27("div", { className: "w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" }),
|
|
10031
|
+
/* @__PURE__ */ jsx27("div", { className: "mt-2 text-sm text-gray-500", children: "Loading PDF viewer..." })
|
|
8987
10032
|
] }) })
|
|
8988
10033
|
}
|
|
8989
10034
|
);
|
|
8990
10035
|
});
|
|
8991
|
-
PDFViewer =
|
|
10036
|
+
PDFViewer = memo26(function PDFViewer2(props) {
|
|
8992
10037
|
if (typeof window === "undefined") {
|
|
8993
|
-
return /* @__PURE__ */
|
|
10038
|
+
return /* @__PURE__ */ jsx27(PDFViewerLoading, { className: props.className });
|
|
8994
10039
|
}
|
|
8995
|
-
return /* @__PURE__ */
|
|
10040
|
+
return /* @__PURE__ */ jsx27(Suspense, { fallback: /* @__PURE__ */ jsx27(PDFViewerLoading, { className: props.className }), children: /* @__PURE__ */ jsx27(PDFViewerClient3, { ...props }) });
|
|
8996
10041
|
});
|
|
8997
10042
|
}
|
|
8998
10043
|
});
|
|
@@ -9021,8 +10066,8 @@ init_AnnotationToolbar2();
|
|
|
9021
10066
|
|
|
9022
10067
|
// src/components/Annotations/StickyNote.tsx
|
|
9023
10068
|
init_utils();
|
|
9024
|
-
import { memo as
|
|
9025
|
-
import { jsx as
|
|
10069
|
+
import { memo as memo27, useState as useState22, useRef as useRef20, useEffect as useEffect23, useCallback as useCallback34 } from "react";
|
|
10070
|
+
import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
9026
10071
|
var NOTE_COLORS = [
|
|
9027
10072
|
"#fef08a",
|
|
9028
10073
|
// yellow
|
|
@@ -9035,7 +10080,7 @@ var NOTE_COLORS = [
|
|
|
9035
10080
|
"#fed7aa"
|
|
9036
10081
|
// orange
|
|
9037
10082
|
];
|
|
9038
|
-
var StickyNote =
|
|
10083
|
+
var StickyNote = memo27(function StickyNote2({
|
|
9039
10084
|
note,
|
|
9040
10085
|
scale,
|
|
9041
10086
|
isSelected,
|
|
@@ -9061,24 +10106,24 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9061
10106
|
textareaRef.current.select();
|
|
9062
10107
|
}
|
|
9063
10108
|
}, [isEditing]);
|
|
9064
|
-
const handleClick =
|
|
10109
|
+
const handleClick = useCallback34((e) => {
|
|
9065
10110
|
e.stopPropagation();
|
|
9066
10111
|
onSelect?.();
|
|
9067
10112
|
if (!isExpanded) {
|
|
9068
10113
|
setIsExpanded(true);
|
|
9069
10114
|
}
|
|
9070
10115
|
}, [isExpanded, onSelect]);
|
|
9071
|
-
const handleDoubleClick =
|
|
10116
|
+
const handleDoubleClick = useCallback34((e) => {
|
|
9072
10117
|
e.stopPropagation();
|
|
9073
10118
|
onStartEdit?.();
|
|
9074
10119
|
}, [onStartEdit]);
|
|
9075
|
-
const handleBlur =
|
|
10120
|
+
const handleBlur = useCallback34(() => {
|
|
9076
10121
|
if (isEditing && localContent !== note.content) {
|
|
9077
10122
|
onUpdate?.({ content: localContent });
|
|
9078
10123
|
}
|
|
9079
10124
|
onEndEdit?.();
|
|
9080
10125
|
}, [isEditing, localContent, note.content, onUpdate, onEndEdit]);
|
|
9081
|
-
const handleKeyDown =
|
|
10126
|
+
const handleKeyDown = useCallback34((e) => {
|
|
9082
10127
|
if (e.key === "Escape") {
|
|
9083
10128
|
setLocalContent(note.content);
|
|
9084
10129
|
onEndEdit?.();
|
|
@@ -9086,16 +10131,16 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9086
10131
|
handleBlur();
|
|
9087
10132
|
}
|
|
9088
10133
|
}, [note.content, onEndEdit, handleBlur]);
|
|
9089
|
-
const handleColorChange =
|
|
10134
|
+
const handleColorChange = useCallback34((color) => {
|
|
9090
10135
|
onUpdate?.({ color });
|
|
9091
10136
|
}, [onUpdate]);
|
|
9092
|
-
const handleCollapse =
|
|
10137
|
+
const handleCollapse = useCallback34((e) => {
|
|
9093
10138
|
e.stopPropagation();
|
|
9094
10139
|
setIsExpanded(false);
|
|
9095
10140
|
onEndEdit?.();
|
|
9096
10141
|
}, [onEndEdit]);
|
|
9097
10142
|
if (!isExpanded) {
|
|
9098
|
-
return /* @__PURE__ */
|
|
10143
|
+
return /* @__PURE__ */ jsx28(
|
|
9099
10144
|
"div",
|
|
9100
10145
|
{
|
|
9101
10146
|
ref: noteRef,
|
|
@@ -9116,14 +10161,14 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9116
10161
|
onMouseDown: onDragStart,
|
|
9117
10162
|
onTouchStart: onDragStart,
|
|
9118
10163
|
title: note.content || "Empty note",
|
|
9119
|
-
children: /* @__PURE__ */
|
|
10164
|
+
children: /* @__PURE__ */ jsx28(
|
|
9120
10165
|
"svg",
|
|
9121
10166
|
{
|
|
9122
10167
|
className: "w-4 h-4 opacity-70",
|
|
9123
10168
|
fill: "currentColor",
|
|
9124
10169
|
viewBox: "0 0 20 20",
|
|
9125
10170
|
style: { color: "#333" },
|
|
9126
|
-
children: /* @__PURE__ */
|
|
10171
|
+
children: /* @__PURE__ */ jsx28(
|
|
9127
10172
|
"path",
|
|
9128
10173
|
{
|
|
9129
10174
|
fillRule: "evenodd",
|
|
@@ -9136,7 +10181,7 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9136
10181
|
}
|
|
9137
10182
|
);
|
|
9138
10183
|
}
|
|
9139
|
-
return /* @__PURE__ */
|
|
10184
|
+
return /* @__PURE__ */ jsxs24(
|
|
9140
10185
|
"div",
|
|
9141
10186
|
{
|
|
9142
10187
|
ref: noteRef,
|
|
@@ -9154,14 +10199,14 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9154
10199
|
},
|
|
9155
10200
|
onClick: handleClick,
|
|
9156
10201
|
children: [
|
|
9157
|
-
/* @__PURE__ */
|
|
10202
|
+
/* @__PURE__ */ jsxs24(
|
|
9158
10203
|
"div",
|
|
9159
10204
|
{
|
|
9160
10205
|
className: "flex items-center justify-between px-2 py-1 border-b border-black/10 cursor-move",
|
|
9161
10206
|
onMouseDown: onDragStart,
|
|
9162
10207
|
onTouchStart: onDragStart,
|
|
9163
10208
|
children: [
|
|
9164
|
-
/* @__PURE__ */
|
|
10209
|
+
/* @__PURE__ */ jsx28("div", { className: "flex gap-1", children: NOTE_COLORS.map((color) => /* @__PURE__ */ jsx28(
|
|
9165
10210
|
"button",
|
|
9166
10211
|
{
|
|
9167
10212
|
className: cn(
|
|
@@ -9178,8 +10223,8 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9178
10223
|
},
|
|
9179
10224
|
color
|
|
9180
10225
|
)) }),
|
|
9181
|
-
/* @__PURE__ */
|
|
9182
|
-
/* @__PURE__ */
|
|
10226
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex gap-1", children: [
|
|
10227
|
+
/* @__PURE__ */ jsx28(
|
|
9183
10228
|
"button",
|
|
9184
10229
|
{
|
|
9185
10230
|
className: "p-0.5 hover:bg-black/10 rounded",
|
|
@@ -9188,23 +10233,23 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9188
10233
|
onDelete?.();
|
|
9189
10234
|
},
|
|
9190
10235
|
title: "Delete note",
|
|
9191
|
-
children: /* @__PURE__ */
|
|
10236
|
+
children: /* @__PURE__ */ jsx28("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx28("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" }) })
|
|
9192
10237
|
}
|
|
9193
10238
|
),
|
|
9194
|
-
/* @__PURE__ */
|
|
10239
|
+
/* @__PURE__ */ jsx28(
|
|
9195
10240
|
"button",
|
|
9196
10241
|
{
|
|
9197
10242
|
className: "p-0.5 hover:bg-black/10 rounded",
|
|
9198
10243
|
onClick: handleCollapse,
|
|
9199
10244
|
title: "Collapse note",
|
|
9200
|
-
children: /* @__PURE__ */
|
|
10245
|
+
children: /* @__PURE__ */ jsx28("svg", { className: "w-3.5 h-3.5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx28("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
9201
10246
|
}
|
|
9202
10247
|
)
|
|
9203
10248
|
] })
|
|
9204
10249
|
]
|
|
9205
10250
|
}
|
|
9206
10251
|
),
|
|
9207
|
-
/* @__PURE__ */
|
|
10252
|
+
/* @__PURE__ */ jsx28("div", { className: "p-2", children: isEditing ? /* @__PURE__ */ jsx28(
|
|
9208
10253
|
"textarea",
|
|
9209
10254
|
{
|
|
9210
10255
|
ref: textareaRef,
|
|
@@ -9219,7 +10264,7 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9219
10264
|
onKeyDown: handleKeyDown,
|
|
9220
10265
|
placeholder: "Enter note..."
|
|
9221
10266
|
}
|
|
9222
|
-
) : /* @__PURE__ */
|
|
10267
|
+
) : /* @__PURE__ */ jsx28(
|
|
9223
10268
|
"div",
|
|
9224
10269
|
{
|
|
9225
10270
|
className: cn(
|
|
@@ -9230,7 +10275,7 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9230
10275
|
children: note.content || "Double-click to edit..."
|
|
9231
10276
|
}
|
|
9232
10277
|
) }),
|
|
9233
|
-
/* @__PURE__ */
|
|
10278
|
+
/* @__PURE__ */ jsx28("div", { className: "px-2 pb-1 text-[10px] text-gray-500", children: new Date(note.updatedAt).toLocaleDateString() })
|
|
9234
10279
|
]
|
|
9235
10280
|
}
|
|
9236
10281
|
);
|
|
@@ -9238,8 +10283,8 @@ var StickyNote = memo26(function StickyNote2({
|
|
|
9238
10283
|
|
|
9239
10284
|
// src/components/Annotations/DrawingCanvas.tsx
|
|
9240
10285
|
init_utils();
|
|
9241
|
-
import { memo as
|
|
9242
|
-
import { jsx as
|
|
10286
|
+
import { memo as memo28, useRef as useRef21, useCallback as useCallback35, useState as useState23 } from "react";
|
|
10287
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
9243
10288
|
function pointsToSvgPath(points) {
|
|
9244
10289
|
if (points.length === 0) return "";
|
|
9245
10290
|
if (points.length === 1) {
|
|
@@ -9277,7 +10322,7 @@ function simplifyPath(points, tolerance = 1) {
|
|
|
9277
10322
|
result.push(points[points.length - 1]);
|
|
9278
10323
|
return result;
|
|
9279
10324
|
}
|
|
9280
|
-
var DrawingCanvas =
|
|
10325
|
+
var DrawingCanvas = memo28(function DrawingCanvas2({
|
|
9281
10326
|
width,
|
|
9282
10327
|
height,
|
|
9283
10328
|
scale,
|
|
@@ -9290,7 +10335,7 @@ var DrawingCanvas = memo27(function DrawingCanvas2({
|
|
|
9290
10335
|
const svgRef = useRef21(null);
|
|
9291
10336
|
const [isDrawing, setIsDrawing] = useState23(false);
|
|
9292
10337
|
const [currentPath, setCurrentPath] = useState23([]);
|
|
9293
|
-
const getPoint =
|
|
10338
|
+
const getPoint = useCallback35((e) => {
|
|
9294
10339
|
if (!svgRef.current) return null;
|
|
9295
10340
|
const svg = svgRef.current;
|
|
9296
10341
|
const rect = svg.getBoundingClientRect();
|
|
@@ -9310,7 +10355,7 @@ var DrawingCanvas = memo27(function DrawingCanvas2({
|
|
|
9310
10355
|
y: (clientY - rect.top) / scale
|
|
9311
10356
|
};
|
|
9312
10357
|
}, [scale]);
|
|
9313
|
-
const handleStart =
|
|
10358
|
+
const handleStart = useCallback35((e) => {
|
|
9314
10359
|
if (!isActive) return;
|
|
9315
10360
|
const point = getPoint(e);
|
|
9316
10361
|
if (point) {
|
|
@@ -9318,14 +10363,14 @@ var DrawingCanvas = memo27(function DrawingCanvas2({
|
|
|
9318
10363
|
setCurrentPath([point]);
|
|
9319
10364
|
}
|
|
9320
10365
|
}, [isActive, getPoint]);
|
|
9321
|
-
const handleMove =
|
|
10366
|
+
const handleMove = useCallback35((e) => {
|
|
9322
10367
|
if (!isDrawing || !isActive) return;
|
|
9323
10368
|
const point = getPoint(e);
|
|
9324
10369
|
if (point) {
|
|
9325
10370
|
setCurrentPath((prev) => [...prev, point]);
|
|
9326
10371
|
}
|
|
9327
10372
|
}, [isDrawing, isActive, getPoint]);
|
|
9328
|
-
const handleEnd =
|
|
10373
|
+
const handleEnd = useCallback35(() => {
|
|
9329
10374
|
if (!isDrawing) return;
|
|
9330
10375
|
setIsDrawing(false);
|
|
9331
10376
|
if (currentPath.length >= 2) {
|
|
@@ -9334,7 +10379,7 @@ var DrawingCanvas = memo27(function DrawingCanvas2({
|
|
|
9334
10379
|
}
|
|
9335
10380
|
setCurrentPath([]);
|
|
9336
10381
|
}, [isDrawing, currentPath, onDrawingComplete]);
|
|
9337
|
-
return /* @__PURE__ */
|
|
10382
|
+
return /* @__PURE__ */ jsx29(
|
|
9338
10383
|
"svg",
|
|
9339
10384
|
{
|
|
9340
10385
|
ref: svgRef,
|
|
@@ -9354,7 +10399,7 @@ var DrawingCanvas = memo27(function DrawingCanvas2({
|
|
|
9354
10399
|
onTouchStart: handleStart,
|
|
9355
10400
|
onTouchMove: handleMove,
|
|
9356
10401
|
onTouchEnd: handleEnd,
|
|
9357
|
-
children: isDrawing && currentPath.length > 0 && /* @__PURE__ */
|
|
10402
|
+
children: isDrawing && currentPath.length > 0 && /* @__PURE__ */ jsx29(
|
|
9358
10403
|
"path",
|
|
9359
10404
|
{
|
|
9360
10405
|
d: pointsToSvgPath(currentPath),
|
|
@@ -9372,9 +10417,9 @@ var DrawingCanvas = memo27(function DrawingCanvas2({
|
|
|
9372
10417
|
|
|
9373
10418
|
// src/components/Annotations/ShapeRenderer.tsx
|
|
9374
10419
|
init_utils();
|
|
9375
|
-
import { memo as
|
|
9376
|
-
import { jsx as
|
|
9377
|
-
var ShapeRenderer =
|
|
10420
|
+
import { memo as memo29, useCallback as useCallback36, useState as useState24, useRef as useRef22 } from "react";
|
|
10421
|
+
import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
10422
|
+
var ShapeRenderer = memo29(function ShapeRenderer2({
|
|
9378
10423
|
shape,
|
|
9379
10424
|
scale,
|
|
9380
10425
|
isSelected,
|
|
@@ -9395,7 +10440,7 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9395
10440
|
const scaledWidth = width * scale;
|
|
9396
10441
|
const scaledHeight = height * scale;
|
|
9397
10442
|
const scaledStroke = strokeWidth * scale;
|
|
9398
|
-
const getResizeHandles =
|
|
10443
|
+
const getResizeHandles = useCallback36(() => {
|
|
9399
10444
|
const handleSize = 8;
|
|
9400
10445
|
const half = handleSize / 2;
|
|
9401
10446
|
return [
|
|
@@ -9409,7 +10454,7 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9409
10454
|
{ position: "w", cursor: "ew-resize", x: scaledX - half, y: scaledY + scaledHeight / 2 - half }
|
|
9410
10455
|
];
|
|
9411
10456
|
}, [scaledX, scaledY, scaledWidth, scaledHeight]);
|
|
9412
|
-
const handleMouseDown =
|
|
10457
|
+
const handleMouseDown = useCallback36((e, handle) => {
|
|
9413
10458
|
e.stopPropagation();
|
|
9414
10459
|
onSelect?.();
|
|
9415
10460
|
if (!isEditing) return;
|
|
@@ -9485,7 +10530,7 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9485
10530
|
document.addEventListener("mousemove", handleMouseMove);
|
|
9486
10531
|
document.addEventListener("mouseup", handleMouseUp);
|
|
9487
10532
|
}, [isEditing, x, y, width, height, scale, onSelect, onUpdate]);
|
|
9488
|
-
const renderShape2 =
|
|
10533
|
+
const renderShape2 = useCallback36(() => {
|
|
9489
10534
|
const commonProps = {
|
|
9490
10535
|
stroke: color,
|
|
9491
10536
|
strokeWidth: scaledStroke,
|
|
@@ -9497,7 +10542,7 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9497
10542
|
};
|
|
9498
10543
|
switch (shapeType) {
|
|
9499
10544
|
case "rect":
|
|
9500
|
-
return /* @__PURE__ */
|
|
10545
|
+
return /* @__PURE__ */ jsx30(
|
|
9501
10546
|
"rect",
|
|
9502
10547
|
{
|
|
9503
10548
|
x: scaledX,
|
|
@@ -9508,7 +10553,7 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9508
10553
|
}
|
|
9509
10554
|
);
|
|
9510
10555
|
case "circle":
|
|
9511
|
-
return /* @__PURE__ */
|
|
10556
|
+
return /* @__PURE__ */ jsx30(
|
|
9512
10557
|
"ellipse",
|
|
9513
10558
|
{
|
|
9514
10559
|
cx: scaledX + scaledWidth / 2,
|
|
@@ -9519,7 +10564,7 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9519
10564
|
}
|
|
9520
10565
|
);
|
|
9521
10566
|
case "line":
|
|
9522
|
-
return /* @__PURE__ */
|
|
10567
|
+
return /* @__PURE__ */ jsx30(
|
|
9523
10568
|
"line",
|
|
9524
10569
|
{
|
|
9525
10570
|
x1: scaledX,
|
|
@@ -9539,22 +10584,22 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9539
10584
|
const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);
|
|
9540
10585
|
const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);
|
|
9541
10586
|
const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);
|
|
9542
|
-
return /* @__PURE__ */
|
|
9543
|
-
/* @__PURE__ */
|
|
9544
|
-
/* @__PURE__ */
|
|
9545
|
-
/* @__PURE__ */
|
|
10587
|
+
return /* @__PURE__ */ jsxs25("g", { children: [
|
|
10588
|
+
/* @__PURE__ */ jsx30("line", { x1: scaledX, y1: scaledY, x2: endX, y2: endY, ...commonProps }),
|
|
10589
|
+
/* @__PURE__ */ jsx30("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
|
|
10590
|
+
/* @__PURE__ */ jsx30("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
|
|
9546
10591
|
] });
|
|
9547
10592
|
default:
|
|
9548
10593
|
return null;
|
|
9549
10594
|
}
|
|
9550
10595
|
}, [shapeType, scaledX, scaledY, scaledWidth, scaledHeight, color, scaledStroke, isSelected]);
|
|
9551
|
-
return /* @__PURE__ */
|
|
10596
|
+
return /* @__PURE__ */ jsxs25(
|
|
9552
10597
|
"g",
|
|
9553
10598
|
{
|
|
9554
10599
|
className: cn("shape-renderer", className),
|
|
9555
10600
|
onMouseDown: (e) => handleMouseDown(e),
|
|
9556
10601
|
children: [
|
|
9557
|
-
/* @__PURE__ */
|
|
10602
|
+
/* @__PURE__ */ jsx30(
|
|
9558
10603
|
"rect",
|
|
9559
10604
|
{
|
|
9560
10605
|
x: scaledX - 5,
|
|
@@ -9567,7 +10612,7 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9567
10612
|
}
|
|
9568
10613
|
),
|
|
9569
10614
|
renderShape2(),
|
|
9570
|
-
isSelected && /* @__PURE__ */
|
|
10615
|
+
isSelected && /* @__PURE__ */ jsx30(
|
|
9571
10616
|
"rect",
|
|
9572
10617
|
{
|
|
9573
10618
|
x: scaledX - 2,
|
|
@@ -9580,7 +10625,7 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9580
10625
|
strokeDasharray: "4 2"
|
|
9581
10626
|
}
|
|
9582
10627
|
),
|
|
9583
|
-
isSelected && isEditing && getResizeHandles().map((handle) => /* @__PURE__ */
|
|
10628
|
+
isSelected && isEditing && getResizeHandles().map((handle) => /* @__PURE__ */ jsx30(
|
|
9584
10629
|
"rect",
|
|
9585
10630
|
{
|
|
9586
10631
|
x: handle.x,
|
|
@@ -9600,7 +10645,7 @@ var ShapeRenderer = memo28(function ShapeRenderer2({
|
|
|
9600
10645
|
}
|
|
9601
10646
|
);
|
|
9602
10647
|
});
|
|
9603
|
-
var ShapePreview =
|
|
10648
|
+
var ShapePreview = memo29(function ShapePreview2({
|
|
9604
10649
|
shapeType,
|
|
9605
10650
|
startPoint,
|
|
9606
10651
|
endPoint,
|
|
@@ -9621,9 +10666,9 @@ var ShapePreview = memo28(function ShapePreview2({
|
|
|
9621
10666
|
};
|
|
9622
10667
|
switch (shapeType) {
|
|
9623
10668
|
case "rect":
|
|
9624
|
-
return /* @__PURE__ */
|
|
10669
|
+
return /* @__PURE__ */ jsx30("rect", { x, y, width, height, ...commonProps });
|
|
9625
10670
|
case "circle":
|
|
9626
|
-
return /* @__PURE__ */
|
|
10671
|
+
return /* @__PURE__ */ jsx30(
|
|
9627
10672
|
"ellipse",
|
|
9628
10673
|
{
|
|
9629
10674
|
cx: x + width / 2,
|
|
@@ -9634,7 +10679,7 @@ var ShapePreview = memo28(function ShapePreview2({
|
|
|
9634
10679
|
}
|
|
9635
10680
|
);
|
|
9636
10681
|
case "line":
|
|
9637
|
-
return /* @__PURE__ */
|
|
10682
|
+
return /* @__PURE__ */ jsx30(
|
|
9638
10683
|
"line",
|
|
9639
10684
|
{
|
|
9640
10685
|
x1: startPoint.x * scale,
|
|
@@ -9656,8 +10701,8 @@ var ShapePreview = memo28(function ShapePreview2({
|
|
|
9656
10701
|
const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);
|
|
9657
10702
|
const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);
|
|
9658
10703
|
const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);
|
|
9659
|
-
return /* @__PURE__ */
|
|
9660
|
-
/* @__PURE__ */
|
|
10704
|
+
return /* @__PURE__ */ jsxs25("g", { children: [
|
|
10705
|
+
/* @__PURE__ */ jsx30(
|
|
9661
10706
|
"line",
|
|
9662
10707
|
{
|
|
9663
10708
|
x1: startPoint.x * scale,
|
|
@@ -9667,8 +10712,8 @@ var ShapePreview = memo28(function ShapePreview2({
|
|
|
9667
10712
|
...commonProps
|
|
9668
10713
|
}
|
|
9669
10714
|
),
|
|
9670
|
-
/* @__PURE__ */
|
|
9671
|
-
/* @__PURE__ */
|
|
10715
|
+
/* @__PURE__ */ jsx30("line", { x1: endX, y1: endY, x2: arrow1X, y2: arrow1Y, ...commonProps }),
|
|
10716
|
+
/* @__PURE__ */ jsx30("line", { x1: endX, y1: endY, x2: arrow2X, y2: arrow2Y, ...commonProps })
|
|
9672
10717
|
] });
|
|
9673
10718
|
default:
|
|
9674
10719
|
return null;
|
|
@@ -9677,9 +10722,9 @@ var ShapePreview = memo28(function ShapePreview2({
|
|
|
9677
10722
|
|
|
9678
10723
|
// src/components/Annotations/QuickNoteButton.tsx
|
|
9679
10724
|
init_utils();
|
|
9680
|
-
import { memo as
|
|
9681
|
-
import { jsx as
|
|
9682
|
-
var QuickNoteButton =
|
|
10725
|
+
import { memo as memo30, useCallback as useCallback37, useState as useState25 } from "react";
|
|
10726
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
10727
|
+
var QuickNoteButton = memo30(function QuickNoteButton2({
|
|
9683
10728
|
pageNumber,
|
|
9684
10729
|
scale,
|
|
9685
10730
|
position = "top-right",
|
|
@@ -9688,7 +10733,7 @@ var QuickNoteButton = memo29(function QuickNoteButton2({
|
|
|
9688
10733
|
visible = true
|
|
9689
10734
|
}) {
|
|
9690
10735
|
const [isHovered, setIsHovered] = useState25(false);
|
|
9691
|
-
const handleClick =
|
|
10736
|
+
const handleClick = useCallback37(
|
|
9692
10737
|
(e) => {
|
|
9693
10738
|
e.stopPropagation();
|
|
9694
10739
|
const x = position === "top-right" ? 80 : 80;
|
|
@@ -9700,7 +10745,7 @@ var QuickNoteButton = memo29(function QuickNoteButton2({
|
|
|
9700
10745
|
if (!visible) {
|
|
9701
10746
|
return null;
|
|
9702
10747
|
}
|
|
9703
|
-
return /* @__PURE__ */
|
|
10748
|
+
return /* @__PURE__ */ jsx31(
|
|
9704
10749
|
"button",
|
|
9705
10750
|
{
|
|
9706
10751
|
onClick: handleClick,
|
|
@@ -9722,7 +10767,7 @@ var QuickNoteButton = memo29(function QuickNoteButton2({
|
|
|
9722
10767
|
),
|
|
9723
10768
|
title: "Add quick note",
|
|
9724
10769
|
"aria-label": "Add quick note",
|
|
9725
|
-
children: /* @__PURE__ */
|
|
10770
|
+
children: /* @__PURE__ */ jsx31(
|
|
9726
10771
|
"svg",
|
|
9727
10772
|
{
|
|
9728
10773
|
className: "w-4 h-4 text-yellow-900",
|
|
@@ -9730,7 +10775,7 @@ var QuickNoteButton = memo29(function QuickNoteButton2({
|
|
|
9730
10775
|
viewBox: "0 0 24 24",
|
|
9731
10776
|
stroke: "currentColor",
|
|
9732
10777
|
strokeWidth: 2,
|
|
9733
|
-
children: /* @__PURE__ */
|
|
10778
|
+
children: /* @__PURE__ */ jsx31("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4v16m8-8H4" })
|
|
9734
10779
|
}
|
|
9735
10780
|
)
|
|
9736
10781
|
}
|
|
@@ -9739,9 +10784,9 @@ var QuickNoteButton = memo29(function QuickNoteButton2({
|
|
|
9739
10784
|
|
|
9740
10785
|
// src/components/Annotations/QuickNotePopover.tsx
|
|
9741
10786
|
init_utils();
|
|
9742
|
-
import { memo as
|
|
9743
|
-
import { jsx as
|
|
9744
|
-
var QuickNotePopover =
|
|
10787
|
+
import { memo as memo31, useCallback as useCallback38, useState as useState26, useRef as useRef23, useEffect as useEffect24 } from "react";
|
|
10788
|
+
import { jsx as jsx32, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
10789
|
+
var QuickNotePopover = memo31(function QuickNotePopover2({
|
|
9745
10790
|
visible,
|
|
9746
10791
|
position,
|
|
9747
10792
|
initialContent = "",
|
|
@@ -9783,14 +10828,14 @@ var QuickNotePopover = memo30(function QuickNotePopover2({
|
|
|
9783
10828
|
}
|
|
9784
10829
|
setAdjustedPosition({ x, y });
|
|
9785
10830
|
}, [position, visible]);
|
|
9786
|
-
const handleSave =
|
|
10831
|
+
const handleSave = useCallback38(() => {
|
|
9787
10832
|
if (content.trim()) {
|
|
9788
10833
|
onSave(content.trim());
|
|
9789
10834
|
} else {
|
|
9790
10835
|
onCancel();
|
|
9791
10836
|
}
|
|
9792
10837
|
}, [content, onSave, onCancel]);
|
|
9793
|
-
const handleKeyDown =
|
|
10838
|
+
const handleKeyDown = useCallback38(
|
|
9794
10839
|
(e) => {
|
|
9795
10840
|
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
|
9796
10841
|
e.preventDefault();
|
|
@@ -9805,7 +10850,7 @@ var QuickNotePopover = memo30(function QuickNotePopover2({
|
|
|
9805
10850
|
if (!visible) {
|
|
9806
10851
|
return null;
|
|
9807
10852
|
}
|
|
9808
|
-
return /* @__PURE__ */
|
|
10853
|
+
return /* @__PURE__ */ jsxs26(
|
|
9809
10854
|
"div",
|
|
9810
10855
|
{
|
|
9811
10856
|
ref: popoverRef,
|
|
@@ -9824,15 +10869,15 @@ var QuickNotePopover = memo30(function QuickNotePopover2({
|
|
|
9824
10869
|
top: adjustedPosition.y
|
|
9825
10870
|
},
|
|
9826
10871
|
children: [
|
|
9827
|
-
agentLastStatement && /* @__PURE__ */
|
|
9828
|
-
/* @__PURE__ */
|
|
9829
|
-
/* @__PURE__ */
|
|
10872
|
+
agentLastStatement && /* @__PURE__ */ jsx32("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__ */ jsxs26("div", { className: "flex items-start gap-1", children: [
|
|
10873
|
+
/* @__PURE__ */ jsx32("svg", { className: "w-3 h-3 mt-0.5 flex-shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx32("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" }) }),
|
|
10874
|
+
/* @__PURE__ */ jsxs26("span", { className: "line-clamp-2", children: [
|
|
9830
10875
|
"AI discussed: \u201C",
|
|
9831
10876
|
agentLastStatement,
|
|
9832
10877
|
"\u201D"
|
|
9833
10878
|
] })
|
|
9834
10879
|
] }) }),
|
|
9835
|
-
/* @__PURE__ */
|
|
10880
|
+
/* @__PURE__ */ jsx32(
|
|
9836
10881
|
"textarea",
|
|
9837
10882
|
{
|
|
9838
10883
|
ref: textareaRef,
|
|
@@ -9851,13 +10896,13 @@ var QuickNotePopover = memo30(function QuickNotePopover2({
|
|
|
9851
10896
|
)
|
|
9852
10897
|
}
|
|
9853
10898
|
),
|
|
9854
|
-
/* @__PURE__ */
|
|
9855
|
-
/* @__PURE__ */
|
|
10899
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between mt-2", children: [
|
|
10900
|
+
/* @__PURE__ */ jsxs26("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
|
|
9856
10901
|
navigator.platform.includes("Mac") ? "\u2318" : "Ctrl",
|
|
9857
10902
|
"+Enter to save"
|
|
9858
10903
|
] }),
|
|
9859
|
-
/* @__PURE__ */
|
|
9860
|
-
/* @__PURE__ */
|
|
10904
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex gap-2", children: [
|
|
10905
|
+
/* @__PURE__ */ jsx32(
|
|
9861
10906
|
"button",
|
|
9862
10907
|
{
|
|
9863
10908
|
onClick: onCancel,
|
|
@@ -9870,7 +10915,7 @@ var QuickNotePopover = memo30(function QuickNotePopover2({
|
|
|
9870
10915
|
children: "Cancel"
|
|
9871
10916
|
}
|
|
9872
10917
|
),
|
|
9873
|
-
/* @__PURE__ */
|
|
10918
|
+
/* @__PURE__ */ jsx32(
|
|
9874
10919
|
"button",
|
|
9875
10920
|
{
|
|
9876
10921
|
onClick: handleSave,
|
|
@@ -9894,9 +10939,9 @@ var QuickNotePopover = memo30(function QuickNotePopover2({
|
|
|
9894
10939
|
|
|
9895
10940
|
// src/components/AskAbout/AskAboutOverlay.tsx
|
|
9896
10941
|
init_utils();
|
|
9897
|
-
import { memo as
|
|
9898
|
-
import { jsx as
|
|
9899
|
-
var AskAboutOverlay =
|
|
10942
|
+
import { memo as memo32 } from "react";
|
|
10943
|
+
import { jsx as jsx33, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
10944
|
+
var AskAboutOverlay = memo32(function AskAboutOverlay2({
|
|
9900
10945
|
visible,
|
|
9901
10946
|
progress,
|
|
9902
10947
|
position,
|
|
@@ -9910,7 +10955,7 @@ var AskAboutOverlay = memo31(function AskAboutOverlay2({
|
|
|
9910
10955
|
const radius = (size - strokeWidth) / 2;
|
|
9911
10956
|
const circumference = 2 * Math.PI * radius;
|
|
9912
10957
|
const strokeDashoffset = circumference * (1 - progress);
|
|
9913
|
-
return /* @__PURE__ */
|
|
10958
|
+
return /* @__PURE__ */ jsxs27(
|
|
9914
10959
|
"div",
|
|
9915
10960
|
{
|
|
9916
10961
|
className: cn(
|
|
@@ -9923,7 +10968,7 @@ var AskAboutOverlay = memo31(function AskAboutOverlay2({
|
|
|
9923
10968
|
top: position.y - size / 2
|
|
9924
10969
|
},
|
|
9925
10970
|
children: [
|
|
9926
|
-
/* @__PURE__ */
|
|
10971
|
+
/* @__PURE__ */ jsxs27(
|
|
9927
10972
|
"svg",
|
|
9928
10973
|
{
|
|
9929
10974
|
width: size,
|
|
@@ -9931,7 +10976,7 @@ var AskAboutOverlay = memo31(function AskAboutOverlay2({
|
|
|
9931
10976
|
viewBox: `0 0 ${size} ${size}`,
|
|
9932
10977
|
className: "transform -rotate-90",
|
|
9933
10978
|
children: [
|
|
9934
|
-
/* @__PURE__ */
|
|
10979
|
+
/* @__PURE__ */ jsx33(
|
|
9935
10980
|
"circle",
|
|
9936
10981
|
{
|
|
9937
10982
|
cx: size / 2,
|
|
@@ -9942,7 +10987,7 @@ var AskAboutOverlay = memo31(function AskAboutOverlay2({
|
|
|
9942
10987
|
strokeWidth
|
|
9943
10988
|
}
|
|
9944
10989
|
),
|
|
9945
|
-
/* @__PURE__ */
|
|
10990
|
+
/* @__PURE__ */ jsx33(
|
|
9946
10991
|
"circle",
|
|
9947
10992
|
{
|
|
9948
10993
|
cx: size / 2,
|
|
@@ -9960,12 +11005,12 @@ var AskAboutOverlay = memo31(function AskAboutOverlay2({
|
|
|
9960
11005
|
]
|
|
9961
11006
|
}
|
|
9962
11007
|
),
|
|
9963
|
-
/* @__PURE__ */
|
|
11008
|
+
/* @__PURE__ */ jsx33(
|
|
9964
11009
|
"div",
|
|
9965
11010
|
{
|
|
9966
11011
|
className: "absolute inset-0 flex items-center justify-center",
|
|
9967
11012
|
style: { color: progress >= 1 ? "#22c55e" : "white" },
|
|
9968
|
-
children: progress >= 1 ? /* @__PURE__ */
|
|
11013
|
+
children: progress >= 1 ? /* @__PURE__ */ jsx33(
|
|
9969
11014
|
"svg",
|
|
9970
11015
|
{
|
|
9971
11016
|
width: "24",
|
|
@@ -9976,9 +11021,9 @@ var AskAboutOverlay = memo31(function AskAboutOverlay2({
|
|
|
9976
11021
|
strokeWidth: "2",
|
|
9977
11022
|
strokeLinecap: "round",
|
|
9978
11023
|
strokeLinejoin: "round",
|
|
9979
|
-
children: /* @__PURE__ */
|
|
11024
|
+
children: /* @__PURE__ */ jsx33("polyline", { points: "20 6 9 17 4 12" })
|
|
9980
11025
|
}
|
|
9981
|
-
) : /* @__PURE__ */
|
|
11026
|
+
) : /* @__PURE__ */ jsxs27(
|
|
9982
11027
|
"svg",
|
|
9983
11028
|
{
|
|
9984
11029
|
width: "20",
|
|
@@ -9990,9 +11035,9 @@ var AskAboutOverlay = memo31(function AskAboutOverlay2({
|
|
|
9990
11035
|
strokeLinecap: "round",
|
|
9991
11036
|
strokeLinejoin: "round",
|
|
9992
11037
|
children: [
|
|
9993
|
-
/* @__PURE__ */
|
|
9994
|
-
/* @__PURE__ */
|
|
9995
|
-
/* @__PURE__ */
|
|
11038
|
+
/* @__PURE__ */ jsx33("circle", { cx: "12", cy: "12", r: "10" }),
|
|
11039
|
+
/* @__PURE__ */ jsx33("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
|
|
11040
|
+
/* @__PURE__ */ jsx33("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
|
|
9996
11041
|
]
|
|
9997
11042
|
}
|
|
9998
11043
|
)
|
|
@@ -10005,9 +11050,9 @@ var AskAboutOverlay = memo31(function AskAboutOverlay2({
|
|
|
10005
11050
|
|
|
10006
11051
|
// src/components/AskAbout/AskAboutTrigger.tsx
|
|
10007
11052
|
init_utils();
|
|
10008
|
-
import { memo as
|
|
10009
|
-
import { jsx as
|
|
10010
|
-
var AskAboutTrigger =
|
|
11053
|
+
import { memo as memo33, useCallback as useCallback39, useState as useState27, useRef as useRef24, useEffect as useEffect25 } from "react";
|
|
11054
|
+
import { jsx as jsx34, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
11055
|
+
var AskAboutTrigger = memo33(function AskAboutTrigger2({
|
|
10011
11056
|
position,
|
|
10012
11057
|
onConfirm,
|
|
10013
11058
|
onCancel,
|
|
@@ -10038,14 +11083,14 @@ var AskAboutTrigger = memo32(function AskAboutTrigger2({
|
|
|
10038
11083
|
const timer = setTimeout(onCancel, autoHideDelay);
|
|
10039
11084
|
return () => clearTimeout(timer);
|
|
10040
11085
|
}, [visible, autoHideDelay, onCancel]);
|
|
10041
|
-
const handleConfirm =
|
|
11086
|
+
const handleConfirm = useCallback39(
|
|
10042
11087
|
(e) => {
|
|
10043
11088
|
e.stopPropagation();
|
|
10044
11089
|
onConfirm();
|
|
10045
11090
|
},
|
|
10046
11091
|
[onConfirm]
|
|
10047
11092
|
);
|
|
10048
|
-
const handleCancel =
|
|
11093
|
+
const handleCancel = useCallback39(
|
|
10049
11094
|
(e) => {
|
|
10050
11095
|
e.stopPropagation();
|
|
10051
11096
|
onCancel();
|
|
@@ -10055,7 +11100,7 @@ var AskAboutTrigger = memo32(function AskAboutTrigger2({
|
|
|
10055
11100
|
if (!visible) {
|
|
10056
11101
|
return null;
|
|
10057
11102
|
}
|
|
10058
|
-
return /* @__PURE__ */
|
|
11103
|
+
return /* @__PURE__ */ jsxs28(
|
|
10059
11104
|
"div",
|
|
10060
11105
|
{
|
|
10061
11106
|
ref: triggerRef,
|
|
@@ -10074,8 +11119,8 @@ var AskAboutTrigger = memo32(function AskAboutTrigger2({
|
|
|
10074
11119
|
transform: "translate(-50%, 0)"
|
|
10075
11120
|
},
|
|
10076
11121
|
children: [
|
|
10077
|
-
/* @__PURE__ */
|
|
10078
|
-
/* @__PURE__ */
|
|
11122
|
+
/* @__PURE__ */ jsx34("span", { className: "text-sm text-gray-600 dark:text-gray-300 px-2", children: "Ask about this?" }),
|
|
11123
|
+
/* @__PURE__ */ jsx34(
|
|
10079
11124
|
"button",
|
|
10080
11125
|
{
|
|
10081
11126
|
onClick: handleConfirm,
|
|
@@ -10088,7 +11133,7 @@ var AskAboutTrigger = memo32(function AskAboutTrigger2({
|
|
|
10088
11133
|
children: "Ask"
|
|
10089
11134
|
}
|
|
10090
11135
|
),
|
|
10091
|
-
/* @__PURE__ */
|
|
11136
|
+
/* @__PURE__ */ jsx34(
|
|
10092
11137
|
"button",
|
|
10093
11138
|
{
|
|
10094
11139
|
onClick: handleCancel,
|
|
@@ -10110,9 +11155,9 @@ var AskAboutTrigger = memo32(function AskAboutTrigger2({
|
|
|
10110
11155
|
// src/components/Minimap/Minimap.tsx
|
|
10111
11156
|
init_hooks();
|
|
10112
11157
|
init_utils();
|
|
10113
|
-
import { memo as
|
|
10114
|
-
import { Fragment as Fragment3, jsx as
|
|
10115
|
-
var PageIndicator =
|
|
11158
|
+
import { memo as memo34, useMemo as useMemo14, useCallback as useCallback40 } from "react";
|
|
11159
|
+
import { Fragment as Fragment3, jsx as jsx35, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
11160
|
+
var PageIndicator = memo34(function PageIndicator2({
|
|
10116
11161
|
pageNumber,
|
|
10117
11162
|
status,
|
|
10118
11163
|
isBookmarked,
|
|
@@ -10126,7 +11171,7 @@ var PageIndicator = memo33(function PageIndicator2({
|
|
|
10126
11171
|
if (status === "visited") return "bg-green-400";
|
|
10127
11172
|
return "bg-gray-200 dark:bg-gray-700";
|
|
10128
11173
|
};
|
|
10129
|
-
return /* @__PURE__ */
|
|
11174
|
+
return /* @__PURE__ */ jsxs29(
|
|
10130
11175
|
"button",
|
|
10131
11176
|
{
|
|
10132
11177
|
onClick,
|
|
@@ -10142,13 +11187,13 @@ var PageIndicator = memo33(function PageIndicator2({
|
|
|
10142
11187
|
title: `Page ${pageNumber}${isBookmarked ? " (bookmarked)" : ""}`,
|
|
10143
11188
|
"aria-label": `Go to page ${pageNumber}`,
|
|
10144
11189
|
children: [
|
|
10145
|
-
isBookmarked && !compact && /* @__PURE__ */
|
|
10146
|
-
showNumber && !compact && /* @__PURE__ */
|
|
11190
|
+
isBookmarked && !compact && /* @__PURE__ */ jsx35("div", { className: "absolute -top-1 -right-1 w-2 h-2 bg-yellow-500 rounded-full border border-white" }),
|
|
11191
|
+
showNumber && !compact && /* @__PURE__ */ jsx35("span", { className: "absolute inset-0 flex items-center justify-center text-[8px] font-medium text-white", children: pageNumber })
|
|
10147
11192
|
]
|
|
10148
11193
|
}
|
|
10149
11194
|
);
|
|
10150
11195
|
});
|
|
10151
|
-
var Minimap =
|
|
11196
|
+
var Minimap = memo34(function Minimap2({
|
|
10152
11197
|
variant = "sidebar",
|
|
10153
11198
|
floatingPosition = "right",
|
|
10154
11199
|
maxHeight = 300,
|
|
@@ -10165,14 +11210,14 @@ var Minimap = memo33(function Minimap2({
|
|
|
10165
11210
|
return new Set(bookmarks.map((b) => b.pageNumber));
|
|
10166
11211
|
}, [bookmarks]);
|
|
10167
11212
|
const compact = numPages > 50;
|
|
10168
|
-
const handlePageClick =
|
|
11213
|
+
const handlePageClick = useCallback40(
|
|
10169
11214
|
(pageNumber) => {
|
|
10170
11215
|
goToPage(pageNumber);
|
|
10171
11216
|
onPageClick?.(pageNumber);
|
|
10172
11217
|
},
|
|
10173
11218
|
[goToPage, onPageClick]
|
|
10174
11219
|
);
|
|
10175
|
-
const getPageStatus =
|
|
11220
|
+
const getPageStatus = useCallback40(
|
|
10176
11221
|
(pageNumber) => {
|
|
10177
11222
|
if (pageNumber === currentPage) return "current";
|
|
10178
11223
|
if (bookmarkedPages.has(pageNumber)) return "bookmarked";
|
|
@@ -10185,7 +11230,7 @@ var Minimap = memo33(function Minimap2({
|
|
|
10185
11230
|
const pages = [];
|
|
10186
11231
|
for (let i = 1; i <= numPages; i++) {
|
|
10187
11232
|
pages.push(
|
|
10188
|
-
/* @__PURE__ */
|
|
11233
|
+
/* @__PURE__ */ jsx35(
|
|
10189
11234
|
PageIndicator,
|
|
10190
11235
|
{
|
|
10191
11236
|
pageNumber: i,
|
|
@@ -10206,16 +11251,16 @@ var Minimap = memo33(function Minimap2({
|
|
|
10206
11251
|
if (numPages === 0) {
|
|
10207
11252
|
return null;
|
|
10208
11253
|
}
|
|
10209
|
-
const content = /* @__PURE__ */
|
|
10210
|
-
/* @__PURE__ */
|
|
10211
|
-
/* @__PURE__ */
|
|
10212
|
-
/* @__PURE__ */
|
|
10213
|
-
/* @__PURE__ */
|
|
11254
|
+
const content = /* @__PURE__ */ jsxs29(Fragment3, { children: [
|
|
11255
|
+
/* @__PURE__ */ jsxs29("div", { className: "mb-3", children: [
|
|
11256
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 mb-1", children: [
|
|
11257
|
+
/* @__PURE__ */ jsx35("span", { children: "Progress" }),
|
|
11258
|
+
/* @__PURE__ */ jsxs29("span", { children: [
|
|
10214
11259
|
progressPercentage,
|
|
10215
11260
|
"%"
|
|
10216
11261
|
] })
|
|
10217
11262
|
] }),
|
|
10218
|
-
/* @__PURE__ */
|
|
11263
|
+
/* @__PURE__ */ jsx35("div", { className: "h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx35(
|
|
10219
11264
|
"div",
|
|
10220
11265
|
{
|
|
10221
11266
|
className: "h-full bg-green-500 rounded-full transition-all duration-300",
|
|
@@ -10223,7 +11268,7 @@ var Minimap = memo33(function Minimap2({
|
|
|
10223
11268
|
}
|
|
10224
11269
|
) })
|
|
10225
11270
|
] }),
|
|
10226
|
-
/* @__PURE__ */
|
|
11271
|
+
/* @__PURE__ */ jsx35(
|
|
10227
11272
|
"div",
|
|
10228
11273
|
{
|
|
10229
11274
|
className: cn(
|
|
@@ -10234,21 +11279,21 @@ var Minimap = memo33(function Minimap2({
|
|
|
10234
11279
|
children: pageIndicators
|
|
10235
11280
|
}
|
|
10236
11281
|
),
|
|
10237
|
-
/* @__PURE__ */
|
|
10238
|
-
/* @__PURE__ */
|
|
10239
|
-
/* @__PURE__ */
|
|
10240
|
-
/* @__PURE__ */
|
|
11282
|
+
/* @__PURE__ */ jsx35("div", { className: "mt-3 pt-2 border-t border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsxs29("div", { className: "flex flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400", children: [
|
|
11283
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-1", children: [
|
|
11284
|
+
/* @__PURE__ */ jsx35("div", { className: "w-2 h-2 rounded-sm bg-blue-500" }),
|
|
11285
|
+
/* @__PURE__ */ jsx35("span", { children: "Current" })
|
|
10241
11286
|
] }),
|
|
10242
|
-
/* @__PURE__ */
|
|
10243
|
-
/* @__PURE__ */
|
|
10244
|
-
/* @__PURE__ */
|
|
11287
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-1", children: [
|
|
11288
|
+
/* @__PURE__ */ jsx35("div", { className: "w-2 h-2 rounded-sm bg-green-400" }),
|
|
11289
|
+
/* @__PURE__ */ jsx35("span", { children: "Visited" })
|
|
10245
11290
|
] }),
|
|
10246
|
-
/* @__PURE__ */
|
|
10247
|
-
/* @__PURE__ */
|
|
10248
|
-
/* @__PURE__ */
|
|
11291
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-1", children: [
|
|
11292
|
+
/* @__PURE__ */ jsx35("div", { className: "w-2 h-2 rounded-sm bg-yellow-400" }),
|
|
11293
|
+
/* @__PURE__ */ jsx35("span", { children: "Bookmarked" })
|
|
10249
11294
|
] })
|
|
10250
11295
|
] }) }),
|
|
10251
|
-
/* @__PURE__ */
|
|
11296
|
+
/* @__PURE__ */ jsxs29("div", { className: "mt-2 text-xs text-gray-500 dark:text-gray-400", children: [
|
|
10252
11297
|
visitedCount,
|
|
10253
11298
|
" of ",
|
|
10254
11299
|
numPages,
|
|
@@ -10256,7 +11301,7 @@ var Minimap = memo33(function Minimap2({
|
|
|
10256
11301
|
] })
|
|
10257
11302
|
] });
|
|
10258
11303
|
if (variant === "floating") {
|
|
10259
|
-
return /* @__PURE__ */
|
|
11304
|
+
return /* @__PURE__ */ jsxs29(
|
|
10260
11305
|
"div",
|
|
10261
11306
|
{
|
|
10262
11307
|
className: cn(
|
|
@@ -10272,13 +11317,13 @@ var Minimap = memo33(function Minimap2({
|
|
|
10272
11317
|
),
|
|
10273
11318
|
style: { maxHeight },
|
|
10274
11319
|
children: [
|
|
10275
|
-
/* @__PURE__ */
|
|
11320
|
+
/* @__PURE__ */ jsx35("h3", { className: "text-sm font-semibold text-gray-700 dark:text-gray-200 mb-2", children: "Reading Progress" }),
|
|
10276
11321
|
content
|
|
10277
11322
|
]
|
|
10278
11323
|
}
|
|
10279
11324
|
);
|
|
10280
11325
|
}
|
|
10281
|
-
return /* @__PURE__ */
|
|
11326
|
+
return /* @__PURE__ */ jsx35(
|
|
10282
11327
|
"div",
|
|
10283
11328
|
{
|
|
10284
11329
|
className: cn(
|
|
@@ -10292,10 +11337,250 @@ var Minimap = memo33(function Minimap2({
|
|
|
10292
11337
|
);
|
|
10293
11338
|
});
|
|
10294
11339
|
|
|
11340
|
+
// src/components/index.ts
|
|
11341
|
+
init_FloatingZoomControls2();
|
|
11342
|
+
|
|
11343
|
+
// src/components/PDFThumbnailNav/PDFThumbnailNav.tsx
|
|
11344
|
+
init_hooks();
|
|
11345
|
+
init_utils();
|
|
11346
|
+
import { memo as memo35, useEffect as useEffect26, useState as useState28, useRef as useRef25, useCallback as useCallback41 } from "react";
|
|
11347
|
+
import { jsx as jsx36, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
11348
|
+
var DEFAULT_WIDTH = 612;
|
|
11349
|
+
var DEFAULT_HEIGHT = 792;
|
|
11350
|
+
var PDFThumbnailNav = memo35(function PDFThumbnailNav2({
|
|
11351
|
+
thumbnailScale = 0.15,
|
|
11352
|
+
orientation = "vertical",
|
|
11353
|
+
maxVisible = 10,
|
|
11354
|
+
className,
|
|
11355
|
+
onThumbnailClick,
|
|
11356
|
+
gap = 8,
|
|
11357
|
+
showPageNumbers = true
|
|
11358
|
+
}) {
|
|
11359
|
+
const { document: document2, numPages, currentPage } = usePDFViewer();
|
|
11360
|
+
const { viewerStore } = usePDFViewerStores();
|
|
11361
|
+
const containerRef = useRef25(null);
|
|
11362
|
+
const [thumbnails, setThumbnails] = useState28(/* @__PURE__ */ new Map());
|
|
11363
|
+
const [visibleRange, setVisibleRange] = useState28({ start: 1, end: maxVisible });
|
|
11364
|
+
const renderQueueRef = useRef25(/* @__PURE__ */ new Set());
|
|
11365
|
+
const pageCache = useRef25(/* @__PURE__ */ new Map());
|
|
11366
|
+
const thumbnailWidth = Math.floor(DEFAULT_WIDTH * thumbnailScale);
|
|
11367
|
+
const thumbnailHeight = Math.floor(DEFAULT_HEIGHT * thumbnailScale);
|
|
11368
|
+
const updateVisibleRange = useCallback41(() => {
|
|
11369
|
+
if (!containerRef.current || numPages === 0) return;
|
|
11370
|
+
const container = containerRef.current;
|
|
11371
|
+
const isHorizontal2 = orientation === "horizontal";
|
|
11372
|
+
const scrollPosition = isHorizontal2 ? container.scrollLeft : container.scrollTop;
|
|
11373
|
+
const viewportSize = isHorizontal2 ? container.clientWidth : container.clientHeight;
|
|
11374
|
+
const itemSize = (isHorizontal2 ? thumbnailWidth : thumbnailHeight) + gap;
|
|
11375
|
+
const firstVisible = Math.max(1, Math.floor(scrollPosition / itemSize) + 1);
|
|
11376
|
+
const visibleCount = Math.ceil(viewportSize / itemSize) + 2;
|
|
11377
|
+
const lastVisible = Math.min(numPages, firstVisible + visibleCount);
|
|
11378
|
+
setVisibleRange({ start: firstVisible, end: lastVisible });
|
|
11379
|
+
}, [numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
|
|
11380
|
+
useEffect26(() => {
|
|
11381
|
+
const container = containerRef.current;
|
|
11382
|
+
if (!container) return;
|
|
11383
|
+
const handleScroll = () => {
|
|
11384
|
+
requestAnimationFrame(updateVisibleRange);
|
|
11385
|
+
};
|
|
11386
|
+
container.addEventListener("scroll", handleScroll, { passive: true });
|
|
11387
|
+
updateVisibleRange();
|
|
11388
|
+
return () => container.removeEventListener("scroll", handleScroll);
|
|
11389
|
+
}, [updateVisibleRange]);
|
|
11390
|
+
useEffect26(() => {
|
|
11391
|
+
if (!document2) {
|
|
11392
|
+
setThumbnails(/* @__PURE__ */ new Map());
|
|
11393
|
+
pageCache.current.clear();
|
|
11394
|
+
return;
|
|
11395
|
+
}
|
|
11396
|
+
const renderThumbnails = async () => {
|
|
11397
|
+
const newThumbnails = new Map(thumbnails);
|
|
11398
|
+
const pagesToRender = [];
|
|
11399
|
+
for (let i = visibleRange.start; i <= visibleRange.end; i++) {
|
|
11400
|
+
if (!newThumbnails.has(i) && !renderQueueRef.current.has(i)) {
|
|
11401
|
+
pagesToRender.push(i);
|
|
11402
|
+
renderQueueRef.current.add(i);
|
|
11403
|
+
}
|
|
11404
|
+
}
|
|
11405
|
+
for (const pageNum of pagesToRender) {
|
|
11406
|
+
try {
|
|
11407
|
+
let page = pageCache.current.get(pageNum);
|
|
11408
|
+
if (!page) {
|
|
11409
|
+
page = await document2.getPage(pageNum);
|
|
11410
|
+
pageCache.current.set(pageNum, page);
|
|
11411
|
+
}
|
|
11412
|
+
const viewport = page.getViewport({ scale: thumbnailScale });
|
|
11413
|
+
const canvas = window.document.createElement("canvas");
|
|
11414
|
+
canvas.width = Math.floor(viewport.width);
|
|
11415
|
+
canvas.height = Math.floor(viewport.height);
|
|
11416
|
+
const ctx = canvas.getContext("2d");
|
|
11417
|
+
if (ctx) {
|
|
11418
|
+
await page.render({
|
|
11419
|
+
canvasContext: ctx,
|
|
11420
|
+
viewport
|
|
11421
|
+
}).promise;
|
|
11422
|
+
newThumbnails.set(pageNum, {
|
|
11423
|
+
pageNumber: pageNum,
|
|
11424
|
+
canvas,
|
|
11425
|
+
width: canvas.width,
|
|
11426
|
+
height: canvas.height
|
|
11427
|
+
});
|
|
11428
|
+
}
|
|
11429
|
+
} catch (error) {
|
|
11430
|
+
console.error(`Failed to render thumbnail for page ${pageNum}:`, error);
|
|
11431
|
+
} finally {
|
|
11432
|
+
renderQueueRef.current.delete(pageNum);
|
|
11433
|
+
}
|
|
11434
|
+
}
|
|
11435
|
+
if (pagesToRender.length > 0) {
|
|
11436
|
+
setThumbnails(newThumbnails);
|
|
11437
|
+
}
|
|
11438
|
+
};
|
|
11439
|
+
renderThumbnails();
|
|
11440
|
+
}, [document2, visibleRange, thumbnailScale, thumbnails]);
|
|
11441
|
+
useEffect26(() => {
|
|
11442
|
+
if (!containerRef.current || numPages === 0) return;
|
|
11443
|
+
const container = containerRef.current;
|
|
11444
|
+
const isHorizontal2 = orientation === "horizontal";
|
|
11445
|
+
const itemSize = (isHorizontal2 ? thumbnailWidth : thumbnailHeight) + gap;
|
|
11446
|
+
const targetPosition = (currentPage - 1) * itemSize;
|
|
11447
|
+
const scrollPosition = isHorizontal2 ? container.scrollLeft : container.scrollTop;
|
|
11448
|
+
const viewportSize = isHorizontal2 ? container.clientWidth : container.clientHeight;
|
|
11449
|
+
if (targetPosition < scrollPosition || targetPosition + itemSize > scrollPosition + viewportSize) {
|
|
11450
|
+
const targetScroll = targetPosition - (viewportSize - itemSize) / 2;
|
|
11451
|
+
container.scrollTo({
|
|
11452
|
+
[isHorizontal2 ? "left" : "top"]: Math.max(0, targetScroll),
|
|
11453
|
+
behavior: "smooth"
|
|
11454
|
+
});
|
|
11455
|
+
}
|
|
11456
|
+
}, [currentPage, numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
|
|
11457
|
+
const handleThumbnailClick = useCallback41((pageNum) => {
|
|
11458
|
+
onThumbnailClick?.(pageNum);
|
|
11459
|
+
viewerStore.getState().requestScrollToPage(pageNum, "smooth");
|
|
11460
|
+
}, [onThumbnailClick, viewerStore]);
|
|
11461
|
+
if (!document2 || numPages === 0) {
|
|
11462
|
+
return /* @__PURE__ */ jsx36(
|
|
11463
|
+
"div",
|
|
11464
|
+
{
|
|
11465
|
+
className: cn(
|
|
11466
|
+
"pdf-thumbnail-nav",
|
|
11467
|
+
"flex items-center justify-center",
|
|
11468
|
+
"bg-gray-100 dark:bg-gray-800",
|
|
11469
|
+
"text-gray-500 dark:text-gray-400",
|
|
11470
|
+
"text-sm",
|
|
11471
|
+
className
|
|
11472
|
+
),
|
|
11473
|
+
style: {
|
|
11474
|
+
width: orientation === "vertical" ? thumbnailWidth + 24 : "100%",
|
|
11475
|
+
height: orientation === "horizontal" ? thumbnailHeight + 40 : "100%"
|
|
11476
|
+
},
|
|
11477
|
+
children: "No document"
|
|
11478
|
+
}
|
|
11479
|
+
);
|
|
11480
|
+
}
|
|
11481
|
+
const isHorizontal = orientation === "horizontal";
|
|
11482
|
+
const totalSize = numPages * ((isHorizontal ? thumbnailWidth : thumbnailHeight) + gap) - gap;
|
|
11483
|
+
return /* @__PURE__ */ jsx36(
|
|
11484
|
+
"div",
|
|
11485
|
+
{
|
|
11486
|
+
ref: containerRef,
|
|
11487
|
+
className: cn(
|
|
11488
|
+
"pdf-thumbnail-nav",
|
|
11489
|
+
"overflow-auto",
|
|
11490
|
+
"bg-gray-100 dark:bg-gray-800",
|
|
11491
|
+
isHorizontal ? "flex-row" : "flex-col",
|
|
11492
|
+
className
|
|
11493
|
+
),
|
|
11494
|
+
style: {
|
|
11495
|
+
...isHorizontal ? { overflowX: "auto", overflowY: "hidden" } : { overflowX: "hidden", overflowY: "auto" }
|
|
11496
|
+
},
|
|
11497
|
+
children: /* @__PURE__ */ jsx36(
|
|
11498
|
+
"div",
|
|
11499
|
+
{
|
|
11500
|
+
className: cn(
|
|
11501
|
+
"relative",
|
|
11502
|
+
isHorizontal ? "flex flex-row items-center" : "flex flex-col items-center"
|
|
11503
|
+
),
|
|
11504
|
+
style: {
|
|
11505
|
+
[isHorizontal ? "width" : "height"]: totalSize,
|
|
11506
|
+
[isHorizontal ? "minWidth" : "minHeight"]: totalSize,
|
|
11507
|
+
padding: gap / 2,
|
|
11508
|
+
gap
|
|
11509
|
+
},
|
|
11510
|
+
children: Array.from({ length: numPages }, (_, i) => i + 1).map((pageNum) => {
|
|
11511
|
+
const thumbnail = thumbnails.get(pageNum);
|
|
11512
|
+
const isActive = pageNum === currentPage;
|
|
11513
|
+
const isVisible = pageNum >= visibleRange.start && pageNum <= visibleRange.end;
|
|
11514
|
+
return /* @__PURE__ */ jsxs30(
|
|
11515
|
+
"div",
|
|
11516
|
+
{
|
|
11517
|
+
className: cn(
|
|
11518
|
+
"pdf-thumbnail",
|
|
11519
|
+
"flex-shrink-0 cursor-pointer transition-all duration-200",
|
|
11520
|
+
"border-2 rounded shadow-sm hover:shadow-md",
|
|
11521
|
+
isActive ? "border-blue-500 ring-2 ring-blue-200 dark:ring-blue-800" : "border-gray-300 dark:border-gray-600 hover:border-blue-400"
|
|
11522
|
+
),
|
|
11523
|
+
style: {
|
|
11524
|
+
width: thumbnailWidth,
|
|
11525
|
+
height: thumbnailHeight + (showPageNumbers ? 24 : 0)
|
|
11526
|
+
},
|
|
11527
|
+
onClick: () => handleThumbnailClick(pageNum),
|
|
11528
|
+
role: "button",
|
|
11529
|
+
tabIndex: 0,
|
|
11530
|
+
"aria-label": `Go to page ${pageNum}`,
|
|
11531
|
+
"aria-current": isActive ? "page" : void 0,
|
|
11532
|
+
onKeyDown: (e) => {
|
|
11533
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
11534
|
+
e.preventDefault();
|
|
11535
|
+
handleThumbnailClick(pageNum);
|
|
11536
|
+
}
|
|
11537
|
+
},
|
|
11538
|
+
children: [
|
|
11539
|
+
/* @__PURE__ */ jsx36(
|
|
11540
|
+
"div",
|
|
11541
|
+
{
|
|
11542
|
+
className: "relative bg-white dark:bg-gray-700",
|
|
11543
|
+
style: {
|
|
11544
|
+
width: thumbnailWidth,
|
|
11545
|
+
height: thumbnailHeight
|
|
11546
|
+
},
|
|
11547
|
+
children: isVisible && thumbnail?.canvas ? /* @__PURE__ */ jsx36(
|
|
11548
|
+
"img",
|
|
11549
|
+
{
|
|
11550
|
+
src: thumbnail.canvas.toDataURL(),
|
|
11551
|
+
alt: `Page ${pageNum}`,
|
|
11552
|
+
className: "w-full h-full object-contain",
|
|
11553
|
+
loading: "lazy"
|
|
11554
|
+
}
|
|
11555
|
+
) : /* @__PURE__ */ jsx36("div", { className: "absolute inset-0 flex items-center justify-center text-gray-400 dark:text-gray-500 text-xs", children: pageNum })
|
|
11556
|
+
}
|
|
11557
|
+
),
|
|
11558
|
+
showPageNumbers && /* @__PURE__ */ jsx36(
|
|
11559
|
+
"div",
|
|
11560
|
+
{
|
|
11561
|
+
className: cn(
|
|
11562
|
+
"text-center text-xs py-1",
|
|
11563
|
+
"bg-gray-50 dark:bg-gray-700",
|
|
11564
|
+
isActive ? "text-blue-600 dark:text-blue-400 font-medium" : "text-gray-600 dark:text-gray-400"
|
|
11565
|
+
),
|
|
11566
|
+
children: pageNum
|
|
11567
|
+
}
|
|
11568
|
+
)
|
|
11569
|
+
]
|
|
11570
|
+
},
|
|
11571
|
+
pageNum
|
|
11572
|
+
);
|
|
11573
|
+
})
|
|
11574
|
+
}
|
|
11575
|
+
)
|
|
11576
|
+
}
|
|
11577
|
+
);
|
|
11578
|
+
});
|
|
11579
|
+
|
|
10295
11580
|
// src/components/ErrorBoundary/PDFErrorBoundary.tsx
|
|
10296
11581
|
init_utils();
|
|
10297
11582
|
import { Component } from "react";
|
|
10298
|
-
import { jsx as
|
|
11583
|
+
import { jsx as jsx37, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
10299
11584
|
var PDFErrorBoundary = class extends Component {
|
|
10300
11585
|
constructor(props) {
|
|
10301
11586
|
super(props);
|
|
@@ -10323,7 +11608,7 @@ var PDFErrorBoundary = class extends Component {
|
|
|
10323
11608
|
return fallback;
|
|
10324
11609
|
}
|
|
10325
11610
|
if (showDefaultUI) {
|
|
10326
|
-
return /* @__PURE__ */
|
|
11611
|
+
return /* @__PURE__ */ jsx37(
|
|
10327
11612
|
DefaultErrorUI,
|
|
10328
11613
|
{
|
|
10329
11614
|
error,
|
|
@@ -10342,7 +11627,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10342
11627
|
const isNetworkError = error.message.includes("fetch") || error.message.includes("network") || error.message.includes("Failed to load");
|
|
10343
11628
|
let title = "Something went wrong";
|
|
10344
11629
|
let description = error.message;
|
|
10345
|
-
let icon = /* @__PURE__ */
|
|
11630
|
+
let icon = /* @__PURE__ */ jsx37("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx37(
|
|
10346
11631
|
"path",
|
|
10347
11632
|
{
|
|
10348
11633
|
strokeLinecap: "round",
|
|
@@ -10354,7 +11639,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10354
11639
|
if (isPDFError) {
|
|
10355
11640
|
title = "Unable to load PDF";
|
|
10356
11641
|
description = "The PDF file could not be loaded. It may be corrupted or in an unsupported format.";
|
|
10357
|
-
icon = /* @__PURE__ */
|
|
11642
|
+
icon = /* @__PURE__ */ jsx37("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx37(
|
|
10358
11643
|
"path",
|
|
10359
11644
|
{
|
|
10360
11645
|
strokeLinecap: "round",
|
|
@@ -10366,7 +11651,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10366
11651
|
} else if (isNetworkError) {
|
|
10367
11652
|
title = "Network error";
|
|
10368
11653
|
description = "Unable to fetch the PDF file. Please check your internet connection and try again.";
|
|
10369
|
-
icon = /* @__PURE__ */
|
|
11654
|
+
icon = /* @__PURE__ */ jsx37("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx37(
|
|
10370
11655
|
"path",
|
|
10371
11656
|
{
|
|
10372
11657
|
strokeLinecap: "round",
|
|
@@ -10376,7 +11661,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10376
11661
|
}
|
|
10377
11662
|
) });
|
|
10378
11663
|
}
|
|
10379
|
-
return /* @__PURE__ */
|
|
11664
|
+
return /* @__PURE__ */ jsxs31(
|
|
10380
11665
|
"div",
|
|
10381
11666
|
{
|
|
10382
11667
|
className: cn(
|
|
@@ -10389,14 +11674,14 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10389
11674
|
),
|
|
10390
11675
|
children: [
|
|
10391
11676
|
icon,
|
|
10392
|
-
/* @__PURE__ */
|
|
10393
|
-
/* @__PURE__ */
|
|
10394
|
-
/* @__PURE__ */
|
|
10395
|
-
/* @__PURE__ */
|
|
10396
|
-
/* @__PURE__ */
|
|
11677
|
+
/* @__PURE__ */ jsx37("h2", { className: "mt-4 text-xl font-semibold text-gray-900 dark:text-gray-100", children: title }),
|
|
11678
|
+
/* @__PURE__ */ jsx37("p", { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 max-w-md", children: description }),
|
|
11679
|
+
/* @__PURE__ */ jsxs31("details", { className: "mt-4 text-left max-w-md w-full", children: [
|
|
11680
|
+
/* @__PURE__ */ jsx37("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" }),
|
|
11681
|
+
/* @__PURE__ */ jsx37("pre", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto", children: error.stack || error.message })
|
|
10397
11682
|
] }),
|
|
10398
|
-
/* @__PURE__ */
|
|
10399
|
-
/* @__PURE__ */
|
|
11683
|
+
/* @__PURE__ */ jsxs31("div", { className: "mt-6 flex gap-3", children: [
|
|
11684
|
+
/* @__PURE__ */ jsx37(
|
|
10400
11685
|
"button",
|
|
10401
11686
|
{
|
|
10402
11687
|
onClick: onReset,
|
|
@@ -10410,7 +11695,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10410
11695
|
children: "Try again"
|
|
10411
11696
|
}
|
|
10412
11697
|
),
|
|
10413
|
-
/* @__PURE__ */
|
|
11698
|
+
/* @__PURE__ */ jsx37(
|
|
10414
11699
|
"button",
|
|
10415
11700
|
{
|
|
10416
11701
|
onClick: () => window.location.reload(),
|
|
@@ -10430,7 +11715,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10430
11715
|
);
|
|
10431
11716
|
}
|
|
10432
11717
|
function withErrorBoundary({ component, ...props }) {
|
|
10433
|
-
return /* @__PURE__ */
|
|
11718
|
+
return /* @__PURE__ */ jsx37(PDFErrorBoundary, { ...props, children: component });
|
|
10434
11719
|
}
|
|
10435
11720
|
|
|
10436
11721
|
// src/index.ts
|
|
@@ -10453,6 +11738,7 @@ export {
|
|
|
10453
11738
|
DocumentContainer,
|
|
10454
11739
|
DrawingCanvas,
|
|
10455
11740
|
DualPageContainer,
|
|
11741
|
+
FloatingZoomControls,
|
|
10456
11742
|
FocusRegionLayer,
|
|
10457
11743
|
HighlightLayer,
|
|
10458
11744
|
HighlightPopover,
|
|
@@ -10463,6 +11749,7 @@ export {
|
|
|
10463
11749
|
OutlinePanel,
|
|
10464
11750
|
PDFErrorBoundary,
|
|
10465
11751
|
PDFPage,
|
|
11752
|
+
PDFThumbnailNav,
|
|
10466
11753
|
PDFViewer,
|
|
10467
11754
|
PDFViewerClient,
|
|
10468
11755
|
PDFViewerContext,
|
|
@@ -10481,9 +11768,11 @@ export {
|
|
|
10481
11768
|
ThumbnailPanel,
|
|
10482
11769
|
Toolbar,
|
|
10483
11770
|
VirtualizedDocumentContainer,
|
|
11771
|
+
applyRotation,
|
|
10484
11772
|
clearHighlights,
|
|
10485
11773
|
clearStudentData,
|
|
10486
11774
|
cn,
|
|
11775
|
+
countTextOnPage,
|
|
10487
11776
|
createAgentAPI,
|
|
10488
11777
|
createAgentStore,
|
|
10489
11778
|
createAnnotationStore,
|
|
@@ -10492,6 +11781,7 @@ export {
|
|
|
10492
11781
|
createSearchStore,
|
|
10493
11782
|
createStudentStore,
|
|
10494
11783
|
createViewerStore,
|
|
11784
|
+
doRectsIntersect,
|
|
10495
11785
|
downloadAnnotationsAsJSON,
|
|
10496
11786
|
downloadAnnotationsAsMarkdown,
|
|
10497
11787
|
downloadFile,
|
|
@@ -10499,25 +11789,39 @@ export {
|
|
|
10499
11789
|
exportAnnotationsAsMarkdown,
|
|
10500
11790
|
exportHighlightsAsJSON,
|
|
10501
11791
|
exportHighlightsAsMarkdown,
|
|
11792
|
+
extractPageText,
|
|
11793
|
+
findTextInDocument,
|
|
11794
|
+
findTextOnPage,
|
|
10502
11795
|
generateDocumentId,
|
|
10503
11796
|
getAllDocumentIds,
|
|
10504
11797
|
getAllStudentDataDocumentIds,
|
|
10505
11798
|
getMetadata,
|
|
10506
11799
|
getOutline,
|
|
10507
11800
|
getPage,
|
|
11801
|
+
getPageText,
|
|
10508
11802
|
getPageTextContent,
|
|
10509
11803
|
getPluginManager,
|
|
11804
|
+
getRectIntersection,
|
|
11805
|
+
getRotatedDimensions,
|
|
10510
11806
|
getStorageStats,
|
|
10511
11807
|
importHighlightsFromJSON,
|
|
10512
11808
|
initializePDFJS,
|
|
10513
11809
|
isPDFJSInitialized,
|
|
11810
|
+
isPointInRect,
|
|
10514
11811
|
loadDocument,
|
|
10515
11812
|
loadHighlights,
|
|
10516
11813
|
loadStudentData,
|
|
11814
|
+
mergeAdjacentRects,
|
|
11815
|
+
pdfToPercent,
|
|
11816
|
+
pdfToViewport,
|
|
10517
11817
|
pdfjsLib,
|
|
11818
|
+
percentToPDF,
|
|
11819
|
+
percentToViewport,
|
|
10518
11820
|
quickViewer,
|
|
11821
|
+
removeRotation,
|
|
10519
11822
|
saveHighlights,
|
|
10520
11823
|
saveStudentData,
|
|
11824
|
+
scaleRect,
|
|
10521
11825
|
useAgentContext,
|
|
10522
11826
|
useAgentStore,
|
|
10523
11827
|
useAnnotationStore,
|
|
@@ -10539,6 +11843,8 @@ export {
|
|
|
10539
11843
|
useTouchGestures,
|
|
10540
11844
|
useViewerStore,
|
|
10541
11845
|
useZoom,
|
|
11846
|
+
viewportToPDF,
|
|
11847
|
+
viewportToPercent,
|
|
10542
11848
|
withErrorBoundary
|
|
10543
11849
|
};
|
|
10544
11850
|
//# sourceMappingURL=index.js.map
|