@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 CHANGED
@@ -55,222 +55,122 @@ function sanitizeHtml(html) {
55
55
  // src/editors/RichTextEditor.tsx
56
56
  var import_jsx_runtime = require("react/jsx-runtime");
57
57
  var PAGE_H = 1122;
58
- var RichTextEditor = (0, import_react.forwardRef)((props, ref) => {
59
- const readOnly = props.mode === "view";
60
- const md = (0, import_react.useMemo)(
61
- () => new import_markdown_it.default({ html: false, linkify: true, breaks: true }),
62
- []
63
- );
64
- const scrollerRef = (0, import_react.useRef)(null);
65
- const editorRef = (0, import_react.useRef)(null);
66
- const captureRef = (0, import_react.useRef)(null);
67
- const [html, setHtml] = (0, import_react.useState)("<p><br/></p>");
68
- (0, import_react.useEffect)(() => {
69
- let cancelled = false;
70
- (async () => {
71
- if (props.mode === "create") {
72
- setHtml("<p><br/></p>");
73
- return;
74
- }
75
- if (!props.arrayBuffer) {
76
- return;
77
- }
78
- if (props.fileType === "docx") {
79
- const res = await import_mammoth.default.convertToHtml({
80
- arrayBuffer: props.arrayBuffer
81
- });
82
- if (!cancelled) {
83
- setHtml(sanitizeHtml(res.value || "<p><br/></p>"));
58
+ var RichTextEditor = (0, import_react.forwardRef)(
59
+ (props, ref) => {
60
+ const readOnly = props.mode === "view";
61
+ const md = (0, import_react.useMemo)(
62
+ () => new import_markdown_it.default({ html: false, linkify: true, breaks: true }),
63
+ []
64
+ );
65
+ const scrollerRef = (0, import_react.useRef)(null);
66
+ const editorRef = (0, import_react.useRef)(null);
67
+ const captureRef = (0, import_react.useRef)(null);
68
+ const initialized = (0, import_react.useRef)(false);
69
+ (0, import_react.useEffect)(() => {
70
+ if (initialized.current) return;
71
+ (async () => {
72
+ if (props.mode === "create") {
73
+ editorRef.current.innerHTML = "<p><br/></p>";
74
+ initialized.current = true;
75
+ return;
84
76
  }
85
- } else {
86
- const text = new TextDecoder().decode(props.arrayBuffer);
87
- if (props.fileType === "md") {
88
- setHtml(sanitizeHtml(md.render(text)));
77
+ if (!props.arrayBuffer) return;
78
+ if (props.fileType === "docx") {
79
+ const res = await import_mammoth.default.convertToHtml({
80
+ arrayBuffer: props.arrayBuffer
81
+ });
82
+ editorRef.current.innerHTML = sanitizeHtml(
83
+ res.value || "<p><br/></p>"
84
+ );
89
85
  } else {
90
- setHtml(`<pre>${escapeHtml(text)}</pre>`);
86
+ const text = new TextDecoder().decode(props.arrayBuffer);
87
+ editorRef.current.innerHTML = props.fileType === "md" ? sanitizeHtml(md.render(text)) : `<pre>${escapeHtml(text)}</pre>`;
91
88
  }
92
- }
93
- })();
94
- return () => {
95
- cancelled = true;
96
- };
97
- }, [props.arrayBuffer, props.fileType, props.mode, md]);
98
- (0, import_react.useEffect)(() => {
99
- const el = scrollerRef.current;
100
- if (!el) {
101
- return;
102
- }
103
- const recompute = () => props.onPageCount(Math.max(1, Math.ceil(el.scrollHeight / PAGE_H)));
104
- recompute();
105
- const ro = new ResizeObserver(recompute);
106
- ro.observe(el);
107
- return () => ro.disconnect();
108
- }, [html, props.headerFooterEnabled]);
109
- function exec(cmd) {
110
- if (readOnly) {
111
- return;
112
- }
113
- document.execCommand(cmd);
114
- }
115
- function onClick(e) {
116
- if (!props.armedSignatureUrl) {
117
- return;
118
- }
119
- const scroller = scrollerRef.current;
120
- if (!scroller) {
121
- return;
89
+ initialized.current = true;
90
+ })();
91
+ }, [props.arrayBuffer, props.fileType, props.mode, md]);
92
+ (0, import_react.useEffect)(() => {
93
+ const el = scrollerRef.current;
94
+ if (!el) return;
95
+ const recompute = () => props.onPageCount(Math.max(1, Math.ceil(el.scrollHeight / PAGE_H)));
96
+ recompute();
97
+ const ro = new ResizeObserver(recompute);
98
+ ro.observe(el);
99
+ return () => ro.disconnect();
100
+ }, [props.headerFooterEnabled]);
101
+ function exec(cmd) {
102
+ if (readOnly) return;
103
+ document.execCommand(cmd);
104
+ editorRef.current?.focus();
122
105
  }
123
- const rect = e.currentTarget.getBoundingClientRect();
124
- const absY = scroller.scrollTop + (e.clientY - rect.top);
125
- const page = Math.max(1, Math.floor(absY / PAGE_H) + 1);
126
- const pageTop = (page - 1) * PAGE_H;
127
- const x = (e.clientX - rect.left) / rect.width;
128
- const y = (absY - pageTop) / PAGE_H;
129
- props.onPlaceSignature({ page, x, y, w: 0.25, h: 0.1 });
130
- }
131
- async function requestThumbnail(index) {
132
- const scroller = scrollerRef.current;
133
- const capture = captureRef.current;
134
- if (!scroller || !capture) {
135
- return void 0;
136
- }
137
- const old = scroller.scrollTop;
138
- scroller.scrollTop = index * PAGE_H;
139
- await new Promise((r) => requestAnimationFrame(() => r(null)));
140
- try {
141
- const canvas = await (0, import_html2canvas.default)(capture, {
142
- backgroundColor: null,
143
- scale: 0.25,
144
- useCORS: true
145
- });
146
- return canvas.toDataURL("image/png");
147
- } catch {
148
- return void 0;
149
- } finally {
150
- scroller.scrollTop = old;
151
- }
152
- }
153
- async function save(exportPdf) {
154
- const inner = editorRef.current?.innerHTML ?? html;
155
- const stitched = `<!doctype html><html><head><meta charset="utf-8" /></head><body>${inner}</body></html>`;
156
- if (exportPdf) {
157
- const b642 = btoa(unescape(encodeURIComponent(stitched)));
158
- props.onSave(b642, {
159
- fileName: replaceExt(props.fileName, "html"),
160
- fileType: "txt",
161
- exportedAsPdf: true,
162
- annotations: { signaturePlacements: props.signaturePlacements }
106
+ function onClickPage(e) {
107
+ if (!props.armedSignatureUrl) return;
108
+ const scroller = scrollerRef.current;
109
+ if (!scroller) return;
110
+ const rect = e.currentTarget.getBoundingClientRect();
111
+ const absY = scroller.scrollTop + (e.clientY - rect.top);
112
+ const page = Math.floor(absY / PAGE_H) + 1;
113
+ props.onPlaceSignature({
114
+ page,
115
+ x: (e.clientX - rect.left) / rect.width,
116
+ y: absY % PAGE_H / PAGE_H,
117
+ w: 0.25,
118
+ h: 0.1
163
119
  });
164
- return;
165
120
  }
166
- if (props.fileType === "docx") {
121
+ async function requestThumbnail(index) {
122
+ const scroller = scrollerRef.current;
123
+ const capture = captureRef.current;
124
+ if (!scroller || !capture) return;
125
+ const old = scroller.scrollTop;
126
+ scroller.scrollTop = index * PAGE_H;
127
+ await new Promise((r) => requestAnimationFrame(r));
167
128
  try {
168
- const response = await fetch("/api/export-docx", {
169
- method: "POST",
170
- headers: { "Content-Type": "application/json" },
171
- body: JSON.stringify({
172
- html: stitched,
173
- fileName: replaceExt(props.fileName, "docx")
174
- })
129
+ const canvas = await (0, import_html2canvas.default)(capture, {
130
+ scale: 0.25,
131
+ useCORS: true
175
132
  });
176
- if (!response.ok) {
177
- throw new Error("Failed to generate DOCX");
178
- }
179
- const blob = await response.blob();
180
- const url = window.URL.createObjectURL(blob);
181
- const a = document.createElement("a");
182
- a.href = url;
183
- a.download = replaceExt(props.fileName, "docx");
184
- document.body.appendChild(a);
185
- a.click();
186
- setTimeout(() => {
187
- window.URL.revokeObjectURL(url);
188
- a.remove();
189
- }, 100);
190
- } catch (err) {
191
- alert(
192
- "DOCX export failed: " + (err instanceof Error ? err.message : String(err))
193
- );
133
+ return canvas.toDataURL("image/png");
134
+ } finally {
135
+ scroller.scrollTop = old;
194
136
  }
195
- return;
196
137
  }
197
- const text = editorRef.current?.innerText ?? "";
198
- const b64 = btoa(unescape(encodeURIComponent(text)));
199
- props.onSave(b64, {
200
- fileName: replaceExt(props.fileName, props.fileType),
201
- fileType: props.fileType,
202
- annotations: { signaturePlacements: props.signaturePlacements }
203
- });
204
- }
205
- (0, import_react.useImperativeHandle)(ref, () => ({ save, requestThumbnail }));
206
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hv-doc", children: [
207
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hv-ribbon", role: "toolbar", children: [
208
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
209
- "button",
210
- {
211
- className: "hv-btn",
212
- onClick: () => exec("bold"),
213
- disabled: readOnly,
214
- children: "B"
215
- }
216
- ),
217
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
218
- "button",
219
- {
220
- className: "hv-btn",
221
- onClick: () => exec("italic"),
222
- disabled: readOnly,
223
- children: "I"
224
- }
225
- ),
226
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
227
- "button",
228
- {
229
- className: "hv-btn",
230
- onClick: () => exec("underline"),
231
- disabled: readOnly,
232
- children: "U"
233
- }
234
- ),
235
- props.armedSignatureUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hv-hint", children: "Click to place signature" }) : null
236
- ] }),
237
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hv-scroll", ref: scrollerRef, onClick, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hv-pageStage", ref: captureRef, children: [
238
- props.headerFooterEnabled && props.headerComponent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hv-letterhead", children: props.headerComponent }) : null,
239
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
138
+ async function save(exportPdf) {
139
+ const html = editorRef.current?.innerHTML ?? "";
140
+ const stitched = `<!doctype html><html><body>${html}</body></html>`;
141
+ const b64 = btoa(unescape(encodeURIComponent(stitched)));
142
+ props.onSave(b64, {
143
+ fileName: props.fileName,
144
+ fileType: props.fileType,
145
+ exportedAsPdf: exportPdf,
146
+ annotations: { signaturePlacements: props.signaturePlacements }
147
+ });
148
+ }
149
+ (0, import_react.useImperativeHandle)(ref, () => ({
150
+ save,
151
+ requestThumbnail
152
+ }));
153
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hv-root", children: [
154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hv-toolbar", children: [
155
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => exec("bold"), disabled: readOnly, children: "B" }),
156
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => exec("italic"), disabled: readOnly, children: "I" }),
157
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => exec("underline"), disabled: readOnly, children: "U" }),
158
+ props.armedSignatureUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hv-hint", children: "Click page to place signature" })
159
+ ] }),
160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hv-scroll", ref: scrollerRef, onClick: onClickPage, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hv-pageStage", ref: captureRef, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
240
161
  "div",
