@anaralabs/lector 3.2.0 → 3.4.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.js CHANGED
@@ -1,13 +1,14 @@
1
1
  'use client';
2
2
 
3
3
  import { AnnotationLayer, TextLayer, getDocument } from 'pdfjs-dist';
4
- import React, { createContext, forwardRef, useContext, useCallback, cloneElement, useState, useRef, useEffect, createRef, useLayoutEffect } from 'react';
4
+ import React, { createContext, forwardRef, useContext, useState, useRef, useCallback, useEffect, cloneElement, createRef, useLayoutEffect } from 'react';
5
5
  import { useVirtualizer, elementScroll, debounce } from '@tanstack/react-virtual';
6
6
  import { useStore, createStore } from 'zustand';
7
7
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
8
8
  import { useDebounce } from 'use-debounce';
9
- import { Slot } from '@radix-ui/react-slot';
9
+ import { v4 } from 'uuid';
10
10
  import { useFloating, autoUpdate, offset, shift, useDismiss, useInteractions } from '@floating-ui/react';
11
+ import { Slot } from '@radix-ui/react-slot';
11
12
 
12
13
  // ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
13
14
  function r(e) {
@@ -130,7 +131,16 @@ var PDFStore = createZustandContext(
130
131
  set({
131
132
  customSelectionRects: val
132
133
  });
133
- }
134
+ },
135
+ coloredHighlights: [],
136
+ addColoredHighlight: (value) => set((prevState) => ({
137
+ coloredHighlights: [...prevState.coloredHighlights, value]
138
+ })),
139
+ deleteColoredHighlight: (uuid) => set((prevState) => ({
140
+ coloredHighlights: prevState.coloredHighlights.filter(
141
+ (rect) => rect.uuid !== uuid
142
+ )
143
+ }))
134
144
  }));
135
145
  }
136
146
  );
@@ -160,10 +170,74 @@ var cancellable = (promise) => {
160
170
  }
161
171
  };
162
172
  };
