hazo_pdf 1.2.0 → 1.3.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/README.md +318 -6
- package/dist/{chunk-ZQMZT7HV.js → chunk-S3AJUZ7D.js} +2 -1
- package/dist/chunk-S3AJUZ7D.js.map +1 -0
- package/dist/index.d.ts +67 -13
- package/dist/index.js +204 -44
- package/dist/index.js.map +1 -1
- package/dist/{pdf_saver-ILJPGAPI.js → pdf_saver-P2MJN45S.js} +2 -2
- package/dist/styles/full.css +2401 -0
- package/dist/styles/full.css.map +1 -0
- package/dist/styles/index.css +208 -401
- package/dist/styles/index.css.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-ZQMZT7HV.js.map +0 -1
- /package/dist/{pdf_saver-ILJPGAPI.js.map → pdf_saver-P2MJN45S.js.map} +0 -0
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@ A React component library for viewing and annotating PDF documents with support
|
|
|
6
6
|
|
|
7
7
|
- 📄 **PDF Viewing** - Render PDF documents with customizable zoom levels
|
|
8
8
|
- ✏️ **Annotations** - Square and FreeText annotation tools
|
|
9
|
+
- 🔍 **Programmatic Highlights** - Ref-based API for creating and managing highlights programmatically
|
|
9
10
|
- 🎨 **Customizable Styling** - Extensive configuration options via INI file
|
|
10
11
|
- ⏰ **Timestamp Support** - Automatic timestamp appending to annotations
|
|
11
12
|
- 🏷️ **Custom Stamps** - Add quick-insert stamps via right-click menu
|
|
@@ -19,6 +20,47 @@ A React component library for viewing and annotating PDF documents with support
|
|
|
19
20
|
npm install hazo_pdf
|
|
20
21
|
```
|
|
21
22
|
|
|
23
|
+
## CSS Import Options
|
|
24
|
+
|
|
25
|
+
The library provides two CSS files to choose from:
|
|
26
|
+
|
|
27
|
+
### For apps with existing styles (Recommended)
|
|
28
|
+
|
|
29
|
+
Use `styles.css` - this does NOT include Tailwind preflight/base resets, so it won't interfere with your existing styles:
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import 'hazo_pdf/styles.css';
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### For standalone apps
|
|
36
|
+
|
|
37
|
+
Use `styles-full.css` - includes Tailwind preflight/base styles for apps without existing CSS resets:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import 'hazo_pdf/styles-full.css';
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Container Requirements
|
|
44
|
+
|
|
45
|
+
The PDF viewer requires its parent container to have explicit dimensions:
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
// Good - explicit dimensions
|
|
49
|
+
<div style={{ width: '100%', height: '600px' }}>
|
|
50
|
+
<PdfViewer url="/document.pdf" />
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
// Bad - no explicit height
|
|
54
|
+
<div>
|
|
55
|
+
<PdfViewer url="/document.pdf" />
|
|
56
|
+
</div>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Requirements:**
|
|
60
|
+
- Parent must have explicit `width` and `height` (CSS or inline style)
|
|
61
|
+
- Recommended minimum size: 400x400px
|
|
62
|
+
- Parent should NOT have `overflow: hidden` (the viewer handles its own scrolling)
|
|
63
|
+
|
|
22
64
|
## Quick Start
|
|
23
65
|
|
|
24
66
|
```tsx
|
|
@@ -307,7 +349,7 @@ function ProductionViewer() {
|
|
|
307
349
|
<div style={{ flex: 1, overflow: 'hidden' }}>
|
|
308
350
|
<PdfViewer
|
|
309
351
|
url="/api/documents/contract.pdf"
|
|
310
|
-
config_file="hazo_pdf_config.ini"
|
|
352
|
+
config_file="config/hazo_pdf_config.ini"
|
|
311
353
|
className="h-full w-full"
|
|
312
354
|
scale={initialScale}
|
|
313
355
|
annotations={annotations}
|
|
@@ -327,7 +369,7 @@ function ProductionViewer() {
|
|
|
327
369
|
```
|
|
328
370
|
|
|
329
371
|
**Features demonstrated:**
|
|
330
|
-
- Configuration file integration (`hazo_pdf_config.ini`)
|
|
372
|
+
- Configuration file integration (`config/hazo_pdf_config.ini`)
|
|
331
373
|
- Custom stamps with styling
|
|
332
374
|
- Timestamp and fixed text suffixes
|
|
333
375
|
- Responsive scaling based on screen size
|
|
@@ -340,7 +382,7 @@ function ProductionViewer() {
|
|
|
340
382
|
|
|
341
383
|
## Configuration File
|
|
342
384
|
|
|
343
|
-
The PDF viewer can be configured via an INI file (default: `hazo_pdf_config.ini`). This allows you to customize styling, colors, fonts, and behavior without modifying code.
|
|
385
|
+
The PDF viewer can be configured via an INI file (default: `config/hazo_pdf_config.ini`). This allows you to customize styling, colors, fonts, and behavior without modifying code.
|
|
344
386
|
|
|
345
387
|
**Basic setup:**
|
|
346
388
|
|
|
@@ -368,7 +410,205 @@ toolbar_button_save_background_color = rgb(34, 197, 94)
|
|
|
368
410
|
right_click_custom_stamps = [{"name":"Verified","text":"✅","order":1,"time_stamp_suffix_enabled":true,"fixed_text_suffix_enabled":true}]
|
|
369
411
|
```
|
|
370
412
|
|
|
371
|
-
See `hazo_pdf_config.ini` in the project root for all available configuration options.
|
|
413
|
+
See `config/hazo_pdf_config.ini` in the project root for all available configuration options.
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## Programmatic Highlight API
|
|
418
|
+
|
|
419
|
+
The PDF viewer exposes a ref-based API for programmatically creating, removing, and managing highlights. This allows external code to control highlights without user interaction.
|
|
420
|
+
|
|
421
|
+
### Basic Usage
|
|
422
|
+
|
|
423
|
+
```tsx
|
|
424
|
+
import { PdfViewer, PdfViewerRef } from 'hazo_pdf';
|
|
425
|
+
import { useRef } from 'react';
|
|
426
|
+
import 'hazo_pdf/styles.css';
|
|
427
|
+
|
|
428
|
+
function HighlightExample() {
|
|
429
|
+
const viewer_ref = useRef<PdfViewerRef>(null);
|
|
430
|
+
|
|
431
|
+
const add_highlight = () => {
|
|
432
|
+
// Highlight region on page 0 at PDF coordinates [100, 500, 300, 550]
|
|
433
|
+
const id = viewer_ref.current?.highlight_region(0, [100, 500, 300, 550], {
|
|
434
|
+
border_color: '#FF0000',
|
|
435
|
+
background_color: '#FFFF00',
|
|
436
|
+
background_opacity: 0.4
|
|
437
|
+
});
|
|
438
|
+
console.log('Created highlight:', id);
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
const remove_specific_highlight = (id: string) => {
|
|
442
|
+
const removed = viewer_ref.current?.remove_highlight(id);
|
|
443
|
+
console.log('Highlight removed:', removed);
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
const clear_all = () => {
|
|
447
|
+
viewer_ref.current?.clear_all_highlights();
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
return (
|
|
451
|
+
<div style={{ width: '100%', height: '800px' }}>
|
|
452
|
+
<button onClick={add_highlight}>Add Highlight</button>
|
|
453
|
+
<button onClick={clear_all}>Clear All Highlights</button>
|
|
454
|
+
|
|
455
|
+
<PdfViewer
|
|
456
|
+
ref={viewer_ref}
|
|
457
|
+
url="/document.pdf"
|
|
458
|
+
/>
|
|
459
|
+
</div>
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### PdfViewerRef Interface
|
|
465
|
+
|
|
466
|
+
The ref exposes three methods for highlight management:
|
|
467
|
+
|
|
468
|
+
#### `highlight_region(page_index, rect, options?)`
|
|
469
|
+
|
|
470
|
+
Creates a new highlight annotation on the specified page.
|
|
471
|
+
|
|
472
|
+
**Parameters:**
|
|
473
|
+
- `page_index` (number): Zero-based page index where the highlight should appear
|
|
474
|
+
- `rect` ([number, number, number, number]): Rectangle coordinates in PDF space [x1, y1, x2, y2]
|
|
475
|
+
- `options` (HighlightOptions, optional): Styling options
|
|
476
|
+
|
|
477
|
+
**Returns:** `string` - The unique ID of the created highlight annotation
|
|
478
|
+
|
|
479
|
+
**HighlightOptions:**
|
|
480
|
+
```typescript
|
|
481
|
+
{
|
|
482
|
+
border_color?: string; // Hex color (e.g., "#FF0000")
|
|
483
|
+
background_color?: string; // Hex color (e.g., "#FFFF00")
|
|
484
|
+
background_opacity?: number; // 0-1 (e.g., 0.4)
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
**Example:**
|
|
489
|
+
```tsx
|
|
490
|
+
const id = viewer_ref.current?.highlight_region(
|
|
491
|
+
0, // Page 0
|
|
492
|
+
[100, 500, 300, 550], // PDF coordinates
|
|
493
|
+
{
|
|
494
|
+
border_color: '#FF0000',
|
|
495
|
+
background_color: '#FFFF00',
|
|
496
|
+
background_opacity: 0.4
|
|
497
|
+
}
|
|
498
|
+
);
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### `remove_highlight(id)`
|
|
502
|
+
|
|
503
|
+
Removes a specific highlight by its ID.
|
|
504
|
+
|
|
505
|
+
**Parameters:**
|
|
506
|
+
- `id` (string): The highlight ID returned from `highlight_region()`
|
|
507
|
+
|
|
508
|
+
**Returns:** `boolean` - `true` if the highlight was found and removed, `false` otherwise
|
|
509
|
+
|
|
510
|
+
**Example:**
|
|
511
|
+
```tsx
|
|
512
|
+
const removed = viewer_ref.current?.remove_highlight('highlight-123');
|
|
513
|
+
if (removed) {
|
|
514
|
+
console.log('Highlight removed successfully');
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
#### `clear_all_highlights()`
|
|
519
|
+
|
|
520
|
+
Removes all highlights created via the `highlight_region()` API. Does not affect user-created annotations.
|
|
521
|
+
|
|
522
|
+
**Example:**
|
|
523
|
+
```tsx
|
|
524
|
+
viewer_ref.current?.clear_all_highlights();
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### Advanced Example: Search Results Highlighting
|
|
528
|
+
|
|
529
|
+
A common use case is highlighting search results in a PDF:
|
|
530
|
+
|
|
531
|
+
```tsx
|
|
532
|
+
import { useState, useRef } from 'react';
|
|
533
|
+
import { PdfViewer, PdfViewerRef } from 'hazo_pdf';
|
|
534
|
+
import 'hazo_pdf/styles.css';
|
|
535
|
+
|
|
536
|
+
interface SearchResult {
|
|
537
|
+
page: number;
|
|
538
|
+
rect: [number, number, number, number];
|
|
539
|
+
text: string;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
function SearchableViewer() {
|
|
543
|
+
const viewer_ref = useRef<PdfViewerRef>(null);
|
|
544
|
+
const [highlight_ids, set_highlight_ids] = useState<string[]>([]);
|
|
545
|
+
|
|
546
|
+
// Simulated search results
|
|
547
|
+
const search_results: SearchResult[] = [
|
|
548
|
+
{ page: 0, rect: [100, 500, 300, 550], text: 'Result 1' },
|
|
549
|
+
{ page: 0, rect: [100, 400, 300, 450], text: 'Result 2' },
|
|
550
|
+
{ page: 1, rect: [150, 600, 350, 650], text: 'Result 3' }
|
|
551
|
+
];
|
|
552
|
+
|
|
553
|
+
const highlight_search_results = () => {
|
|
554
|
+
// Clear previous highlights
|
|
555
|
+
viewer_ref.current?.clear_all_highlights();
|
|
556
|
+
|
|
557
|
+
// Add new highlights
|
|
558
|
+
const ids = search_results.map(result =>
|
|
559
|
+
viewer_ref.current?.highlight_region(result.page, result.rect, {
|
|
560
|
+
border_color: '#3B82F6',
|
|
561
|
+
background_color: '#DBEAFE',
|
|
562
|
+
background_opacity: 0.3
|
|
563
|
+
})
|
|
564
|
+
).filter(Boolean) as string[];
|
|
565
|
+
|
|
566
|
+
set_highlight_ids(ids);
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
const clear_search = () => {
|
|
570
|
+
viewer_ref.current?.clear_all_highlights();
|
|
571
|
+
set_highlight_ids([]);
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
return (
|
|
575
|
+
<div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
|
|
576
|
+
<div style={{ padding: '1rem', background: '#f0f0f0' }}>
|
|
577
|
+
<button onClick={highlight_search_results}>
|
|
578
|
+
Highlight Search Results ({search_results.length})
|
|
579
|
+
</button>
|
|
580
|
+
<button onClick={clear_search}>Clear Highlights</button>
|
|
581
|
+
<span>Highlighted: {highlight_ids.length} results</span>
|
|
582
|
+
</div>
|
|
583
|
+
|
|
584
|
+
<div style={{ flex: 1 }}>
|
|
585
|
+
<PdfViewer
|
|
586
|
+
ref={viewer_ref}
|
|
587
|
+
url="/document.pdf"
|
|
588
|
+
/>
|
|
589
|
+
</div>
|
|
590
|
+
</div>
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### Coordinate System Notes
|
|
596
|
+
|
|
597
|
+
- Highlights use PDF coordinate space (points), not screen pixels
|
|
598
|
+
- PDF coordinates start at the bottom-left corner (Y increases upward)
|
|
599
|
+
- The `rect` parameter format is `[x1, y1, x2, y2]` where:
|
|
600
|
+
- `x1, y1`: Bottom-left corner
|
|
601
|
+
- `x2, y2`: Top-right corner
|
|
602
|
+
- If you need to convert screen coordinates to PDF coordinates, you'll need to use the PDF page viewport (see the test app for examples)
|
|
603
|
+
|
|
604
|
+
### Styling Defaults
|
|
605
|
+
|
|
606
|
+
If no `options` are provided to `highlight_region()`, the highlight uses default colors from the configuration file:
|
|
607
|
+
- `border_color`: From `highlight_border_color` config setting
|
|
608
|
+
- `background_color`: From `highlight_fill_color` config setting
|
|
609
|
+
- `background_opacity`: From `highlight_fill_opacity` config setting
|
|
610
|
+
|
|
611
|
+
You can override any or all of these on a per-highlight basis.
|
|
372
612
|
|
|
373
613
|
---
|
|
374
614
|
|
|
@@ -391,7 +631,7 @@ See `hazo_pdf_config.ini` in the project root for all available configuration op
|
|
|
391
631
|
| `className` | `string` | `""` | Additional CSS classes to apply to the viewer container. |
|
|
392
632
|
| `scale` | `number` | `1.0` | Initial zoom level. Values > 1.0 zoom in, < 1.0 zoom out. |
|
|
393
633
|
| `background_color` | `string` | `"#2d2d2d"` | Background color for areas outside PDF pages (hex format: `#RRGGBB`). Overrides config file value. |
|
|
394
|
-
| `config_file` | `string` | `undefined` | Path to configuration INI file (e.g., `"hazo_pdf_config.ini"`). If not provided, uses default configuration. |
|
|
634
|
+
| `config_file` | `string` | `undefined` | Path to configuration INI file (e.g., `"config/hazo_pdf_config.ini"`). If not provided, uses default configuration. |
|
|
395
635
|
|
|
396
636
|
##### Event Callbacks
|
|
397
637
|
|
|
@@ -469,12 +709,50 @@ const stamps = JSON.stringify([
|
|
|
469
709
|
}
|
|
470
710
|
]);
|
|
471
711
|
|
|
472
|
-
<PdfViewer
|
|
712
|
+
<PdfViewer
|
|
473
713
|
url="/document.pdf"
|
|
474
714
|
right_click_custom_stamps={stamps}
|
|
475
715
|
/>
|
|
476
716
|
```
|
|
477
717
|
|
|
718
|
+
##### Toolbar Visibility
|
|
719
|
+
|
|
720
|
+
Props to control toolbar button visibility. These override config file values.
|
|
721
|
+
|
|
722
|
+
| Prop | Type | Default | Description |
|
|
723
|
+
|------|------|---------|-------------|
|
|
724
|
+
| `toolbar_enabled` | `boolean` | `true` | Master toggle to show/hide the entire toolbar. |
|
|
725
|
+
| `show_zoom_controls` | `boolean` | `true` | Show zoom in/out/reset buttons. |
|
|
726
|
+
| `show_square_button` | `boolean` | `true` | Show square annotation button. |
|
|
727
|
+
| `show_undo_button` | `boolean` | `true` | Show undo button. |
|
|
728
|
+
| `show_redo_button` | `boolean` | `true` | Show redo button. |
|
|
729
|
+
| `show_save_button` | `boolean` | `true` | Show save button. |
|
|
730
|
+
| `show_metadata_button` | `boolean` | `true` | Show metadata panel button (only visible when `sidepanel_metadata_enabled` is true). |
|
|
731
|
+
| `on_close` | `() => void` | `undefined` | Callback when close button is clicked. When provided, shows a close button (X) in the toolbar. Useful for modal/dialog usage. |
|
|
732
|
+
|
|
733
|
+
**Example - Minimal toolbar:**
|
|
734
|
+
|
|
735
|
+
```tsx
|
|
736
|
+
<PdfViewer
|
|
737
|
+
url="/document.pdf"
|
|
738
|
+
toolbar_enabled={true}
|
|
739
|
+
show_zoom_controls={true}
|
|
740
|
+
show_square_button={false}
|
|
741
|
+
show_undo_button={false}
|
|
742
|
+
show_redo_button={false}
|
|
743
|
+
show_save_button={false}
|
|
744
|
+
/>
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
**Example - Dialog with close button:**
|
|
748
|
+
|
|
749
|
+
```tsx
|
|
750
|
+
<PdfViewer
|
|
751
|
+
url="/document.pdf"
|
|
752
|
+
on_close={() => setDialogOpen(false)}
|
|
753
|
+
/>
|
|
754
|
+
```
|
|
755
|
+
|
|
478
756
|
### PdfAnnotation Interface
|
|
479
757
|
|
|
480
758
|
Represents a PDF annotation in the standard PDF coordinate space.
|
|
@@ -494,6 +772,40 @@ interface PdfAnnotation {
|
|
|
494
772
|
}
|
|
495
773
|
```
|
|
496
774
|
|
|
775
|
+
**Note:** Highlights created via the programmatic API (`PdfViewerRef.highlight_region()`) will have `type: 'Highlight'` and `flags: 'api_highlight'` to distinguish them from user-created annotations.
|
|
776
|
+
|
|
777
|
+
### PdfViewerRef Interface
|
|
778
|
+
|
|
779
|
+
Interface for the ref exposed by `PdfViewer`. Use with `useRef<PdfViewerRef>()` to access programmatic highlight methods.
|
|
780
|
+
|
|
781
|
+
```typescript
|
|
782
|
+
interface PdfViewerRef {
|
|
783
|
+
highlight_region: (
|
|
784
|
+
page_index: number,
|
|
785
|
+
rect: [number, number, number, number],
|
|
786
|
+
options?: HighlightOptions
|
|
787
|
+
) => string;
|
|
788
|
+
|
|
789
|
+
remove_highlight: (id: string) => boolean;
|
|
790
|
+
|
|
791
|
+
clear_all_highlights: () => void;
|
|
792
|
+
}
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
See [Programmatic Highlight API](#programmatic-highlight-api) for detailed usage.
|
|
796
|
+
|
|
797
|
+
### HighlightOptions Interface
|
|
798
|
+
|
|
799
|
+
Options for customizing highlights created via the API.
|
|
800
|
+
|
|
801
|
+
```typescript
|
|
802
|
+
interface HighlightOptions {
|
|
803
|
+
border_color?: string; // Hex format (e.g., "#FF0000")
|
|
804
|
+
background_color?: string; // Hex format (e.g., "#FFFF00")
|
|
805
|
+
background_opacity?: number; // 0-1 (e.g., 0.4)
|
|
806
|
+
}
|
|
807
|
+
```
|
|
808
|
+
|
|
497
809
|
### PDFDocumentProxy
|
|
498
810
|
|
|
499
811
|
Type from `pdfjs-dist`. Contains PDF metadata and page proxies.
|
|
@@ -95,6 +95,7 @@ var default_config = {
|
|
|
95
95
|
toolbar_show_redo_button: true,
|
|
96
96
|
toolbar_show_save_button: true,
|
|
97
97
|
toolbar_show_metadata_button: true,
|
|
98
|
+
toolbar_show_annotate_button: true,
|
|
98
99
|
toolbar_zoom_out_label: "\u2212",
|
|
99
100
|
toolbar_zoom_in_label: "+",
|
|
100
101
|
toolbar_zoom_reset_label: "Reset",
|
|
@@ -311,4 +312,4 @@ export {
|
|
|
311
312
|
download_pdf,
|
|
312
313
|
save_and_download_pdf
|
|
313
314
|
};
|
|
314
|
-
//# sourceMappingURL=chunk-
|
|
315
|
+
//# sourceMappingURL=chunk-S3AJUZ7D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/default_config.ts","../src/utils/pdf_saver.ts"],"sourcesContent":["/**\n * Default configuration values for hazo_pdf\n * All styling defaults organized by category\n */\n\nimport type { PdfViewerConfig } from '../types/config';\n\n/**\n * Default PDF Viewer Configuration\n * These values are used when no config file is provided or when values are missing\n */\nexport const default_config: PdfViewerConfig = {\n fonts: {\n freetext_font_family: 'Arial, sans-serif',\n freetext_font_size_min: 12,\n freetext_font_size_max: 24,\n freetext_font_size_default: 14,\n font_foreground_color: '#000000', // Black by default\n },\n\n highlight_annotation: {\n highlight_fill_color: '#FFFF00',\n highlight_fill_opacity: 0.3,\n highlight_border_color: '#FFD700',\n highlight_border_color_hover: '#FFD700',\n highlight_fill_opacity_hover: 0.4,\n },\n\n square_annotation: {\n square_fill_color: '#FF0000',\n square_fill_opacity: 0.2,\n square_border_color: '#FF0000',\n square_border_color_hover: '#CC0000',\n square_fill_opacity_hover: 0.3,\n },\n\n freetext_annotation: {\n freetext_text_color: '#000000',\n freetext_text_color_hover: '#000000',\n freetext_border_color: '#003366',\n freetext_border_width: 1,\n freetext_background_color: '#E6F3FF',\n freetext_background_opacity: 0.1,\n freetext_font_weight: 'normal',\n freetext_font_style: 'normal',\n freetext_text_decoration: 'none',\n freetext_padding_horizontal: 4,\n freetext_padding_vertical: 2,\n },\n\n page_styling: {\n page_border_color: '#999999',\n page_box_shadow: '0 2px 8px rgba(0, 0, 0, 0.3)',\n page_background_color: '#ffffff',\n },\n\n viewer: {\n viewer_background_color: '#2d2d2d',\n append_timestamp_to_text_edits: false,\n annotation_text_suffix_fixed_text: '',\n add_enclosing_brackets_to_suffixes: true,\n suffix_enclosing_brackets: '[]',\n suffix_text_position: 'below_multi_line',\n },\n\n context_menu: {\n context_menu_background_color: '#ffffff',\n context_menu_border_color: '#d1d5db',\n context_menu_item_hover_background: '#f3f4f6',\n context_menu_item_disabled_opacity: 0.5,\n right_click_custom_stamps: '', // Empty string means no custom stamps\n },\n\n dialog: {\n dialog_backdrop_opacity: 0.2,\n dialog_background_color: '#ffffff',\n dialog_border_color: '#d1d5db',\n dialog_button_submit_color: '#16a34a',\n dialog_button_submit_color_hover: '#15803d',\n dialog_button_cancel_color: '#6b7280',\n dialog_button_cancel_color_hover: '#4b5563',\n dialog_button_disabled_opacity: 0.4,\n },\n\n toolbar: {\n toolbar_background_color: '#f9fafb',\n toolbar_border_color: '#e5e7eb',\n toolbar_font_family: 'system-ui, -apple-system, sans-serif',\n toolbar_font_size: 14,\n toolbar_font_color: '#111827',\n toolbar_button_background_color: '#ffffff',\n toolbar_button_background_color_hover: '#f3f4f6',\n toolbar_button_text_color: '#374151',\n toolbar_button_active_background_color: '#3b82f6',\n toolbar_button_active_text_color: '#ffffff',\n toolbar_button_save_background_color: '#10b981',\n toolbar_button_save_background_color_hover: '#059669',\n toolbar_button_save_text_color: '#ffffff',\n toolbar_button_disabled_opacity: 0.5,\n toolbar_show_zoom_controls: true,\n toolbar_show_square_button: true,\n toolbar_show_undo_button: true,\n toolbar_show_redo_button: true,\n toolbar_show_save_button: true,\n toolbar_show_metadata_button: true,\n toolbar_show_annotate_button: true,\n toolbar_zoom_out_label: '−',\n toolbar_zoom_in_label: '+',\n toolbar_zoom_reset_label: 'Reset',\n toolbar_square_label: 'Square',\n toolbar_undo_label: 'Undo',\n toolbar_redo_label: 'Redo',\n toolbar_save_label: 'Save',\n toolbar_saving_label: 'Saving...',\n toolbar_metadata_label: 'Metadata',\n },\n};\n","/**\n * PDF Saver Utility\n * Saves annotations directly into PDF documents using pdf-lib\n * This allows annotations to be embedded in the PDF file itself\n */\n\nimport type { PdfAnnotation, PdfViewerConfig } from '../types';\nimport { default_config } from '../config/default_config';\n\n/**\n * Save annotations into a PDF document\n * This function fetches the PDF, adds annotations, and downloads the modified PDF\n * @param pdf_url - URL of the PDF file\n * @param annotations - Array of annotations to save\n * @param output_filename - Name for the saved PDF file (default: original filename with '_annotated' suffix)\n * @param config - Optional configuration for styling values\n * @returns Promise that resolves when the PDF is saved\n */\nexport async function save_annotations_to_pdf(\n pdf_url: string,\n annotations: PdfAnnotation[],\n _output_filename?: string, // Currently unused, kept for API compatibility\n config?: PdfViewerConfig | null\n): Promise<Uint8Array> {\n try {\n // Dynamically import pdf-lib\n const { PDFDocument, rgb } = await import('pdf-lib');\n \n // Fetch the original PDF\n console.log('[PDF Saver] Fetching PDF from:', pdf_url);\n const pdf_response = await fetch(pdf_url);\n if (!pdf_response.ok) {\n throw new Error(`Failed to fetch PDF: ${pdf_response.status} ${pdf_response.statusText}`);\n }\n \n const pdf_bytes = await pdf_response.arrayBuffer();\n console.log('[PDF Saver] PDF fetched, size:', pdf_bytes.byteLength, 'bytes');\n \n // Load the PDF document\n const pdf_doc = await PDFDocument.load(pdf_bytes);\n console.log('[PDF Saver] PDF loaded, pages:', pdf_doc.getPageCount());\n \n // Get config values or use defaults\n const fonts_config = config?.fonts || default_config.fonts;\n const highlight_config = config?.highlight_annotation || default_config.highlight_annotation;\n const square_config = config?.square_annotation || default_config.square_annotation;\n const freetext_config = config?.freetext_annotation || default_config.freetext_annotation;\n \n // Add annotations to each page\n for (const annotation of annotations) {\n if (annotation.page_index >= pdf_doc.getPageCount()) {\n console.warn(`[PDF Saver] Annotation ${annotation.id} references page ${annotation.page_index}, but PDF only has ${pdf_doc.getPageCount()} pages. Skipping.`);\n continue;\n }\n \n const page = pdf_doc.getPage(annotation.page_index);\n const [x1, y1, x2, y2] = annotation.rect;\n \n // PDF coordinate system: bottom-left is origin (pdfjs-dist)\n // pdf-lib uses bottom-left as origin too, so coordinates should be fine\n // But we need to ensure rect is normalized\n const rect_x = Math.min(x1, x2);\n const rect_y = Math.min(y1, y2);\n const rect_width = Math.abs(x2 - x1);\n const rect_height = Math.abs(y2 - y1);\n \n // Parse color (hex or rgb to RGB for pdf-lib)\n // Supports both hex (#RRGGBB) and rgb(r, g, b) formats\n let color = rgb(0, 0, 0); // Default black\n if (annotation.color) {\n const color_str = annotation.color.trim();\n \n // Handle rgb(r, g, b) format\n const rgb_pattern = /^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/i;\n const rgb_match = color_str.match(rgb_pattern);\n if (rgb_match) {\n const r = parseInt(rgb_match[1], 10);\n const g = parseInt(rgb_match[2], 10);\n const b = parseInt(rgb_match[3], 10);\n // Validate RGB values (0-255) and convert to 0-1 range for pdf-lib\n if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {\n color = rgb(r / 255, g / 255, b / 255);\n } else {\n console.warn(`[PDF Saver] Invalid RGB values for annotation ${annotation.id}: r=${r}, g=${g}, b=${b}`);\n }\n } else if (color_str.startsWith('#')) {\n // Handle hex format (#RRGGBB)\n const hex = color_str.slice(1).trim();\n if (hex.length === 6 && /^[0-9A-Fa-f]{6}$/.test(hex)) {\n const r = parseInt(hex.substring(0, 2), 16) / 255;\n const g = parseInt(hex.substring(2, 4), 16) / 255;\n const b = parseInt(hex.substring(4, 6), 16) / 255;\n color = rgb(r, g, b);\n } else {\n console.warn(`[PDF Saver] Invalid hex color format for annotation ${annotation.id}: ${color_str}`);\n }\n } else {\n console.warn(`[PDF Saver] Unrecognized color format for annotation ${annotation.id}: ${color_str}`);\n }\n }\n \n // Create annotation based on type using pdf-lib's annotation methods\n try {\n switch (annotation.type) {\n case 'Square': {\n // Create a rectangle/square annotation\n page.drawRectangle({\n x: rect_x,\n y: rect_y,\n width: rect_width,\n height: rect_height,\n borderColor: color,\n borderWidth: 2,\n borderOpacity: 0.8,\n });\n \n // Add text comment if present\n if (annotation.contents) {\n const comment_color_str = (annotation.color || square_config.square_border_color).trim();\n let comment_r = 0, comment_g = 0, comment_b = 0;\n \n // Parse color (hex or rgb format)\n const rgb_pattern = /^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/i;\n const rgb_match = comment_color_str.match(rgb_pattern);\n if (rgb_match) {\n comment_r = parseInt(rgb_match[1], 10) / 255;\n comment_g = parseInt(rgb_match[2], 10) / 255;\n comment_b = parseInt(rgb_match[3], 10) / 255;\n } else if (comment_color_str.startsWith('#')) {\n const hex = comment_color_str.slice(1).trim();\n if (hex.length === 6 && /^[0-9A-Fa-f]{6}$/.test(hex)) {\n comment_r = parseInt(hex.substring(0, 2), 16) / 255;\n comment_g = parseInt(hex.substring(2, 4), 16) / 255;\n comment_b = parseInt(hex.substring(4, 6), 16) / 255;\n }\n }\n \n page.drawText(annotation.contents, {\n x: rect_x,\n y: rect_y + rect_height + 5,\n size: fonts_config.freetext_font_size_default,\n color: rgb(comment_r, comment_g, comment_b),\n });\n }\n break;\n }\n \n case 'Highlight': {\n // Create a highlight annotation (semi-transparent rectangle)\n const highlight_color_str = (annotation.color || highlight_config.highlight_fill_color).trim();\n let highlight_r = 255 / 255, highlight_g = 255 / 255, highlight_b = 0 / 255; // Default yellow\n \n // Parse color (hex or rgb format)\n const rgb_pattern = /^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/i;\n const rgb_match = highlight_color_str.match(rgb_pattern);\n if (rgb_match) {\n highlight_r = parseInt(rgb_match[1], 10) / 255;\n highlight_g = parseInt(rgb_match[2], 10) / 255;\n highlight_b = parseInt(rgb_match[3], 10) / 255;\n } else if (highlight_color_str.startsWith('#')) {\n const hex = highlight_color_str.slice(1).trim();\n if (hex.length === 6 && /^[0-9A-Fa-f]{6}$/.test(hex)) {\n highlight_r = parseInt(hex.substring(0, 2), 16) / 255;\n highlight_g = parseInt(hex.substring(2, 4), 16) / 255;\n highlight_b = parseInt(hex.substring(4, 6), 16) / 255;\n }\n }\n const highlight_color = rgb(highlight_r, highlight_g, highlight_b);\n \n page.drawRectangle({\n x: rect_x,\n y: rect_y,\n width: rect_width,\n height: rect_height,\n color: highlight_color,\n opacity: highlight_config.highlight_fill_opacity,\n });\n \n // Add text comment if present\n if (annotation.contents) {\n page.drawText(annotation.contents, {\n x: rect_x,\n y: rect_y + rect_height + 5,\n size: fonts_config.freetext_font_size_default,\n color: rgb(0, 0, 0),\n });\n }\n break;\n }\n \n case 'FreeText': {\n // Create a free text annotation\n if (annotation.contents) {\n // Text color priority: annotation.color > freetext_text_color > font_foreground_color > default black\n const text_color_str = (annotation.color || \n freetext_config.freetext_text_color || \n fonts_config.font_foreground_color || \n '#000000').trim();\n let text_r = 0, text_g = 0, text_b = 0;\n \n // Parse color (hex or rgb format)\n const rgb_pattern = /^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/i;\n const rgb_match = text_color_str.match(rgb_pattern);\n if (rgb_match) {\n text_r = parseInt(rgb_match[1], 10) / 255;\n text_g = parseInt(rgb_match[2], 10) / 255;\n text_b = parseInt(rgb_match[3], 10) / 255;\n } else if (text_color_str.startsWith('#')) {\n const hex = text_color_str.slice(1).trim();\n if (hex.length === 6 && /^[0-9A-Fa-f]{6}$/.test(hex)) {\n text_r = parseInt(hex.substring(0, 2), 16) / 255;\n text_g = parseInt(hex.substring(2, 4), 16) / 255;\n text_b = parseInt(hex.substring(4, 6), 16) / 255;\n }\n }\n \n page.drawText(annotation.contents, {\n x: rect_x,\n y: rect_y,\n size: fonts_config.freetext_font_size_default,\n color: rgb(text_r, text_g, text_b),\n maxWidth: rect_width,\n });\n }\n break;\n }\n \n default:\n console.warn(`[PDF Saver] Unsupported annotation type: ${annotation.type}`);\n }\n } catch (annotation_error) {\n console.error(`[PDF Saver] Error adding annotation ${annotation.id}:`, annotation_error);\n // Continue with other annotations\n }\n }\n \n // Save the PDF\n const modified_pdf_bytes = await pdf_doc.save();\n console.log('[PDF Saver] PDF modified, size:', modified_pdf_bytes.length, 'bytes');\n \n return modified_pdf_bytes;\n } catch (error) {\n if (error && typeof error === 'object' && 'message' in error && \n typeof error.message === 'string' && error.message.includes('pdf-lib')) {\n throw new Error('pdf-lib is required to save annotations to PDF. Please install it: npm install pdf-lib');\n }\n console.error('[PDF Saver] Error saving PDF:', error);\n throw error;\n }\n}\n\n/**\n * Download PDF bytes as a file\n * @param pdf_bytes - PDF file bytes\n * @param filename - Name for the downloaded file\n */\nexport function download_pdf(pdf_bytes: Uint8Array, filename: string): void {\n // Create a new ArrayBuffer view to ensure compatibility with Blob constructor\n // Uint8Array.buffer can be SharedArrayBuffer, which Blob doesn't accept directly\n const buffer = new Uint8Array(pdf_bytes).buffer;\n const blob = new Blob([buffer], { type: 'application/pdf' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n\n/**\n * Save annotations to PDF and download\n * @param pdf_url - URL of the PDF file\n * @param annotations - Array of annotations to save\n * @param output_filename - Name for the saved PDF file (default: original filename with '_annotated' suffix)\n * @param config - Optional configuration for styling values\n */\nexport async function save_and_download_pdf(\n pdf_url: string,\n annotations: PdfAnnotation[],\n output_filename?: string,\n config?: PdfViewerConfig | null\n): Promise<void> {\n const pdf_bytes = await save_annotations_to_pdf(pdf_url, annotations, output_filename, config);\n \n // Generate output filename\n const original_filename = pdf_url.split('/').pop() || 'document.pdf';\n const filename_without_ext = original_filename.replace(/\\.pdf$/i, '');\n const final_filename = output_filename || `${filename_without_ext}_annotated.pdf`;\n \n // Download the modified PDF\n download_pdf(pdf_bytes, final_filename);\n console.log('[PDF Saver] PDF saved as:', final_filename);\n}\n\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import React__default from 'react';
|
|
2
3
|
import { PDFDocumentProxy, PDFPageProxy } from 'pdfjs-dist';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -168,6 +169,8 @@ interface PdfViewerConfig {
|
|
|
168
169
|
toolbar_show_save_button: boolean;
|
|
169
170
|
/** Whether to show metadata panel button (true/false) */
|
|
170
171
|
toolbar_show_metadata_button: boolean;
|
|
172
|
+
/** Whether to show annotate (FreeText) button (true/false) */
|
|
173
|
+
toolbar_show_annotate_button: boolean;
|
|
171
174
|
/** Label for zoom out button (default: "−") */
|
|
172
175
|
toolbar_zoom_out_label: string;
|
|
173
176
|
/** Label for zoom in button (default: "+") */
|
|
@@ -220,7 +223,7 @@ interface PdfViewerProps {
|
|
|
220
223
|
on_save?: (pdf_bytes: Uint8Array, filename: string) => void;
|
|
221
224
|
/** Background color for areas outside PDF pages (default: dark grey) */
|
|
222
225
|
background_color?: string;
|
|
223
|
-
/** Optional path to configuration INI file (e.g., "hazo_pdf_config.ini") */
|
|
226
|
+
/** Optional path to configuration INI file (e.g., "config/hazo_pdf_config.ini") */
|
|
224
227
|
config_file?: string;
|
|
225
228
|
/** Whether to append timestamp to annotated text edits (default: false) */
|
|
226
229
|
append_timestamp_to_text_edits?: boolean;
|
|
@@ -241,6 +244,24 @@ interface PdfViewerProps {
|
|
|
241
244
|
updatedRow: MetadataDataItem;
|
|
242
245
|
allData: MetadataInput;
|
|
243
246
|
};
|
|
247
|
+
/** Whether to show the toolbar at all (default: true) */
|
|
248
|
+
toolbar_enabled?: boolean;
|
|
249
|
+
/** Whether to show zoom controls (default: true) */
|
|
250
|
+
show_zoom_controls?: boolean;
|
|
251
|
+
/** Whether to show square annotation button (default: true) */
|
|
252
|
+
show_square_button?: boolean;
|
|
253
|
+
/** Whether to show undo button (default: true) */
|
|
254
|
+
show_undo_button?: boolean;
|
|
255
|
+
/** Whether to show redo button (default: true) */
|
|
256
|
+
show_redo_button?: boolean;
|
|
257
|
+
/** Whether to show save button (default: true) */
|
|
258
|
+
show_save_button?: boolean;
|
|
259
|
+
/** Whether to show metadata panel button (default: true, only visible when sidepanel_metadata_enabled) */
|
|
260
|
+
show_metadata_button?: boolean;
|
|
261
|
+
/** Whether to show annotate (FreeText) button (default: true) */
|
|
262
|
+
show_annotate_button?: boolean;
|
|
263
|
+
/** Callback when close button is clicked (shows close button in toolbar when provided) */
|
|
264
|
+
on_close?: () => void;
|
|
244
265
|
}
|
|
245
266
|
/**
|
|
246
267
|
* PDF Annotation interface matching PDF standard
|
|
@@ -383,18 +404,48 @@ interface MetadataInput {
|
|
|
383
404
|
/** Array of footer items */
|
|
384
405
|
footer: MetadataFooterItem[];
|
|
385
406
|
}
|
|
386
|
-
|
|
387
407
|
/**
|
|
388
|
-
*
|
|
389
|
-
* Main component for displaying and interacting with PDF documents
|
|
390
|
-
* Integrates PDF rendering, annotation overlay, and layout management
|
|
408
|
+
* Options for programmatic highlight creation via PdfViewerRef
|
|
391
409
|
*/
|
|
410
|
+
interface HighlightOptions {
|
|
411
|
+
/** Border color in hex format (default: from config highlight_border_color) */
|
|
412
|
+
border_color?: string;
|
|
413
|
+
/** Background/fill color in hex format (default: from config highlight_fill_color) */
|
|
414
|
+
background_color?: string;
|
|
415
|
+
/** Background opacity 0-1 (default: from config highlight_fill_opacity) */
|
|
416
|
+
background_opacity?: number;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Ref interface for programmatic PDF viewer control
|
|
420
|
+
* Use with useRef<PdfViewerRef>() to get access to imperative methods
|
|
421
|
+
*/
|
|
422
|
+
interface PdfViewerRef {
|
|
423
|
+
/**
|
|
424
|
+
* Create a highlight on a specific page region
|
|
425
|
+
* @param page_index - Zero-based page index
|
|
426
|
+
* @param rect - Rectangle coordinates in PDF space [x1, y1, x2, y2]
|
|
427
|
+
* @param options - Optional styling overrides (border_color, background_color, background_opacity)
|
|
428
|
+
* @returns The highlight annotation ID
|
|
429
|
+
*/
|
|
430
|
+
highlight_region: (page_index: number, rect: [number, number, number, number], options?: HighlightOptions) => string;
|
|
431
|
+
/**
|
|
432
|
+
* Remove a specific highlight by ID
|
|
433
|
+
* @param id - The highlight annotation ID returned from highlight_region
|
|
434
|
+
* @returns true if highlight was found and removed, false otherwise
|
|
435
|
+
*/
|
|
436
|
+
remove_highlight: (id: string) => boolean;
|
|
437
|
+
/**
|
|
438
|
+
* Remove all highlights created via the highlight_region API
|
|
439
|
+
* Does not affect user-created annotations
|
|
440
|
+
*/
|
|
441
|
+
clear_all_highlights: () => void;
|
|
442
|
+
}
|
|
392
443
|
|
|
393
444
|
/**
|
|
394
445
|
* PDF Viewer Component
|
|
395
446
|
* Main entry point for PDF viewing and annotation
|
|
396
447
|
*/
|
|
397
|
-
declare const PdfViewer: React.
|
|
448
|
+
declare const PdfViewer: React.ForwardRefExoticComponent<PdfViewerProps & React.RefAttributes<PdfViewerRef>>;
|
|
398
449
|
|
|
399
450
|
/**
|
|
400
451
|
* PDF Viewer Layout Component
|
|
@@ -411,8 +462,9 @@ interface PdfViewerLayoutProps {
|
|
|
411
462
|
annotations: PdfAnnotation[];
|
|
412
463
|
current_tool: 'Square' | 'Highlight' | 'FreeText' | 'CustomBookmark' | null;
|
|
413
464
|
on_annotation_create: (annotation: PdfAnnotation) => void;
|
|
414
|
-
on_context_menu: (e:
|
|
465
|
+
on_context_menu: (e: React__default.MouseEvent, page_index: number, screen_x: number, screen_y: number, mapper: CoordinateMapper) => void;
|
|
415
466
|
on_annotation_click: (annotation: PdfAnnotation, screen_x: number, screen_y: number, mapper: CoordinateMapper) => void;
|
|
467
|
+
on_freetext_click?: (page_index: number, screen_x: number, screen_y: number, mapper: CoordinateMapper) => void;
|
|
416
468
|
background_color?: string;
|
|
417
469
|
config: PdfViewerConfig | null;
|
|
418
470
|
className?: string;
|
|
@@ -421,7 +473,7 @@ interface PdfViewerLayoutProps {
|
|
|
421
473
|
* PDF Viewer Layout Component
|
|
422
474
|
* Manages page rendering and annotation overlay coordination
|
|
423
475
|
*/
|
|
424
|
-
declare const PdfViewerLayout:
|
|
476
|
+
declare const PdfViewerLayout: React__default.FC<PdfViewerLayoutProps>;
|
|
425
477
|
|
|
426
478
|
/**
|
|
427
479
|
* PDF Page Renderer Component
|
|
@@ -450,7 +502,7 @@ interface PdfPageRendererProps {
|
|
|
450
502
|
* PDF Page Renderer Component
|
|
451
503
|
* Handles rendering of a single PDF page to canvas
|
|
452
504
|
*/
|
|
453
|
-
declare const PdfPageRenderer:
|
|
505
|
+
declare const PdfPageRenderer: React__default.FC<PdfPageRendererProps>;
|
|
454
506
|
|
|
455
507
|
/**
|
|
456
508
|
* Annotation Overlay Component
|
|
@@ -476,9 +528,11 @@ interface AnnotationOverlayProps {
|
|
|
476
528
|
/** Callback when annotation is created */
|
|
477
529
|
on_annotation_create?: (annotation: PdfAnnotation) => void;
|
|
478
530
|
/** Callback when right-click occurs */
|
|
479
|
-
on_context_menu?: (event:
|
|
531
|
+
on_context_menu?: (event: React__default.MouseEvent, screen_x: number, screen_y: number) => void;
|
|
480
532
|
/** Callback when annotation is clicked */
|
|
481
533
|
on_annotation_click?: (annotation: PdfAnnotation, screen_x: number, screen_y: number) => void;
|
|
534
|
+
/** Callback when FreeText tool is active and user clicks on empty area */
|
|
535
|
+
on_freetext_click?: (screen_x: number, screen_y: number) => void;
|
|
482
536
|
/** Configuration object for styling */
|
|
483
537
|
config?: PdfViewerConfig | null;
|
|
484
538
|
/** Optional class name */
|
|
@@ -488,7 +542,7 @@ interface AnnotationOverlayProps {
|
|
|
488
542
|
* Annotation Overlay Component
|
|
489
543
|
* Handles mouse interactions for creating annotations
|
|
490
544
|
*/
|
|
491
|
-
declare const AnnotationOverlay:
|
|
545
|
+
declare const AnnotationOverlay: React__default.FC<AnnotationOverlayProps>;
|
|
492
546
|
|
|
493
547
|
/**
|
|
494
548
|
* PDF Worker Setup
|
|
@@ -706,4 +760,4 @@ declare function load_pdf_config(config_file?: string): PdfViewerConfig;
|
|
|
706
760
|
*/
|
|
707
761
|
declare const default_config: PdfViewerConfig;
|
|
708
762
|
|
|
709
|
-
export { AnnotationOverlay, type CoordinateMapper, type CustomStamp, type MetadataDataItem, type MetadataFooterItem, type MetadataFormatType, type MetadataHeaderItem, type MetadataInput, type PageDimensions, type PdfAnnotation, type PdfBookmark, type PdfDocument, type PdfPage, PdfPageRenderer, PdfViewer, type PdfViewerConfig, PdfViewerLayout, type PdfViewerProps, build_config_from_ini, calculate_rectangle_coords, create_coordinate_mapper, default_config, download_pdf, download_xfdf, export_annotations_to_xfdf, generate_xfdf, get_viewport_dimensions, is_rectangle_too_small, load_pdf_config, load_pdf_config_async, load_pdf_document, parse_color, parse_number, parse_opacity, parse_string, pdf_rect_to_rectangle, rectangle_to_pdf_rect, save_and_download_pdf, save_annotations_to_pdf };
|
|
763
|
+
export { AnnotationOverlay, type CoordinateMapper, type CustomStamp, type HighlightOptions, type MetadataDataItem, type MetadataFooterItem, type MetadataFormatType, type MetadataHeaderItem, type MetadataInput, type PageDimensions, type PdfAnnotation, type PdfBookmark, type PdfDocument, type PdfPage, PdfPageRenderer, PdfViewer, type PdfViewerConfig, PdfViewerLayout, type PdfViewerProps, type PdfViewerRef, build_config_from_ini, calculate_rectangle_coords, create_coordinate_mapper, default_config, download_pdf, download_xfdf, export_annotations_to_xfdf, generate_xfdf, get_viewport_dimensions, is_rectangle_too_small, load_pdf_config, load_pdf_config_async, load_pdf_document, parse_color, parse_number, parse_opacity, parse_string, pdf_rect_to_rectangle, rectangle_to_pdf_rect, save_and_download_pdf, save_annotations_to_pdf };
|