241
162
  {
242
163
  ref: editorRef,
243
- className: readOnly ? "hv-editor hv-editor--ro" : "hv-editor",
164
+ className: `hv-editor ${readOnly ? "ro" : ""}`,
244
165
  contentEditable: !readOnly,
245
- suppressContentEditableWarning: true,
246
- onInput: () => setHtml(editorRef.current?.innerHTML ?? ""),
247
- dangerouslySetInnerHTML: { __html: html }
166
+ suppressContentEditableWarning: true
248
167
  }
249
- ),
250
- props.headerFooterEnabled && props.footerComponent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hv-letterhead hv-letterhead--footer", children: props.footerComponent }) : null,
251
- props.mode === "create" && props.signatures.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hv-signatures-inline", children: props.signatures.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hv-sign-inline", children: [
252
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
253
- "img",
254
- {
255
- src: s.signatureImageUrl,
256
- alt: "",
257
- className: "hv-sign-img"
258
- }
259
- ),
260
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
261
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hv-sign-name", children: s.signedBy }),
262
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hv-sign-date", children: new Date(s.dateSigned).toLocaleString() })
263
- ] })
264
- ] }, i)) }) : null
265
- ] }) })
266
- ] });
267
- });
268
- function replaceExt(name, ext) {
269
- const base = name.includes(".") ? name.slice(0, name.lastIndexOf(".")) : name;
270
- return `${base}.${ext}`;
271
- }
168
+ ) }) })
169
+ ] });
170
+ }
171
+ );
272
172
  function escapeHtml(s) {
273
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
173
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;");
274
174
  }
