hazo_pdf 1.6.0 → 1.6.2
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 +38 -0
- package/dist/{chunk-ROKBDX4O.js → chunk-ETZ57VO7.js} +200 -44
- package/dist/chunk-ETZ57VO7.js.map +1 -0
- package/dist/{chunk-RQOQLZRS.js → chunk-GGEFUU2N.js} +2 -2
- package/dist/{chunk-CXHR3TT6.js → chunk-LTUXHTQF.js} +4 -2
- package/dist/chunk-LTUXHTQF.js.map +1 -0
- package/dist/index.d.ts +17 -1
- package/dist/index.js +4 -4
- package/dist/{pdf_saver-JXAIRQVL.js → pdf_saver-C2X4AZYR.js} +3 -3
- package/dist/{pdf_viewer-ZTWYOEX3.js → pdf_viewer-CS3WEARI.js} +3 -3
- package/dist/styles/full.css +6 -0
- package/dist/styles/full.css.map +1 -1
- package/dist/styles/index.css +6 -0
- package/dist/styles/index.css.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-CXHR3TT6.js.map +0 -1
- package/dist/chunk-ROKBDX4O.js.map +0 -1
- /package/dist/{chunk-RQOQLZRS.js.map → chunk-GGEFUU2N.js.map} +0 -0
- /package/dist/{pdf_saver-JXAIRQVL.js.map → pdf_saver-C2X4AZYR.js.map} +0 -0
- /package/dist/{pdf_viewer-ZTWYOEX3.js.map → pdf_viewer-CS3WEARI.js.map} +0 -0
package/README.md
CHANGED
|
@@ -890,6 +890,7 @@ You can override any or all of these on a per-highlight basis.
|
|
|
890
890
|
| `on_load` | `(pdf: PDFDocumentProxy) => void` | Called when PDF is successfully loaded. Receives the PDF document proxy with metadata (page count, etc.). |
|
|
891
891
|
| `on_error` | `(error: Error) => void` | Called when an error occurs (PDF load failure, rendering error, etc.). Receives the error object. |
|
|
892
892
|
| `on_save` | `(pdf_bytes: Uint8Array, filename: string) => void` | Called when user clicks the Save button. Receives the PDF bytes with annotations embedded and a suggested filename. You can create a Blob and trigger download, or upload to a server. |
|
|
893
|
+
| `on_download` | `(filename: string) => void` | Called after the Download button triggers a browser download. Receives the filename used. |
|
|
893
894
|
|
|
894
895
|
##### Annotation Management
|
|
895
896
|
|
|
@@ -999,6 +1000,7 @@ Props for managing multiple PDF files. Mutually exclusive with `url` prop.
|
|
|
999
1000
|
| `on_file_delete` | `(file_id: string) => void` | `undefined` | Callback when a file is deleted in multi-file mode. Receives file ID. |
|
|
1000
1001
|
| `on_upload` | `(file: File, converted_pdf?: Uint8Array) => Promise<UploadResult>` | `undefined` | Callback for file upload. Receives original file and optional converted PDF (for non-PDF files). Must return `{ success: boolean, file_id?: string, url?: string, error?: string }`. |
|
|
1001
1002
|
| `on_files_change` | `(files: FileItem[]) => void` | `undefined` | Callback when files array changes (file added, deleted, or reordered). |
|
|
1003
|
+
| `direct_upload` | `boolean` | `false` | When `true`, clicking "+ Add file" opens the native file picker directly (1-click). The button also accepts drag & drop. When `false` (default), clicking shows a dropzone modal first (2-click). Can also be set via `file_upload.direct_upload` in INI config. |
|
|
1002
1004
|
| `enable_popout` | `boolean` | `false` | Enable popout to new tab feature. Shows popout button in toolbar. |
|
|
1003
1005
|
| `popout_route` | `string` | `'/pdf-viewer'` | Route path for popout viewer. Used to construct new tab URL. |
|
|
1004
1006
|
| `on_popout` | `(context: PopoutContext) => void` | `undefined` | Custom popout handler. Overrides default sessionStorage behavior. Receives context with file info and annotations. |
|
|
@@ -1028,7 +1030,10 @@ Props to control toolbar button visibility. These override config file values.
|
|
|
1028
1030
|
| `show_metadata_button` | `boolean` | `true` | Show metadata panel button (only visible when `sidepanel_metadata_enabled` is true). |
|
|
1029
1031
|
| `show_annotate_button` | `boolean` | `true` | Show annotate (FreeText) button. |
|
|
1030
1032
|
| `show_file_info_button` | `boolean` | `true` | Show file info sidepanel button (only visible when `file_metadata` is provided). |
|
|
1033
|
+
| `show_download_button` | `boolean` | `false` | Show Download button. Downloads the PDF with annotations baked in. |
|
|
1031
1034
|
| `show_extract_button` | `boolean` | `false` | Show Extract button for data extraction. Requires extraction props to be configured. |
|
|
1035
|
+
| `download_filename` | `string` | `undefined` | Custom filename for the downloaded PDF. Defaults to the original filename or `"document.pdf"`. |
|
|
1036
|
+
| `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. |
|
|
1032
1037
|
| `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. |
|
|
1033
1038
|
|
|
1034
1039
|
**Example - Minimal toolbar:**
|
|
@@ -1838,6 +1843,39 @@ interface FileItem {
|
|
|
1838
1843
|
- Files can be uploaded as PDFs or non-PDF formats (images, Excel, text files)
|
|
1839
1844
|
- Non-PDF files are automatically converted to PDF before upload
|
|
1840
1845
|
|
|
1846
|
+
### Direct Upload Mode
|
|
1847
|
+
|
|
1848
|
+
By default, clicking "+ Add file" opens a dropzone modal where the user must click again to browse files (2-click flow). Set `direct_upload={true}` for a faster 1-click flow where clicking "+ Add file" immediately opens the native file picker. The button also doubles as a drag & drop target.
|
|
1849
|
+
|
|
1850
|
+
```tsx
|
|
1851
|
+
// 1-click upload: click "Add file" → file picker opens immediately
|
|
1852
|
+
<PdfViewer
|
|
1853
|
+
files={files}
|
|
1854
|
+
on_files_change={setFiles}
|
|
1855
|
+
on_upload={handle_upload}
|
|
1856
|
+
direct_upload={true}
|
|
1857
|
+
/>
|
|
1858
|
+
|
|
1859
|
+
// Also works with PdfViewerDialog
|
|
1860
|
+
<PdfViewerDialog
|
|
1861
|
+
open={is_open}
|
|
1862
|
+
on_open_change={set_is_open}
|
|
1863
|
+
files={files}
|
|
1864
|
+
on_files_change={setFiles}
|
|
1865
|
+
on_upload={handle_upload}
|
|
1866
|
+
direct_upload={true}
|
|
1867
|
+
/>
|
|
1868
|
+
```
|
|
1869
|
+
|
|
1870
|
+
This is recommended when embedding the viewer in workflows where users already know which file to upload (e.g., row-level file icons in data tables). The drag & drop capability is preserved — dragging files onto the "+ Add file" button shows a "Drop here" indicator.
|
|
1871
|
+
|
|
1872
|
+
Can also be set via INI config:
|
|
1873
|
+
|
|
1874
|
+
```ini
|
|
1875
|
+
[file_upload]
|
|
1876
|
+
direct_upload = true
|
|
1877
|
+
```
|
|
1878
|
+
|
|
1841
1879
|
---
|
|
1842
1880
|
|
|
1843
1881
|
## PDF Rotation
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
default_config
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LTUXHTQF.js";
|
|
5
5
|
import {
|
|
6
6
|
__require
|
|
7
7
|
} from "./chunk-AOSHQP7D.js";
|
|
8
8
|
|
|
9
9
|
// src/components/pdf_viewer/pdf_viewer.tsx
|
|
10
|
-
import { useState as useState13, useEffect as useEffect10, useRef as useRef11, useCallback as
|
|
11
|
-
import { Save, Undo2 as Undo22, Redo2, PanelRight, PanelRightOpen, ZoomIn, ZoomOut, RotateCcw, RotateCw, RefreshCw, Square, Type, ExternalLink, Info, Sparkles, X as X5 } from "lucide-react";
|
|
10
|
+
import { useState as useState13, useEffect as useEffect10, useRef as useRef11, useCallback as useCallback5, forwardRef, useImperativeHandle } from "react";
|
|
11
|
+
import { Save, Download, Undo2 as Undo22, Redo2, PanelRight, PanelRightOpen, ZoomIn, ZoomOut, RotateCcw, RotateCw, RefreshCw, Square, Type, ExternalLink, Info, Sparkles, X as X5 } from "lucide-react";
|
|
12
12
|
|
|
13
13
|
// src/components/pdf_viewer/toolbar_dropdown_button.tsx
|
|
14
14
|
import { useState, useRef, useEffect } from "react";
|
|
@@ -2651,6 +2651,10 @@ function build_config_from_ini(get_value) {
|
|
|
2651
2651
|
get_value("toolbar", "toolbar_show_extract_button"),
|
|
2652
2652
|
default_config.toolbar.toolbar_show_extract_button
|
|
2653
2653
|
),
|
|
2654
|
+
toolbar_show_download_button: parse_boolean(
|
|
2655
|
+
get_value("toolbar", "toolbar_show_download_button"),
|
|
2656
|
+
default_config.toolbar.toolbar_show_download_button
|
|
2657
|
+
),
|
|
2654
2658
|
toolbar_zoom_out_label: parse_string(
|
|
2655
2659
|
get_value("toolbar", "toolbar_zoom_out_label"),
|
|
2656
2660
|
default_config.toolbar.toolbar_zoom_out_label
|
|
@@ -2754,6 +2758,10 @@ function build_config_from_ini(get_value) {
|
|
|
2754
2758
|
dropzone_background_color: parse_color(
|
|
2755
2759
|
get_value("file_upload", "dropzone_background_color"),
|
|
2756
2760
|
default_config.file_upload.dropzone_background_color
|
|
2761
|
+
),
|
|
2762
|
+
direct_upload: parse_boolean(
|
|
2763
|
+
get_value("file_upload", "direct_upload"),
|
|
2764
|
+
default_config.file_upload.direct_upload
|
|
2757
2765
|
)
|
|
2758
2766
|
},
|
|
2759
2767
|
pdf_conversion: {
|
|
@@ -2966,10 +2974,10 @@ function get_logger() {
|
|
|
2966
2974
|
}
|
|
2967
2975
|
|
|
2968
2976
|
// src/components/file_manager/index.tsx
|
|
2969
|
-
import { useState as useState12, useCallback as
|
|
2977
|
+
import { useState as useState12, useCallback as useCallback4, useEffect as useEffect9 } from "react";
|
|
2970
2978
|
|
|
2971
2979
|
// src/components/file_manager/file_list.tsx
|
|
2972
|
-
import { useRef as useRef9, useState as useState9, useEffect as useEffect8 } from "react";
|
|
2980
|
+
import { useRef as useRef9, useState as useState9, useEffect as useEffect8, useCallback as useCallback2 } from "react";
|
|
2973
2981
|
import { ChevronLeft as ChevronLeft3, ChevronRight as ChevronRight3, Plus } from "lucide-react";
|
|
2974
2982
|
|
|
2975
2983
|
// src/components/file_manager/file_list_item.tsx
|
|
@@ -3056,7 +3064,7 @@ var FileListItem = ({
|
|
|
3056
3064
|
};
|
|
3057
3065
|
|
|
3058
3066
|
// src/components/file_manager/file_list.tsx
|
|
3059
|
-
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3067
|
+
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3060
3068
|
var FileList = ({
|
|
3061
3069
|
files,
|
|
3062
3070
|
selected_file_id,
|
|
@@ -3064,13 +3072,19 @@ var FileList = ({
|
|
|
3064
3072
|
on_select,
|
|
3065
3073
|
on_delete,
|
|
3066
3074
|
on_add_click,
|
|
3075
|
+
on_files_selected,
|
|
3067
3076
|
className
|
|
3068
3077
|
}) => {
|
|
3069
3078
|
const scroll_ref = useRef9(null);
|
|
3079
|
+
const file_input_ref = useRef9(null);
|
|
3080
|
+
const drag_counter = useRef9(0);
|
|
3070
3081
|
const [can_scroll_left, setCanScrollLeft] = useState9(false);
|
|
3071
3082
|
const [can_scroll_right, setCanScrollRight] = useState9(false);
|
|
3083
|
+
const [is_dragging, setIsDragging] = useState9(false);
|
|
3072
3084
|
const file_manager_config = config?.file_manager;
|
|
3073
3085
|
const upload_config = config?.file_upload;
|
|
3086
|
+
const is_direct_upload = !!on_files_selected;
|
|
3087
|
+
const accept_string = upload_config?.allowed_types || "application/pdf";
|
|
3074
3088
|
const update_scroll_state = () => {
|
|
3075
3089
|
if (!scroll_ref.current) return;
|
|
3076
3090
|
const { scrollLeft, scrollWidth, clientWidth } = scroll_ref.current;
|
|
@@ -3105,11 +3119,54 @@ var FileList = ({
|
|
|
3105
3119
|
});
|
|
3106
3120
|
}
|
|
3107
3121
|
}, [selected_file_id]);
|
|
3122
|
+
const handle_add_click = useCallback2(() => {
|
|
3123
|
+
if (is_direct_upload) {
|
|
3124
|
+
file_input_ref.current?.click();
|
|
3125
|
+
} else {
|
|
3126
|
+
on_add_click?.();
|
|
3127
|
+
}
|
|
3128
|
+
}, [is_direct_upload, on_add_click]);
|
|
3129
|
+
const handle_input_change = useCallback2((e) => {
|
|
3130
|
+
if (e.target.files && e.target.files.length > 0) {
|
|
3131
|
+
on_files_selected?.(Array.from(e.target.files));
|
|
3132
|
+
e.target.value = "";
|
|
3133
|
+
}
|
|
3134
|
+
}, [on_files_selected]);
|
|
3135
|
+
const handle_drag_enter = useCallback2((e) => {
|
|
3136
|
+
e.preventDefault();
|
|
3137
|
+
e.stopPropagation();
|
|
3138
|
+
drag_counter.current++;
|
|
3139
|
+
if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
|
|
3140
|
+
setIsDragging(true);
|
|
3141
|
+
}
|
|
3142
|
+
}, []);
|
|
3143
|
+
const handle_drag_leave = useCallback2((e) => {
|
|
3144
|
+
e.preventDefault();
|
|
3145
|
+
e.stopPropagation();
|
|
3146
|
+
drag_counter.current--;
|
|
3147
|
+
if (drag_counter.current === 0) {
|
|
3148
|
+
setIsDragging(false);
|
|
3149
|
+
}
|
|
3150
|
+
}, []);
|
|
3151
|
+
const handle_drag_over = useCallback2((e) => {
|
|
3152
|
+
e.preventDefault();
|
|
3153
|
+
e.stopPropagation();
|
|
3154
|
+
}, []);
|
|
3155
|
+
const handle_drop = useCallback2((e) => {
|
|
3156
|
+
e.preventDefault();
|
|
3157
|
+
e.stopPropagation();
|
|
3158
|
+
setIsDragging(false);
|
|
3159
|
+
drag_counter.current = 0;
|
|
3160
|
+
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
3161
|
+
on_files_selected?.(Array.from(e.dataTransfer.files));
|
|
3162
|
+
}
|
|
3163
|
+
}, [on_files_selected]);
|
|
3108
3164
|
const height = file_manager_config?.file_list_height || 60;
|
|
3109
3165
|
const background_color = file_manager_config?.file_list_background_color || "#f3f4f6";
|
|
3110
3166
|
const border_color = file_manager_config?.file_list_border_color || "#e5e7eb";
|
|
3111
3167
|
const allow_delete = file_manager_config?.allow_delete ?? true;
|
|
3112
3168
|
const show_add_button = upload_config?.show_add_button ?? true;
|
|
3169
|
+
const has_add_handler = is_direct_upload || !!on_add_click;
|
|
3113
3170
|
return /* @__PURE__ */ jsxs9(
|
|
3114
3171
|
"div",
|
|
3115
3172
|
{
|
|
@@ -3153,19 +3210,41 @@ var FileList = ({
|
|
|
3153
3210
|
},
|
|
3154
3211
|
file.id
|
|
3155
3212
|
)),
|
|
3156
|
-
show_add_button &&
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3213
|
+
show_add_button && has_add_handler && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
3214
|
+
/* @__PURE__ */ jsxs9(
|
|
3215
|
+
"button",
|
|
3216
|
+
{
|
|
3217
|
+
className: cn(
|
|
3218
|
+
"cls_file_list_add_btn",
|
|
3219
|
+
is_dragging && "cls_file_list_add_btn_dragging"
|
|
3220
|
+
),
|
|
3221
|
+
onClick: handle_add_click,
|
|
3222
|
+
onDragEnter: is_direct_upload ? handle_drag_enter : void 0,
|
|
3223
|
+
onDragLeave: is_direct_upload ? handle_drag_leave : void 0,
|
|
3224
|
+
onDragOver: is_direct_upload ? handle_drag_over : void 0,
|
|
3225
|
+
onDrop: is_direct_upload ? handle_drop : void 0,
|
|
3226
|
+
"aria-label": "Add file",
|
|
3227
|
+
title: is_direct_upload ? "Click to browse or drag files here" : "Add file",
|
|
3228
|
+
children: [
|
|
3229
|
+
/* @__PURE__ */ jsx10(Plus, { size: 16 }),
|
|
3230
|
+
/* @__PURE__ */ jsx10("span", { className: "cls_file_list_add_btn_text", children: is_dragging ? "Drop here" : "Add file" })
|
|
3231
|
+
]
|
|
3232
|
+
}
|
|
3233
|
+
),
|
|
3234
|
+
is_direct_upload && /* @__PURE__ */ jsx10(
|
|
3235
|
+
"input",
|
|
3236
|
+
{
|
|
3237
|
+
ref: file_input_ref,
|
|
3238
|
+
type: "file",
|
|
3239
|
+
accept: accept_string,
|
|
3240
|
+
multiple: true,
|
|
3241
|
+
onChange: handle_input_change,
|
|
3242
|
+
style: { display: "none" },
|
|
3243
|
+
"aria-hidden": "true",
|
|
3244
|
+
tabIndex: -1
|
|
3245
|
+
}
|
|
3246
|
+
)
|
|
3247
|
+
] })
|
|
3169
3248
|
]
|
|
3170
3249
|
}
|
|
3171
3250
|
),
|
|
@@ -3189,7 +3268,7 @@ var FileList = ({
|
|
|
3189
3268
|
};
|
|
3190
3269
|
|
|
3191
3270
|
// src/components/file_manager/upload_dropzone.tsx
|
|
3192
|
-
import { useState as useState10, useRef as useRef10, useCallback as
|
|
3271
|
+
import { useState as useState10, useRef as useRef10, useCallback as useCallback3 } from "react";
|
|
3193
3272
|
import { Upload, X as X4 } from "lucide-react";
|
|
3194
3273
|
|
|
3195
3274
|
// src/components/file_manager/upload_progress.tsx
|
|
@@ -3279,7 +3358,7 @@ var UploadDropzone = ({
|
|
|
3279
3358
|
const allowed_types = (upload_config?.allowed_types || "application/pdf").split(",").map((t) => t.trim());
|
|
3280
3359
|
const max_file_size = upload_config?.max_file_size || 10485760;
|
|
3281
3360
|
const max_files = upload_config?.max_files || 10;
|
|
3282
|
-
const validate_file =
|
|
3361
|
+
const validate_file = useCallback3((file) => {
|
|
3283
3362
|
const is_type_allowed = allowed_types.some((type) => {
|
|
3284
3363
|
const trimmed = type.trim().toLowerCase();
|
|
3285
3364
|
const file_type = file.type.toLowerCase();
|
|
@@ -3299,7 +3378,7 @@ var UploadDropzone = ({
|
|
|
3299
3378
|
}
|
|
3300
3379
|
return null;
|
|
3301
3380
|
}, [allowed_types, max_file_size]);
|
|
3302
|
-
const handle_files =
|
|
3381
|
+
const handle_files = useCallback3((file_list) => {
|
|
3303
3382
|
const files = Array.from(file_list);
|
|
3304
3383
|
setValidationError(null);
|
|
3305
3384
|
if (files.length === 0) {
|
|
@@ -4169,11 +4248,11 @@ var FileManager = ({
|
|
|
4169
4248
|
setInternalSelectedId(external_selected_id);
|
|
4170
4249
|
}
|
|
4171
4250
|
}, [external_selected_id]);
|
|
4172
|
-
const handle_file_select =
|
|
4251
|
+
const handle_file_select = useCallback4((file) => {
|
|
4173
4252
|
setInternalSelectedId(file.id);
|
|
4174
4253
|
on_file_select?.(file);
|
|
4175
4254
|
}, [on_file_select]);
|
|
4176
|
-
const handle_file_delete =
|
|
4255
|
+
const handle_file_delete = useCallback4((file_id) => {
|
|
4177
4256
|
const new_files = files.filter((f) => f.id !== file_id);
|
|
4178
4257
|
setInternalFiles(new_files);
|
|
4179
4258
|
setTimeout(() => on_files_change?.(new_files), 0);
|
|
@@ -4184,7 +4263,7 @@ var FileManager = ({
|
|
|
4184
4263
|
setInternalSelectedId(null);
|
|
4185
4264
|
}
|
|
4186
4265
|
}, [files, selected_file_id, on_files_change, on_file_delete, handle_file_select]);
|
|
4187
|
-
const handle_files_selected =
|
|
4266
|
+
const handle_files_selected = useCallback4(async (selected_files) => {
|
|
4188
4267
|
const conversion_config = config?.pdf_conversion;
|
|
4189
4268
|
for (const file of selected_files) {
|
|
4190
4269
|
const file_id = generate_file_id();
|
|
@@ -4316,6 +4395,7 @@ var FileManager = ({
|
|
|
4316
4395
|
}, [config, on_upload, on_files_change, handle_file_select]);
|
|
4317
4396
|
const file_manager_config = config?.file_manager;
|
|
4318
4397
|
const upload_config = config?.file_upload;
|
|
4398
|
+
const is_direct_upload = upload_config?.direct_upload ?? false;
|
|
4319
4399
|
if (show_button_only) {
|
|
4320
4400
|
return /* @__PURE__ */ jsx14(
|
|
4321
4401
|
FileManagerButton,
|
|
@@ -4336,10 +4416,11 @@ var FileManager = ({
|
|
|
4336
4416
|
config,
|
|
4337
4417
|
on_select: handle_file_select,
|
|
4338
4418
|
on_delete: file_manager_config?.allow_delete !== false ? handle_file_delete : void 0,
|
|
4339
|
-
on_add_click: upload_config?.upload_enabled !== false ? () => setShowDropzone(true) : void 0
|
|
4419
|
+
on_add_click: upload_config?.upload_enabled !== false && !is_direct_upload ? () => setShowDropzone(true) : void 0,
|
|
4420
|
+
on_files_selected: upload_config?.upload_enabled !== false && is_direct_upload ? handle_files_selected : void 0
|
|
4340
4421
|
}
|
|
4341
4422
|
),
|
|
4342
|
-
show_dropzone && /* @__PURE__ */ jsx14("div", { className: "cls_file_manager_dropzone_overlay", children: /* @__PURE__ */ jsx14("div", { className: "cls_file_manager_dropzone_dialog", children: /* @__PURE__ */ jsx14(
|
|
4423
|
+
show_dropzone && !is_direct_upload && /* @__PURE__ */ jsx14("div", { className: "cls_file_manager_dropzone_overlay", children: /* @__PURE__ */ jsx14("div", { className: "cls_file_manager_dropzone_dialog", children: /* @__PURE__ */ jsx14(
|
|
4343
4424
|
UploadDropzone,
|
|
4344
4425
|
{
|
|
4345
4426
|
config,
|
|
@@ -4411,7 +4492,7 @@ async function save_pdf_data(pdf_bytes, remote_path, file_manager, overwrite = t
|
|
|
4411
4492
|
}
|
|
4412
4493
|
|
|
4413
4494
|
// src/components/pdf_viewer/pdf_viewer.tsx
|
|
4414
|
-
import { Fragment as
|
|
4495
|
+
import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4415
4496
|
var POPOUT_STORAGE_KEY = "hazo_pdf_popout";
|
|
4416
4497
|
var PdfViewer = forwardRef(({
|
|
4417
4498
|
url,
|
|
@@ -4441,6 +4522,7 @@ var PdfViewer = forwardRef(({
|
|
|
4441
4522
|
show_undo_button,
|
|
4442
4523
|
show_redo_button,
|
|
4443
4524
|
show_save_button,
|
|
4525
|
+
show_download_button,
|
|
4444
4526
|
show_metadata_button,
|
|
4445
4527
|
show_annotate_button,
|
|
4446
4528
|
show_file_info_button,
|
|
@@ -4460,6 +4542,9 @@ var PdfViewer = forwardRef(({
|
|
|
4460
4542
|
on_upload,
|
|
4461
4543
|
on_files_change,
|
|
4462
4544
|
// file_manager_display_mode is reserved for future use (dialog/standalone modes)
|
|
4545
|
+
download_filename,
|
|
4546
|
+
display_filename,
|
|
4547
|
+
on_download,
|
|
4463
4548
|
enable_popout = false,
|
|
4464
4549
|
popout_route = "/pdf-viewer",
|
|
4465
4550
|
on_popout,
|
|
@@ -4468,6 +4553,8 @@ var PdfViewer = forwardRef(({
|
|
|
4468
4553
|
// hazo_files integration props
|
|
4469
4554
|
file_manager,
|
|
4470
4555
|
save_path,
|
|
4556
|
+
// Upload behavior
|
|
4557
|
+
direct_upload,
|
|
4471
4558
|
// File info sidepanel data props
|
|
4472
4559
|
doc_data,
|
|
4473
4560
|
highlight_fields_info,
|
|
@@ -4484,6 +4571,7 @@ var PdfViewer = forwardRef(({
|
|
|
4484
4571
|
const [annotations, setAnnotations] = useState13(initial_annotations);
|
|
4485
4572
|
const [current_tool, setCurrentTool] = useState13(null);
|
|
4486
4573
|
const [saving, setSaving] = useState13(false);
|
|
4574
|
+
const [downloading, setDownloading] = useState13(false);
|
|
4487
4575
|
const [extracting, setExtracting] = useState13(false);
|
|
4488
4576
|
const [extract_error, setExtractError] = useState13(null);
|
|
4489
4577
|
const [sidepanel_open, setSidepanelOpen] = useState13(false);
|
|
@@ -4494,6 +4582,7 @@ var PdfViewer = forwardRef(({
|
|
|
4494
4582
|
const [auto_highlight_ids, setAutoHighlightIds] = useState13(/* @__PURE__ */ new Set());
|
|
4495
4583
|
const [page_rotations, setPageRotations] = useState13(/* @__PURE__ */ new Map());
|
|
4496
4584
|
const [current_visible_page, setCurrentVisiblePage] = useState13(0);
|
|
4585
|
+
const [, setConfigVersion] = useState13(0);
|
|
4497
4586
|
const [current_file, setCurrentFile] = useState13(
|
|
4498
4587
|
files && files.length > 0 ? files[0] : null
|
|
4499
4588
|
);
|
|
@@ -4531,11 +4620,11 @@ var PdfViewer = forwardRef(({
|
|
|
4531
4620
|
setCurrentFile(null);
|
|
4532
4621
|
}
|
|
4533
4622
|
}, [files]);
|
|
4534
|
-
const handle_file_select =
|
|
4623
|
+
const handle_file_select = useCallback5((file) => {
|
|
4535
4624
|
setCurrentFile(file);
|
|
4536
4625
|
on_file_select?.(file);
|
|
4537
4626
|
}, [on_file_select]);
|
|
4538
|
-
const config_ref = useRef11(
|
|
4627
|
+
const config_ref = useRef11(load_pdf_config());
|
|
4539
4628
|
useEffect10(() => {
|
|
4540
4629
|
if (!config_file) {
|
|
4541
4630
|
config_ref.current = load_pdf_config();
|
|
@@ -4545,6 +4634,7 @@ var PdfViewer = forwardRef(({
|
|
|
4545
4634
|
if (is_browser) {
|
|
4546
4635
|
load_pdf_config_async(config_file).then((config) => {
|
|
4547
4636
|
config_ref.current = config;
|
|
4637
|
+
setConfigVersion((v) => v + 1);
|
|
4548
4638
|
console.log("[PdfViewer] Config loaded:", {
|
|
4549
4639
|
append_timestamp_to_text_edits: config.viewer.append_timestamp_to_text_edits,
|
|
4550
4640
|
config_object: config
|
|
@@ -4552,6 +4642,7 @@ var PdfViewer = forwardRef(({
|
|
|
4552
4642
|
}).catch((error2) => {
|
|
4553
4643
|
console.warn(`[PdfViewer] Could not load config file "${config_file}", using defaults:`, error2);
|
|
4554
4644
|
config_ref.current = load_pdf_config();
|
|
4645
|
+
setConfigVersion((v) => v + 1);
|
|
4555
4646
|
});
|
|
4556
4647
|
} else {
|
|
4557
4648
|
config_ref.current = load_pdf_config(config_file);
|
|
@@ -4560,6 +4651,15 @@ var PdfViewer = forwardRef(({
|
|
|
4560
4651
|
});
|
|
4561
4652
|
}
|
|
4562
4653
|
}, [config_file]);
|
|
4654
|
+
if (direct_upload !== void 0 && config_ref.current) {
|
|
4655
|
+
config_ref.current = {
|
|
4656
|
+
...config_ref.current,
|
|
4657
|
+
file_upload: {
|
|
4658
|
+
...config_ref.current.file_upload,
|
|
4659
|
+
direct_upload
|
|
4660
|
+
}
|
|
4661
|
+
};
|
|
4662
|
+
}
|
|
4563
4663
|
const effective_background_color = background_color || config_ref.current?.viewer.viewer_background_color || "#2d2d2d";
|
|
4564
4664
|
const format_annotation_timestamp = () => {
|
|
4565
4665
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -5016,7 +5116,7 @@ ${suffix_line}`;
|
|
|
5016
5116
|
}
|
|
5017
5117
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5018
5118
|
}), [annotations, handle_annotation_create, handle_annotation_delete]);
|
|
5019
|
-
const handle_undo =
|
|
5119
|
+
const handle_undo = useCallback5(() => {
|
|
5020
5120
|
if (history_index > 0) {
|
|
5021
5121
|
history_ref.current.saving = true;
|
|
5022
5122
|
const previous_index = history_index - 1;
|
|
@@ -5028,7 +5128,7 @@ ${suffix_line}`;
|
|
|
5028
5128
|
}, 0);
|
|
5029
5129
|
}
|
|
5030
5130
|
}, [history_index, history]);
|
|
5031
|
-
const handle_redo =
|
|
5131
|
+
const handle_redo = useCallback5(() => {
|
|
5032
5132
|
if (history_index < history.length - 1) {
|
|
5033
5133
|
history_ref.current.saving = true;
|
|
5034
5134
|
const next_index = history_index + 1;
|
|
@@ -5074,7 +5174,7 @@ ${suffix_line}`;
|
|
|
5074
5174
|
if (normalized < 0) normalized += 360;
|
|
5075
5175
|
return normalized;
|
|
5076
5176
|
};
|
|
5077
|
-
const handle_rotate_left =
|
|
5177
|
+
const handle_rotate_left = useCallback5(() => {
|
|
5078
5178
|
setPageRotations((prev) => {
|
|
5079
5179
|
const new_map = new Map(prev);
|
|
5080
5180
|
const current_rotation = new_map.get(current_visible_page) || 0;
|
|
@@ -5082,7 +5182,7 @@ ${suffix_line}`;
|
|
|
5082
5182
|
return new_map;
|
|
5083
5183
|
});
|
|
5084
5184
|
}, [current_visible_page]);
|
|
5085
|
-
const handle_rotate_right =
|
|
5185
|
+
const handle_rotate_right = useCallback5(() => {
|
|
5086
5186
|
setPageRotations((prev) => {
|
|
5087
5187
|
const new_map = new Map(prev);
|
|
5088
5188
|
const current_rotation = new_map.get(current_visible_page) || 0;
|
|
@@ -5090,7 +5190,7 @@ ${suffix_line}`;
|
|
|
5090
5190
|
return new_map;
|
|
5091
5191
|
});
|
|
5092
5192
|
}, [current_visible_page]);
|
|
5093
|
-
const handle_rotate_all_left =
|
|
5193
|
+
const handle_rotate_all_left = useCallback5(() => {
|
|
5094
5194
|
if (!pdf_document) return;
|
|
5095
5195
|
setPageRotations((prev) => {
|
|
5096
5196
|
const new_map = new Map(prev);
|
|
@@ -5101,7 +5201,7 @@ ${suffix_line}`;
|
|
|
5101
5201
|
return new_map;
|
|
5102
5202
|
});
|
|
5103
5203
|
}, [pdf_document]);
|
|
5104
|
-
const handle_rotate_all_right =
|
|
5204
|
+
const handle_rotate_all_right = useCallback5(() => {
|
|
5105
5205
|
if (!pdf_document) return;
|
|
5106
5206
|
setPageRotations((prev) => {
|
|
5107
5207
|
const new_map = new Map(prev);
|
|
@@ -5112,7 +5212,7 @@ ${suffix_line}`;
|
|
|
5112
5212
|
return new_map;
|
|
5113
5213
|
});
|
|
5114
5214
|
}, [pdf_document]);
|
|
5115
|
-
const handle_visible_page_change =
|
|
5215
|
+
const handle_visible_page_change = useCallback5((page_index) => {
|
|
5116
5216
|
setCurrentVisiblePage(page_index);
|
|
5117
5217
|
}, []);
|
|
5118
5218
|
const handle_sidepanel_toggle = () => {
|
|
@@ -5133,7 +5233,7 @@ ${suffix_line}`;
|
|
|
5133
5233
|
}
|
|
5134
5234
|
return { updatedRow, allData };
|
|
5135
5235
|
};
|
|
5136
|
-
const handle_popout =
|
|
5236
|
+
const handle_popout = useCallback5(() => {
|
|
5137
5237
|
if (!files || files.length === 0) {
|
|
5138
5238
|
console.warn("PdfViewer: No files to popout");
|
|
5139
5239
|
return;
|
|
@@ -5272,7 +5372,7 @@ ${suffix_line}`;
|
|
|
5272
5372
|
const original_filename = is_multi_file_mode && current_file ? current_file.name : effective_url.split("/").pop() || "document.pdf";
|
|
5273
5373
|
const filename_without_ext = original_filename.replace(/\.pdf$/i, "");
|
|
5274
5374
|
const output_filename = `${filename_without_ext}_annotated.pdf`;
|
|
5275
|
-
const { save_annotations_to_pdf, download_pdf } = await import("./pdf_saver-
|
|
5375
|
+
const { save_annotations_to_pdf, download_pdf } = await import("./pdf_saver-C2X4AZYR.js");
|
|
5276
5376
|
const pdf_source = cached_pdf_data || effective_url;
|
|
5277
5377
|
logger2.debug("[PdfViewer] Saving PDF", { source_type: cached_pdf_data ? "cached ArrayBuffer" : "URL" });
|
|
5278
5378
|
const pdf_bytes = await save_annotations_to_pdf(pdf_source, annotations, output_filename, config_ref.current, page_rotations);
|
|
@@ -5299,6 +5399,32 @@ ${suffix_line}`;
|
|
|
5299
5399
|
setSaving(false);
|
|
5300
5400
|
}
|
|
5301
5401
|
};
|
|
5402
|
+
const handle_download = async () => {
|
|
5403
|
+
if (!effective_url && !cached_pdf_data) {
|
|
5404
|
+
console.error("PdfViewer: No PDF available for download");
|
|
5405
|
+
return;
|
|
5406
|
+
}
|
|
5407
|
+
setDownloading(true);
|
|
5408
|
+
try {
|
|
5409
|
+
const logger2 = get_logger();
|
|
5410
|
+
const { save_annotations_to_pdf, download_pdf } = await import("./pdf_saver-C2X4AZYR.js");
|
|
5411
|
+
const original_filename = is_multi_file_mode && current_file ? current_file.name : effective_url?.split("/").pop() || "document.pdf";
|
|
5412
|
+
const output_filename = download_filename || original_filename;
|
|
5413
|
+
const pdf_source = cached_pdf_data || effective_url;
|
|
5414
|
+
logger2.debug("[PdfViewer] Downloading PDF", { filename: output_filename });
|
|
5415
|
+
const pdf_bytes = await save_annotations_to_pdf(pdf_source, annotations, output_filename, config_ref.current, page_rotations);
|
|
5416
|
+
download_pdf(pdf_bytes, output_filename);
|
|
5417
|
+
on_download?.(output_filename);
|
|
5418
|
+
} catch (error2) {
|
|
5419
|
+
console.error("PdfViewer: Error downloading PDF:", error2);
|
|
5420
|
+
const error_obj = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
5421
|
+
if (on_error) {
|
|
5422
|
+
on_error(error_obj);
|
|
5423
|
+
}
|
|
5424
|
+
} finally {
|
|
5425
|
+
setDownloading(false);
|
|
5426
|
+
}
|
|
5427
|
+
};
|
|
5302
5428
|
const handle_extract = async () => {
|
|
5303
5429
|
if (!extract_api_endpoint) {
|
|
5304
5430
|
console.warn("PdfViewer: No extract_api_endpoint configured");
|
|
@@ -5322,7 +5448,7 @@ ${suffix_line}`;
|
|
|
5322
5448
|
setExtractError(null);
|
|
5323
5449
|
try {
|
|
5324
5450
|
const logger2 = get_logger();
|
|
5325
|
-
const current_filename = is_multi_file_mode ? current_file?.name : url ? url.split("/").pop() || "unknown" : "unknown";
|
|
5451
|
+
const current_filename = is_multi_file_mode ? current_file?.name : display_filename || (url ? url.split("/").pop() || "unknown" : "unknown");
|
|
5326
5452
|
logger2.info("[PdfViewer] Starting data extraction", { filename: current_filename });
|
|
5327
5453
|
const bytes = new Uint8Array(cached_pdf_data);
|
|
5328
5454
|
let binary = "";
|
|
@@ -5412,6 +5538,7 @@ ${suffix_line}`;
|
|
|
5412
5538
|
toolbar_show_annotate_button: show_annotate_button ?? base_toolbar_config.toolbar_show_annotate_button,
|
|
5413
5539
|
toolbar_show_file_info_button: show_file_info_button ?? base_toolbar_config.toolbar_show_file_info_button,
|
|
5414
5540
|
toolbar_show_extract_button: show_extract_button ?? base_toolbar_config.toolbar_show_extract_button,
|
|
5541
|
+
toolbar_show_download_button: show_download_button ?? base_toolbar_config.toolbar_show_download_button,
|
|
5415
5542
|
toolbar_show_rotation_controls: base_toolbar_config.toolbar_show_rotation_controls ?? true
|
|
5416
5543
|
};
|
|
5417
5544
|
const is_toolbar_enabled = toolbar_enabled ?? true;
|
|
@@ -5690,6 +5817,35 @@ ${suffix_line}`;
|
|
|
5690
5817
|
children: /* @__PURE__ */ jsx15(Save, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
5691
5818
|
}
|
|
5692
5819
|
) }),
|
|
5820
|
+
toolbar_config.toolbar_show_download_button && /* @__PURE__ */ jsx15("div", { className: "cls_pdf_viewer_toolbar_group", children: /* @__PURE__ */ jsx15(
|
|
5821
|
+
"button",
|
|
5822
|
+
{
|
|
5823
|
+
type: "button",
|
|
5824
|
+
onClick: handle_download,
|
|
5825
|
+
disabled: downloading || !pdf_document,
|
|
5826
|
+
className: cn(
|
|
5827
|
+
"cls_pdf_viewer_toolbar_button",
|
|
5828
|
+
"cls_pdf_viewer_toolbar_button_download",
|
|
5829
|
+
(downloading || !pdf_document) && "cls_pdf_viewer_toolbar_button_disabled"
|
|
5830
|
+
),
|
|
5831
|
+
"aria-label": "Download PDF",
|
|
5832
|
+
title: downloading ? "Downloading..." : "Download PDF",
|
|
5833
|
+
style: {
|
|
5834
|
+
backgroundColor: toolbar_config.toolbar_button_background_color,
|
|
5835
|
+
color: toolbar_config.toolbar_button_text_color,
|
|
5836
|
+
opacity: downloading || !pdf_document ? toolbar_config.toolbar_button_disabled_opacity : 1
|
|
5837
|
+
},
|
|
5838
|
+
onMouseEnter: (e) => {
|
|
5839
|
+
if (!(downloading || !pdf_document)) {
|
|
5840
|
+
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color_hover;
|
|
5841
|
+
}
|
|
5842
|
+
},
|
|
5843
|
+
onMouseLeave: (e) => {
|
|
5844
|
+
e.currentTarget.style.backgroundColor = toolbar_config.toolbar_button_background_color;
|
|
5845
|
+
},
|
|
5846
|
+
children: /* @__PURE__ */ jsx15(Download, { className: "cls_pdf_viewer_toolbar_icon", size: 16 })
|
|
5847
|
+
}
|
|
5848
|
+
) }),
|
|
5693
5849
|
toolbar_config.toolbar_show_extract_button && extract_api_endpoint && /* @__PURE__ */ jsx15("div", { className: "cls_pdf_viewer_toolbar_group", children: /* @__PURE__ */ jsx15(
|
|
5694
5850
|
"button",
|
|
5695
5851
|
{
|
|
@@ -5924,7 +6080,7 @@ ${suffix_line}`;
|
|
|
5924
6080
|
is_open: file_info_sidepanel_open,
|
|
5925
6081
|
on_toggle: handle_file_info_sidepanel_toggle,
|
|
5926
6082
|
item: (() => {
|
|
5927
|
-
const filename = current_file?.name || (url ? url.split("/").pop() || "" : "");
|
|
6083
|
+
const filename = current_file?.name || display_filename || (url ? url.split("/").pop() || "" : "");
|
|
5928
6084
|
const filepath = effective_url || "";
|
|
5929
6085
|
if (!filename) return null;
|
|
5930
6086
|
return {
|
|
@@ -5938,14 +6094,14 @@ ${suffix_line}`;
|
|
|
5938
6094
|
width: file_info_sidepanel_width,
|
|
5939
6095
|
on_width_change: handle_file_info_sidepanel_width_change,
|
|
5940
6096
|
file_metadata,
|
|
5941
|
-
current_filename: current_file?.name || (url ? url.split("/").pop() || "" : ""),
|
|
6097
|
+
current_filename: current_file?.name || display_filename || (url ? url.split("/").pop() || "" : ""),
|
|
5942
6098
|
doc_data,
|
|
5943
6099
|
highlight_fields_info
|
|
5944
6100
|
}
|
|
5945
6101
|
)
|
|
5946
6102
|
] });
|
|
5947
6103
|
})(),
|
|
5948
|
-
context_menu?.visible && /* @__PURE__ */ jsxs14(
|
|
6104
|
+
context_menu?.visible && /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
5949
6105
|
/* @__PURE__ */ jsx15(
|
|
5950
6106
|
"div",
|
|
5951
6107
|
{
|
|
@@ -6152,4 +6308,4 @@ export {
|
|
|
6152
6308
|
PdfViewer,
|
|
6153
6309
|
pdf_viewer_default
|
|
6154
6310
|
};
|
|
6155
|
-
//# sourceMappingURL=chunk-
|
|
6311
|
+
//# sourceMappingURL=chunk-ETZ57VO7.js.map
|