@zerohive/hive-viewer 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +185 -245
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +186 -247
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +186 -247
- package/dist/styles.css +200 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,8 +10,7 @@ import {
|
|
|
10
10
|
useEffect,
|
|
11
11
|
useImperativeHandle,
|
|
12
12
|
useMemo,
|
|
13
|
-
useRef
|
|
14
|
-
useState
|
|
13
|
+
useRef
|
|
15
14
|
} from "react";
|
|
16
15
|
|
|
17
16
|
// src/utils/sanitize.ts
|
|
@@ -26,222 +25,122 @@ function sanitizeHtml(html) {
|
|
|
26
25
|
// src/editors/RichTextEditor.tsx
|
|
27
26
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
28
27
|
var PAGE_H = 1122;
|
|
29
|
-
var RichTextEditor = forwardRef(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
if (props.fileType === "docx") {
|
|
50
|
-
const res = await mammoth.convertToHtml({
|
|
51
|
-
arrayBuffer: props.arrayBuffer
|
|
52
|
-
});
|
|
53
|
-
if (!cancelled) {
|
|
54
|
-
setHtml(sanitizeHtml(res.value || "<p><br/></p>"));
|
|
28
|
+
var RichTextEditor = forwardRef(
|
|
29
|
+
(props, ref) => {
|
|
30
|
+
const readOnly = props.mode === "view";
|
|
31
|
+
const md = useMemo(
|
|
32
|
+
() => new MarkdownIt({ html: false, linkify: true, breaks: true }),
|
|
33
|
+
[]
|
|
34
|
+
);
|
|
35
|
+
const scrollerRef = useRef(null);
|
|
36
|
+
const editorRef = useRef(null);
|
|
37
|
+
const captureRef = useRef(null);
|
|
38
|
+
const initialized = useRef(false);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (initialized.current) return;
|
|
41
|
+
(async () => {
|
|
42
|
+
if (props.mode === "create") {
|
|
43
|
+
editorRef.current.innerHTML = "<p><br/></p>";
|
|
44
|
+
initialized.current = true;
|
|
45
|
+
return;
|
|
55
46
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
if (!props.arrayBuffer) return;
|
|
48
|
+
if (props.fileType === "docx") {
|
|
49
|
+
const res = await mammoth.convertToHtml({
|
|
50
|
+
arrayBuffer: props.arrayBuffer
|
|
51
|
+
});
|
|
52
|
+
editorRef.current.innerHTML = sanitizeHtml(
|
|
53
|
+
res.value || "<p><br/></p>"
|
|
54
|
+
);
|
|
60
55
|
} else {
|
|
61
|
-
|
|
56
|
+
const text = new TextDecoder().decode(props.arrayBuffer);
|
|
57
|
+
editorRef.current.innerHTML = props.fileType === "md" ? sanitizeHtml(md.render(text)) : `<pre>${escapeHtml(text)}</pre>`;
|
|
62
58
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}, [html, props.headerFooterEnabled]);
|
|
80
|
-
function exec(cmd) {
|
|
81
|
-
if (readOnly) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
document.execCommand(cmd);
|
|
85
|
-
}
|
|
86
|
-
function onClick(e) {
|
|
87
|
-
if (!props.armedSignatureUrl) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const scroller = scrollerRef.current;
|
|
91
|
-
if (!scroller) {
|
|
92
|
-
return;
|
|
59
|
+
initialized.current = true;
|
|
60
|
+
})();
|
|
61
|
+
}, [props.arrayBuffer, props.fileType, props.mode, md]);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
const el = scrollerRef.current;
|
|
64
|
+
if (!el) return;
|
|
65
|
+
const recompute = () => props.onPageCount(Math.max(1, Math.ceil(el.scrollHeight / PAGE_H)));
|
|
66
|
+
recompute();
|
|
67
|
+
const ro = new ResizeObserver(recompute);
|
|
68
|
+
ro.observe(el);
|
|
69
|
+
return () => ro.disconnect();
|
|
70
|
+
}, [props.headerFooterEnabled]);
|
|
71
|
+
function exec(cmd) {
|
|
72
|
+
if (readOnly) return;
|
|
73
|
+
document.execCommand(cmd);
|
|
74
|
+
editorRef.current?.focus();
|
|
93
75
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
const old = scroller.scrollTop;
|
|
109
|
-
scroller.scrollTop = index * PAGE_H;
|
|
110
|
-
await new Promise((r) => requestAnimationFrame(() => r(null)));
|
|
111
|
-
try {
|
|
112
|
-
const canvas = await html2canvas(capture, {
|
|
113
|
-
backgroundColor: null,
|
|
114
|
-
scale: 0.25,
|
|
115
|
-
useCORS: true
|
|
116
|
-
});
|
|
117
|
-
return canvas.toDataURL("image/png");
|
|
118
|
-
} catch {
|
|
119
|
-
return void 0;
|
|
120
|
-
} finally {
|
|
121
|
-
scroller.scrollTop = old;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
async function save(exportPdf) {
|
|
125
|
-
const inner = editorRef.current?.innerHTML ?? html;
|
|
126
|
-
const stitched = `<!doctype html><html><head><meta charset="utf-8" /></head><body>${inner}</body></html>`;
|
|
127
|
-
if (exportPdf) {
|
|
128
|
-
const b642 = btoa(unescape(encodeURIComponent(stitched)));
|
|
129
|
-
props.onSave(b642, {
|
|
130
|
-
fileName: replaceExt(props.fileName, "html"),
|
|
131
|
-
fileType: "txt",
|
|
132
|
-
exportedAsPdf: true,
|
|
133
|
-
annotations: { signaturePlacements: props.signaturePlacements }
|
|
76
|
+
function onClickPage(e) {
|
|
77
|
+
if (!props.armedSignatureUrl) return;
|
|
78
|
+
const scroller = scrollerRef.current;
|
|
79
|
+
if (!scroller) return;
|
|
80
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
81
|
+
const absY = scroller.scrollTop + (e.clientY - rect.top);
|
|
82
|
+
const page = Math.floor(absY / PAGE_H) + 1;
|
|
83
|
+
props.onPlaceSignature({
|
|
84
|
+
page,
|
|
85
|
+
x: (e.clientX - rect.left) / rect.width,
|
|
86
|
+
y: absY % PAGE_H / PAGE_H,
|
|
87
|
+
w: 0.25,
|
|
88
|
+
h: 0.1
|
|
134
89
|
});
|
|
135
|
-
return;
|
|
136
90
|
}
|
|
137
|
-
|
|
91
|
+
async function requestThumbnail(index) {
|
|
92
|
+
const scroller = scrollerRef.current;
|
|
93
|
+
const capture = captureRef.current;
|
|
94
|
+
if (!scroller || !capture) return;
|
|
95
|
+
const old = scroller.scrollTop;
|
|
96
|
+
scroller.scrollTop = index * PAGE_H;
|
|
97
|
+
await new Promise((r) => requestAnimationFrame(r));
|
|
138
98
|
try {
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
body: JSON.stringify({
|
|
143
|
-
html: stitched,
|
|
144
|
-
fileName: replaceExt(props.fileName, "docx")
|
|
145
|
-
})
|
|
99
|
+
const canvas = await html2canvas(capture, {
|
|
100
|
+
scale: 0.25,
|
|
101
|
+
useCORS: true
|
|
146
102
|
});
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const blob = await response.blob();
|
|
151
|
-
const url = window.URL.createObjectURL(blob);
|
|
152
|
-
const a = document.createElement("a");
|
|
153
|
-
a.href = url;
|
|
154
|
-
a.download = replaceExt(props.fileName, "docx");
|
|
155
|
-
document.body.appendChild(a);
|
|
156
|
-
a.click();
|
|
157
|
-
setTimeout(() => {
|
|
158
|
-
window.URL.revokeObjectURL(url);
|
|
159
|
-
a.remove();
|
|
160
|
-
}, 100);
|
|
161
|
-
} catch (err) {
|
|
162
|
-
alert(
|
|
163
|
-
"DOCX export failed: " + (err instanceof Error ? err.message : String(err))
|
|
164
|
-
);
|
|
103
|
+
return canvas.toDataURL("image/png");
|
|
104
|
+
} finally {
|
|
105
|
+
scroller.scrollTop = old;
|
|
165
106
|
}
|
|
166
|
-
return;
|
|
167
107
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
className: "hv-btn",
|
|
192
|
-
onClick: () => exec("italic"),
|
|
193
|
-
disabled: readOnly,
|
|
194
|
-
children: "I"
|
|
195
|
-
}
|
|
196
|
-
),
|
|
197
|
-
/* @__PURE__ */ jsx(
|
|
198
|
-
"button",
|
|
199
|
-
{
|
|
200
|
-
className: "hv-btn",
|
|
201
|
-
onClick: () => exec("underline"),
|
|
202
|
-
disabled: readOnly,
|
|
203
|
-
children: "U"
|
|
204
|
-
}
|
|
205
|
-
),
|
|
206
|
-
props.armedSignatureUrl ? /* @__PURE__ */ jsx("div", { className: "hv-hint", children: "Click to place signature" }) : null
|
|
207
|
-
] }),
|
|
208
|
-
/* @__PURE__ */ jsx("div", { className: "hv-scroll", ref: scrollerRef, onClick, children: /* @__PURE__ */ jsxs("div", { className: "hv-pageStage", ref: captureRef, children: [
|
|
209
|
-
props.headerFooterEnabled && props.headerComponent ? /* @__PURE__ */ jsx("div", { className: "hv-letterhead", children: props.headerComponent }) : null,
|
|
210
|
-
/* @__PURE__ */ jsx(
|
|
108
|
+
async function save(exportPdf) {
|
|
109
|
+
const html = editorRef.current?.innerHTML ?? "";
|
|
110
|
+
const stitched = `<!doctype html><html><body>${html}</body></html>`;
|
|
111
|
+
const b64 = btoa(unescape(encodeURIComponent(stitched)));
|
|
112
|
+
props.onSave(b64, {
|
|
113
|
+
fileName: props.fileName,
|
|
114
|
+
fileType: props.fileType,
|
|
115
|
+
exportedAsPdf: exportPdf,
|
|
116
|
+
annotations: { signaturePlacements: props.signaturePlacements }
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
useImperativeHandle(ref, () => ({
|
|
120
|
+
save,
|
|
121
|
+
requestThumbnail
|
|
122
|
+
}));
|
|
123
|
+
return /* @__PURE__ */ jsxs("div", { className: "hv-root", children: [
|
|
124
|
+
/* @__PURE__ */ jsxs("div", { className: "hv-toolbar", children: [
|
|
125
|
+
/* @__PURE__ */ jsx("button", { onClick: () => exec("bold"), disabled: readOnly, children: "B" }),
|
|
126
|
+
/* @__PURE__ */ jsx("button", { onClick: () => exec("italic"), disabled: readOnly, children: "I" }),
|
|
127
|
+
/* @__PURE__ */ jsx("button", { onClick: () => exec("underline"), disabled: readOnly, children: "U" }),
|
|
128
|
+
props.armedSignatureUrl && /* @__PURE__ */ jsx("span", { className: "hv-hint", children: "Click page to place signature" })
|
|
129
|
+
] }),
|
|
130
|
+
/* @__PURE__ */ jsx("div", { className: "hv-scroll", ref: scrollerRef, onClick: onClickPage, children: /* @__PURE__ */ jsx("div", { className: "hv-pageStage", ref: captureRef, children: /* @__PURE__ */ jsx(
|
|
211
131
|
"div",
|
|
212
132
|
{
|
|
213
133
|
ref: editorRef,
|
|
214
|
-
className: readOnly ? "
|
|
134
|
+
className: `hv-editor ${readOnly ? "ro" : ""}`,
|
|
215
135
|
contentEditable: !readOnly,
|
|
216
|
-
suppressContentEditableWarning: true
|
|
217
|
-
onInput: () => setHtml(editorRef.current?.innerHTML ?? ""),
|
|
218
|
-
dangerouslySetInnerHTML: { __html: html }
|
|
136
|
+
suppressContentEditableWarning: true
|
|
219
137
|
}
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
"img",
|
|
225
|
-
{
|
|
226
|
-
src: s.signatureImageUrl,
|
|
227
|
-
alt: "",
|
|
228
|
-
className: "hv-sign-img"
|
|
229
|
-
}
|
|
230
|
-
),
|
|
231
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
232
|
-
/* @__PURE__ */ jsx("div", { className: "hv-sign-name", children: s.signedBy }),
|
|
233
|
-
/* @__PURE__ */ jsx("div", { className: "hv-sign-date", children: new Date(s.dateSigned).toLocaleString() })
|
|
234
|
-
] })
|
|
235
|
-
] }, i)) }) : null
|
|
236
|
-
] }) })
|
|
237
|
-
] });
|
|
238
|
-
});
|
|
239
|
-
function replaceExt(name, ext) {
|
|
240
|
-
const base = name.includes(".") ? name.slice(0, name.lastIndexOf(".")) : name;
|
|
241
|
-
return `${base}.${ext}`;
|
|
242
|
-
}
|
|
138
|
+
) }) })
|
|
139
|
+
] });
|
|
140
|
+
}
|
|
141
|
+
);
|
|
243
142
|
function escapeHtml(s) {
|
|
244
|
-
return s.replace(/&/g, "&").replace(/</g, "<")
|
|
143
|
+
return s.replace(/&/g, "&").replace(/</g, "<");
|
|
245
144
|
}
|
|
246
145
|
|
|
247
146
|
// src/editors/SpreadsheetEditor.tsx
|
|
@@ -941,49 +840,46 @@ function Toolbar(props) {
|
|
|
941
840
|
role: "toolbar",
|
|
942
841
|
"aria-label": t("a11y.toolbar", "Document toolbar"),
|
|
943
842
|
children: [
|
|
944
|
-
/* @__PURE__ */ jsxs8("div", { className: "hv-
|
|
843
|
+
/* @__PURE__ */ jsxs8("div", { className: "hv-toolbar__group", children: [
|
|
945
844
|
/* @__PURE__ */ jsx8(
|
|
946
845
|
"button",
|
|
947
846
|
{
|
|
948
|
-
|
|
949
|
-
className: "hv-btn",
|
|
847
|
+
className: `hv-btn ${props.showThumbnails ? "hv-btn--active" : ""}`,
|
|
950
848
|
onClick: props.onToggleThumbnails,
|
|
951
849
|
"aria-pressed": props.showThumbnails,
|
|
952
|
-
children:
|
|
850
|
+
children: "Thumbnails"
|
|
953
851
|
}
|
|
954
852
|
),
|
|
955
853
|
props.mode !== "create" && /* @__PURE__ */ jsx8(
|
|
956
854
|
"button",
|
|
957
855
|
{
|
|
958
|
-
|
|
959
|
-
className: "hv-btn",
|
|
856
|
+
className: `hv-btn ${props.showSignatures ? "hv-btn--active" : ""}`,
|
|
960
857
|
onClick: props.onToggleSignatures,
|
|
961
858
|
"aria-pressed": props.showSignatures,
|
|
962
|
-
children:
|
|
859
|
+
children: "Signatures"
|
|
963
860
|
}
|
|
964
|
-
)
|
|
965
|
-
|
|
861
|
+
)
|
|
862
|
+
] }),
|
|
863
|
+
/* @__PURE__ */ jsxs8("div", { className: "hv-toolbar__group hv-segment", children: [
|
|
966
864
|
/* @__PURE__ */ jsx8(
|
|
967
865
|
"button",
|
|
968
866
|
{
|
|
969
|
-
|
|
970
|
-
className: props.layout === "single" ? "hv-btn hv-btn--active" : "hv-btn",
|
|
867
|
+
className: `hv-btn ${props.layout === "single" ? "hv-btn--active" : ""}`,
|
|
971
868
|
onClick: () => props.onChangeLayout("single"),
|
|
972
|
-
children:
|
|
869
|
+
children: "Single page"
|
|
973
870
|
}
|
|
974
871
|
),
|
|
975
872
|
/* @__PURE__ */ jsx8(
|
|
976
873
|
"button",
|
|
977
874
|
{
|
|
978
|
-
|
|
979
|
-
className: props.layout === "side-by-side" ? "hv-btn hv-btn--active" : "hv-btn",
|
|
875
|
+
className: `hv-btn ${props.layout === "side-by-side" ? "hv-btn--active" : ""}`,
|
|
980
876
|
onClick: () => props.onChangeLayout("side-by-side"),
|
|
981
|
-
children:
|
|
877
|
+
children: "Side-by-side"
|
|
982
878
|
}
|
|
983
879
|
)
|
|
984
880
|
] }),
|
|
985
|
-
/* @__PURE__ */ jsxs8("div", { className: "hv-
|
|
986
|
-
props.showHeaderFooterToggle && /* @__PURE__ */ jsxs8("label", { className: "hv-
|
|
881
|
+
/* @__PURE__ */ jsxs8("div", { className: "hv-toolbar__group hv-toolbar__actions", children: [
|
|
882
|
+
props.showHeaderFooterToggle && /* @__PURE__ */ jsxs8("label", { className: "hv-switch", children: [
|
|
987
883
|
/* @__PURE__ */ jsx8(
|
|
988
884
|
"input",
|
|
989
885
|
{
|
|
@@ -992,28 +888,20 @@ function Toolbar(props) {
|
|
|
992
888
|
onChange: props.onToggleHeaderFooter
|
|
993
889
|
}
|
|
994
890
|
),
|
|
995
|
-
/* @__PURE__ */ jsx8("span", {
|
|
891
|
+
/* @__PURE__ */ jsx8("span", { className: "hv-switch__slider" }),
|
|
892
|
+
/* @__PURE__ */ jsx8("span", { className: "hv-switch__label", children: t("toolbar.letterhead", "Letterhead") })
|
|
996
893
|
] }),
|
|
997
894
|
props.allowSigning && /* @__PURE__ */ jsx8(
|
|
998
895
|
"button",
|
|
999
896
|
{
|
|
1000
|
-
type: "button",
|
|
1001
897
|
className: "hv-btn hv-btn--primary",
|
|
1002
898
|
onClick: props.onSign,
|
|
1003
899
|
disabled: props.signingDisabled,
|
|
1004
|
-
children:
|
|
900
|
+
children: "Sign document"
|
|
1005
901
|
}
|
|
1006
902
|
),
|
|
1007
|
-
props.canExportPdf && /* @__PURE__ */ jsx8("button", {
|
|
1008
|
-
props.canSave && /* @__PURE__ */ jsx8(
|
|
1009
|
-
"button",
|
|
1010
|
-
{
|
|
1011
|
-
type: "button",
|
|
1012
|
-
className: "hv-btn hv-btn--primary",
|
|
1013
|
-
onClick: props.onSave,
|
|
1014
|
-
children: t("toolbar.save", "Save")
|
|
1015
|
-
}
|
|
1016
|
-
)
|
|
903
|
+
props.canExportPdf && /* @__PURE__ */ jsx8("button", { className: "hv-btn", onClick: props.onExportPdf, children: "Export PDF" }),
|
|
904
|
+
props.canSave && /* @__PURE__ */ jsx8("button", { className: "hv-btn hv-btn--primary", onClick: props.onSave, children: "Save" })
|
|
1017
905
|
] })
|
|
1018
906
|
]
|
|
1019
907
|
}
|
|
@@ -1025,8 +913,13 @@ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
|
1025
913
|
function DocumentViewer(props) {
|
|
1026
914
|
const mode = props.mode ?? "view";
|
|
1027
915
|
const theme = props.theme ?? "light";
|
|
1028
|
-
const locale = useMemo6(
|
|
1029
|
-
|
|
916
|
+
const locale = useMemo6(
|
|
917
|
+
() => ({ ...defaultLocale, ...props.locale ?? {} }),
|
|
918
|
+
[props.locale]
|
|
919
|
+
);
|
|
920
|
+
const [layout, setLayout] = useState6(
|
|
921
|
+
props.defaultLayout ?? "single"
|
|
922
|
+
);
|
|
1030
923
|
const [showThumbnails, setShowThumbnails] = useState6(true);
|
|
1031
924
|
const [showSignatures, setShowSignatures] = useState6(true);
|
|
1032
925
|
const [headerFooterEnabled, setHeaderFooterEnabled] = useState6(true);
|
|
@@ -1037,10 +930,17 @@ function DocumentViewer(props) {
|
|
|
1037
930
|
const [pageCount, setPageCount] = useState6(1);
|
|
1038
931
|
const [currentPage, setCurrentPage] = useState6(1);
|
|
1039
932
|
const [thumbs, setThumbs] = useState6([]);
|
|
1040
|
-
const [localSignatures, setLocalSignatures] = useState6(
|
|
1041
|
-
|
|
933
|
+
const [localSignatures, setLocalSignatures] = useState6(
|
|
934
|
+
props.signatures ?? []
|
|
935
|
+
);
|
|
936
|
+
useEffect6(
|
|
937
|
+
() => setLocalSignatures(props.signatures ?? []),
|
|
938
|
+
[props.signatures]
|
|
939
|
+
);
|
|
1042
940
|
const [sigPlacements, setSigPlacements] = useState6([]);
|
|
1043
|
-
const [armedSignatureUrl, setArmedSignatureUrl] = useState6(
|
|
941
|
+
const [armedSignatureUrl, setArmedSignatureUrl] = useState6(
|
|
942
|
+
null
|
|
943
|
+
);
|
|
1044
944
|
const editorRef = useRef3(null);
|
|
1045
945
|
useEffect6(() => {
|
|
1046
946
|
let cancelled = false;
|
|
@@ -1054,7 +954,10 @@ function DocumentViewer(props) {
|
|
|
1054
954
|
setArmedSignatureUrl(null);
|
|
1055
955
|
if (mode === "create") {
|
|
1056
956
|
const ft = props.fileType ?? "docx";
|
|
1057
|
-
setResolved({
|
|
957
|
+
setResolved({
|
|
958
|
+
fileType: ft,
|
|
959
|
+
fileName: props.fileName ?? `Untitled.${ft}`
|
|
960
|
+
});
|
|
1058
961
|
return;
|
|
1059
962
|
}
|
|
1060
963
|
try {
|
|
@@ -1068,7 +971,12 @@ function DocumentViewer(props) {
|
|
|
1068
971
|
if (cancelled) {
|
|
1069
972
|
return;
|
|
1070
973
|
}
|
|
1071
|
-
setResolved({
|
|
974
|
+
setResolved({
|
|
975
|
+
fileType: res.fileType,
|
|
976
|
+
fileName: res.fileName,
|
|
977
|
+
url: res.url,
|
|
978
|
+
arrayBuffer: res.arrayBuffer
|
|
979
|
+
});
|
|
1072
980
|
} catch (e) {
|
|
1073
981
|
if (cancelled) {
|
|
1074
982
|
return;
|
|
@@ -1079,7 +987,14 @@ function DocumentViewer(props) {
|
|
|
1079
987
|
return () => {
|
|
1080
988
|
cancelled = true;
|
|
1081
989
|
};
|
|
1082
|
-
}, [
|
|
990
|
+
}, [
|
|
991
|
+
mode,
|
|
992
|
+
props.fileUrl,
|
|
993
|
+
props.base64,
|
|
994
|
+
props.blob,
|
|
995
|
+
props.fileName,
|
|
996
|
+
props.fileType
|
|
997
|
+
]);
|
|
1083
998
|
const thumbnails = useMemo6(() => {
|
|
1084
999
|
const n = Math.max(1, pageCount);
|
|
1085
1000
|
return Array.from({ length: n }, (_, i) => ({
|
|
@@ -1105,7 +1020,10 @@ function DocumentViewer(props) {
|
|
|
1105
1020
|
if (!armedSignatureUrl) {
|
|
1106
1021
|
return;
|
|
1107
1022
|
}
|
|
1108
|
-
setSigPlacements((prev) => [
|
|
1023
|
+
setSigPlacements((prev) => [
|
|
1024
|
+
...prev,
|
|
1025
|
+
{ ...p, signatureImageUrl: armedSignatureUrl }
|
|
1026
|
+
]);
|
|
1109
1027
|
setArmedSignatureUrl(null);
|
|
1110
1028
|
}
|
|
1111
1029
|
async function handleSave(exportPdf) {
|
|
@@ -1117,7 +1035,11 @@ function DocumentViewer(props) {
|
|
|
1117
1035
|
return;
|
|
1118
1036
|
}
|
|
1119
1037
|
const b64 = arrayBufferToBase642(resolved.arrayBuffer);
|
|
1120
|
-
props.onSave?.(b64, {
|
|
1038
|
+
props.onSave?.(b64, {
|
|
1039
|
+
fileName: resolved.fileName,
|
|
1040
|
+
fileType: resolved.fileType,
|
|
1041
|
+
annotations: { sigPlacements }
|
|
1042
|
+
});
|
|
1121
1043
|
}
|
|
1122
1044
|
const canSave = mode === "edit" || mode === "create";
|
|
1123
1045
|
const canExportPdf = (mode === "edit" || mode === "create") && (resolved?.fileType === "docx" || resolved?.fileType === "md" || resolved?.fileType === "txt" || resolved?.fileType === "xlsx");
|
|
@@ -1174,10 +1096,16 @@ function DocumentViewer(props) {
|
|
|
1174
1096
|
onCurrentPageChange: setCurrentPage,
|
|
1175
1097
|
onPageCount: (n) => {
|
|
1176
1098
|
setPageCount(n);
|
|
1177
|
-
setThumbs(
|
|
1099
|
+
setThumbs(
|
|
1100
|
+
(prev) => prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])
|
|
1101
|
+
);
|
|
1178
1102
|
},
|
|
1179
1103
|
onThumbs: (t) => setThumbs(t),
|
|
1180
|
-
signatureStamp: armedSignatureUrl ? {
|
|
1104
|
+
signatureStamp: armedSignatureUrl ? {
|
|
1105
|
+
imageUrl: armedSignatureUrl,
|
|
1106
|
+
armed: true,
|
|
1107
|
+
onPlaced: placeSignature
|
|
1108
|
+
} : void 0
|
|
1181
1109
|
}
|
|
1182
1110
|
) : null,
|
|
1183
1111
|
resolved.fileType === "docx" || resolved.fileType === "md" || resolved.fileType === "txt" ? /* @__PURE__ */ jsx9(
|
|
@@ -1196,7 +1124,9 @@ function DocumentViewer(props) {
|
|
|
1196
1124
|
signaturePlacements: sigPlacements,
|
|
1197
1125
|
onPageCount: (n) => {
|
|
1198
1126
|
setPageCount(n);
|
|
1199
|
-
setThumbs(
|
|
1127
|
+
setThumbs(
|
|
1128
|
+
(prev) => prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])
|
|
1129
|
+
);
|
|
1200
1130
|
},
|
|
1201
1131
|
onSave: (b64, meta) => props.onSave?.(b64, meta),
|
|
1202
1132
|
armedSignatureUrl,
|
|
@@ -1223,12 +1153,21 @@ function DocumentViewer(props) {
|
|
|
1223
1153
|
onCurrentPageChange: setCurrentPage,
|
|
1224
1154
|
onSlideCount: (n) => {
|
|
1225
1155
|
setPageCount(n);
|
|
1226
|
-
setThumbs(
|
|
1156
|
+
setThumbs(
|
|
1157
|
+
(prev) => prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])
|
|
1158
|
+
);
|
|
1227
1159
|
},
|
|
1228
1160
|
onThumbs: (t) => setThumbs(t)
|
|
1229
1161
|
}
|
|
1230
1162
|
) : null,
|
|
1231
|
-
resolved.fileType === "png" || resolved.fileType === "jpg" || resolved.fileType === "svg" ? /* @__PURE__ */ jsx9(
|
|
1163
|
+
resolved.fileType === "png" || resolved.fileType === "jpg" || resolved.fileType === "svg" ? /* @__PURE__ */ jsx9(
|
|
1164
|
+
ImageRenderer,
|
|
1165
|
+
{
|
|
1166
|
+
arrayBuffer: resolved.arrayBuffer,
|
|
1167
|
+
fileType: resolved.fileType,
|
|
1168
|
+
fileName: resolved.fileName
|
|
1169
|
+
}
|
|
1170
|
+
) : null
|
|
1232
1171
|
] }),
|
|
1233
1172
|
mode !== "create" && localSignatures.length ? /* @__PURE__ */ jsx9(
|
|
1234
1173
|
SignaturePanel,
|