173
+
174
+ // src/hooks/pages/usePdfJump.tsx
175
+ var usePdfJump = () => {
176
+ const virtualizer = usePdf((state) => state.virtualizer);
177
+ const setHighlight = usePdf((state) => state.setHighlight);
178
+ const jumpToPage = (pageIndex, options) => {
179
+ if (!virtualizer) return;
180
+ const defaultOptions = {
181
+ align: "start",
182
+ behavior: "smooth"
183
+ };
184
+ const finalOptions = { ...defaultOptions, ...options };
185
+ virtualizer.scrollToIndex(pageIndex - 1, finalOptions);
186
+ };
187
+ const jumpToOffset = (offset2) => {
188
+ if (!virtualizer) return;
189
+ virtualizer.scrollToOffset(offset2, {
190
+ align: "start",
191
+ behavior: "smooth"
192
+ });
193
+ };
194
+ const jumpToHighlightRects = (rects, type, align = "start", additionalOffset = 0) => {
195
+ if (!virtualizer) return;
196
+ setHighlight(rects);
197
+ const firstPage = Math.min(...rects.map((rect) => rect.pageNumber));
198
+ const pageOffset = virtualizer.getOffsetForIndex(firstPage - 1, "start");
199
+ if (pageOffset === null) return;
200
+ const targetRect = rects.find((rect) => rect.pageNumber === firstPage);
201
+ if (!targetRect) return;
202
+ const isNumber = pageOffset?.[0] != null;
203
+ if (!isNumber) return;
204
+ const pageStart = pageOffset[0] ?? 0;
205
+ let rectTop;
206
+ let rectHeight;
207
+ if (type === "percent") {
208
+ const estimatePageHeight = virtualizer.options.estimateSize(
209
+ firstPage - 1
210
+ );
211
+ rectTop = targetRect.top / 100 * estimatePageHeight;
212
+ rectHeight = targetRect.height / 100 * estimatePageHeight;
213
+ } else {
214
+ rectTop = targetRect.top;
215
+ rectHeight = targetRect.height;
216
+ }
217
+ let scrollOffset;
218
+ if (align === "center") {
219
+ const viewportHeight = virtualizer.scrollElement?.clientHeight || 0;
220
+ const rectCenter = pageStart + rectTop + rectHeight / 2;
221
+ scrollOffset = rectCenter - viewportHeight / 2;
222
+ } else {
223
+ scrollOffset = pageStart + rectTop;
224
+ }
225
+ scrollOffset += additionalOffset;
226
+ const adjustedOffset = Math.max(0, scrollOffset);
227
+ virtualizer.scrollToOffset(adjustedOffset, {
228
+ align: "start",
229
+ // Always use start when we've calculated our own centering
230
+ behavior: "smooth"
231
+ });
232
+ };
233
+ return { jumpToPage, jumpToOffset, jumpToHighlightRects };
234
+ };
163
235
  var LinkService = class {
164
236
  _pdfDocumentProxy;
165
237
  externalLinkEnabled = true;
166
238
  isInPresentationMode = false;
239
+ _currentPageNumber = 0;
240
+ _pageNavigationCallback;
167
241
  get pdfDocumentProxy() {
168
242
  if (!this._pdfDocumentProxy) {
169
243
  throw new Error("pdfDocumentProxy is not set");
@@ -173,17 +247,66 @@ var LinkService = class {
173
247
  constructor() {
174
248
  }
175
249
  get pagesCount() {
176
- return this.pdfDocumentProxy.numPages;
250
+ return this._pdfDocumentProxy?.numPages || 0;
251
+ }
252
+ get page() {
253
+ return this._currentPageNumber;
254
+ }
255
+ set page(value) {
256
+ this._currentPageNumber = value;
257
+ if (this._pageNavigationCallback) {
258
+ this._pageNavigationCallback(value);
259
+ }
260
+ }
261
+ // Required for link annotations to work
262
+ setDocument(pdfDocument) {
263
+ this._pdfDocumentProxy = pdfDocument;
264
+ }
265
+ setViewer() {
177
266
  }
178
267
  getDestinationHash(dest) {
179
- return `#dest-${dest[0].num}`;
268
+ if (!dest) return "";
269
+ const destRef = dest[0];
270
+ if (dest.length > 1 && typeof dest[1] === "object" && dest[1] !== null && "url" in dest[1]) {
271
+ const urlDest = dest[1];
272
+ return urlDest.url;
273
+ }
274
+ if (destRef && typeof destRef === "object") {
275
+ if ("num" in destRef) {
276
+ const numRef = destRef;
277
+ return `#page=${numRef.num + 1}`;
278
+ }
279
+ if ("gen" in destRef) {
280
+ const genRef = destRef;
281
+ const refNum = genRef.num ?? 0;
282
+ return `#page=${refNum + 1}`;
283
+ }
284
+ }
285
+ if (typeof destRef === "number") {
286
+ return `#page=${destRef + 1}`;
287
+ }
288
+ return `#dest-${String(dest)}`;
180
289
  }
181
- getAnchorUrl() {
182
- return "#";
290
+ getAnchorUrl(hash) {
291
+ if (hash.startsWith("http://") || hash.startsWith("https://")) {
292
+ return hash;
293
+ }
294
+ return `#${hash}`;
183
295
  }
184
296
  addLinkAttributes(link, url, newWindow) {
185
- link.href = url;
186
- link.target = newWindow === false ? "" : "_blank";
297
+ if (!link) return;
298
+ const isExternalLink = url.startsWith("http://") || url.startsWith("https://");
299
+ if (isExternalLink && this.externalLinkEnabled) {
300
+ link.href = url;
301
+ link.target = newWindow === false ? "" : "_blank";
302
+ link.rel = "noopener noreferrer";
303
+ } else if (!isExternalLink) {
304
+ link.href = url;
305
+ link.target = "";
306
+ } else {
307
+ link.href = "#";
308
+ link.target = "";
309
+ }
187
310
  }
188
311
  async goToDestination(dest) {
189
312
  let explicitDest;
@@ -197,11 +320,70 @@ var LinkService = class {
197
320
  if (!explicitDest) {
198
321
  return;
199
322
  }
200
- const explicitRef = explicitDest[0];
201
- await this.pdfDocumentProxy.getPageIndex(explicitRef);
323
+ if (explicitDest.length > 1 && typeof explicitDest[1] === "object" && explicitDest[1] !== null && "url" in explicitDest[1]) {
324
+ return;
325
+ }
326
+ const destRef = explicitDest[0];
327
+ let pageIndex;
328
+ if (destRef && typeof destRef === "object") {
329
+ if ("num" in destRef) {
330
+ try {
331
+ const refProxy = destRef;
332
+ pageIndex = await this.pdfDocumentProxy.getPageIndex(refProxy);
333
+ } catch (_error) {
334
+ return;
335
+ }
336
+ } else {
337
+ return;
338
+ }
339
+ } else if (typeof destRef === "number") {
340
+ pageIndex = destRef;
341
+ } else {
342
+ return;
343
+ }
344
+ const pageNumber = pageIndex + 1;
345
+ if (this._pageNavigationCallback) {
346
+ this._pageNavigationCallback(pageNumber);
347
+ }
348
+ }
349
+ executeNamedAction() {
350
+ }
351
+ navigateTo(dest) {
352
+ this.goToDestination(dest);
353
+ }
354
+ get rotation() {
355
+ return 0;
356
+ }
357
+ set rotation(value) {
358
+ }
359
+ goToPage(pageNumber) {
360
+ if (pageNumber >= 1 && pageNumber <= this.pagesCount) {
361
+ if (this._pageNavigationCallback) {
362
+ this._pageNavigationCallback(pageNumber);
363
+ }
364
+ }
365
+ }
366
+ setHash(hash) {
367
+ if (hash.startsWith("#page=")) {
368
+ const pageNumber = parseInt(hash.substring(6), 10);
369
+ if (!isNaN(pageNumber)) {
370
+ this.goToPage(pageNumber);
371
+ }
372
+ }
373
+ }
374
+ executeSetOCGState() {
375
+ }
376
+ // Method to register navigation callback
377
+ registerPageNavigationCallback(callback) {
378
+ this._pageNavigationCallback = callback;
379
+ }
380
+ // Method to unregister navigation callback
381
+ unregisterPageNavigationCallback() {
382
+ this._pageNavigationCallback = void 0;
202
383
  }
203
384
  };
204
- var PDFLinkServiceContext = createContext(null);
385
+ var defaultLinkService = new LinkService();
386
+ var PDFLinkServiceContext = createContext(defaultLinkService);
205
387
  var usePDFLinkService = () => {
206
388
  return useContext(PDFLinkServiceContext);
207
389
  };
@@ -230,9 +412,12 @@ var useVisibility = ({
230
412
 
231
413
  // src/hooks/layers/useAnnotationLayer.tsx
232
414
  var defaultAnnotationLayerParams = {
233
- renderForms: true
415
+ renderForms: true,
416
+ externalLinksEnabled: true,
417
+ jumpOptions: { behavior: "smooth", align: "start" }
234
418
  };
235
419
  var useAnnotationLayer = (params) => {
420
+ const mergedParams = { ...defaultAnnotationLayerParams, ...params };
236
421
  const annotationLayerRef = useRef(null);
237
422
  const annotationLayerObjectRef = useRef(null);
238
423
  const linkService = usePDFLinkService();
@@ -241,6 +426,83 @@ var useAnnotationLayer = (params) => {
241
426
  });
242
427
  const pageNumber = usePDFPageNumber();
243
428
  const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
429
+ const pdfDocumentProxy = usePdf((state) => state.pdfDocumentProxy);
430
+ useEffect(() => {
431
+ linkService.externalLinkEnabled = mergedParams.externalLinksEnabled;
432
+ }, [linkService, mergedParams.externalLinksEnabled]);
433
+ const { jumpToPage } = usePdfJump();
434
+ useEffect(() => {
435
+ if (!jumpToPage) return;
436
+ const handlePageNavigation = (pageNumber2) => {
437
+ jumpToPage(pageNumber2, mergedParams.jumpOptions);
438
+ };
439
+ linkService.registerPageNavigationCallback(handlePageNavigation);
440
+ return () => {
441
+ linkService.unregisterPageNavigationCallback();
442
+ };
443
+ }, [jumpToPage, linkService, mergedParams.jumpOptions]);
444
+ useEffect(() => {
445
+ const style = document.createElement("style");
446
+ style.textContent = `
447
+ .annotationLayer {
448
+ position: absolute;
449
+ left: 0;
450
+ top: 0;
451
+ right: 0;
452
+ bottom: 0;
453
+ overflow: hidden;
454
+ opacity: 1;
455
+ z-index: 3;
456
+ }
457
+
458
+ .annotationLayer section {
459
+ position: absolute;
460
+ }
461
+
462
+ .annotationLayer .linkAnnotation > a,
463
+ .annotationLayer .buttonWidgetAnnotation.pushButton > a {
464
+ position: absolute;
465
+ font-size: 1em;
466
+ top: 0;
467
+ left: 0;
468
+ width: 100%;
469
+ height: 100%;
470
+ background: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7") 0 0 repeat;
471
+ cursor: pointer;
472
+ }
473
+
474
+ .annotationLayer .linkAnnotation > a:hover,
475
+ .annotationLayer .buttonWidgetAnnotation.pushButton > a:hover {
476
+ opacity: 0.2;
477
+ background: rgba(255, 255, 0, 1);
478
+ box-shadow: 0 2px 10px rgba(255, 255, 0, 1);
479
+ }
480
+ `;
481
+ document.head.appendChild(style);
482
+ return () => {
483
+ document.head.removeChild(style);
484
+ };
485
+ }, []);
486
+ useEffect(() => {
487
+ if (!annotationLayerRef.current) return;
488
+ const element = annotationLayerRef.current;
489
+ const handleLinkClick = (e) => {
490
+ if (!e.target || !(e.target instanceof HTMLAnchorElement)) return;
491
+ const target = e.target;
492
+ const href = target.getAttribute("href") || "";
493
+ if (href.startsWith("#page=")) {
494
+ e.preventDefault();
495
+ const pageNumber2 = parseInt(href.substring(6), 10);
496
+ if (!isNaN(pageNumber2)) {
497
+ linkService.goToPage(pageNumber2);
498
+ }
499
+ }
500
+ };
501
+ element.addEventListener("click", handleLinkClick);
502
+ return () => {
503
+ element.removeEventListener("click", handleLinkClick);
504
+ };
505
+ }, [linkService]);
244
506
  useEffect(() => {
245
507
  if (!annotationLayerRef.current) {
246
508
  return;
@@ -252,14 +514,20 @@ var useAnnotationLayer = (params) => {
252
514
  }
253
515
  }, [visible]);
254
516
  useEffect(() => {
255
- if (!annotationLayerRef.current) {
517
+ if (!annotationLayerRef.current || !pdfPageProxy || !pdfDocumentProxy) {
256
518
  return;
257
519
  }
520
+ if (linkService._pdfDocumentProxy !== pdfDocumentProxy) {
521
+ linkService.setDocument(pdfDocumentProxy);
522
+ }
258
523
  annotationLayerRef.current.innerHTML = "";
524
+ annotationLayerRef.current.className = "annotationLayer";
525
+ const viewport = pdfPageProxy.getViewport({ scale: 1 });
259
526
  const annotationLayerConfig = {
260
527
  div: annotationLayerRef.current,
261
- viewport: pdfPageProxy.getViewport({ scale: 1 }),
528
+ viewport,
262
529
  page: pdfPageProxy,
530
+ linkService,
263
531
  accessibilityManager: void 0,
264
532
  annotationCanvasMap: void 0,
265
533
  annotationEditorUIManager: void 0,
@@ -269,33 +537,38 @@ var useAnnotationLayer = (params) => {
269
537
  annotationLayerObjectRef.current = annotationLayer;
270
538
  const { cancel } = cancellable(
271
539
  (async () => {
272
- await annotationLayer.render({
273
- ...annotationLayerConfig,
274
- ...defaultAnnotationLayerParams,
275
- ...params,
276
- annotations: await pdfPageProxy.getAnnotations(),
277
- // @ts-expect-error TODO: Fix this
278
- linkService
279
- });
540
+ try {
541
+ const annotations = await pdfPageProxy.getAnnotations();
542
+ await annotationLayer.render({
543
+ ...annotationLayerConfig,
544
+ ...mergedParams,
545
+ annotations,
546
+ linkService
547
+ });
548
+ } catch (_error) {
549
+ }
280
550
  })()
281
551
  );
282
- cancel();
283
552
  return () => {
284
553
  cancel();
285
554
  };
286
- }, [pdfPageProxy, params, linkService]);
555
+ }, [pdfPageProxy, pdfDocumentProxy, mergedParams, linkService]);
287
556
  return {
288
557
  annotationLayerRef
289
558
  };
290
559
  };
291
560
  var AnnotationLayer2 = ({
292
561
  renderForms = true,
562
+ externalLinksEnabled = true,
563
+ jumpOptions = { behavior: "smooth", align: "start" },
293
564
  className,
294
565
  style,
295
566
  ...props
296
567
  }) => {
297
568
  const { annotationLayerRef } = useAnnotationLayer({
298
- renderForms
569
+ renderForms,
570
+ externalLinksEnabled,
571
+ jumpOptions
299
572
  });
300
573
  return /* @__PURE__ */ jsx(
301
574
  "div",
@@ -335,7 +608,7 @@ var useDpr = () => {
335
608
  };
336
609
 
337
610
  // src/hooks/layers/useCanvasLayer.tsx
338
- var useCanvasLayer = () => {
611
+ var useCanvasLayer = ({ background }) => {
339
612
  const canvasRef = useRef(null);
340
613
  const pageNumber = usePDFPageNumber();
341
614
  const dpr = useDpr();
@@ -357,7 +630,8 @@ var useCanvasLayer = () => {
357
630
  canvasContext.scale(scale, scale);
358
631
  const renderingTask = pdfPageProxy.render({
359
632
  canvasContext,
360
- viewport
633
+ viewport,
634
+ background
361
635
  });
362
636
  renderingTask.promise.catch((error) => {
363
637
  if (error.name === "RenderingCancelledException") {
@@ -373,26 +647,442 @@ var useCanvasLayer = () => {
373
647
  canvasRef
374
648
  };
375
649
  };
376
- var CanvasLayer = ({
377
- style,
378
- ...props
650
+ var CanvasLayer = ({
651
+ style,
652
+ background,
653
+ ...props
654
+ }) => {
655
+ const { canvasRef } = useCanvasLayer({ background });
656
+ return /* @__PURE__ */ jsx(
657
+ "canvas",
658
+ {
659
+ style: {
660
+ ...style,
661
+ position: "absolute",
662
+ top: 0,
663
+ left: 0,
664
+ width: "100%",
665
+ height: "100%"
666
+ },
667
+ ...props,
668
+ ref: canvasRef
669
+ }
670
+ );
671
+ };
672
+
673
+ // src/hooks/useSelectionDimensions.tsx
674
+ var MERGE_THRESHOLD = 20;
675
+ var shouldMergeRectangles = (rect1, rect2) => {
676
+ const verticalOverlap = !(rect1.top > rect2.top + rect2.height || rect2.top > rect1.top + rect1.height);
677
+ const horizontallyClose = Math.abs(rect1.left + rect1.width - rect2.left) < MERGE_THRESHOLD || Math.abs(rect2.left + rect2.width - rect1.left) < MERGE_THRESHOLD || rect1.left < rect2.left + rect2.width && rect2.left < rect1.left + rect1.width;
678
+ return verticalOverlap && horizontallyClose;
679
+ };
680
+ var mergeRectangles = (rect1, rect2) => {
681
+ return {
682
+ left: Math.min(rect1.left, rect2.left),
683
+ top: Math.min(rect1.top, rect2.top),
684
+ width: Math.max(rect1.left + rect1.width, rect2.left + rect2.width) - Math.min(rect1.left, rect2.left),
685
+ height: Math.max(rect1.top + rect1.height, rect2.top + rect2.height) - Math.min(rect1.top, rect2.top),
686
+ pageNumber: rect1.pageNumber
687
+ };
688
+ };
689
+ var consolidateRects = (rects) => {
690
+ if (rects.length <= 1) return rects;
691
+ const sortedRectangles = rects.toSorted((a, b) => a.top - b.top);
692
+ let withinThresholdMergedRectangles = sortedRectangles[0];
693
+ const allMergedRectangles = [];
694
+ const blowUpMergedRectangles = (rect) => {
695
+ return {
696
+ ...rect,
697
+ left: rect.left - 2,
698
+ top: rect.top - 2,
699
+ width: rect.width + 4,
700
+ height: rect.height + 2
701
+ };
702
+ };
703
+ for (const [index, currentRectangle] of sortedRectangles.entries()) {
704
+ withinThresholdMergedRectangles = mergeRectangles(
705
+ withinThresholdMergedRectangles,
706
+ currentRectangle
707
+ );
708
+ const nextRectangle = sortedRectangles[index + 1];
709
+ if (!nextRectangle) {
710
+ allMergedRectangles.push(
711
+ blowUpMergedRectangles(withinThresholdMergedRectangles)
712
+ );
713
+ break;
714
+ }
715
+ if (!shouldMergeRectangles(withinThresholdMergedRectangles, nextRectangle)) {
716
+ allMergedRectangles.push(
717
+ blowUpMergedRectangles(withinThresholdMergedRectangles)
718
+ );
719
+ withinThresholdMergedRectangles = nextRectangle;
720
+ }
721
+ }
722
+ return allMergedRectangles;
723
+ };
724
+ var useSelectionDimensions = () => {
725
+ const store = PDFStore.useContext();
726
+ const getDimension = () => {
727
+ const selection = window.getSelection();
728
+ if (!selection || selection.isCollapsed) return;
729
+ const range = selection.getRangeAt(0);
730
+ const highlights = [];
731
+ const textLayerMap = /* @__PURE__ */ new Map();
732
+ const clientRects = Array.from(range.getClientRects()).filter(
733
+ (rect) => rect.width > 2 && rect.height > 2
734
+ );
735
+ clientRects.forEach((clientRect) => {
736
+ const element = document.elementFromPoint(
737
+ clientRect.left + 1,
738
+ clientRect.top + clientRect.height / 2
739
+ );
740
+ const textLayer = element?.closest(".textLayer");
741
+ if (!textLayer) return;
742
+ const pageNumber = parseInt(
743
+ textLayer.getAttribute("data-page-number") || "1",
744
+ 10
745
+ );
746
+ const textLayerRect = textLayer.getBoundingClientRect();
747
+ const zoom = store.getState().zoom;
748
+ const rect = {
749
+ width: clientRect.width / zoom,
750
+ height: clientRect.height / zoom,
751
+ top: (clientRect.top - textLayerRect.top) / zoom,
752
+ left: (clientRect.left - textLayerRect.left) / zoom,
753
+ pageNumber
754
+ };
755
+ if (!textLayerMap.has(pageNumber)) {
756
+ textLayerMap.set(pageNumber, []);
757
+ }
758
+ textLayerMap.get(pageNumber)?.push(rect);
759
+ });
760
+ textLayerMap.forEach((rects) => {
761
+ if (rects.length > 0) {
762
+ highlights.push(...consolidateRects(rects));
763
+ }
764
+ });
765
+ return {
766
+ highlights: highlights.sort((a, b) => a.pageNumber - b.pageNumber),
767
+ text: range.toString().trim(),
768
+ isCollapsed: false
769
+ };
770
+ };
771
+ const getSelection = () => getDimension();
772
+ return { getDimension, getSelection };
773
+ };
774
+ var SelectionTooltip = ({ children }) => {
775
+ const [isOpen, setIsOpen] = useState(false);
776
+ const lastSelectionRef = useRef(null);
777
+ const viewportRef = usePdf((state) => state.viewportRef);
778
+ const { refs, floatingStyles, context } = useFloating({
779
+ placement: "bottom",
780
+ open: isOpen,
781
+ onOpenChange: setIsOpen,
782
+ whileElementsMounted: autoUpdate,
783
+ middleware: [offset(10), shift({ padding: 8 })]
784
+ });
785
+ const dismiss = useDismiss(context);
786
+ const { getFloatingProps } = useInteractions([dismiss]);
787
+ const updateTooltipPosition = useCallback(() => {
788
+ const selection = document.getSelection();
789
+ if (!selection || selection.isCollapsed) {
790
+ setIsOpen(false);
791
+ lastSelectionRef.current = null;
792
+ return;
793
+ }
794
+ const range = selection.getRangeAt(0);
795
+ if (!range) return;
796
+ const rects = range.getClientRects();
797
+ const lastRect = rects[rects.length - 1];
798
+ lastSelectionRef.current = range;
799
+ if (lastRect) {
800
+ refs.setReference({
801
+ getBoundingClientRect: () => ({
802
+ width: lastRect.width,
803
+ height: lastRect.height,
804
+ x: lastRect.left,
805
+ y: lastRect.bottom,
806
+ // Position below the last line of selection
807
+ top: lastRect.bottom,
808
+ right: lastRect.right,
809
+ bottom: lastRect.bottom + lastRect.height,
810
+ left: lastRect.left
811
+ }),
812
+ getClientRects: () => [lastRect]
813
+ });
814
+ setIsOpen(true);
815
+ } else {
816
+ setIsOpen(false);
817
+ }
818
+ }, [refs]);
819
+ useEffect(() => {
820
+ const handleSelectionChange = () => {
821
+ const selection = document.getSelection();
822
+ if (selection && viewportRef.current?.contains(selection.anchorNode)) {
823
+ requestAnimationFrame(updateTooltipPosition);
824
+ } else {
825
+ setIsOpen(false);
826
+ }
827
+ };
828
+ const handleScroll = () => {
829
+ if (!isOpen || !lastSelectionRef.current) return;
830
+ requestAnimationFrame(updateTooltipPosition);
831
+ };
832
+ document.addEventListener("selectionchange", handleSelectionChange);
833
+ if (viewportRef.current) {
834
+ viewportRef.current.addEventListener("scroll", handleScroll, {
835
+ passive: true
836
+ });
837
+ }
838
+ return () => {
839
+ document.removeEventListener("selectionchange", handleSelectionChange);
840
+ if (viewportRef.current) {
841
+ viewportRef.current.removeEventListener("scroll", handleScroll);
842
+ }
843
+ };
844
+ }, [refs, isOpen, viewportRef, updateTooltipPosition]);
845
+ useEffect(() => {
846
+ const handleFloatingClick = (e) => {
847
+ if (refs.floating.current?.contains(e.target)) {
848
+ e.stopPropagation();
849
+ }
850
+ };
851
+ document.addEventListener("click", handleFloatingClick);
852
+ return () => document.removeEventListener("click", handleFloatingClick);
853
+ }, [refs.floating]);
854
+ return /* @__PURE__ */ jsx(Fragment, { children: isOpen && /* @__PURE__ */ jsx(
855
+ "div",
856
+ {
857
+ ref: refs.setFloating,
858
+ style: {
859
+ ...floatingStyles
860
+ },
861
+ ...getFloatingProps(),
862
+ children
863
+ }
864
+ ) });
865
+ };
866
+ var defaultColors = [
867
+ {
868
+ color: "#e3b127",
869
+ localization: {
870
+ id: "yellow",
871
+ defaultMessage: "Yellow"
872
+ }
873
+ },
874
+ {
875
+ color: "#419931",
876
+ localization: {
877
+ id: "green",
878
+ defaultMessage: "Green"
879
+ }
880
+ },
881
+ {
882
+ color: "#4286c9",
883
+ localization: {
884
+ id: "blue",
885
+ defaultMessage: "Blue"
886
+ }
887
+ },
888
+ {
889
+ color: "#f246b6",
890
+ localization: {
891
+ id: "pink",
892
+ defaultMessage: "Pink"
893
+ }
894
+ },
895
+ {
896
+ color: "#a53dd1",
897
+ localization: {
898
+ id: "purple",
899
+ defaultMessage: "Purple"
900
+ }
901
+ },
902
+ {
903
+ color: "#f09037",
904
+ localization: {
905
+ id: "orange",
906
+ defaultMessage: "Orange"
907
+ }
908
+ },
909
+ {
910
+ color: "#37f0d4",
911
+ localization: {
912
+ id: "teal",
913
+ defaultMessage: "Teal"
914
+ }
915
+ },
916
+ {
917
+ color: "#3d0ff5",
918
+ localization: {
919
+ id: "purple",
920
+ defaultMessage: "Purple"
921
+ }
922
+ },
923
+ {
924
+ color: "#f50f26",
925
+ localization: {
926
+ id: "red",
927
+ defaultMessage: "Red"
928
+ }
929
+ }
930
+ ];
931
+ var ColorSelectionTool = ({
932
+ highlighterColors = defaultColors,
933
+ onColorSelection
934
+ }) => {
935
+ return /* @__PURE__ */ jsx(SelectionTooltip, { children: /* @__PURE__ */ jsx(
936
+ "div",
937
+ {
938
+ style: {
939
+ display: "flex",
940
+ gap: "0.5rem",
941
+ padding: "0.5rem",
942
+ backgroundColor: "#363636",
943
+ borderRadius: "0.5rem"
944
+ },
945
+ children: highlighterColors.map((colorItem, index) => /* @__PURE__ */ jsx(
946
+ "button",
947
+ {
948
+ onClick: () => onColorSelection(colorItem),
949
+ title: colorItem.localization.defaultMessage,
950
+ "aria-label": colorItem.localization.defaultMessage,
951
+ style: {
952
+ width: "1.25rem",
953
+ height: "1.25rem",
954
+ borderRadius: "0.25rem",
955
+ cursor: "pointer",
956
+ backgroundColor: colorItem.color
957
+ }
958
+ },
959
+ index
960
+ ))
961
+ }
962
+ ) });
963
+ };
964
+
965
+ // src/utils/selectionUtils.ts
966
+ var getEndOfHighlight = (selection) => {
967
+ const lastRectangle = selection.rectangles[selection.rectangles.length - 1];
968
+ return lastRectangle.left + lastRectangle.width + 10;
969
+ };
970
+ var getMidHeightOfHighlightLine = (selection) => {
971
+ const lastRectangle = selection.rectangles[selection.rectangles.length - 1];
972
+ return lastRectangle.top + lastRectangle.height / 2;
973
+ };
974
+ var ColoredHighlightComponent = ({
975
+ selection
976
+ }) => {
977
+ const deleteColoredHighlight = usePdf(
978
+ (state) => state.deleteColoredHighlight
979
+ );
980
+ const [showButton, setShowButton] = useState(false);
981
+ return /* @__PURE__ */ jsxs("div", { className: "colored-highlight", children: [
982
+ selection.rectangles.map((rect, index) => /* @__PURE__ */ jsx(
983
+ "span",
984
+ {
985
+ onClick: () => setShowButton(!showButton),
986
+ style: {
987
+ position: "absolute",
988
+ top: rect.top,
989
+ left: rect.left,
990
+ height: rect.height,
991
+ width: rect.width,
992
+ cursor: "pointer",
993
+ zIndex: 30,
994
+ backgroundColor: selection.color,
995
+ // mixBlendMode: "lighten", // changes the color of the text
996
+ mixBlendMode: "darken",
997
+ // best results
998
+ // mixBlendMode: "multiply", // works but coloring has some inconsistencies
999
+ borderRadius: "0.2rem"
1000
+ }
1001
+ },
1002
+ `${selection.uuid}-${index}`
1003
+ )),
1004
+ showButton && /* @__PURE__ */ jsx(
1005
+ "button",
1006
+ {
1007
+ style: {
1008
+ backgroundColor: "white",
1009
+ color: "white",
1010
+ borderRadius: "5px",
1011
+ padding: "5px",
1012
+ cursor: "pointer",
1013
+ boxShadow: "2px 2px 5px black",
1014
+ position: "absolute",
1015
+ top: getMidHeightOfHighlightLine(selection),
1016
+ left: getEndOfHighlight(selection),
1017
+ zIndex: 30,
1018
+ transform: "translateY(-50%)"
1019
+ },
1020
+ onClick: () => deleteColoredHighlight(selection.uuid),
1021
+ children: /* @__PURE__ */ jsx(
1022
+ "svg",
1023
+ {
1024
+ fill: "#000000",
1025
+ version: "1.1",
1026
+ id: "Capa_1",
1027
+ xmlns: "http://www.w3.org/2000/svg",
1028
+ width: "15px",
1029
+ height: "15px",
1030
+ viewBox: "0 0 485 485",
1031
+ children: /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsxs("g", { children: [
1032
+ /* @__PURE__ */ jsx("rect", { x: "67.224", width: "350.535", height: "71.81" }),
1033
+ /* @__PURE__ */ jsx(
1034
+ "path",
1035
+ {
1036
+ d: "M417.776,92.829H67.237V485h350.537V92.829H417.776z M165.402,431.447h-28.362V146.383h28.362V431.447z M256.689,431.447\n h-28.363V146.383h28.363V431.447z M347.97,431.447h-28.361V146.383h28.361V431.447z"
1037
+ }
1038
+ )
1039
+ ] }) })
1040
+ }
1041
+ )
1042
+ },
1043
+ `${selection.uuid}-delete-button`
1044
+ )
1045
+ ] });
1046
+ };
1047
+ var ColoredHighlightLayer = ({
1048
+ onHighlight
379
1049
  }) => {
380
- const { canvasRef } = useCanvasLayer();
381
- return /* @__PURE__ */ jsx(
382
- "canvas",
383
- {
384
- style: {
385
- ...style,
386
- position: "absolute",
387
- top: 0,
388
- left: 0,
389
- width: "100%",
390
- height: "100%"
391
- },
392
- ...props,
393
- ref: canvasRef
394
- }
1050
+ const pageNumber = usePDFPageNumber();
1051
+ const { getSelection } = useSelectionDimensions();
1052
+ const highlights = usePdf(
1053
+ (state) => state.coloredHighlights
395
1054
  );
1055
+ const addColoredHighlight = usePdf((state) => state.addColoredHighlight);
1056
+ const handleHighlighting = useCallback((color) => {
1057
+ const { highlights: highlights2, text } = getSelection();
1058
+ if (highlights2[0]) {
1059
+ const highlight = {
1060
+ uuid: v4(),
1061
+ pageNumber: highlights2[0].pageNumber,
1062
+ // usePDFPageNumber() doesn't return the correct page number, so i'm getting the number directly from the first highlight
1063
+ color,
1064
+ rectangles: highlights2,
1065
+ text
1066
+ };
1067
+ addColoredHighlight(highlight);
1068
+ if (onHighlight) onHighlight(highlight);
1069
+ }
1070
+ }, []);
1071
+ return /* @__PURE__ */ jsxs("div", { className: "colored-highlights-layer", children: [
1072
+ highlights.filter((selection) => selection.pageNumber === pageNumber).map((selection) => /* @__PURE__ */ jsx(
1073
+ ColoredHighlightComponent,
1074
+ {
1075
+ selection
1076
+ },
1077
+ selection.uuid
1078
+ )),
1079
+ /* @__PURE__ */ jsx(
1080
+ ColorSelectionTool,
1081
+ {
1082
+ onColorSelection: (colorItem) => handleHighlighting(colorItem.color)
1083
+ }
1084
+ )
1085
+ ] });
396
1086
  };
397
1087
 
398
1088
  // src/components/layers/custom-layer.tsx
@@ -489,68 +1179,6 @@ var TextLayer2 = ({
489
1179
  }
490
1180
  );
491
1181
  };
492
-
493
- // src/hooks/pages/usePdfJump.tsx
494
- var usePdfJump = () => {
495
- const virtualizer = usePdf((state) => state.virtualizer);
496
- const setHighlight = usePdf((state) => state.setHighlight);
497
- const jumpToPage = (pageIndex, options) => {
498
- if (!virtualizer) return;
499
- const defaultOptions = {
500
- align: "start",
501
- behavior: "smooth"
502
- };
503
- const finalOptions = { ...defaultOptions, ...options };
504
- virtualizer.scrollToIndex(pageIndex - 1, finalOptions);
505
- };
506
- const jumpToOffset = (offset2) => {
507
- if (!virtualizer) return;
508
- virtualizer.scrollToOffset(offset2, {
509
- align: "start",
510
- behavior: "smooth"
511
- });
512
- };
513
- const jumpToHighlightRects = (rects, type, align = "start", additionalOffset = 0) => {
514
- if (!virtualizer) return;
515
- setHighlight(rects);
516
- const firstPage = Math.min(...rects.map((rect) => rect.pageNumber));
517
- const pageOffset = virtualizer.getOffsetForIndex(firstPage - 1, "start");
518
- if (pageOffset === null) return;
519
- const targetRect = rects.find((rect) => rect.pageNumber === firstPage);
520
- if (!targetRect) return;
521
- const isNumber = pageOffset?.[0] != null;
522
- if (!isNumber) return;
523
- const pageStart = pageOffset[0] ?? 0;
524
- let rectTop;
525
- let rectHeight;
526
- if (type === "percent") {
527
- const estimatePageHeight = virtualizer.options.estimateSize(
528
- firstPage - 1
529
- );
530
- rectTop = targetRect.top / 100 * estimatePageHeight;
531
- rectHeight = targetRect.height / 100 * estimatePageHeight;
532
- } else {
533
- rectTop = targetRect.top;
534
- rectHeight = targetRect.height;
535
- }
536
- let scrollOffset;
537
- if (align === "center") {
538
- const viewportHeight = virtualizer.scrollElement?.clientHeight || 0;
539
- const rectCenter = pageStart + rectTop + rectHeight / 2;
540
- scrollOffset = rectCenter - viewportHeight / 2;
541
- } else {
542
- scrollOffset = pageStart + rectTop;
543
- }
544
- scrollOffset += additionalOffset;
545
- const adjustedOffset = Math.max(0, scrollOffset);
546
- virtualizer.scrollToOffset(adjustedOffset, {
547
- align: "start",
548
- // Always use start when we've calculated our own centering
549
- behavior: "smooth"
550
- });
551
- };
552
- return { jumpToPage, jumpToOffset, jumpToHighlightRects };
553
- };
554
1182
  var usePDFOutline = () => {
555
1183
  const pdfDocumentProxy = usePdf((state) => state.pdfDocumentProxy);
556
1184
  const [outline, setOutline] = useState();
@@ -2953,12 +3581,10 @@ var Pages = ({
2953
3581
  toOffset -= size;
2954
3582
  }
2955
3583
  const scrollSizeProp = virtualizer.options.horizontal ? "scrollWidth" : "scrollHeight";
2956
- const scrollSize = virtualizer.scrollElement ? "document" in virtualizer.scrollElement ? (
3584
+ virtualizer.scrollElement ? "document" in virtualizer.scrollElement ? (
2957
3585
  //@ts-expect-error this is a private stuff
2958
3586
  virtualizer.scrollElement.document.documentElement[scrollSizeProp]
2959
3587
  ) : virtualizer.scrollElement[scrollSizeProp] : 0;
2960
- const maxOffset = scrollSize - size;
2961
- console.log(scrollSize, maxOffset, toOffset);
2962
3588
  return Math.max(toOffset, 0);
2963
3589
  };
2964
3590
  }, [zoom, virtualizer]);
@@ -3151,98 +3777,6 @@ var Search = ({ children, loading = "Loading..." }) => {
3151
3777
  }, [proxies, getTextContent]);
3152
3778
  return isLoading ? loading : children;
3153
3779
  };
3154
- var SelectionTooltip = ({ children }) => {
3155
- const [isOpen, setIsOpen] = useState(false);
3156
- const lastSelectionRef = useRef(null);
3157
- const viewportRef = usePdf((state) => state.viewportRef);
3158
- const { refs, floatingStyles, context } = useFloating({
3159
- placement: "bottom",
3160
- open: isOpen,
3161
- onOpenChange: setIsOpen,
3162
- whileElementsMounted: autoUpdate,
3163
- middleware: [offset(10), shift({ padding: 8 })]
3164
- });
3165
- const dismiss = useDismiss(context);
3166
- const { getFloatingProps } = useInteractions([dismiss]);
3167
- const updateTooltipPosition = useCallback(() => {
3168
- const selection = document.getSelection();
3169
- if (!selection || selection.isCollapsed) {
3170
- setIsOpen(false);
3171
- lastSelectionRef.current = null;
3172
- return;
3173
- }
3174
- const range = selection.getRangeAt(0);
3175
- if (!range) return;
3176
- const rects = range.getClientRects();
3177
- const lastRect = rects[rects.length - 1];
3178
- lastSelectionRef.current = range;
3179
- if (lastRect) {
3180
- refs.setReference({
3181
- getBoundingClientRect: () => ({
3182
- width: lastRect.width,
3183
- height: lastRect.height,
3184
- x: lastRect.left,
3185
- y: lastRect.bottom,
3186
- // Position below the last line of selection
3187
- top: lastRect.bottom,
3188
- right: lastRect.right,
3189
- bottom: lastRect.bottom + lastRect.height,
3190
- left: lastRect.left
3191
- }),
3192
- getClientRects: () => [lastRect]
3193
- });
3194
- setIsOpen(true);
3195
- } else {
3196
- setIsOpen(false);
3197
- }
3198
- }, [refs]);
3199
- useEffect(() => {
3200
- const handleSelectionChange = () => {
3201
- const selection = document.getSelection();
3202
- if (selection && viewportRef.current?.contains(selection.anchorNode)) {
3203
- requestAnimationFrame(updateTooltipPosition);
3204
- } else {
3205
- setIsOpen(false);
3206
- }
3207
- };
3208
- const handleScroll = () => {
3209
- if (!isOpen || !lastSelectionRef.current) return;
3210
- requestAnimationFrame(updateTooltipPosition);
3211
- };
3212
- document.addEventListener("selectionchange", handleSelectionChange);
3213
- if (viewportRef.current) {
3214
- viewportRef.current.addEventListener("scroll", handleScroll, {
3215
- passive: true
3216
- });
3217
- }
3218
- return () => {
3219
- document.removeEventListener("selectionchange", handleSelectionChange);
3220
- if (viewportRef.current) {
3221
- viewportRef.current.removeEventListener("scroll", handleScroll);
3222
- }
3223
- };
3224
- }, [refs, isOpen, viewportRef, updateTooltipPosition]);
3225
- useEffect(() => {
3226
- const handleFloatingClick = (e) => {
3227
- if (refs.floating.current?.contains(e.target)) {
3228
- e.stopPropagation();
3229
- }
3230
- };
3231
- document.addEventListener("click", handleFloatingClick);
3232
- return () => document.removeEventListener("click", handleFloatingClick);
3233
- }, [refs.floating]);
3234
- return /* @__PURE__ */ jsx(Fragment, { children: isOpen && /* @__PURE__ */ jsx(
3235
- "div",
3236
- {
3237
- ref: refs.setFloating,
3238
- style: {
3239
- ...floatingStyles
3240
- },
3241
- ...getFloatingProps(),
3242
- children
3243
- }
3244
- ) });
3245
- };
3246
3780
  var DEFAULT_CONFIG = {
3247
3781
  maxHeight: 800,
3248
3782
  maxWidth: 400
@@ -3442,7 +3976,8 @@ var useSearch = () => {
3442
3976
  text: text.substr(matchIndex, searchText.length + textSize),
3443
3977
  score: 1,
3444
3978
  matchIndex,
3445
- isExactMatch: true
3979
+ isExactMatch: true,
3980
+ searchText
3446
3981
  });
3447
3982
  index = matchIndex + searchText.length;
3448
3983
  }
@@ -3471,7 +4006,8 @@ var useSearch = () => {
3471
4006
  text: text.substr(index, searchLower.length + textSize),
3472
4007
  score,
3473
4008
  matchIndex: index,
3474
- isExactMatch: false
4009
+ isExactMatch: false,
4010
+ searchText
3475
4011
  });
3476
4012
  index += searchLower.length;
3477
4013
  } else {
@@ -3546,7 +4082,7 @@ var useSearch = () => {
3546
4082
  async function calculateHighlightRects(pageProxy, textMatch) {
3547
4083
  const textContent = await pageProxy.getTextContent();
3548
4084
  const items = textContent.items;
3549
- const matchLength = textMatch.text.length;
4085
+ const matchLength = textMatch.searchText ? textMatch.searchText.length : textMatch.text.length;
3550
4086
  const matchRects = [];
3551
4087
  let currentIndex = 0;
3552
4088
  let remainingMatchLength = matchLength;
@@ -3617,95 +4153,4 @@ function mergeAdjacentRects(rects) {
3617
4153
  return merged;
3618
4154
  }
3619
4155
 
3620
- // src/hooks/useSelectionDimensions.tsx
3621
- var MERGE_THRESHOLD = 5;
3622
- var shouldMergeRects = (rect1, rect2) => {
3623
- const verticalOverlap = !(rect1.top > rect2.top + rect2.height || rect2.top > rect1.top + rect1.height);
3624
- const horizontallyClose = Math.abs(rect1.left + rect1.width - rect2.left) < MERGE_THRESHOLD || Math.abs(rect2.left + rect2.width - rect1.left) < MERGE_THRESHOLD || rect1.left < rect2.left + rect2.width && rect2.left < rect1.left + rect1.width;
3625
- return verticalOverlap && horizontallyClose;
3626
- };
3627
- var mergeRects = (rect1, rect2) => {
3628
- return {
3629
- left: Math.min(rect1.left, rect2.left),
3630
- top: Math.min(rect1.top, rect2.top),
3631
- width: Math.max(rect1.left + rect1.width, rect2.left + rect2.width) - Math.min(rect1.left, rect2.left),
3632
- height: Math.max(rect1.top + rect1.height, rect2.top + rect2.height) - Math.min(rect1.top, rect2.top),
3633
- pageNumber: rect1.pageNumber
3634
- };
3635
- };
3636
- var consolidateRects = (rects) => {
3637
- if (rects.length <= 1) return rects;
3638
- const sortedRects = [...rects].sort((a, b) => a.top - b.top);
3639
- let hasChanges;
3640
- do {
3641
- hasChanges = false;
3642
- let currentRect = sortedRects[0];
3643
- const tempResult = [];
3644
- for (let i = 1; i < sortedRects.length; i++) {
3645
- const sorted = sortedRects[i];
3646
- if (!currentRect || !sorted) continue;
3647
- if (shouldMergeRects(currentRect, sorted)) {
3648
- currentRect = mergeRects(currentRect, sorted);
3649
- hasChanges = true;
3650
- } else {
3651
- tempResult.push(currentRect);
3652
- currentRect = sorted;
3653
- }
3654
- }
3655
- if (currentRect) tempResult.push(currentRect);
3656
- sortedRects.length = 0;
3657
- sortedRects.push(...tempResult);
3658
- } while (hasChanges);
3659
- return sortedRects;
3660
- };
3661
- var useSelectionDimensions = () => {
3662
- const store = PDFStore.useContext();
3663
- const getDimension = () => {
3664
- const selection = window.getSelection();
3665
- if (!selection || selection.isCollapsed) return;
3666
- const range = selection.getRangeAt(0);
3667
- const highlights = [];
3668
- const textLayerMap = /* @__PURE__ */ new Map();
3669
- const clientRects = Array.from(range.getClientRects()).filter(
3670
- (rect) => rect.width > 2 && rect.height > 2
3671
- );
3672
- clientRects.forEach((clientRect) => {
3673
- const element = document.elementFromPoint(
3674
- clientRect.left + 1,
3675
- clientRect.top + clientRect.height / 2
3676
- );
3677
- const textLayer = element?.closest(".textLayer");
3678
- if (!textLayer) return;
3679
- const pageNumber = parseInt(
3680
- textLayer.getAttribute("data-page-number") || "1",
3681
- 10
3682
- );
3683
- const textLayerRect = textLayer.getBoundingClientRect();
3684
- const zoom = store.getState().zoom;
3685
- const rect = {
3686
- width: clientRect.width / zoom,
3687
- height: clientRect.height / zoom,
3688
- top: (clientRect.top - textLayerRect.top) / zoom,
3689
- left: (clientRect.left - textLayerRect.left) / zoom,
3690
- pageNumber
3691
- };
3692
- if (!textLayerMap.has(pageNumber)) {
3693
- textLayerMap.set(pageNumber, []);
3694
- }
3695
- textLayerMap.get(pageNumber)?.push(rect);
3696
- });
3697
- textLayerMap.forEach((rects) => {
3698
- if (rects.length > 0) {
3699
- highlights.push(...consolidateRects(rects));
3700
- }
3701
- });
3702
- return {
3703
- highlights: highlights.sort((a, b) => a.pageNumber - b.pageNumber),
3704
- text: range.toString().trim(),
3705
- isCollapsed: false
3706
- };
3707
- };
3708
- return { getDimension };
3709
- };
3710
-
3711
- export { AnnotationLayer2 as AnnotationLayer, CanvasLayer, CurrentPage, CurrentZoom, CustomLayer, HighlightLayer, LinkService, NextPage, Outline, OutlineChildItems, OutlineItem, Page, Pages, PreviousPage, Root, Search, SelectionTooltip, TextLayer2 as TextLayer, Thumbnail, Thumbnails, TotalPages, ZoomIn, ZoomOut, calculateHighlightRects, usePdf, usePdfJump, useSearch, useSelectionDimensions };
4156
+ export { AnnotationLayer2 as AnnotationLayer, CanvasLayer, ColoredHighlightLayer, CurrentPage, CurrentZoom, CustomLayer, HighlightLayer, LinkService, NextPage, Outline, OutlineChildItems, OutlineItem, Page, Pages, PreviousPage, Root, Search, SelectionTooltip, TextLayer2 as TextLayer, Thumbnail, Thumbnails, TotalPages, ZoomIn, ZoomOut, calculateHighlightRects, usePdf, usePdfJump, useSearch, useSelectionDimensions };