275
175
 
276
176
  // src/editors/SpreadsheetEditor.tsx
@@ -968,49 +868,46 @@ function Toolbar(props) {
968
868
  role: "toolbar",
969
869
  "aria-label": t("a11y.toolbar", "Document toolbar"),
970
870
  children: [
971
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hv-toolbar__left gap-2", children: [
871
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hv-toolbar__group", children: [
972
872
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
973
873
  "button",
974
874
  {
975
- type: "button",
976
- className: "hv-btn",
875
+ className: `hv-btn ${props.showThumbnails ? "hv-btn--active" : ""}`,
977
876
  onClick: props.onToggleThumbnails,
978
877
  "aria-pressed": props.showThumbnails,
979
- children: t("toolbar.thumbs", "Thumbnails")
878
+ children: "Thumbnails"
980
879
  }
981
880
  ),
982
881
  props.mode !== "create" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
983
882
  "button",
984
883
  {
985
- type: "button",
986
- className: "hv-btn",
884
+ className: `hv-btn ${props.showSignatures ? "hv-btn--active" : ""}`,
987
885
  onClick: props.onToggleSignatures,
988
886
  "aria-pressed": props.showSignatures,
989
- children: t("toolbar.signatures", "Signatures")
887
+ children: "Signatures"
990
888
  }
991
- ),
992
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hv-sep" }),
889
+ )
890
+ ] }),
891
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hv-toolbar__group hv-segment", children: [
993
892
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
994
893
  "button",
