hazo_pdf 1.2.0 → 1.2.1
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 +85 -6
- package/dist/{chunk-ZQMZT7HV.js → chunk-S3AJUZ7D.js} +2 -1
- package/dist/chunk-S3AJUZ7D.js.map +1 -0
- package/dist/index.d.ts +24 -1
- package/dist/index.js +127 -34
- package/dist/index.js.map +1 -1
- package/dist/{pdf_saver-ILJPGAPI.js → pdf_saver-P2MJN45S.js} +2 -2
- package/dist/styles/full.css +2352 -0
- package/dist/styles/full.css.map +1 -0
- package/dist/styles/index.css +159 -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
|
@@ -19,6 +19,47 @@ A React component library for viewing and annotating PDF documents with support
|
|
|
19
19
|
npm install hazo_pdf
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
## CSS Import Options
|
|
23
|
+
|
|
24
|
+
The library provides two CSS files to choose from:
|
|
25
|
+
|
|
26
|
+
### For apps with existing styles (Recommended)
|
|
27
|
+
|
|
28
|
+
Use `styles.css` - this does NOT include Tailwind preflight/base resets, so it won't interfere with your existing styles:
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import 'hazo_pdf/styles.css';
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### For standalone apps
|
|
35
|
+
|
|
36
|
+
Use `styles-full.css` - includes Tailwind preflight/base styles for apps without existing CSS resets:
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import 'hazo_pdf/styles-full.css';
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Container Requirements
|
|
43
|
+
|
|
44
|
+
The PDF viewer requires its parent container to have explicit dimensions:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
// Good - explicit dimensions
|
|
48
|
+
<div style={{ width: '100%', height: '600px' }}>
|
|
49
|
+
<PdfViewer url="/document.pdf" />
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
// Bad - no explicit height
|
|
53
|
+
<div>
|
|
54
|
+
<PdfViewer url="/document.pdf" />
|
|
55
|
+
</div>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Requirements:**
|
|
59
|
+
- Parent must have explicit `width` and `height` (CSS or inline style)
|
|
60
|
+
- Recommended minimum size: 400x400px
|
|
61
|
+
- Parent should NOT have `overflow: hidden` (the viewer handles its own scrolling)
|
|
62
|
+
|
|
22
63
|
## Quick Start
|
|
23
64
|
|
|
24
65
|
```tsx
|
|
@@ -307,7 +348,7 @@ function ProductionViewer() {
|
|
|
307
348
|
<div style={{ flex: 1, overflow: 'hidden' }}>
|
|
308
349
|
<PdfViewer
|
|
309
350
|
url="/api/documents/contract.pdf"
|
|
310
|
-
config_file="hazo_pdf_config.ini"
|
|
351
|
+
config_file="config/hazo_pdf_config.ini"
|
|
311
352
|
className="h-full w-full"
|
|
312
353
|
scale={initialScale}
|
|
313
354
|
annotations={annotations}
|
|
@@ -327,7 +368,7 @@ function ProductionViewer() {
|
|
|
327
368
|
```
|
|
328
369
|
|
|
329
370
|
**Features demonstrated:**
|
|
330
|
-
- Configuration file integration (`hazo_pdf_config.ini`)
|
|
371
|
+
- Configuration file integration (`config/hazo_pdf_config.ini`)
|
|
331
372
|
- Custom stamps with styling
|
|
332
373
|
- Timestamp and fixed text suffixes
|
|
333
374
|
- Responsive scaling based on screen size
|
|
@@ -340,7 +381,7 @@ function ProductionViewer() {
|
|
|
340
381
|
|
|
341
382
|
## Configuration File
|
|
342
383
|
|
|
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.
|
|
384
|
+
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
385
|
|
|
345
386
|
**Basic setup:**
|
|
346
387
|
|
|
@@ -368,7 +409,7 @@ toolbar_button_save_background_color = rgb(34, 197, 94)
|
|
|
368
409
|
right_click_custom_stamps = [{"name":"Verified","text":"✅","order":1,"time_stamp_suffix_enabled":true,"fixed_text_suffix_enabled":true}]
|
|
369
410
|
```
|
|
370
411
|
|
|
371
|
-
See `hazo_pdf_config.ini` in the project root for all available configuration options.
|
|
412
|
+
See `config/hazo_pdf_config.ini` in the project root for all available configuration options.
|
|
372
413
|
|
|
373
414
|
---
|
|
374
415
|
|
|
@@ -391,7 +432,7 @@ See `hazo_pdf_config.ini` in the project root for all available configuration op
|
|
|
391
432
|
| `className` | `string` | `""` | Additional CSS classes to apply to the viewer container. |
|
|
392
433
|
| `scale` | `number` | `1.0` | Initial zoom level. Values > 1.0 zoom in, < 1.0 zoom out. |
|
|
393
434
|
| `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. |
|
|
435
|
+
| `config_file` | `string` | `undefined` | Path to configuration INI file (e.g., `"config/hazo_pdf_config.ini"`). If not provided, uses default configuration. |
|
|
395
436
|
|
|
396
437
|
##### Event Callbacks
|
|
397
438
|
|
|
@@ -469,12 +510,50 @@ const stamps = JSON.stringify([
|
|
|
469
510
|
}
|
|
470
511
|
]);
|
|
471
512
|
|
|
472
|
-
<PdfViewer
|
|
513
|
+
<PdfViewer
|
|
473
514
|
url="/document.pdf"
|
|
474
515
|
right_click_custom_stamps={stamps}
|
|
475
516
|
/>
|
|
476
517
|
```
|
|
477
518
|
|
|
519
|
+
##### Toolbar Visibility
|
|
520
|
+
|
|
521
|
+
Props to control toolbar button visibility. These override config file values.
|
|
522
|
+
|
|
523
|
+
| Prop | Type | Default | Description |
|
|
524
|
+
|------|------|---------|-------------|
|
|
525
|
+
| `toolbar_enabled` | `boolean` | `true` | Master toggle to show/hide the entire toolbar. |
|
|
526
|
+
| `show_zoom_controls` | `boolean` | `true` | Show zoom in/out/reset buttons. |
|
|
527
|
+
| `show_square_button` | `boolean` | `true` | Show square annotation button. |
|
|
528
|
+
| `show_undo_button` | `boolean` | `true` | Show undo button. |
|
|
529
|
+
| `show_redo_button` | `boolean` | `true` | Show redo button. |
|
|
530
|
+
| `show_save_button` | `boolean` | `true` | Show save button. |
|
|
531
|
+
| `show_metadata_button` | `boolean` | `true` | Show metadata panel button (only visible when `sidepanel_metadata_enabled` is true). |
|
|
532
|
+
| `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. |
|
|
533
|
+
|
|
534
|
+
**Example - Minimal toolbar:**
|
|
535
|
+
|
|
536
|
+
```tsx
|
|
537
|
+
<PdfViewer
|
|
538
|
+
url="/document.pdf"
|
|
539
|
+
toolbar_enabled={true}
|
|
540
|
+
show_zoom_controls={true}
|
|
541
|
+
show_square_button={false}
|
|
542
|
+
show_undo_button={false}
|
|
543
|
+
show_redo_button={false}
|
|
544
|
+
show_save_button={false}
|
|
545
|
+
/>
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
**Example - Dialog with close button:**
|
|
549
|
+
|
|
550
|
+
```tsx
|
|
551
|
+
<PdfViewer
|
|
552
|
+
url="/document.pdf"
|
|
553
|
+
on_close={() => setDialogOpen(false)}
|
|
554
|
+
/>
|
|
555
|
+
```
|
|
556
|
+
|
|
478
557
|
### PdfAnnotation Interface
|
|
479
558
|
|
|
480
559
|
Represents a PDF annotation in the standard PDF coordinate space.
|
|
@@ -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
|
@@ -168,6 +168,8 @@ interface PdfViewerConfig {
|
|
|
168
168
|
toolbar_show_save_button: boolean;
|
|
169
169
|
/** Whether to show metadata panel button (true/false) */
|
|
170
170
|
toolbar_show_metadata_button: boolean;
|
|
171
|
+
/** Whether to show annotate (FreeText) button (true/false) */
|
|
172
|
+
toolbar_show_annotate_button: boolean;
|
|
171
173
|
/** Label for zoom out button (default: "−") */
|
|
172
174
|
toolbar_zoom_out_label: string;
|
|
173
175
|
/** Label for zoom in button (default: "+") */
|
|
@@ -220,7 +222,7 @@ interface PdfViewerProps {
|
|
|
220
222
|
on_save?: (pdf_bytes: Uint8Array, filename: string) => void;
|
|
221
223
|
/** Background color for areas outside PDF pages (default: dark grey) */
|
|
222
224
|
background_color?: string;
|
|
223
|
-
/** Optional path to configuration INI file (e.g., "hazo_pdf_config.ini") */
|
|
225
|
+
/** Optional path to configuration INI file (e.g., "config/hazo_pdf_config.ini") */
|
|
224
226
|
config_file?: string;
|
|
225
227
|
/** Whether to append timestamp to annotated text edits (default: false) */
|
|
226
228
|
append_timestamp_to_text_edits?: boolean;
|
|
@@ -241,6 +243,24 @@ interface PdfViewerProps {
|
|
|
241
243
|
updatedRow: MetadataDataItem;
|
|
242
244
|
allData: MetadataInput;
|
|
243
245
|
};
|
|
246
|
+
/** Whether to show the toolbar at all (default: true) */
|
|
247
|
+
toolbar_enabled?: boolean;
|
|
248
|
+
/** Whether to show zoom controls (default: true) */
|
|
249
|
+
show_zoom_controls?: boolean;
|
|
250
|
+
/** Whether to show square annotation button (default: true) */
|
|
251
|
+
show_square_button?: boolean;
|
|
252
|
+
/** Whether to show undo button (default: true) */
|
|
253
|
+
show_undo_button?: boolean;
|
|
254
|
+
/** Whether to show redo button (default: true) */
|
|
255
|
+
show_redo_button?: boolean;
|
|
256
|
+
/** Whether to show save button (default: true) */
|
|
257
|
+
show_save_button?: boolean;
|
|
258
|
+
/** Whether to show metadata panel button (default: true, only visible when sidepanel_metadata_enabled) */
|
|
259
|
+
show_metadata_button?: boolean;
|
|
260
|
+
/** Whether to show annotate (FreeText) button (default: true) */
|
|
261
|
+
show_annotate_button?: boolean;
|
|
262
|
+
/** Callback when close button is clicked (shows close button in toolbar when provided) */
|
|
263
|
+
on_close?: () => void;
|
|
244
264
|
}
|
|
245
265
|
/**
|
|
246
266
|
* PDF Annotation interface matching PDF standard
|
|
@@ -413,6 +433,7 @@ interface PdfViewerLayoutProps {
|
|
|
413
433
|
on_annotation_create: (annotation: PdfAnnotation) => void;
|
|
414
434
|
on_context_menu: (e: React.MouseEvent, page_index: number, screen_x: number, screen_y: number, mapper: CoordinateMapper) => void;
|
|
415
435
|
on_annotation_click: (annotation: PdfAnnotation, screen_x: number, screen_y: number, mapper: CoordinateMapper) => void;
|
|
436
|
+
on_freetext_click?: (page_index: number, screen_x: number, screen_y: number, mapper: CoordinateMapper) => void;
|
|
416
437
|
background_color?: string;
|
|
417
438
|
config: PdfViewerConfig | null;
|
|
418
439
|
className?: string;
|
|
@@ -479,6 +500,8 @@ interface AnnotationOverlayProps {
|
|
|
479
500
|
on_context_menu?: (event: React.MouseEvent, screen_x: number, screen_y: number) => void;
|
|
480
501
|
/** Callback when annotation is clicked */
|
|
481
502
|
on_annotation_click?: (annotation: PdfAnnotation, screen_x: number, screen_y: number) => void;
|
|
503
|
+
/** Callback when FreeText tool is active and user clicks on empty area */
|
|
504
|
+
on_freetext_click?: (screen_x: number, screen_y: number) => void;
|
|
482
505
|
/** Configuration object for styling */
|
|
483
506
|
config?: PdfViewerConfig | null;
|
|
484
507
|
/** Optional class name */
|
package/dist/index.js
CHANGED
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
download_pdf,
|
|
6
6
|
save_and_download_pdf,
|
|
7
7
|
save_annotations_to_pdf
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-S3AJUZ7D.js";
|
|
9
9
|
|
|
10
10
|
// src/components/pdf_viewer/pdf_viewer.tsx
|
|
11
11
|
import { useState as useState6, useEffect as useEffect6, useRef as useRef7, useCallback as useCallback2 } from "react";
|
|
12
|
-
import { Save, Undo2 as Undo22, Redo2, PanelRight } from "lucide-react";
|
|
12
|
+
import { Save, Undo2 as Undo22, Redo2, PanelRight, ZoomIn, ZoomOut, RotateCcw, Square, Type } from "lucide-react";
|
|
13
13
|
|
|
14
14
|
// src/components/pdf_viewer/pdf_worker_setup.ts
|
|
15
15
|
var worker_configured = false;
|
|
@@ -371,6 +371,7 @@ var AnnotationOverlay = ({
|
|
|
371
371
|
on_annotation_create,
|
|
372
372
|
on_context_menu,
|
|
373
373
|
on_annotation_click,
|
|
374
|
+
on_freetext_click,
|
|
374
375
|
config = null,
|
|
375
376
|
className = ""
|
|
376
377
|
}) => {
|
|
@@ -448,6 +449,14 @@ var AnnotationOverlay = ({
|
|
|
448
449
|
if (!current_tool) {
|
|
449
450
|
return;
|
|
450
451
|
}
|
|
452
|
+
if (current_tool === "FreeText") {
|
|
453
|
+
e.preventDefault();
|
|
454
|
+
e.stopPropagation();
|
|
455
|
+
if (on_freetext_click) {
|
|
456
|
+
on_freetext_click(point.x, point.y);
|
|
457
|
+
}
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
451
460
|
setIsDrawing(true);
|
|
452
461
|
setStartPoint(point);
|
|
453
462
|
setCurrentPoint(point);
|
|
@@ -857,6 +866,7 @@ var PdfViewerLayout = ({
|
|
|
857
866
|
on_annotation_create,
|
|
858
867
|
on_context_menu,
|
|
859
868
|
on_annotation_click,
|
|
869
|
+
on_freetext_click,
|
|
860
870
|
background_color = "#2d2d2d",
|
|
861
871
|
config = null,
|
|
862
872
|
className = ""
|
|
@@ -1071,6 +1081,11 @@ var PdfViewerLayout = ({
|
|
|
1071
1081
|
if (on_annotation_click && mapper_data.mapper) {
|
|
1072
1082
|
on_annotation_click(annotation, screen_x, screen_y, mapper_data.mapper);
|
|
1073
1083
|
}
|
|
1084
|
+
},
|
|
1085
|
+
on_freetext_click: (screen_x, screen_y) => {
|
|
1086
|
+
if (on_freetext_click && mapper_data.mapper) {
|
|
1087
|
+
on_freetext_click(index, screen_x, screen_y, mapper_data.mapper);
|
|
1088
|
+
}
|
|
1074
1089
|
}
|
|
1075
1090
|
}
|
|
1076
1091
|
)
|
|
@@ -1756,7 +1771,7 @@ function parse_ini_browser(ini_text) {
|
|
|
1756
1771
|
}
|
|
1757
1772
|
async function load_config_browser(config_file) {
|
|
1758
1773
|
try {
|
|
1759
|
-
const config_url = config_file === "hazo_pdf_config.ini" || config_file.includes("hazo_pdf_config.ini") ? "/api/config" : config_file;
|
|
1774
|
+
const config_url = config_file === "config/hazo_pdf_config.ini" || config_file.includes("config/hazo_pdf_config.ini") ? "/api/config" : config_file;
|
|
1760
1775
|
const response = await fetch(config_url);
|
|
1761
1776
|
if (!response.ok) {
|
|
1762
1777
|
throw new Error(`Failed to fetch config file: ${response.status} ${response.statusText}`);
|
|
@@ -2140,6 +2155,10 @@ function build_config_from_ini(get_value) {
|
|
|
2140
2155
|
get_value("toolbar", "toolbar_show_metadata_button"),
|
|
2141
2156
|
default_config.toolbar.toolbar_show_metadata_button
|
|
2142
2157
|
),
|
|
2158
|
+
toolbar_show_annotate_button: parse_boolean(
|
|
2159
|
+
get_value("toolbar", "toolbar_show_annotate_button"),
|
|
2160
|
+
default_config.toolbar.toolbar_show_annotate_button
|
|
2161
|
+
),
|
|
2143
2162
|
toolbar_zoom_out_label: parse_string(
|
|
2144
2163
|
get_value("toolbar", "toolbar_zoom_out_label"),
|
|
2145
2164
|
default_config.toolbar.toolbar_zoom_out_label
|
|
@@ -2271,7 +2290,17 @@ var PdfViewer = ({
|
|
|
2271
2290
|
right_click_custom_stamps,
|
|
2272
2291
|
sidepanel_metadata_enabled = false,
|
|
2273
2292
|
metadata_input,
|
|
2274
|
-
on_metadata_change
|
|
2293
|
+
on_metadata_change,
|
|
2294
|
+
// Toolbar visibility props (override config file values)
|
|
2295
|
+
toolbar_enabled,
|
|
2296
|
+
show_zoom_controls,
|
|
2297
|
+
show_square_button,
|
|
2298
|
+
show_undo_button,
|
|
2299
|
+
show_redo_button,
|
|
2300
|
+
show_save_button,
|
|
2301
|
+
show_metadata_button,
|
|
2302
|
+
show_annotate_button,
|
|
2303
|
+
on_close
|
|
2275
2304
|
}) => {
|
|
2276
2305
|
const [pdf_document, setPdfDocument] = useState6(null);
|
|
2277
2306
|
const [loading, setLoading] = useState6(true);
|
|
@@ -2711,7 +2740,7 @@ ${suffix_line}`;
|
|
|
2711
2740
|
const original_filename = url.split("/").pop() || "document.pdf";
|
|
2712
2741
|
const filename_without_ext = original_filename.replace(/\.pdf$/i, "");
|
|
2713
2742
|
const output_filename = `${filename_without_ext}_annotated.pdf`;
|
|
2714
|
-
const { save_annotations_to_pdf: save_annotations_to_pdf2, download_pdf: download_pdf2 } = await import("./pdf_saver-
|
|
2743
|
+
const { save_annotations_to_pdf: save_annotations_to_pdf2, download_pdf: download_pdf2 } = await import("./pdf_saver-P2MJN45S.js");
|
|
2715
2744
|
const pdf_bytes = await save_annotations_to_pdf2(url, annotations, output_filename, config_ref.current);
|
|
2716
2745
|
download_pdf2(pdf_bytes, output_filename);
|
|
2717
2746
|
if (on_save) {
|
|
@@ -2739,9 +2768,21 @@ ${suffix_line}`;
|
|
|
2739
2768
|
if (!pdf_document) {
|
|
2740
2769
|
return /* @__PURE__ */ jsx7("div", { className: cn("cls_pdf_viewer", className), children: /* @__PURE__ */ jsx7("div", { className: "cls_pdf_viewer_no_document", children: "No PDF document loaded" }) });
|
|
2741
2770
|
}
|
|
2742
|
-
const
|
|
2743
|
-
|
|
2744
|
-
|
|
2771
|
+
const base_toolbar_config = config_ref.current?.toolbar || default_config.toolbar;
|
|
2772
|
+
const toolbar_config = {
|
|
2773
|
+
...base_toolbar_config,
|
|
2774
|
+
// Props override config file values (undefined means use config value)
|
|
2775
|
+
toolbar_show_zoom_controls: show_zoom_controls ?? base_toolbar_config.toolbar_show_zoom_controls,
|
|
2776
|
+
toolbar_show_square_button: show_square_button ?? base_toolbar_config.toolbar_show_square_button,
|
|
2777
|
+
toolbar_show_undo_button: show_undo_button ?? base_toolbar_config.toolbar_show_undo_button,
|
|
2778
|
+
toolbar_show_redo_button: show_redo_button ?? base_toolbar_config.toolbar_show_redo_button,
|
|
2779
|
+
toolbar_show_save_button: show_save_button ?? base_toolbar_config.toolbar_show_save_button,
|
|
2780
|
+
toolbar_show_metadata_button: show_metadata_button ?? base_toolbar_config.toolbar_show_metadata_button,
|
|
2781
|
+
toolbar_show_annotate_button: show_annotate_button ?? base_toolbar_config.toolbar_show_annotate_button
|
|
2782
|
+
};
|
|
2783
|
+
const is_toolbar_enabled = toolbar_enabled ?? true;
|
|
2784
|
+
return /* @__PURE__ */ jsxs6("div", { className: cn("hazo-pdf-root cls_pdf_viewer", className), children: [
|
|
2785
|
+
is_toolbar_enabled && /* @__PURE__ */ jsxs6(
|
|
2745
2786
|
"div",
|
|
2746
2787
|
{
|
|
2747
2788
|
className: "cls_pdf_viewer_toolbar",
|
|
@@ -2761,6 +2802,7 @@ ${suffix_line}`;
|
|
|
2761
2802
|
onClick: handle_zoom_out,
|
|
2762
2803
|
className: "cls_pdf_viewer_toolbar_button",
|
|
2763
2804
|
"aria-label": "Zoom out",
|
|
2805
|
+
title: "Zoom out",
|
|
2764
2806
|
style: {
|
|
2765
2807
|
backgroundColor: toolbar_config.toolbar_button_background_color,
|
|
2766
2808
|
color: toolbar_config.toolbar_button_text_color
|
|
@@ -2771,7 +2813,7 @@ ${suffix_line}`;
|
|
|
2771
2813
|
onMouseLeave: (e) => {
|
|
2772
2814
|
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color;
|
|
2773
2815
|
},
|
|
2774
|
-
children:
|
|
2816
|
+
children: /* @__PURE__ */ jsx7(ZoomOut, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
2775
2817
|
}
|
|
2776
2818
|
),
|
|
2777
2819
|
/* @__PURE__ */ jsxs6("span", { className: "cls_pdf_viewer_zoom_level", children: [
|
|
@@ -2785,6 +2827,7 @@ ${suffix_line}`;
|
|
|
2785
2827
|
onClick: handle_zoom_in,
|
|
2786
2828
|
className: "cls_pdf_viewer_toolbar_button",
|
|
2787
2829
|
"aria-label": "Zoom in",
|
|
2830
|
+
title: "Zoom in",
|
|
2788
2831
|
style: {
|
|
2789
2832
|
backgroundColor: toolbar_config.toolbar_button_background_color,
|
|
2790
2833
|
color: toolbar_config.toolbar_button_text_color
|
|
@@ -2795,7 +2838,7 @@ ${suffix_line}`;
|
|
|
2795
2838
|
onMouseLeave: (e) => {
|
|
2796
2839
|
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color;
|
|
2797
2840
|
},
|
|
2798
|
-
children:
|
|
2841
|
+
children: /* @__PURE__ */ jsx7(ZoomIn, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
2799
2842
|
}
|
|
2800
2843
|
),
|
|
2801
2844
|
/* @__PURE__ */ jsx7(
|
|
@@ -2805,6 +2848,7 @@ ${suffix_line}`;
|
|
|
2805
2848
|
onClick: handle_zoom_reset,
|
|
2806
2849
|
className: "cls_pdf_viewer_toolbar_button",
|
|
2807
2850
|
"aria-label": "Reset zoom",
|
|
2851
|
+
title: "Reset zoom",
|
|
2808
2852
|
style: {
|
|
2809
2853
|
backgroundColor: toolbar_config.toolbar_button_background_color,
|
|
2810
2854
|
color: toolbar_config.toolbar_button_text_color
|
|
@@ -2815,7 +2859,7 @@ ${suffix_line}`;
|
|
|
2815
2859
|
onMouseLeave: (e) => {
|
|
2816
2860
|
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color;
|
|
2817
2861
|
},
|
|
2818
|
-
children:
|
|
2862
|
+
children: /* @__PURE__ */ jsx7(RotateCcw, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
2819
2863
|
}
|
|
2820
2864
|
)
|
|
2821
2865
|
] }),
|
|
@@ -2823,12 +2867,13 @@ ${suffix_line}`;
|
|
|
2823
2867
|
"button",
|
|
2824
2868
|
{
|
|
2825
2869
|
type: "button",
|
|
2826
|
-
onClick: () => setCurrentTool("Square"),
|
|
2870
|
+
onClick: () => setCurrentTool(current_tool === "Square" ? null : "Square"),
|
|
2827
2871
|
className: cn(
|
|
2828
2872
|
"cls_pdf_viewer_toolbar_button",
|
|
2829
2873
|
current_tool === "Square" && "cls_pdf_viewer_toolbar_button_active"
|
|
2830
2874
|
),
|
|
2831
2875
|
"aria-label": "Square annotation tool",
|
|
2876
|
+
title: "Square annotation",
|
|
2832
2877
|
style: {
|
|
2833
2878
|
backgroundColor: current_tool === "Square" ? toolbar_config.toolbar_button_active_background_color : toolbar_config.toolbar_button_background_color,
|
|
2834
2879
|
color: current_tool === "Square" ? toolbar_config.toolbar_button_active_text_color : toolbar_config.toolbar_button_text_color
|
|
@@ -2843,11 +2888,39 @@ ${suffix_line}`;
|
|
|
2843
2888
|
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color;
|
|
2844
2889
|
}
|
|
2845
2890
|
},
|
|
2846
|
-
children:
|
|
2891
|
+
children: /* @__PURE__ */ jsx7(Square, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
2892
|
+
}
|
|
2893
|
+
) }),
|
|
2894
|
+
toolbar_config.toolbar_show_annotate_button && /* @__PURE__ */ jsx7("div", { className: "cls_pdf_viewer_toolbar_group", children: /* @__PURE__ */ jsx7(
|
|
2895
|
+
"button",
|
|
2896
|
+
{
|
|
2897
|
+
type: "button",
|
|
2898
|
+
onClick: () => setCurrentTool(current_tool === "FreeText" ? null : "FreeText"),
|
|
2899
|
+
className: cn(
|
|
2900
|
+
"cls_pdf_viewer_toolbar_button",
|
|
2901
|
+
current_tool === "FreeText" && "cls_pdf_viewer_toolbar_button_active"
|
|
2902
|
+
),
|
|
2903
|
+
"aria-label": "Text annotation tool",
|
|
2904
|
+
title: "Text annotation",
|
|
2905
|
+
style: {
|
|
2906
|
+
backgroundColor: current_tool === "FreeText" ? toolbar_config.toolbar_button_active_background_color : toolbar_config.toolbar_button_background_color,
|
|
2907
|
+
color: current_tool === "FreeText" ? toolbar_config.toolbar_button_active_text_color : toolbar_config.toolbar_button_text_color
|
|
2908
|
+
},
|
|
2909
|
+
onMouseEnter: (e) => {
|
|
2910
|
+
if (current_tool !== "FreeText") {
|
|
2911
|
+
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color_hover;
|
|
2912
|
+
}
|
|
2913
|
+
},
|
|
2914
|
+
onMouseLeave: (e) => {
|
|
2915
|
+
if (current_tool !== "FreeText") {
|
|
2916
|
+
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color;
|
|
2917
|
+
}
|
|
2918
|
+
},
|
|
2919
|
+
children: /* @__PURE__ */ jsx7(Type, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
2847
2920
|
}
|
|
2848
2921
|
) }),
|
|
2849
2922
|
(toolbar_config.toolbar_show_undo_button || toolbar_config.toolbar_show_redo_button) && /* @__PURE__ */ jsxs6("div", { className: "cls_pdf_viewer_toolbar_group", children: [
|
|
2850
|
-
toolbar_config.toolbar_show_undo_button && /* @__PURE__ */
|
|
2923
|
+
toolbar_config.toolbar_show_undo_button && /* @__PURE__ */ jsx7(
|
|
2851
2924
|
"button",
|
|
2852
2925
|
{
|
|
2853
2926
|
type: "button",
|
|
@@ -2872,13 +2945,10 @@ ${suffix_line}`;
|
|
|
2872
2945
|
onMouseLeave: (e) => {
|
|
2873
2946
|
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color;
|
|
2874
2947
|
},
|
|
2875
|
-
children:
|
|
2876
|
-
/* @__PURE__ */ jsx7(Undo22, { className: "cls_pdf_viewer_toolbar_icon", size: 16 }),
|
|
2877
|
-
/* @__PURE__ */ jsx7("span", { className: "cls_pdf_viewer_toolbar_button_text", children: toolbar_config.toolbar_undo_label })
|
|
2878
|
-
]
|
|
2948
|
+
children: /* @__PURE__ */ jsx7(Undo22, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
2879
2949
|
}
|
|
2880
2950
|
),
|
|
2881
|
-
toolbar_config.toolbar_show_redo_button && /* @__PURE__ */
|
|
2951
|
+
toolbar_config.toolbar_show_redo_button && /* @__PURE__ */ jsx7(
|
|
2882
2952
|
"button",
|
|
2883
2953
|
{
|
|
2884
2954
|
type: "button",
|
|
@@ -2903,14 +2973,11 @@ ${suffix_line}`;
|
|
|
2903
2973
|
onMouseLeave: (e) => {
|
|
2904
2974
|
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color;
|
|
2905
2975
|
},
|
|
2906
|
-
children:
|
|
2907
|
-
/* @__PURE__ */ jsx7(Redo2, { className: "cls_pdf_viewer_toolbar_icon", size: 16 }),
|
|
2908
|
-
/* @__PURE__ */ jsx7("span", { className: "cls_pdf_viewer_toolbar_button_text", children: toolbar_config.toolbar_redo_label })
|
|
2909
|
-
]
|
|
2976
|
+
children: /* @__PURE__ */ jsx7(Redo2, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
2910
2977
|
}
|
|
2911
2978
|
)
|
|
2912
2979
|
] }),
|
|
2913
|
-
toolbar_config.toolbar_show_save_button && /* @__PURE__ */ jsx7("div", { className: "cls_pdf_viewer_toolbar_group", children: /* @__PURE__ */
|
|
2980
|
+
toolbar_config.toolbar_show_save_button && /* @__PURE__ */ jsx7("div", { className: "cls_pdf_viewer_toolbar_group", children: /* @__PURE__ */ jsx7(
|
|
2914
2981
|
"button",
|
|
2915
2982
|
{
|
|
2916
2983
|
type: "button",
|
|
@@ -2922,7 +2989,7 @@ ${suffix_line}`;
|
|
|
2922
2989
|
(saving || annotations.length === 0) && "cls_pdf_viewer_toolbar_button_disabled"
|
|
2923
2990
|
),
|
|
2924
2991
|
"aria-label": "Save annotations to PDF",
|
|
2925
|
-
title: annotations.length === 0 ? "No annotations to save" : "Save annotations to PDF",
|
|
2992
|
+
title: saving ? "Saving..." : annotations.length === 0 ? "No annotations to save" : "Save annotations to PDF",
|
|
2926
2993
|
style: {
|
|
2927
2994
|
backgroundColor: toolbar_config.toolbar_button_save_background_color,
|
|
2928
2995
|
color: toolbar_config.toolbar_button_save_text_color,
|
|
@@ -2936,13 +3003,10 @@ ${suffix_line}`;
|
|
|
2936
3003
|
onMouseLeave: (e) => {
|
|
2937
3004
|
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_save_background_color;
|
|
2938
3005
|
},
|
|
2939
|
-
children:
|
|
2940
|
-
/* @__PURE__ */ jsx7(Save, { className: "cls_pdf_viewer_toolbar_icon", size: 16 }),
|
|
2941
|
-
/* @__PURE__ */ jsx7("span", { className: "cls_pdf_viewer_toolbar_button_text", children: saving ? toolbar_config.toolbar_saving_label : toolbar_config.toolbar_save_label })
|
|
2942
|
-
]
|
|
3006
|
+
children: /* @__PURE__ */ jsx7(Save, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
2943
3007
|
}
|
|
2944
3008
|
) }),
|
|
2945
|
-
sidepanel_metadata_enabled && metadata_input && toolbar_config.toolbar_show_metadata_button && /* @__PURE__ */ jsx7("div", { className: "cls_pdf_viewer_toolbar_group", children: /* @__PURE__ */
|
|
3009
|
+
sidepanel_metadata_enabled && metadata_input && toolbar_config.toolbar_show_metadata_button && /* @__PURE__ */ jsx7("div", { className: "cls_pdf_viewer_toolbar_group", children: /* @__PURE__ */ jsx7(
|
|
2946
3010
|
"button",
|
|
2947
3011
|
{
|
|
2948
3012
|
type: "button",
|
|
@@ -2965,10 +3029,27 @@ ${suffix_line}`;
|
|
|
2965
3029
|
onMouseLeave: (e) => {
|
|
2966
3030
|
e.currentTarget.style.backgroundColor = sidepanel_open ? toolbar_config.toolbar_button_active_background_color : toolbar_config.toolbar_button_background_color;
|
|
2967
3031
|
},
|
|
2968
|
-
children:
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
3032
|
+
children: /* @__PURE__ */ jsx7(PanelRight, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
3033
|
+
}
|
|
3034
|
+
) }),
|
|
3035
|
+
on_close && /* @__PURE__ */ jsx7("div", { className: "cls_pdf_viewer_toolbar_group", children: /* @__PURE__ */ jsx7(
|
|
3036
|
+
"button",
|
|
3037
|
+
{
|
|
3038
|
+
type: "button",
|
|
3039
|
+
onClick: on_close,
|
|
3040
|
+
className: "cls_pdf_viewer_toolbar_button",
|
|
3041
|
+
"aria-label": "Close viewer",
|
|
3042
|
+
style: {
|
|
3043
|
+
backgroundColor: toolbar_config.toolbar_button_background_color,
|
|
3044
|
+
color: toolbar_config.toolbar_button_text_color
|
|
3045
|
+
},
|
|
3046
|
+
onMouseEnter: (e) => {
|
|
3047
|
+
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color_hover;
|
|
3048
|
+
},
|
|
3049
|
+
onMouseLeave: (e) => {
|
|
3050
|
+
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color;
|
|
3051
|
+
},
|
|
3052
|
+
children: "\u2715"
|
|
2972
3053
|
}
|
|
2973
3054
|
) })
|
|
2974
3055
|
]
|
|
@@ -3021,6 +3102,18 @@ ${suffix_line}`;
|
|
|
3021
3102
|
screen_y,
|
|
3022
3103
|
mapper
|
|
3023
3104
|
});
|
|
3105
|
+
},
|
|
3106
|
+
on_freetext_click: (page_index, screen_x, screen_y, mapper) => {
|
|
3107
|
+
setTextDialog({
|
|
3108
|
+
open: true,
|
|
3109
|
+
page_index,
|
|
3110
|
+
x: screen_x,
|
|
3111
|
+
y: screen_y,
|
|
3112
|
+
screen_x,
|
|
3113
|
+
screen_y,
|
|
3114
|
+
mapper
|
|
3115
|
+
});
|
|
3116
|
+
setCurrentTool(null);
|
|
3024
3117
|
}
|
|
3025
3118
|
}
|
|
3026
3119
|
)
|