hazo_pdf 1.6.1 → 1.6.4
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 +24 -0
- package/dist/{chunk-YEHKU7NV.js → chunk-EPV2C5AQ.js} +33 -25
- package/dist/chunk-EPV2C5AQ.js.map +1 -0
- package/dist/index.d.ts +8 -6
- package/dist/index.js +2 -2
- package/dist/{pdf_viewer-3J5HIOJT.js → pdf_viewer-7B7KJAXD.js} +2 -2
- package/dist/styles/full.css +2 -2
- package/dist/styles/full.css.map +1 -1
- package/dist/styles/index.css +2 -2
- package/dist/styles/index.css.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-YEHKU7NV.js.map +0 -1
- /package/dist/{pdf_viewer-3J5HIOJT.js.map → pdf_viewer-7B7KJAXD.js.map} +0 -0
package/README.md
CHANGED
|
@@ -879,6 +879,7 @@ You can override any or all of these on a per-highlight basis.
|
|
|
879
879
|
|------|------|---------|-------------|
|
|
880
880
|
| `className` | `string` | `""` | Additional CSS classes to apply to the viewer container. |
|
|
881
881
|
| `scale` | `number` | `1.0` | Initial zoom level. Values > 1.0 zoom in, < 1.0 zoom out. |
|
|
882
|
+
| `fit_to_width` | `boolean` | `false` | If `true`, automatically scales the PDF to fit the container width. Manual zoom buttons override auto-scaling. Container must have explicit dimensions. |
|
|
882
883
|
| `background_color` | `string` | `"#2d2d2d"` | Background color for areas outside PDF pages (hex format: `#RRGGBB`). Overrides config file value. |
|
|
883
884
|
| `config_file` | `string` | `undefined` | Path to configuration INI file (e.g., `"config/hazo_pdf_config.ini"`). If not provided, uses default configuration. |
|
|
884
885
|
| `logger` | `Logger` | `undefined` | Logger instance from hazo_logs or custom logger matching the Logger interface. If not provided, falls back to console-based logging. Useful for debugging and monitoring PDF operations. |
|
|
@@ -1033,6 +1034,7 @@ Props to control toolbar button visibility. These override config file values.
|
|
|
1033
1034
|
| `show_download_button` | `boolean` | `false` | Show Download button. Downloads the PDF with annotations baked in. |
|
|
1034
1035
|
| `show_extract_button` | `boolean` | `false` | Show Extract button for data extraction. Requires extraction props to be configured. |
|
|
1035
1036
|
| `download_filename` | `string` | `undefined` | Custom filename for the downloaded PDF. Defaults to the original filename or `"document.pdf"`. |
|
|
1037
|
+
| `display_filename` | `string` | `undefined` | Override the displayed filename in the file info sidepanel. Useful when `url` is an API endpoint that produces a non-human-readable path. |
|
|
1036
1038
|
| `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. |
|
|
1037
1039
|
|
|
1038
1040
|
**Example - Minimal toolbar:**
|
|
@@ -1318,6 +1320,28 @@ The PDF viewer includes a toolbar at the top with the following controls:
|
|
|
1318
1320
|
- Click "Reset" to return to default zoom
|
|
1319
1321
|
- Zoom affects the PDF page size but maintains aspect ratio
|
|
1320
1322
|
|
|
1323
|
+
### Fit-to-Width Mode
|
|
1324
|
+
|
|
1325
|
+
Enable automatic width-based scaling with the `fit_to_width` prop:
|
|
1326
|
+
|
|
1327
|
+
```tsx
|
|
1328
|
+
<PdfViewer
|
|
1329
|
+
url="/document.pdf"
|
|
1330
|
+
fit_to_width={true}
|
|
1331
|
+
/>
|
|
1332
|
+
```
|
|
1333
|
+
|
|
1334
|
+
**Behavior:**
|
|
1335
|
+
- When enabled, the PDF automatically scales to fit the container width on initial load and after window resize
|
|
1336
|
+
- User can manually zoom in/out with zoom buttons, which disables auto-scaling for that session
|
|
1337
|
+
- Changing the `fit_to_width` prop value re-enables auto-scaling behavior
|
|
1338
|
+
- Use case: Viewing documents where full-width display is preferred (e.g., forms, contracts)
|
|
1339
|
+
|
|
1340
|
+
**Technical Notes:**
|
|
1341
|
+
- Does not conflict with the `scale` prop (scale is the initial value, fit_to_width can override it after render)
|
|
1342
|
+
- Manual zoom buttons override fit-to-width mode, allowing users to adjust as needed
|
|
1343
|
+
- Container must have explicit width and height (see [Container Requirements](#container-requirements))
|
|
1344
|
+
|
|
1321
1345
|
### Annotation Tools
|
|
1322
1346
|
|
|
1323
1347
|
- **Square button**: Activates square/rectangle annotation tool
|
|
@@ -657,7 +657,7 @@ var AnnotationOverlay = ({
|
|
|
657
657
|
e.stopPropagation();
|
|
658
658
|
e.nativeEvent.stopImmediatePropagation();
|
|
659
659
|
log_annotation_click(annotation, "svg_hit_test", point);
|
|
660
|
-
on_annotation_click(annotation, point.x, point.y);
|
|
660
|
+
on_annotation_click(annotation, point.x, point.y, e.clientX, e.clientY);
|
|
661
661
|
return;
|
|
662
662
|
}
|
|
663
663
|
}
|
|
@@ -673,7 +673,7 @@ var AnnotationOverlay = ({
|
|
|
673
673
|
e.preventDefault();
|
|
674
674
|
e.stopPropagation();
|
|
675
675
|
if (on_freetext_click) {
|
|
676
|
-
on_freetext_click(point.x, point.y);
|
|
676
|
+
on_freetext_click(point.x, point.y, e.clientX, e.clientY);
|
|
677
677
|
}
|
|
678
678
|
return;
|
|
679
679
|
}
|
|
@@ -906,7 +906,7 @@ var AnnotationOverlay = ({
|
|
|
906
906
|
const click_x = e.clientX - rect.left;
|
|
907
907
|
const click_y = e.clientY - rect.top;
|
|
908
908
|
log_annotation_click(annotation, "freetext_rect", { x: click_x, y: click_y });
|
|
909
|
-
on_annotation_click(annotation, click_x, click_y);
|
|
909
|
+
on_annotation_click(annotation, click_x, click_y, e.clientX, e.clientY);
|
|
910
910
|
}
|
|
911
911
|
},
|
|
912
912
|
onClick: (e) => {
|
|
@@ -1020,7 +1020,7 @@ var AnnotationOverlay = ({
|
|
|
1020
1020
|
const click_x = e.clientX - rect.left;
|
|
1021
1021
|
const click_y = e.clientY - rect.top;
|
|
1022
1022
|
log_annotation_click(annotation, "rect_overlay", { x: click_x, y: click_y });
|
|
1023
|
-
on_annotation_click(annotation, click_x, click_y);
|
|
1023
|
+
on_annotation_click(annotation, click_x, click_y, e.clientX, e.clientY);
|
|
1024
1024
|
}
|
|
1025
1025
|
},
|
|
1026
1026
|
onClick: (e) => {
|
|
@@ -1349,14 +1349,14 @@ var PdfViewerLayout = ({
|
|
|
1349
1349
|
on_context_menu(e, index, screen_x, screen_y, mapper_data.mapper);
|
|
1350
1350
|
}
|
|
1351
1351
|
},
|
|
1352
|
-
on_annotation_click: (annotation, screen_x, screen_y) => {
|
|
1352
|
+
on_annotation_click: (annotation, screen_x, screen_y, viewport_x, viewport_y) => {
|
|
1353
1353
|
if (on_annotation_click && mapper_data.mapper) {
|
|
1354
|
-
on_annotation_click(annotation, screen_x, screen_y, mapper_data.mapper);
|
|
1354
|
+
on_annotation_click(annotation, screen_x, screen_y, mapper_data.mapper, viewport_x, viewport_y);
|
|
1355
1355
|
}
|
|
1356
1356
|
},
|
|
1357
|
-
on_freetext_click: (screen_x, screen_y) => {
|
|
1357
|
+
on_freetext_click: (screen_x, screen_y, viewport_x, viewport_y) => {
|
|
1358
1358
|
if (on_freetext_click && mapper_data.mapper) {
|
|
1359
|
-
on_freetext_click(index, screen_x, screen_y, mapper_data.mapper);
|
|
1359
|
+
on_freetext_click(index, screen_x, screen_y, mapper_data.mapper, viewport_x, viewport_y);
|
|
1360
1360
|
}
|
|
1361
1361
|
}
|
|
1362
1362
|
}
|
|
@@ -4543,6 +4543,7 @@ var PdfViewer = forwardRef(({
|
|
|
4543
4543
|
on_files_change,
|
|
4544
4544
|
// file_manager_display_mode is reserved for future use (dialog/standalone modes)
|
|
4545
4545
|
download_filename,
|
|
4546
|
+
display_filename,
|
|
4546
4547
|
on_download,
|
|
4547
4548
|
enable_popout = false,
|
|
4548
4549
|
popout_route = "/pdf-viewer",
|
|
@@ -4610,6 +4611,7 @@ var PdfViewer = forwardRef(({
|
|
|
4610
4611
|
}, []);
|
|
4611
4612
|
const content_container_ref = useRef11(null);
|
|
4612
4613
|
const [first_page_width, setFirstPageWidth] = useState13(null);
|
|
4614
|
+
const [fit_to_width_active, setFitToWidthActive] = useState13(fit_to_width);
|
|
4613
4615
|
useEffect10(() => {
|
|
4614
4616
|
if (files && files.length > 0) {
|
|
4615
4617
|
if (!current_file || !files.find((f) => f.id === current_file.id)) {
|
|
@@ -4993,7 +4995,10 @@ ${suffix_line}`;
|
|
|
4993
4995
|
});
|
|
4994
4996
|
}, [pdf_document]);
|
|
4995
4997
|
useEffect10(() => {
|
|
4996
|
-
|
|
4998
|
+
setFitToWidthActive(fit_to_width);
|
|
4999
|
+
}, [fit_to_width]);
|
|
5000
|
+
useEffect10(() => {
|
|
5001
|
+
if (!fit_to_width_active || !first_page_width || !content_container_ref.current) {
|
|
4997
5002
|
return;
|
|
4998
5003
|
}
|
|
4999
5004
|
const calculate_fit_scale = () => {
|
|
@@ -5002,9 +5007,7 @@ ${suffix_line}`;
|
|
|
5002
5007
|
const padding = 40;
|
|
5003
5008
|
const available_width = container_width - padding;
|
|
5004
5009
|
const new_scale = Math.max(0.1, Math.min(3, available_width / first_page_width));
|
|
5005
|
-
|
|
5006
|
-
setScale(new_scale);
|
|
5007
|
-
}
|
|
5010
|
+
setScale(new_scale);
|
|
5008
5011
|
};
|
|
5009
5012
|
calculate_fit_scale();
|
|
5010
5013
|
const resize_observer = new ResizeObserver(() => {
|
|
@@ -5014,7 +5017,7 @@ ${suffix_line}`;
|
|
|
5014
5017
|
return () => {
|
|
5015
5018
|
resize_observer.disconnect();
|
|
5016
5019
|
};
|
|
5017
|
-
}, [
|
|
5020
|
+
}, [fit_to_width_active, first_page_width]);
|
|
5018
5021
|
const save_to_history = (new_annotations) => {
|
|
5019
5022
|
if (history_ref.current.saving) {
|
|
5020
5023
|
return;
|
|
@@ -5160,13 +5163,19 @@ ${suffix_line}`;
|
|
|
5160
5163
|
};
|
|
5161
5164
|
}, [handle_undo, handle_redo]);
|
|
5162
5165
|
const handle_zoom_in = () => {
|
|
5166
|
+
setFitToWidthActive(false);
|
|
5163
5167
|
setScale((prev) => Math.min(prev + 0.25, 3));
|
|
5164
5168
|
};
|
|
5165
5169
|
const handle_zoom_out = () => {
|
|
5170
|
+
setFitToWidthActive(false);
|
|
5166
5171
|
setScale((prev) => Math.max(prev - 0.25, 0.5));
|
|
5167
5172
|
};
|
|
5168
5173
|
const handle_zoom_reset = () => {
|
|
5169
|
-
|
|
5174
|
+
if (fit_to_width) {
|
|
5175
|
+
setFitToWidthActive(true);
|
|
5176
|
+
} else {
|
|
5177
|
+
setScale(1);
|
|
5178
|
+
}
|
|
5170
5179
|
};
|
|
5171
5180
|
const normalize_rotation = (rotation) => {
|
|
5172
5181
|
let normalized = rotation % 360;
|
|
@@ -5447,7 +5456,7 @@ ${suffix_line}`;
|
|
|
5447
5456
|
setExtractError(null);
|
|
5448
5457
|
try {
|
|
5449
5458
|
const logger2 = get_logger();
|
|
5450
|
-
const current_filename = is_multi_file_mode ? current_file?.name : url ? url.split("/").pop() || "unknown" : "unknown";
|
|
5459
|
+
const current_filename = is_multi_file_mode ? current_file?.name : display_filename || (url ? url.split("/").pop() || "unknown" : "unknown");
|
|
5451
5460
|
logger2.info("[PdfViewer] Starting data extraction", { filename: current_filename });
|
|
5452
5461
|
const bytes = new Uint8Array(cached_pdf_data);
|
|
5453
5462
|
let binary = "";
|
|
@@ -6014,18 +6023,17 @@ ${suffix_line}`;
|
|
|
6014
6023
|
page_rotations,
|
|
6015
6024
|
on_visible_page_change: handle_visible_page_change,
|
|
6016
6025
|
on_annotation_create: handle_annotation_create,
|
|
6017
|
-
on_annotation_click: (annotation, screen_x, screen_y, mapper) => {
|
|
6026
|
+
on_annotation_click: (annotation, screen_x, screen_y, mapper, viewport_x, viewport_y) => {
|
|
6018
6027
|
console.log(
|
|
6019
6028
|
`\u{1F7E0} [AnnotationClick] opening editor id=${annotation.id}, page=${annotation.page_index}, screen=(${screen_x.toFixed(
|
|
6020
6029
|
1
|
|
6021
6030
|
)}, ${screen_y.toFixed(1)})`
|
|
6022
6031
|
);
|
|
6023
|
-
const
|
|
6024
|
-
const dialog_y = Math.max(50, screen_y);
|
|
6032
|
+
const dialog_y = Math.max(50, viewport_y);
|
|
6025
6033
|
setTextDialog({
|
|
6026
6034
|
open: true,
|
|
6027
6035
|
page_index: annotation.page_index,
|
|
6028
|
-
x:
|
|
6036
|
+
x: viewport_x,
|
|
6029
6037
|
y: dialog_y,
|
|
6030
6038
|
screen_x,
|
|
6031
6039
|
screen_y,
|
|
@@ -6046,12 +6054,12 @@ ${suffix_line}`;
|
|
|
6046
6054
|
mapper
|
|
6047
6055
|
});
|
|
6048
6056
|
},
|
|
6049
|
-
on_freetext_click: (page_index, screen_x, screen_y, mapper) => {
|
|
6057
|
+
on_freetext_click: (page_index, screen_x, screen_y, mapper, viewport_x, viewport_y) => {
|
|
6050
6058
|
setTextDialog({
|
|
6051
6059
|
open: true,
|
|
6052
6060
|
page_index,
|
|
6053
|
-
x:
|
|
6054
|
-
y:
|
|
6061
|
+
x: viewport_x,
|
|
6062
|
+
y: viewport_y,
|
|
6055
6063
|
screen_x,
|
|
6056
6064
|
screen_y,
|
|
6057
6065
|
mapper
|
|
@@ -6079,7 +6087,7 @@ ${suffix_line}`;
|
|
|
6079
6087
|
is_open: file_info_sidepanel_open,
|
|
6080
6088
|
on_toggle: handle_file_info_sidepanel_toggle,
|
|
6081
6089
|
item: (() => {
|
|
6082
|
-
const filename = current_file?.name || (url ? url.split("/").pop() || "" : "");
|
|
6090
|
+
const filename = current_file?.name || display_filename || (url ? url.split("/").pop() || "" : "");
|
|
6083
6091
|
const filepath = effective_url || "";
|
|
6084
6092
|
if (!filename) return null;
|
|
6085
6093
|
return {
|
|
@@ -6093,7 +6101,7 @@ ${suffix_line}`;
|
|
|
6093
6101
|
width: file_info_sidepanel_width,
|
|
6094
6102
|
on_width_change: handle_file_info_sidepanel_width_change,
|
|
6095
6103
|
file_metadata,
|
|
6096
|
-
current_filename: current_file?.name || (url ? url.split("/").pop() || "" : ""),
|
|
6104
|
+
current_filename: current_file?.name || display_filename || (url ? url.split("/").pop() || "" : ""),
|
|
6097
6105
|
doc_data,
|
|
6098
6106
|
highlight_fields_info
|
|
6099
6107
|
}
|
|
@@ -6307,4 +6315,4 @@ export {
|
|
|
6307
6315
|
PdfViewer,
|
|
6308
6316
|
pdf_viewer_default
|
|
6309
6317
|
};
|
|
6310
|
-
//# sourceMappingURL=chunk-
|
|
6318
|
+
//# sourceMappingURL=chunk-EPV2C5AQ.js.map
|