995
894
  {
996
- type: "button",
997
- className: props.layout === "single" ? "hv-btn hv-btn--active" : "hv-btn",
895
+ className: `hv-btn ${props.layout === "single" ? "hv-btn--active" : ""}`,
998
896
  onClick: () => props.onChangeLayout("single"),
999
- children: t("toolbar.layout.single", "Single")
897
+ children: "Single page"
1000
898
  }
1001
899
  ),
1002
900
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1003
901
  "button",
1004
902
  {
1005
- type: "button",
1006
- className: props.layout === "side-by-side" ? "hv-btn hv-btn--active" : "hv-btn",
903
+ className: `hv-btn ${props.layout === "side-by-side" ? "hv-btn--active" : ""}`,
1007
904
  onClick: () => props.onChangeLayout("side-by-side"),
1008
- children: t("toolbar.layout.two", "Two")
905
+ children: "Side-by-side"
1009
906
  }
1010
907
  )
1011
908
  ] }),
1012
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hv-toolbar__right", children: [
1013
- props.showHeaderFooterToggle && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "hv-toggle", children: [
909
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hv-toolbar__group hv-toolbar__actions", children: [
910
+ props.showHeaderFooterToggle && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "hv-switch", children: [
1014
911
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1015
912
  "input",
1016
913
  {
@@ -1019,28 +916,20 @@ function Toolbar(props) {
1019
916
  onChange: props.onToggleHeaderFooter
1020
917
  }
1021
918
  ),
1022
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: t("toolbar.letterhead", "Letterhead") })
919
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hv-switch__slider" }),
920
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hv-switch__label", children: t("toolbar.letterhead", "Letterhead") })
1023
921
  ] }),
1024
922
  props.allowSigning && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1025
923
  "button",
1026
924
  {
1027
- type: "button",
1028
925
  className: "hv-btn hv-btn--primary",
1029
926
  onClick: props.onSign,
1030
927
  disabled: props.signingDisabled,
1031
- children: t("toolbar.sign", "Sign Document")
928
+ children: "Sign document"
1032
929
  }
1033
930
  ),
1034
- props.canExportPdf && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: "hv-btn", onClick: props.onExportPdf, children: t("toolbar.exportPdf", "Export as PDF") }),
1035
- props.canSave && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1036
- "button",
1037
- {
1038
- type: "button",
1039
- className: "hv-btn hv-btn--primary",
1040
- onClick: props.onSave,
1041
- children: t("toolbar.save", "Save")
1042
- }
1043
- )
931
+ props.canExportPdf && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hv-btn", onClick: props.onExportPdf, children: "Export PDF" }),
932
+ props.canSave && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hv-btn hv-btn--primary", onClick: props.onSave, children: "Save" })
1044
933
  ] })
1045
934
  ]
1046
935
  }
@@ -1052,8 +941,13 @@ var import_jsx_runtime9 = require("react/jsx-runtime");
1052
941
  function DocumentViewer(props) {
1053
942
  const mode = props.mode ?? "view";
1054
943
  const theme = props.theme ?? "light";
1055
- const locale = (0, import_react7.useMemo)(() => ({ ...defaultLocale, ...props.locale ?? {} }), [props.locale]);
1056
- const [layout, setLayout] = (0, import_react7.useState)(props.defaultLayout ?? "single");
944
+ const locale = (0, import_react7.useMemo)(
945
+ () => ({ ...defaultLocale, ...props.locale ?? {} }),
946
+ [props.locale]
947
+ );
948
+ const [layout, setLayout] = (0, import_react7.useState)(
949
+ props.defaultLayout ?? "single"
950
+ );
1057
951
  const [showThumbnails, setShowThumbnails] = (0, import_react7.useState)(true);
1058
952
  const [showSignatures, setShowSignatures] = (0, import_react7.useState)(true);
1059
953
  const [headerFooterEnabled, setHeaderFooterEnabled] = (0, import_react7.useState)(true);
@@ -1064,10 +958,17 @@ function DocumentViewer(props) {
1064
958
  const [pageCount, setPageCount] = (0, import_react7.useState)(1);
1065
959
  const [currentPage, setCurrentPage] = (0, import_react7.useState)(1);
1066
960
  const [thumbs, setThumbs] = (0, import_react7.useState)([]);
1067
- const [localSignatures, setLocalSignatures] = (0, import_react7.useState)(props.signatures ?? []);
1068
- (0, import_react7.useEffect)(() => setLocalSignatures(props.signatures ?? []), [props.signatures]);
961
+ const [localSignatures, setLocalSignatures] = (0, import_react7.useState)(
962
+ props.signatures ?? []
963
+ );
964
+ (0, import_react7.useEffect)(
965
+ () => setLocalSignatures(props.signatures ?? []),
966
+ [props.signatures]
967
+ );
1069
968
  const [sigPlacements, setSigPlacements] = (0, import_react7.useState)([]);
1070
- const [armedSignatureUrl, setArmedSignatureUrl] = (0, import_react7.useState)(null);
969
+ const [armedSignatureUrl, setArmedSignatureUrl] = (0, import_react7.useState)(
970
+ null
971
+ );
1071
972
  const editorRef = (0, import_react7.useRef)(null);
1072
973
  (0, import_react7.useEffect)(() => {
1073
974
  let cancelled = false;
@@ -1081,7 +982,10 @@ function DocumentViewer(props) {
1081
982
  setArmedSignatureUrl(null);
1082
983
  if (mode === "create") {
1083
984
  const ft = props.fileType ?? "docx";
1084
- setResolved({ fileType: ft, fileName: props.fileName ?? `Untitled.${ft}` });
985
+ setResolved({
986
+ fileType: ft,
987
+ fileName: props.fileName ?? `Untitled.${ft}`
988
+ });
1085
989
  return;
1086
990
  }
1087
991
  try {
@@ -1095,7 +999,12 @@ function DocumentViewer(props) {
1095
999
  if (cancelled) {
1096
1000
  return;
1097
1001
  }
1098
- setResolved({ fileType: res.fileType, fileName: res.fileName, url: res.url, arrayBuffer: res.arrayBuffer });
1002
+ setResolved({
1003
+ fileType: res.fileType,
1004
+ fileName: res.fileName,
1005
+ url: res.url,
1006
+ arrayBuffer: res.arrayBuffer
1007
+ });
1099
1008
  } catch (e) {
1100
1009
  if (cancelled) {
1101
1010
  return;
@@ -1106,7 +1015,14 @@ function DocumentViewer(props) {
1106
1015
  return () => {
1107
1016
  cancelled = true;
1108
1017
  };
1109
- }, [mode, props.fileUrl, props.base64, props.blob, props.fileName, props.fileType]);
1018
+ }, [
1019
+ mode,
1020
+ props.fileUrl,
1021
+ props.base64,
1022
+ props.blob,
1023
+ props.fileName,
1024
+ props.fileType
1025
+ ]);
1110
1026
  const thumbnails = (0, import_react7.useMemo)(() => {
1111
1027
  const n = Math.max(1, pageCount);
1112
1028
  return Array.from({ length: n }, (_, i) => ({
@@ -1132,7 +1048,10 @@ function DocumentViewer(props) {
1132
1048
  if (!armedSignatureUrl) {
1133
1049
  return;
1134
1050
  }
1135
- setSigPlacements((prev) => [...prev, { ...p, signatureImageUrl: armedSignatureUrl }]);
1051
+ setSigPlacements((prev) => [
1052
+ ...prev,
1053
+ { ...p, signatureImageUrl: armedSignatureUrl }
1054
+ ]);
1136
1055
  setArmedSignatureUrl(null);
1137
1056
  }
1138
1057
  async function handleSave(exportPdf) {
@@ -1144,7 +1063,11 @@ function DocumentViewer(props) {
1144
1063
  return;
1145
1064
  }
1146
1065
  const b64 = arrayBufferToBase642(resolved.arrayBuffer);
1147
- props.onSave?.(b64, { fileName: resolved.fileName, fileType: resolved.fileType, annotations: { sigPlacements } });
1066
+ props.onSave?.(b64, {
1067
+ fileName: resolved.fileName,
1068
+ fileType: resolved.fileType,
1069
+ annotations: { sigPlacements }
1070
+ });
1148
1071
  }
1149
1072
  const canSave = mode === "edit" || mode === "create";
1150
1073
  const canExportPdf = (mode === "edit" || mode === "create") && (resolved?.fileType === "docx" || resolved?.fileType === "md" || resolved?.fileType === "txt" || resolved?.fileType === "xlsx");
@@ -1201,10 +1124,16 @@ function DocumentViewer(props) {
1201
1124
  onCurrentPageChange: setCurrentPage,
1202
1125
  onPageCount: (n) => {
1203
1126
  setPageCount(n);
1204
- setThumbs((prev) => prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i]));
1127
+ setThumbs(
1128
+ (prev) => prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])
1129
+ );
1205
1130
  },
1206
1131
  onThumbs: (t) => setThumbs(t),
1207
- signatureStamp: armedSignatureUrl ? { imageUrl: armedSignatureUrl, armed: true, onPlaced: placeSignature } : void 0
1132
+ signatureStamp: armedSignatureUrl ? {
1133
+ imageUrl: armedSignatureUrl,
1134
+ armed: true,
1135
+ onPlaced: placeSignature
1136
+ } : void 0
1208
1137
  }
1209
1138
  ) : null,
1210
1139
  resolved.fileType === "docx" || resolved.fileType === "md" || resolved.fileType === "txt" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
@@ -1223,7 +1152,9 @@ function DocumentViewer(props) {
1223
1152
  signaturePlacements: sigPlacements,
1224
1153
  onPageCount: (n) => {
1225
1154
  setPageCount(n);
1226
- setThumbs((prev) => prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i]));
1155
+ setThumbs(
1156
+ (prev) => prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])
1157
+ );
1227
1158
  },
1228
1159
  onSave: (b64, meta) => props.onSave?.(b64, meta),
1229
1160
  armedSignatureUrl,
@@ -1250,12 +1181,21 @@ function DocumentViewer(props) {
1250
1181
  onCurrentPageChange: setCurrentPage,
1251
1182
  onSlideCount: (n) => {
1252
1183
  setPageCount(n);
1253
- setThumbs((prev) => prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i]));
1184
+ setThumbs(
1185
+ (prev) => prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])
1186
+ );
1254
1187
  },
1255
1188
  onThumbs: (t) => setThumbs(t)
1256
1189
  }
1257
1190
  ) : null,
1258
- resolved.fileType === "png" || resolved.fileType === "jpg" || resolved.fileType === "svg" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ImageRenderer, { arrayBuffer: resolved.arrayBuffer, fileType: resolved.fileType, fileName: resolved.fileName }) : null
1191
+ resolved.fileType === "png" || resolved.fileType === "jpg" || resolved.fileType === "svg" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1192
+ ImageRenderer,
1193
+ {
1194
+ arrayBuffer: resolved.arrayBuffer,
1195
+ fileType: resolved.fileType,
1196
+ fileName: resolved.fileName
1197
+ }
1198
+ ) : null
1259
1199
  ] }),
1260
1200
  mode !== "create" && localSignatures.length ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1261
1201
  SignaturePanel,