@zerohive/hive-viewer 0.1.1 → 0.2.0

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
@@ -349,7 +349,6 @@ function PdfRenderer(props) {
349
349
  // src/editors/RichTextEditor.tsx
350
350
  var import_react2 = require("react");
351
351
  var import_mammoth = __toESM(require("mammoth"), 1);
352
- var import_html_to_docx = __toESM(require("html-to-docx"), 1);
353
352
  var import_markdown_it = __toESM(require("markdown-it"), 1);
354
353
  var import_html2canvas = __toESM(require("html2canvas"), 1);
355
354
 
@@ -367,7 +366,10 @@ var import_jsx_runtime5 = require("react/jsx-runtime");
367
366
  var PAGE_H = 1122;
368
367
  var RichTextEditor = (0, import_react2.forwardRef)((props, ref) => {
369
368
  const readOnly = props.mode === "view";
370
- const md = (0, import_react2.useMemo)(() => new import_markdown_it.default({ html: false, linkify: true, breaks: true }), []);
369
+ const md = (0, import_react2.useMemo)(
370
+ () => new import_markdown_it.default({ html: false, linkify: true, breaks: true }),
371
+ []
372
+ );
371
373
  const scrollerRef = (0, import_react2.useRef)(null);
372
374
  const editorRef = (0, import_react2.useRef)(null);
373
375
  const captureRef = (0, import_react2.useRef)(null);
@@ -381,7 +383,9 @@ var RichTextEditor = (0, import_react2.forwardRef)((props, ref) => {
381
383
  }
382
384
  if (!props.arrayBuffer) return;
383
385
  if (props.fileType === "docx") {
384
- const res = await import_mammoth.default.convertToHtml({ arrayBuffer: props.arrayBuffer });
386
+ const res = await import_mammoth.default.convertToHtml({
387
+ arrayBuffer: props.arrayBuffer
388
+ });
385
389
  if (!cancelled) setHtml(sanitizeHtml(res.value || "<p><br/></p>"));
386
390
  } else {
387
391
  const text = new TextDecoder().decode(props.arrayBuffer);
@@ -426,7 +430,11 @@ var RichTextEditor = (0, import_react2.forwardRef)((props, ref) => {
426
430
  scroller.scrollTop = index * PAGE_H;
427
431
  await new Promise((r) => requestAnimationFrame(() => r(null)));
428
432
  try {
429
- const canvas = await (0, import_html2canvas.default)(capture, { backgroundColor: null, scale: 0.25, useCORS: true });
433
+ const canvas = await (0, import_html2canvas.default)(capture, {
434
+ backgroundColor: null,
435
+ scale: 0.25,
436
+ useCORS: true
437
+ });
430
438
  return canvas.toDataURL("image/png");
431
439
  } catch {
432
440
  return void 0;
@@ -439,25 +447,69 @@ var RichTextEditor = (0, import_react2.forwardRef)((props, ref) => {
439
447
  const stitched = `<!doctype html><html><head><meta charset="utf-8" /></head><body>${inner}</body></html>`;
440
448
  if (exportPdf) {
441
449
  const b642 = btoa(unescape(encodeURIComponent(stitched)));
442
- props.onSave(b642, { fileName: replaceExt(props.fileName, "html"), fileType: "txt", exportedAsPdf: true, annotations: { signaturePlacements: props.signaturePlacements } });
450
+ props.onSave(b642, {
451
+ fileName: replaceExt(props.fileName, "html"),
452
+ fileType: "txt",
453
+ exportedAsPdf: true,
454
+ annotations: { signaturePlacements: props.signaturePlacements }
455
+ });
443
456
  return;
444
457
  }
445
458
  if (props.fileType === "docx") {
446
- const blob = await (0, import_html_to_docx.default)(stitched);
447
- const ab = await blob.arrayBuffer();
448
- props.onSave(arrayBufferToBase64(ab), { fileName: replaceExt(props.fileName, "docx"), fileType: "docx", annotations: { signaturePlacements: props.signaturePlacements } });
459
+ try {
460
+ const htmlToDocx = (await import("html-to-docx")).default;
461
+ const blob = await htmlToDocx(stitched);
462
+ const ab = await blob.arrayBuffer();
463
+ props.onSave(arrayBufferToBase64(ab), {
464
+ fileName: replaceExt(props.fileName, "docx"),
465
+ fileType: "docx",
466
+ annotations: { signaturePlacements: props.signaturePlacements }
467
+ });
468
+ } catch (err) {
469
+ alert(
470
+ "DOCX export is not supported in this environment. Please use this feature in a Node.js/server context."
471
+ );
472
+ }
449
473
  return;
450
474
  }
451
475
  const text = editorRef.current?.innerText ?? "";
452
476
  const b64 = btoa(unescape(encodeURIComponent(text)));
453
- props.onSave(b64, { fileName: replaceExt(props.fileName, props.fileType), fileType: props.fileType, annotations: { signaturePlacements: props.signaturePlacements } });
477
+ props.onSave(b64, {
478
+ fileName: replaceExt(props.fileName, props.fileType),
479
+ fileType: props.fileType,
480
+ annotations: { signaturePlacements: props.signaturePlacements }
481
+ });
454
482
  }
455
483
  (0, import_react2.useImperativeHandle)(ref, () => ({ save, requestThumbnail }));
456
484
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hv-doc", children: [
457
485
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hv-ribbon", role: "toolbar", children: [
458
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "hv-btn", onClick: () => exec("bold"), disabled: readOnly, children: "B" }),
459
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "hv-btn", onClick: () => exec("italic"), disabled: readOnly, children: "I" }),
460
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "hv-btn", onClick: () => exec("underline"), disabled: readOnly, children: "U" }),
486
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
487
+ "button",
488
+ {
489
+ className: "hv-btn",
490
+ onClick: () => exec("bold"),
491
+ disabled: readOnly,
492
+ children: "B"
493
+ }
494
+ ),
495
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
496
+ "button",
497
+ {
498
+ className: "hv-btn",
499
+ onClick: () => exec("italic"),
500
+ disabled: readOnly,
501
+ children: "I"
502
+ }
503
+ ),
504
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
505
+ "button",
506
+ {
507
+ className: "hv-btn",
508
+ onClick: () => exec("underline"),
509
+ disabled: readOnly,
510
+ children: "U"
511
+ }
512
+ ),
461
513
  props.armedSignatureUrl ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hv-hint", children: "Click to place signature" }) : null
462
514
  ] }),
463
515
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hv-scroll", ref: scrollerRef, onClick, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hv-pageStage", ref: captureRef, children: [
@@ -475,7 +527,14 @@ var RichTextEditor = (0, import_react2.forwardRef)((props, ref) => {
475
527
  ),
476
528
  props.headerFooterEnabled && props.footerComponent ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hv-letterhead hv-letterhead--footer", children: props.footerComponent }) : null,
477
529
  props.mode === "create" && props.signatures.length ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hv-signatures-inline", children: props.signatures.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hv-sign-inline", children: [
478
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src: s.signatureImageUrl, alt: "", className: "hv-sign-img" }),
530
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
531
+ "img",
532
+ {
533
+ src: s.signatureImageUrl,
534
+ alt: "",
535
+ className: "hv-sign-img"
536
+ }
537
+ ),
479
538
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
480
539
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hv-sign-name", children: s.signedBy }),
481
540
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hv-sign-date", children: new Date(s.dateSigned).toLocaleString() })
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx","../src/components/DocumentViewer.tsx","../src/utils/locale.ts","../src/utils/fileSource.ts","../src/components/Toolbar.tsx","../src/components/ThumbnailsSidebar.tsx","../src/components/SignaturePanel.tsx","../src/renderers/PdfRenderer.tsx","../src/editors/RichTextEditor.tsx","../src/utils/sanitize.ts","../src/editors/SpreadsheetEditor.tsx","../src/renderers/ImageRenderer.tsx","../src/renderers/PptxRenderer.tsx"],"sourcesContent":["export { DocumentViewer } from './components/DocumentViewer';\nexport type { DocumentViewerProps, DocumentMode, PageLayout, Signature, SupportedFileType, DocumentViewerSaveMeta } from './types';\n","'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport type { DocumentMode, DocumentViewerProps, PageLayout, Signature, SupportedFileType } from '../types';\nimport { defaultLocale } from '../utils/locale';\nimport { resolveSource } from '../utils/fileSource';\nimport { Toolbar } from './Toolbar';\nimport { ThumbnailsSidebar, type Thumbnail } from './ThumbnailsSidebar';\nimport { SignaturePanel } from './SignaturePanel';\nimport { PdfRenderer } from '../renderers/PdfRenderer';\nimport { RichTextEditor, type RichTextEditorHandle } from '../editors/RichTextEditor';\nimport { SpreadsheetEditor, type SpreadsheetEditorHandle } from '../editors/SpreadsheetEditor';\nimport { ImageRenderer } from '../renderers/ImageRenderer';\nimport { PptxRenderer } from '../renderers/PptxRenderer';\n\ntype SigPlacement = { page: number; x: number; y: number; w: number; h: number; signatureImageUrl: string };\n\ntype EditorHandle = (RichTextEditorHandle | SpreadsheetEditorHandle) & { save: (exportPdf?: boolean) => Promise<void> };\n\nexport function DocumentViewer(props: DocumentViewerProps) {\n const mode: DocumentMode = props.mode ?? 'view';\n const theme = props.theme ?? 'light';\n const locale = useMemo(() => ({ ...defaultLocale, ...(props.locale ?? {}) }), [props.locale]);\n\n const [layout, setLayout] = useState<PageLayout>(props.defaultLayout ?? 'single');\n const [showThumbnails, setShowThumbnails] = useState(true);\n const [showSignatures, setShowSignatures] = useState(true);\n const [headerFooterEnabled, setHeaderFooterEnabled] = useState(true);\n\n const allowSigning = props.allowSigning ?? false;\n const [signingBusy, setSigningBusy] = useState(false);\n\n const [resolved, setResolved] = useState<{ fileType: SupportedFileType; fileName: string; url?: string; arrayBuffer?: ArrayBuffer } | null>(null);\n const [error, setError] = useState<string>('');\n const [pageCount, setPageCount] = useState(1);\n const [currentPage, setCurrentPage] = useState(1);\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n\n const [localSignatures, setLocalSignatures] = useState<Signature[]>(props.signatures ?? []);\n useEffect(() => setLocalSignatures(props.signatures ?? []), [props.signatures]);\n\n const [sigPlacements, setSigPlacements] = useState<SigPlacement[]>([]);\n const [armedSignatureUrl, setArmedSignatureUrl] = useState<string | null>(null);\n\n const editorRef = useRef<EditorHandle | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setError('');\n setResolved(null);\n setThumbs([]);\n setPageCount(1);\n setCurrentPage(1);\n setSigPlacements([]);\n setArmedSignatureUrl(null);\n\n if (mode === 'create') {\n const ft = (props.fileType ?? 'docx') as SupportedFileType;\n setResolved({ fileType: ft, fileName: props.fileName ?? `Untitled.${ft}` });\n return;\n }\n\n try {\n const res = await resolveSource({\n fileUrl: props.fileUrl,\n base64: props.base64,\n blob: props.blob,\n fileName: props.fileName,\n fileType: props.fileType\n });\n if (cancelled) return;\n setResolved({ fileType: res.fileType, fileName: res.fileName, url: res.url, arrayBuffer: res.arrayBuffer });\n } catch (e) {\n if (cancelled) return;\n setError(e instanceof Error ? e.message : String(e));\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [mode, props.fileUrl, props.base64, props.blob, props.fileName, props.fileType]);\n\n const thumbnails: Thumbnail[] = useMemo(() => {\n const n = Math.max(1, pageCount);\n return Array.from({ length: n }, (_, i) => ({\n id: `p-${i + 1}`,\n label: `${locale['thumbnails.page'] ?? 'Page'} ${i + 1}`,\n dataUrl: thumbs[i]\n }));\n }, [pageCount, thumbs, locale]);\n\n async function handleSignRequest() {\n if (!allowSigning || signingBusy || !props.onSignRequest) return;\n setSigningBusy(true);\n try {\n const sig = await props.onSignRequest();\n setLocalSignatures((prev: Signature[]) => [...prev, sig]);\n setArmedSignatureUrl(sig.signatureImageUrl);\n } finally {\n setSigningBusy(false);\n }\n }\n\n function placeSignature(p: { page: number; x: number; y: number; w: number; h: number }) {\n if (!armedSignatureUrl) return;\n setSigPlacements((prev: SigPlacement[]) => [...prev, { ...p, signatureImageUrl: armedSignatureUrl }]);\n setArmedSignatureUrl(null);\n }\n\n async function handleSave(exportPdf?: boolean) {\n if (editorRef.current) {\n await editorRef.current.save(!!exportPdf);\n return;\n }\n if (!resolved?.arrayBuffer) return;\n const b64 = arrayBufferToBase64(resolved.arrayBuffer);\n props.onSave?.(b64, { fileName: resolved.fileName, fileType: resolved.fileType, annotations: { sigPlacements } });\n }\n\n const canSave = mode === 'edit' || mode === 'create';\n const canExportPdf = (mode === 'edit' || mode === 'create') && (resolved?.fileType === 'docx' || resolved?.fileType === 'md' || resolved?.fileType === 'txt' || resolved?.fileType === 'xlsx');\n\n return (\n <div className={`hv-root`} data-hv-theme={theme}>\n <Toolbar\n locale={locale}\n mode={mode}\n fileType={resolved?.fileType}\n layout={layout}\n onChangeLayout={setLayout}\n showThumbnails={showThumbnails}\n onToggleThumbnails={() => setShowThumbnails((v: boolean) => !v)}\n showSignatures={showSignatures}\n onToggleSignatures={() => setShowSignatures((v: boolean) => !v)}\n onSign={() => void handleSignRequest()}\n allowSigning={allowSigning}\n signingDisabled={signingBusy || !props.onSignRequest}\n canSave={canSave}\n onSave={() => void handleSave(false)}\n canExportPdf={canExportPdf}\n onExportPdf={() => void handleSave(true)}\n headerFooterEnabled={headerFooterEnabled}\n showHeaderFooterToggle={(props.enableHeaderFooterToggle ?? true) && mode === 'create'}\n onToggleHeaderFooter={() => setHeaderFooterEnabled((v: boolean) => !v)}\n />\n\n {error ? (\n <div className=\"hv-error\" role=\"alert\">\n <div className=\"hv-error-title\">{locale['error.title'] ?? 'Error'}</div>\n <div className=\"hv-error-body\">{error}</div>\n </div>\n ) : null}\n\n {!resolved && !error ? <div className=\"hv-loading\" aria-busy=\"true\">{locale['loading'] ?? 'Loading…'}</div> : null}\n\n {resolved ? (\n <div className=\"hv-shell\">\n {mode !== 'create' ? (\n <ThumbnailsSidebar\n locale={locale}\n thumbnails={thumbnails}\n currentPage={currentPage}\n collapsed={!showThumbnails}\n onToggle={() => setShowThumbnails((v: boolean) => !v)}\n onSelectPage={setCurrentPage}\n />\n ) : null}\n\n <main className=\"hv-main\">\n {resolved.fileType === 'pdf' ? (\n <PdfRenderer\n url={resolved.url}\n arrayBuffer={resolved.arrayBuffer}\n layout={layout}\n currentPage={currentPage}\n onCurrentPageChange={setCurrentPage}\n onPageCount={(n) => {\n setPageCount(n);\n setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])));\n }}\n onThumbs={(t) => setThumbs(t)}\n signatureStamp={armedSignatureUrl ? { imageUrl: armedSignatureUrl, armed: true, onPlaced: placeSignature } : undefined}\n />\n ) : null}\n\n {resolved.fileType === 'docx' || resolved.fileType === 'md' || resolved.fileType === 'txt' ? (\n <RichTextEditor\n ref={editorRef as any}\n mode={mode}\n fileType={resolved.fileType}\n fileName={resolved.fileName}\n arrayBuffer={resolved.arrayBuffer}\n headerComponent={props.headerComponent}\n footerComponent={props.footerComponent}\n headerFooterEnabled={headerFooterEnabled}\n locale={locale}\n signatures={localSignatures}\n signaturePlacements={sigPlacements}\n onPageCount={(n) => { setPageCount(n); setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i]))); }}\n onSave={(b64, meta) => props.onSave?.(b64, meta)}\n armedSignatureUrl={armedSignatureUrl}\n onPlaceSignature={placeSignature}\n />\n ) : null}\n\n {resolved.fileType === 'xlsx' ? (\n <SpreadsheetEditor\n ref={editorRef as any}\n mode={mode}\n fileName={resolved.fileName}\n arrayBuffer={resolved.arrayBuffer}\n locale={locale}\n onSave={(b64, meta) => props.onSave?.(b64, meta)}\n />\n ) : null}\n\n {resolved.fileType === 'pptx' ? (\n <PptxRenderer\n arrayBuffer={resolved.arrayBuffer}\n layout={layout}\n currentPage={currentPage}\n onCurrentPageChange={setCurrentPage}\n onSlideCount={(n) => {\n setPageCount(n);\n setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])));\n }}\n onThumbs={(t) => setThumbs(t)}\n />\n ) : null}\n\n {resolved.fileType === 'png' || resolved.fileType === 'jpg' || resolved.fileType === 'svg' ? (\n <ImageRenderer arrayBuffer={resolved.arrayBuffer} fileType={resolved.fileType} fileName={resolved.fileName} />\n ) : null}\n </main>\n\n {mode !== 'create' && localSignatures.length ? (\n <SignaturePanel\n locale={locale}\n signatures={localSignatures}\n collapsed={!showSignatures}\n onToggle={() => setShowSignatures((v: boolean) => !v)}\n />\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction arrayBufferToBase64(ab: ArrayBuffer): string {\n const bytes = new Uint8Array(ab);\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n","export const defaultLocale: Record<string, string> = {\n 'loading': 'Loading…',\n 'error.title': 'Error',\n 'toolbar.layout.single': 'Single page',\n 'toolbar.layout.two': 'Side-by-side',\n 'toolbar.thumbs': 'Thumbnails',\n 'toolbar.signatures': 'Signatures',\n 'toolbar.sign': 'Sign Document',\n 'toolbar.save': 'Save',\n 'toolbar.exportPdf': 'Export as PDF',\n 'thumbnails.title': 'Thumbnails',\n 'thumbnails.page': 'Page',\n 'signatures.title': 'Signatures',\n 'signatures.empty': 'No signatures',\n 'signatures.placeHint': 'Click on the document to place the signature.',\n 'a11y.viewer': 'Document viewer',\n 'a11y.ribbon': 'Ribbon',\n 'a11y.editor': 'Document editor'\n};\n","import type { SupportedFileType } from '../types';\n\nexport function guessFileType(name?: string, explicit?: SupportedFileType): SupportedFileType {\n if (explicit) return explicit;\n const ext = (name?.split('.').pop() || '').toLowerCase();\n const allowed: SupportedFileType[] = ['pdf','md','docx','xlsx','pptx','txt','png','jpg','svg'];\n return (allowed as string[]).includes(ext) ? (ext as SupportedFileType) : 'txt';\n}\n\nexport function arrayBufferToBase64(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n\nexport async function base64ToArrayBuffer(b64: string): Promise<ArrayBuffer> {\n const bin = atob(b64);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes.buffer;\n}\n\nexport async function resolveSource(args: {\n fileUrl?: string;\n base64?: string;\n blob?: Blob;\n fileName?: string;\n fileType?: SupportedFileType;\n onProgress?: (loaded: number, total?: number) => void;\n}): Promise<{ fileType: SupportedFileType; fileName: string; arrayBuffer: ArrayBuffer; url?: string }>{\n const fileType = guessFileType(args.fileName, args.fileType);\n const fileName = args.fileName ?? `document.${fileType}`;\n\n if (args.blob) {\n const ab = await args.blob.arrayBuffer();\n const url = URL.createObjectURL(args.blob);\n return { fileType, fileName, arrayBuffer: ab, url };\n }\n\n if (args.base64) {\n const ab = await base64ToArrayBuffer(args.base64);\n return { fileType, fileName, arrayBuffer: ab };\n }\n\n if (!args.fileUrl) throw new Error('No file source provided. Use fileUrl, blob, or base64.');\n\n const res = await fetch(args.fileUrl);\n if (!res.ok) throw new Error(`Failed to fetch file (${res.status})`);\n\n const total = Number(res.headers.get('content-length') || '') || undefined;\n if (!res.body) {\n const ab = await res.arrayBuffer();\n args.onProgress?.(ab.byteLength, total);\n return { fileType, fileName, arrayBuffer: ab, url: args.fileUrl };\n }\n\n const reader = res.body.getReader();\n const chunks: Uint8Array[] = [];\n let loaded = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) {\n chunks.push(value);\n loaded += value.length;\n args.onProgress?.(loaded, total);\n }\n }\n const out = new Uint8Array(loaded);\n let offset = 0;\n for (const c of chunks) { out.set(c, offset); offset += c.length; }\n return { fileType, fileName, arrayBuffer: out.buffer, url: args.fileUrl };\n}\n","'use client';\n\nimport React from 'react';\nimport type { DocumentMode, PageLayout, SupportedFileType } from '../types';\n\nexport function Toolbar(props: {\n locale: Record<string, string>;\n mode: DocumentMode;\n fileType?: SupportedFileType;\n layout: PageLayout;\n onChangeLayout: (l: PageLayout) => void;\n showThumbnails: boolean;\n onToggleThumbnails: () => void;\n showSignatures: boolean;\n onToggleSignatures: () => void;\n allowSigning: boolean;\n signingDisabled: boolean;\n onSign: () => void;\n canSave: boolean;\n onSave: () => void;\n canExportPdf: boolean;\n onExportPdf: () => void;\n showHeaderFooterToggle: boolean;\n headerFooterEnabled: boolean;\n onToggleHeaderFooter: () => void;\n}) {\n const t = (k: string, fallback: string) => props.locale[k] ?? fallback;\n\n return (\n <div className=\"hv-toolbar\" role=\"toolbar\" aria-label={t('a11y.toolbar', 'Document toolbar')}>\n <div className=\"hv-toolbar__left\">\n <button type=\"button\" className=\"hv-btn\" onClick={props.onToggleThumbnails} aria-pressed={props.showThumbnails}>\n {t('toolbar.thumbs', 'Thumbnails')}\n </button>\n {props.mode !== 'create' && (\n <button type=\"button\" className=\"hv-btn\" onClick={props.onToggleSignatures} aria-pressed={props.showSignatures}>\n {t('toolbar.signatures', 'Signatures')}\n </button>\n )}\n <span className=\"hv-sep\" />\n <button type=\"button\" className={props.layout === 'single' ? 'hv-btn hv-btn--active' : 'hv-btn'} onClick={() => props.onChangeLayout('single')}>\n {t('toolbar.layout.single', 'Single')}\n </button>\n <button type=\"button\" className={props.layout === 'side-by-side' ? 'hv-btn hv-btn--active' : 'hv-btn'} onClick={() => props.onChangeLayout('side-by-side')}>\n {t('toolbar.layout.two', 'Two')}\n </button>\n </div>\n\n <div className=\"hv-toolbar__right\">\n {props.showHeaderFooterToggle && (\n <label className=\"hv-toggle\">\n <input type=\"checkbox\" checked={props.headerFooterEnabled} onChange={props.onToggleHeaderFooter} />\n <span>{t('toolbar.letterhead', 'Letterhead')}</span>\n </label>\n )}\n\n {props.allowSigning && (\n <button type=\"button\" className=\"hv-btn hv-btn--primary\" onClick={props.onSign} disabled={props.signingDisabled}>\n {t('toolbar.sign', 'Sign Document')}\n </button>\n )}\n\n {props.canExportPdf && (\n <button type=\"button\" className=\"hv-btn\" onClick={props.onExportPdf}>\n {t('toolbar.exportPdf', 'Export as PDF')}\n </button>\n )}\n {props.canSave && (\n <button type=\"button\" className=\"hv-btn hv-btn--primary\" onClick={props.onSave}>\n {t('toolbar.save', 'Save')}\n </button>\n )}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport React from 'react';\n\nexport type Thumbnail = {\n id: string;\n label: string;\n dataUrl?: string;\n};\n\nexport function ThumbnailsSidebar(props: {\n locale: Record<string, string>;\n thumbnails: Thumbnail[];\n currentPage: number;\n collapsed: boolean;\n onToggle: () => void;\n onSelectPage: (p: number) => void;\n}) {\n const t = props.locale['thumbnails.title'] ?? 'Thumbnails';\n return (\n <aside className={props.collapsed ? 'hv-thumbs hv-thumbs--collapsed' : 'hv-thumbs'} aria-label={t}>\n <div className=\"hv-thumbs__header\">\n <button type=\"button\" className=\"hv-icon\" onClick={props.onToggle} aria-label={props.collapsed ? (props.locale['thumbnails.open'] ?? 'Open thumbnails') : (props.locale['thumbnails.close'] ?? 'Close thumbnails')}\n >{props.collapsed ? '▸' : '▾'}</button>\n {!props.collapsed ? <div className=\"hv-thumbs__title\">{t}</div> : null}\n </div>\n {!props.collapsed ? (\n <div className=\"hv-thumbs__list\" role=\"list\">\n {props.thumbnails.map((th, idx) => {\n const p = idx + 1;\n const active = p === props.currentPage;\n return (\n <button\n key={th.id}\n type=\"button\"\n role=\"listitem\"\n className={active ? 'hv-thumb hv-thumb--active' : 'hv-thumb'}\n onClick={() => props.onSelectPage(p)}\n aria-current={active ? 'page' : undefined}\n >\n <div className=\"hv-thumb__img\" aria-hidden>\n {th.dataUrl ? <img src={th.dataUrl} alt=\"\" /> : <div className=\"hv-thumb__placeholder\" />}\n </div>\n <div className=\"hv-thumb__label\">{th.label}</div>\n </button>\n );\n })}\n </div>\n ) : null}\n </aside>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport type { Signature } from '../types';\n\nexport function SignaturePanel(props: {\n locale: Record<string, string>;\n signatures: Signature[];\n collapsed: boolean;\n onToggle: () => void;\n}) {\n const title = props.locale['signatures.title'] ?? 'Signatures';\n return (\n <aside className={props.collapsed ? 'hv-side hv-side--collapsed' : 'hv-side'} aria-label={title}>\n <div className=\"hv-sidebar-header\">\n <button type=\"button\" className=\"hv-icon\" onClick={props.onToggle} aria-label={props.locale['toolbar.signatures'] ?? 'Signatures'}>\n ✍\n </button>\n <div className=\"hv-sidebar-title\">{title}</div>\n </div>\n <div className=\"hv-sidebar-body\">\n {props.signatures.map((s, idx) => (\n <div key={`${s.signedBy}-${s.dateSigned}-${idx}`} className=\"hv-signature-card\">\n <img src={s.signatureImageUrl} alt={`Signature by ${s.signedBy}`} className=\"hv-signature-img\" />\n <div className=\"hv-signature-meta\">\n <div className=\"hv-signature-name\">{s.signedBy}</div>\n <div className=\"hv-signature-date\">{new Date(s.dateSigned).toLocaleString()}</div>\n {s.comment ? <div className=\"hv-signature-comment\">{s.comment}</div> : null}\n </div>\n </div>\n ))}\n </div>\n </aside>\n );\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { GlobalWorkerOptions, getDocument, type PDFDocumentProxy } from 'pdfjs-dist';\nimport type { PageLayout } from '../types';\n\nexport function PdfRenderer(props: {\n url?: string;\n arrayBuffer?: ArrayBuffer;\n layout: PageLayout;\n currentPage: number;\n onCurrentPageChange: (p: number) => void;\n onPageCount: (n: number) => void;\n onThumbs: (thumbs: (string | undefined)[]) => void;\n signatureStamp?: {\n imageUrl: string;\n armed: boolean;\n onPlaced: (placement: { page: number; x: number; y: number; w: number; h: number }) => void;\n };\n}) {\n const { url, arrayBuffer } = props;\n const [doc, setDoc] = useState<PDFDocumentProxy | null>(null);\n const [pageCount, setPageCount] = useState(0);\n const [rendered, setRendered] = useState<Map<number, HTMLCanvasElement>>(new Map());\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n const [size, setSize] = useState({ w: 840, h: 1188 });\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n try {\n GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString();\n } catch {}\n }, []);\n\n useEffect(() => {\n let cancel = false;\n (async () => {\n setDoc(null);\n setRendered(new Map());\n setThumbs([]);\n if (!url && !arrayBuffer) return;\n const task = getDocument(url ? { url, rangeChunkSize: 512 * 1024 } : { data: arrayBuffer! });\n const pdf = await task.promise;\n if (cancel) return;\n setDoc(pdf);\n setPageCount(pdf.numPages);\n props.onPageCount(pdf.numPages);\n setThumbs(Array.from({ length: pdf.numPages }));\n const p1 = await pdf.getPage(1);\n const base = p1.getViewport({ scale: 1 });\n const w = Math.min(980, Math.max(640, base.width));\n const s = w / base.width;\n const vp = p1.getViewport({ scale: s });\n setSize({ w: Math.round(vp.width), h: Math.round(vp.height) });\n })().catch(() => {\n // ignore; caller shows error\n });\n return () => { cancel = true; };\n }, [url, arrayBuffer]);\n\n useEffect(() => {\n props.onThumbs(thumbs);\n }, [thumbs]);\n\n const pagesToShow = useMemo(() => {\n if (props.layout === 'side-by-side') {\n const left = props.currentPage;\n const right = Math.min(pageCount || left + 1, left + 1);\n return [left, right];\n }\n return [props.currentPage];\n }, [props.currentPage, props.layout, pageCount]);\n\n useEffect(() => {\n if (!doc) return;\n let cancel = false;\n (async () => {\n for (const p of pagesToShow) {\n if (rendered.has(p)) continue;\n const page = await doc.getPage(p);\n if (cancel) return;\n const base = page.getViewport({ scale: 1 });\n const vp = page.getViewport({ scale: size.w / base.width });\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(vp.width);\n canvas.height = Math.round(vp.height);\n const ctx = canvas.getContext('2d', { alpha: false });\n if (!ctx) continue;\n await page.render({ canvasContext: ctx, viewport: vp }).promise;\n if (cancel) return;\n setRendered(prev => {\n const next = new Map(prev);\n next.set(p, canvas);\n return next;\n });\n try {\n const tw = 140;\n const th = Math.round(tw * (canvas.height / canvas.width));\n const t = document.createElement('canvas');\n t.width = tw; t.height = th;\n const tctx = t.getContext('2d');\n if (tctx) {\n tctx.drawImage(canvas, 0, 0, tw, th);\n const url = t.toDataURL('image/jpeg', 0.75);\n setThumbs(prev => {\n const next = prev.slice();\n next[p - 1] = url;\n return next;\n });\n }\n } catch {}\n }\n })();\n return () => { cancel = true; };\n }, [doc, pagesToShow, size.w, rendered]);\n\n function onWheel(e: React.WheelEvent) {\n if (!pageCount) return;\n if (Math.abs(e.deltaY) < 10) return;\n const dir = e.deltaY > 0 ? 1 : -1;\n const step = props.layout === 'side-by-side' ? 2 : 1;\n const next = Math.max(1, Math.min(pageCount, props.currentPage + dir * step));\n props.onCurrentPageChange(next);\n }\n\n function clickPlace(e: React.MouseEvent, page: number) {\n const stamp = props.signatureStamp;\n if (!stamp?.armed) return;\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const x = (e.clientX - rect.left) / rect.width;\n const y = (e.clientY - rect.top) / rect.height;\n stamp.onPlaced({ page, x, y, w: 0.22, h: 0.08 });\n }\n\n return (\n <div className=\"hv-doc\" ref={containerRef} onWheel={onWheel}>\n {!doc ? <div className=\"hv-loading\">Loading PDF…</div> : null}\n {doc ? (\n <div className={props.layout === 'side-by-side' ? 'hv-pages hv-pages--two' : 'hv-pages'}>\n {pagesToShow.map(p => {\n const c = rendered.get(p);\n return (\n <div key={p} className=\"hv-page\" style={{ width: size.w, height: size.h }} onClick={(e) => clickPlace(e, p)}>\n {c ? (\n <canvas\n className=\"hv-canvas\"\n width={c.width}\n height={c.height}\n ref={(node) => {\n if (!node) return;\n const ctx = node.getContext('2d');\n if (ctx) ctx.drawImage(c, 0, 0);\n }}\n />\n ) : <div className=\"hv-loading\">Rendering…</div>}\n </div>\n );\n })}\n </div>\n ) : null}\n </div>\n );\n}\n","'use client';\n\nimport React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';\nimport mammoth from 'mammoth';\nimport htmlToDocx from 'html-to-docx';\nimport MarkdownIt from 'markdown-it';\nimport html2canvas from 'html2canvas';\nimport { sanitizeHtml } from '../utils/sanitize';\nimport { arrayBufferToBase64 } from '../utils/fileSource';\nimport type { DocumentMode, Signature, SupportedFileType } from '../types';\n\nconst PAGE_H = 1122; // virtual A4\n\nexport type RichTextEditorHandle = {\n save: (exportPdf?: boolean) => Promise<void>;\n requestThumbnail: (index: number) => Promise<string | undefined>;\n};\n\nexport const RichTextEditor = forwardRef<RichTextEditorHandle, {\n mode: DocumentMode;\n fileType: 'docx' | 'md' | 'txt';\n fileName: string;\n arrayBuffer?: ArrayBuffer;\n locale: Record<string, string>;\n headerComponent?: React.ReactNode;\n footerComponent?: React.ReactNode;\n headerFooterEnabled: boolean;\n signatures: Signature[];\n signaturePlacements: { page: number; x: number; y: number; w: number; h: number; signatureImageUrl: string }[];\n armedSignatureUrl: string | null;\n onPlaceSignature: (p: { page: number; x: number; y: number; w: number; h: number }) => void;\n onSave: (b64: string, meta: { fileName: string; fileType: SupportedFileType; exportedAsPdf?: boolean; annotations?: unknown }) => void;\n onPageCount: (n: number) => void;\n}>((props, ref) => {\n const readOnly = props.mode === 'view';\n const md = useMemo(() => new MarkdownIt({ html: false, linkify: true, breaks: true }), []);\n const scrollerRef = useRef<HTMLDivElement | null>(null);\n const editorRef = useRef<HTMLDivElement | null>(null);\n const captureRef = useRef<HTMLDivElement | null>(null);\n\n const [html, setHtml] = useState('<p><br/></p>');\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n if (props.mode === 'create') {\n setHtml('<p><br/></p>');\n return;\n }\n if (!props.arrayBuffer) return;\n if (props.fileType === 'docx') {\n const res = await mammoth.convertToHtml({ arrayBuffer: props.arrayBuffer });\n if (!cancelled) setHtml(sanitizeHtml(res.value || '<p><br/></p>'));\n } else {\n const text = new TextDecoder().decode(props.arrayBuffer);\n if (props.fileType === 'md') setHtml(sanitizeHtml(md.render(text)));\n else setHtml(`<pre>${escapeHtml(text)}</pre>`);\n }\n })();\n return () => { cancelled = true; };\n }, [props.arrayBuffer, props.fileType, props.mode, md]);\n\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return;\n const recompute = () => props.onPageCount(Math.max(1, Math.ceil(el.scrollHeight / PAGE_H)));\n recompute();\n const ro = new ResizeObserver(recompute);\n ro.observe(el);\n return () => ro.disconnect();\n }, [html, props.headerFooterEnabled]);\n\n function exec(cmd: string) {\n if (readOnly) return;\n document.execCommand(cmd);\n }\n\n function onClick(e: React.MouseEvent<HTMLDivElement>) {\n if (!props.armedSignatureUrl) return;\n const scroller = scrollerRef.current;\n if (!scroller) return;\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const absY = scroller.scrollTop + (e.clientY - rect.top);\n const page = Math.max(1, Math.floor(absY / PAGE_H) + 1);\n const pageTop = (page - 1) * PAGE_H;\n const x = (e.clientX - rect.left) / rect.width;\n const y = (absY - pageTop) / PAGE_H;\n props.onPlaceSignature({ page, x, y, w: 0.25, h: 0.1 });\n }\n\n async function requestThumbnail(index: number): Promise<string | undefined> {\n const scroller = scrollerRef.current;\n const capture = captureRef.current;\n if (!scroller || !capture) return undefined;\n const old = scroller.scrollTop;\n scroller.scrollTop = index * PAGE_H;\n await new Promise((r) => requestAnimationFrame(() => r(null)));\n try {\n const canvas = await html2canvas(capture, { backgroundColor: null, scale: 0.25, useCORS: true });\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n } finally {\n scroller.scrollTop = old;\n }\n }\n\n async function save(exportPdf?: boolean) {\n const inner = editorRef.current?.innerHTML ?? html;\n const stitched = `<!doctype html><html><head><meta charset=\"utf-8\" /></head><body>${inner}</body></html>`;\n\n if (exportPdf) {\n // client-side: return print-ready HTML as base64\n const b64 = btoa(unescape(encodeURIComponent(stitched)));\n props.onSave(b64, { fileName: replaceExt(props.fileName, 'html'), fileType: 'txt', exportedAsPdf: true, annotations: { signaturePlacements: props.signaturePlacements } });\n return;\n }\n\n if (props.fileType === 'docx') {\n const blob = await htmlToDocx(stitched);\n const ab = await blob.arrayBuffer();\n props.onSave(arrayBufferToBase64(ab), { fileName: replaceExt(props.fileName, 'docx'), fileType: 'docx', annotations: { signaturePlacements: props.signaturePlacements } });\n return;\n }\n\n const text = editorRef.current?.innerText ?? '';\n const b64 = btoa(unescape(encodeURIComponent(text)));\n props.onSave(b64, { fileName: replaceExt(props.fileName, props.fileType), fileType: props.fileType, annotations: { signaturePlacements: props.signaturePlacements } });\n }\n\n useImperativeHandle(ref, () => ({ save, requestThumbnail }));\n\n return (\n <div className=\"hv-doc\">\n <div className=\"hv-ribbon\" role=\"toolbar\">\n <button className=\"hv-btn\" onClick={() => exec('bold')} disabled={readOnly}>B</button>\n <button className=\"hv-btn\" onClick={() => exec('italic')} disabled={readOnly}>I</button>\n <button className=\"hv-btn\" onClick={() => exec('underline')} disabled={readOnly}>U</button>\n {props.armedSignatureUrl ? <div className=\"hv-hint\">Click to place signature</div> : null}\n </div>\n\n <div className=\"hv-scroll\" ref={scrollerRef} onClick={onClick}>\n <div className=\"hv-pageStage\" ref={captureRef}>\n {props.headerFooterEnabled && props.headerComponent ? <div className=\"hv-letterhead\">{props.headerComponent}</div> : null}\n\n <div\n ref={editorRef}\n className={readOnly ? 'hv-editor hv-editor--ro' : 'hv-editor'}\n contentEditable={!readOnly}\n suppressContentEditableWarning\n onInput={() => setHtml(editorRef.current?.innerHTML ?? '')}\n dangerouslySetInnerHTML={{ __html: html }}\n />\n\n {props.headerFooterEnabled && props.footerComponent ? <div className=\"hv-letterhead hv-letterhead--footer\">{props.footerComponent}</div> : null}\n\n {props.mode === 'create' && props.signatures.length ? (\n <div className=\"hv-signatures-inline\">\n {props.signatures.map((s, i) => (\n <div key={i} className=\"hv-sign-inline\">\n <img src={s.signatureImageUrl} alt=\"\" className=\"hv-sign-img\" />\n <div>\n <div className=\"hv-sign-name\">{s.signedBy}</div>\n <div className=\"hv-sign-date\">{new Date(s.dateSigned).toLocaleString()}</div>\n </div>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n </div>\n );\n});\n\nfunction replaceExt(name: string, ext: string) {\n const base = name.includes('.') ? name.slice(0, name.lastIndexOf('.')) : name;\n return `${base}.${ext}`;\n}\n\nfunction escapeHtml(s: string) {\n return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n}\n","import DOMPurify from 'dompurify';\n\nexport function sanitizeHtml(html: string): string {\n // DOMPurify is safe to call in the browser. For SSR, callers should only run after mount.\n return DOMPurify.sanitize(html, {\n USE_PROFILES: { html: true },\n ADD_ATTR: ['target', 'rel']\n });\n}\n","'use client';\n\nimport React, { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react';\nimport * as XLSX from 'xlsx';\nimport { arrayBufferToBase64 } from '../utils/fileSource';\nimport type { DocumentMode, SupportedFileType } from '../types';\n\nexport type SpreadsheetEditorHandle = {\n save: (exportPdf?: boolean) => Promise<void>;\n requestThumbnails: (index: number) => Promise<void>;\n};\n\nexport const SpreadsheetEditor = forwardRef<SpreadsheetEditorHandle, {\n mode: DocumentMode;\n fileName: string;\n arrayBuffer?: ArrayBuffer;\n locale: Record<string, string>;\n onSave: (base64: string, meta: { fileName: string; fileType: SupportedFileType; exportedAsPdf?: boolean }) => void;\n}>(function SpreadsheetEditor(props, ref) {\n const readonly = props.mode === 'view';\n const [grid, setGrid] = useState<string[][]>(() => Array.from({ length: 30 }, () => Array.from({ length: 12 }, () => '')));\n\n useEffect(() => {\n if (!props.arrayBuffer) return;\n try {\n const wb = XLSX.read(props.arrayBuffer, { type: 'array' });\n const name = wb.SheetNames[0];\n const ws = wb.Sheets[name];\n const aoa = XLSX.utils.sheet_to_json(ws, { header: 1, raw: true }) as any[][];\n const rows = Math.max(30, aoa.length);\n const cols = Math.max(12, Math.max(...aoa.map(r => (r?.length ?? 0)), 0));\n const next = Array.from({ length: rows }, (_, r) => Array.from({ length: cols }, (_, c) => {\n const v = aoa[r]?.[c];\n return v == null ? '' : String(v);\n }));\n setGrid(next);\n } catch {\n // ignore\n }\n }, [props.arrayBuffer]);\n\n async function save(exportPdf?: boolean) {\n const ws = XLSX.utils.aoa_to_sheet(grid);\n const wb = XLSX.utils.book_new();\n XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');\n const out = XLSX.write(wb, { type: 'array', bookType: 'xlsx' }) as ArrayBuffer;\n const b64 = arrayBufferToBase64(out);\n props.onSave(b64, { fileName: ensureExt(props.fileName, 'xlsx'), fileType: 'xlsx', exportedAsPdf: !!exportPdf });\n }\n\n useImperativeHandle(ref, () => ({\n save,\n requestThumbnails: async () => undefined\n }));\n\n const cols = useMemo(() => Array.from({ length: grid[0]?.length ?? 0 }, (_, i) => String.fromCharCode(65 + (i % 26))), [grid]);\n\n return (\n <div className=\"hv-sheet\">\n <div className=\"hv-sheetbar\">\n <div className=\"hv-sheetbar-title\">{props.fileName}</div>\n {!readonly ? <button className=\"hv-btn\" type=\"button\" onClick={() => void save(false)}>{props.locale['toolbar.save'] ?? 'Save'}</button> : null}\n </div>\n <div className=\"hv-sheetgrid\" role=\"table\" aria-label=\"Spreadsheet\">\n <div className=\"hv-sheetrow hv-sheetrow--header\" role=\"row\">\n <div className=\"hv-sheetcell hv-sheetcell--corner\" role=\"columnheader\" />\n {cols.map((c, i) => <div key={i} className=\"hv-sheetcell hv-sheetcell--header\" role=\"columnheader\">{c}</div>)}\n </div>\n {grid.map((row, r) => (\n <div key={r} className=\"hv-sheetrow\" role=\"row\">\n <div className=\"hv-sheetcell hv-sheetcell--header\" role=\"rowheader\">{r + 1}</div>\n {row.map((val, c) => (\n <div\n key={c}\n className=\"hv-sheetcell\"\n role=\"cell\"\n contentEditable={!readonly}\n suppressContentEditableWarning\n onInput={(e) => {\n const text = (e.currentTarget.textContent ?? '');\n setGrid((prev) => {\n const next = prev.map(rr => rr.slice());\n next[r][c] = text;\n return next;\n });\n }}\n >{val}</div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n});\n\nfunction ensureExt(name: string, ext: string) {\n const base = name.includes('.') ? name.slice(0, name.lastIndexOf('.')) : name;\n return `${base}.${ext}`;\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport type { SupportedFileType } from '../types';\n\nexport function ImageRenderer({ arrayBuffer, fileType, fileName }: { arrayBuffer?: ArrayBuffer; fileType: SupportedFileType; fileName: string }) {\n const [zoom, setZoom] = useState(1);\n const url = useMemo(() => {\n if (!arrayBuffer) return undefined;\n const mime = fileType === 'svg' ? 'image/svg+xml' : fileType === 'png' ? 'image/png' : 'image/jpeg';\n return URL.createObjectURL(new Blob([arrayBuffer], { type: mime }));\n }, [arrayBuffer, fileType]);\n\n useEffect(() => {\n return () => { if (url) URL.revokeObjectURL(url); };\n }, [url]);\n\n return (\n <div className=\"hv-doc\">\n <div className=\"hv-mini-toolbar\">\n <div className=\"hv-title\">{fileName}</div>\n <div className=\"hv-spacer\" />\n <button type=\"button\" className=\"hv-btn\" onClick={() => setZoom((z) => Math.max(0.25, z - 0.25))}>-</button>\n <div className=\"hv-zoom\">{Math.round(zoom * 100)}%</div>\n <button type=\"button\" className=\"hv-btn\" onClick={() => setZoom((z) => Math.min(4, z + 0.25))}>+</button>\n </div>\n <div className=\"hv-center\">\n {url ? <img src={url} alt={fileName} style={{ transform: `scale(${zoom})` }} className=\"hv-image\" /> : <div className=\"hv-loading\">Loading…</div>}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport JSZip from 'jszip';\nimport type { PageLayout } from '../types';\n\ntype Slide = { index: number; text: string };\n\nfunction decodeXml(s: string): string {\n return s\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\");\n}\n\nfunction extractText(xml: string) {\n return [...xml.matchAll(/<a:t>(.*?)<\\/a:t>/g)].map(m => decodeXml(m[1] || '')).join(' ').trim();\n}\n\nexport function PptxRenderer(props: {\n arrayBuffer?: ArrayBuffer;\n layout: PageLayout;\n currentPage: number;\n onCurrentPageChange: (p: number) => void;\n onSlideCount: (n: number) => void;\n onThumbs: (thumbs: (string|undefined)[]) => void;\n}) {\n const [slides, setSlides] = useState<Slide[]>([]);\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setSlides([]); setThumbs([]);\n if (!props.arrayBuffer) { props.onSlideCount(1); setSlides([{index:1,text:'No content'}]); return; }\n const zip = await JSZip.loadAsync(props.arrayBuffer);\n const files = Object.keys(zip.files).filter(p => /^ppt\\/slides\\/slide\\d+\\.xml$/.test(p)).sort((a,b)=>{\n const na = Number(a.match(/slide(\\d+)\\.xml/)?.[1]||0);\n const nb = Number(b.match(/slide(\\d+)\\.xml/)?.[1]||0);\n return na-nb;\n });\n const out: Slide[] = [];\n for (let i=0;i<files.length;i++) {\n const xml = await zip.file(files[i])!.async('string');\n out.push({ index:i+1, text: extractText(xml) });\n }\n if (cancelled) return;\n const count = Math.max(1,out.length);\n props.onSlideCount(count);\n setSlides(out.length?out:[{index:1,text:'(empty)'}]);\n setThumbs(Array.from({length:count}, (_,i)=>`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgThumb(i+1))}`));\n })().catch(()=>{\n props.onSlideCount(1);\n setSlides([{index:1,text:'Unable to render this .pptx in-browser.'}]);\n setThumbs([undefined]);\n });\n return ()=>{cancelled=true;};\n }, [props.arrayBuffer]);\n\n useEffect(()=>{ props.onThumbs(thumbs); }, [thumbs]);\n\n const pagesToShow = useMemo(()=>{\n if (props.layout==='side-by-side') return [props.currentPage, Math.min(slides.length||props.currentPage+1, props.currentPage+1)];\n return [props.currentPage];\n }, [props.currentPage, props.layout, slides.length]);\n\n return (\n <div className=\"hv-doc\">\n <div className={props.layout==='side-by-side' ? 'hv-pages hv-pages--two' : 'hv-pages'}>\n {pagesToShow.map(p=>{\n const s = slides[p-1];\n return (\n <div key={p} className=\"hv-slide\" tabIndex={0} onFocus={()=>props.onCurrentPageChange(p)}>\n <div className=\"hv-slide-title\">Slide {p}</div>\n <div className=\"hv-slide-text\">{s?.text || ''}</div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction svgThumb(n: number) {\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"180\" height=\"100\"><rect width=\"100%\" height=\"100%\" rx=\"12\" fill=\"#111827\"/><text x=\"50%\" y=\"54%\" font-size=\"18\" fill=\"#e5e7eb\" text-anchor=\"middle\">${n}</text></svg>`;\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","url","import_react","DOMPurify","import_jsx_runtime","MarkdownIt","mammoth","html2canvas","b64","htmlToDocx","import_react","import_jsx_runtime","SpreadsheetEditor","cols","_","import_react","import_jsx_runtime","import_react","import_jsx_runtime","JSZip","import_jsx_runtime","arrayBufferToBase64"]}
1
+ {"version":3,"sources":["../src/index.tsx","../src/components/DocumentViewer.tsx","../src/utils/locale.ts","../src/utils/fileSource.ts","../src/components/Toolbar.tsx","../src/components/ThumbnailsSidebar.tsx","../src/components/SignaturePanel.tsx","../src/renderers/PdfRenderer.tsx","../src/editors/RichTextEditor.tsx","../src/utils/sanitize.ts","../src/editors/SpreadsheetEditor.tsx","../src/renderers/ImageRenderer.tsx","../src/renderers/PptxRenderer.tsx"],"sourcesContent":["export { DocumentViewer } from './components/DocumentViewer';\nexport type { DocumentViewerProps, DocumentMode, PageLayout, Signature, SupportedFileType, DocumentViewerSaveMeta } from './types';\n","'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport type { DocumentMode, DocumentViewerProps, PageLayout, Signature, SupportedFileType } from '../types';\nimport { defaultLocale } from '../utils/locale';\nimport { resolveSource } from '../utils/fileSource';\nimport { Toolbar } from './Toolbar';\nimport { ThumbnailsSidebar, type Thumbnail } from './ThumbnailsSidebar';\nimport { SignaturePanel } from './SignaturePanel';\nimport { PdfRenderer } from '../renderers/PdfRenderer';\nimport { RichTextEditor, type RichTextEditorHandle } from '../editors/RichTextEditor';\nimport { SpreadsheetEditor, type SpreadsheetEditorHandle } from '../editors/SpreadsheetEditor';\nimport { ImageRenderer } from '../renderers/ImageRenderer';\nimport { PptxRenderer } from '../renderers/PptxRenderer';\n\ntype SigPlacement = { page: number; x: number; y: number; w: number; h: number; signatureImageUrl: string };\n\ntype EditorHandle = (RichTextEditorHandle | SpreadsheetEditorHandle) & { save: (exportPdf?: boolean) => Promise<void> };\n\nexport function DocumentViewer(props: DocumentViewerProps) {\n const mode: DocumentMode = props.mode ?? 'view';\n const theme = props.theme ?? 'light';\n const locale = useMemo(() => ({ ...defaultLocale, ...(props.locale ?? {}) }), [props.locale]);\n\n const [layout, setLayout] = useState<PageLayout>(props.defaultLayout ?? 'single');\n const [showThumbnails, setShowThumbnails] = useState(true);\n const [showSignatures, setShowSignatures] = useState(true);\n const [headerFooterEnabled, setHeaderFooterEnabled] = useState(true);\n\n const allowSigning = props.allowSigning ?? false;\n const [signingBusy, setSigningBusy] = useState(false);\n\n const [resolved, setResolved] = useState<{ fileType: SupportedFileType; fileName: string; url?: string; arrayBuffer?: ArrayBuffer } | null>(null);\n const [error, setError] = useState<string>('');\n const [pageCount, setPageCount] = useState(1);\n const [currentPage, setCurrentPage] = useState(1);\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n\n const [localSignatures, setLocalSignatures] = useState<Signature[]>(props.signatures ?? []);\n useEffect(() => setLocalSignatures(props.signatures ?? []), [props.signatures]);\n\n const [sigPlacements, setSigPlacements] = useState<SigPlacement[]>([]);\n const [armedSignatureUrl, setArmedSignatureUrl] = useState<string | null>(null);\n\n const editorRef = useRef<EditorHandle | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setError('');\n setResolved(null);\n setThumbs([]);\n setPageCount(1);\n setCurrentPage(1);\n setSigPlacements([]);\n setArmedSignatureUrl(null);\n\n if (mode === 'create') {\n const ft = (props.fileType ?? 'docx') as SupportedFileType;\n setResolved({ fileType: ft, fileName: props.fileName ?? `Untitled.${ft}` });\n return;\n }\n\n try {\n const res = await resolveSource({\n fileUrl: props.fileUrl,\n base64: props.base64,\n blob: props.blob,\n fileName: props.fileName,\n fileType: props.fileType\n });\n if (cancelled) return;\n setResolved({ fileType: res.fileType, fileName: res.fileName, url: res.url, arrayBuffer: res.arrayBuffer });\n } catch (e) {\n if (cancelled) return;\n setError(e instanceof Error ? e.message : String(e));\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [mode, props.fileUrl, props.base64, props.blob, props.fileName, props.fileType]);\n\n const thumbnails: Thumbnail[] = useMemo(() => {\n const n = Math.max(1, pageCount);\n return Array.from({ length: n }, (_, i) => ({\n id: `p-${i + 1}`,\n label: `${locale['thumbnails.page'] ?? 'Page'} ${i + 1}`,\n dataUrl: thumbs[i]\n }));\n }, [pageCount, thumbs, locale]);\n\n async function handleSignRequest() {\n if (!allowSigning || signingBusy || !props.onSignRequest) return;\n setSigningBusy(true);\n try {\n const sig = await props.onSignRequest();\n setLocalSignatures((prev: Signature[]) => [...prev, sig]);\n setArmedSignatureUrl(sig.signatureImageUrl);\n } finally {\n setSigningBusy(false);\n }\n }\n\n function placeSignature(p: { page: number; x: number; y: number; w: number; h: number }) {\n if (!armedSignatureUrl) return;\n setSigPlacements((prev: SigPlacement[]) => [...prev, { ...p, signatureImageUrl: armedSignatureUrl }]);\n setArmedSignatureUrl(null);\n }\n\n async function handleSave(exportPdf?: boolean) {\n if (editorRef.current) {\n await editorRef.current.save(!!exportPdf);\n return;\n }\n if (!resolved?.arrayBuffer) return;\n const b64 = arrayBufferToBase64(resolved.arrayBuffer);\n props.onSave?.(b64, { fileName: resolved.fileName, fileType: resolved.fileType, annotations: { sigPlacements } });\n }\n\n const canSave = mode === 'edit' || mode === 'create';\n const canExportPdf = (mode === 'edit' || mode === 'create') && (resolved?.fileType === 'docx' || resolved?.fileType === 'md' || resolved?.fileType === 'txt' || resolved?.fileType === 'xlsx');\n\n return (\n <div className={`hv-root`} data-hv-theme={theme}>\n <Toolbar\n locale={locale}\n mode={mode}\n fileType={resolved?.fileType}\n layout={layout}\n onChangeLayout={setLayout}\n showThumbnails={showThumbnails}\n onToggleThumbnails={() => setShowThumbnails((v: boolean) => !v)}\n showSignatures={showSignatures}\n onToggleSignatures={() => setShowSignatures((v: boolean) => !v)}\n onSign={() => void handleSignRequest()}\n allowSigning={allowSigning}\n signingDisabled={signingBusy || !props.onSignRequest}\n canSave={canSave}\n onSave={() => void handleSave(false)}\n canExportPdf={canExportPdf}\n onExportPdf={() => void handleSave(true)}\n headerFooterEnabled={headerFooterEnabled}\n showHeaderFooterToggle={(props.enableHeaderFooterToggle ?? true) && mode === 'create'}\n onToggleHeaderFooter={() => setHeaderFooterEnabled((v: boolean) => !v)}\n />\n\n {error ? (\n <div className=\"hv-error\" role=\"alert\">\n <div className=\"hv-error-title\">{locale['error.title'] ?? 'Error'}</div>\n <div className=\"hv-error-body\">{error}</div>\n </div>\n ) : null}\n\n {!resolved && !error ? <div className=\"hv-loading\" aria-busy=\"true\">{locale['loading'] ?? 'Loading…'}</div> : null}\n\n {resolved ? (\n <div className=\"hv-shell\">\n {mode !== 'create' ? (\n <ThumbnailsSidebar\n locale={locale}\n thumbnails={thumbnails}\n currentPage={currentPage}\n collapsed={!showThumbnails}\n onToggle={() => setShowThumbnails((v: boolean) => !v)}\n onSelectPage={setCurrentPage}\n />\n ) : null}\n\n <main className=\"hv-main\">\n {resolved.fileType === 'pdf' ? (\n <PdfRenderer\n url={resolved.url}\n arrayBuffer={resolved.arrayBuffer}\n layout={layout}\n currentPage={currentPage}\n onCurrentPageChange={setCurrentPage}\n onPageCount={(n) => {\n setPageCount(n);\n setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])));\n }}\n onThumbs={(t) => setThumbs(t)}\n signatureStamp={armedSignatureUrl ? { imageUrl: armedSignatureUrl, armed: true, onPlaced: placeSignature } : undefined}\n />\n ) : null}\n\n {resolved.fileType === 'docx' || resolved.fileType === 'md' || resolved.fileType === 'txt' ? (\n <RichTextEditor\n ref={editorRef as any}\n mode={mode}\n fileType={resolved.fileType}\n fileName={resolved.fileName}\n arrayBuffer={resolved.arrayBuffer}\n headerComponent={props.headerComponent}\n footerComponent={props.footerComponent}\n headerFooterEnabled={headerFooterEnabled}\n locale={locale}\n signatures={localSignatures}\n signaturePlacements={sigPlacements}\n onPageCount={(n) => { setPageCount(n); setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i]))); }}\n onSave={(b64, meta) => props.onSave?.(b64, meta)}\n armedSignatureUrl={armedSignatureUrl}\n onPlaceSignature={placeSignature}\n />\n ) : null}\n\n {resolved.fileType === 'xlsx' ? (\n <SpreadsheetEditor\n ref={editorRef as any}\n mode={mode}\n fileName={resolved.fileName}\n arrayBuffer={resolved.arrayBuffer}\n locale={locale}\n onSave={(b64, meta) => props.onSave?.(b64, meta)}\n />\n ) : null}\n\n {resolved.fileType === 'pptx' ? (\n <PptxRenderer\n arrayBuffer={resolved.arrayBuffer}\n layout={layout}\n currentPage={currentPage}\n onCurrentPageChange={setCurrentPage}\n onSlideCount={(n) => {\n setPageCount(n);\n setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])));\n }}\n onThumbs={(t) => setThumbs(t)}\n />\n ) : null}\n\n {resolved.fileType === 'png' || resolved.fileType === 'jpg' || resolved.fileType === 'svg' ? (\n <ImageRenderer arrayBuffer={resolved.arrayBuffer} fileType={resolved.fileType} fileName={resolved.fileName} />\n ) : null}\n </main>\n\n {mode !== 'create' && localSignatures.length ? (\n <SignaturePanel\n locale={locale}\n signatures={localSignatures}\n collapsed={!showSignatures}\n onToggle={() => setShowSignatures((v: boolean) => !v)}\n />\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction arrayBufferToBase64(ab: ArrayBuffer): string {\n const bytes = new Uint8Array(ab);\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n","export const defaultLocale: Record<string, string> = {\n 'loading': 'Loading…',\n 'error.title': 'Error',\n 'toolbar.layout.single': 'Single page',\n 'toolbar.layout.two': 'Side-by-side',\n 'toolbar.thumbs': 'Thumbnails',\n 'toolbar.signatures': 'Signatures',\n 'toolbar.sign': 'Sign Document',\n 'toolbar.save': 'Save',\n 'toolbar.exportPdf': 'Export as PDF',\n 'thumbnails.title': 'Thumbnails',\n 'thumbnails.page': 'Page',\n 'signatures.title': 'Signatures',\n 'signatures.empty': 'No signatures',\n 'signatures.placeHint': 'Click on the document to place the signature.',\n 'a11y.viewer': 'Document viewer',\n 'a11y.ribbon': 'Ribbon',\n 'a11y.editor': 'Document editor'\n};\n","import type { SupportedFileType } from '../types';\n\nexport function guessFileType(name?: string, explicit?: SupportedFileType): SupportedFileType {\n if (explicit) return explicit;\n const ext = (name?.split('.').pop() || '').toLowerCase();\n const allowed: SupportedFileType[] = ['pdf','md','docx','xlsx','pptx','txt','png','jpg','svg'];\n return (allowed as string[]).includes(ext) ? (ext as SupportedFileType) : 'txt';\n}\n\nexport function arrayBufferToBase64(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n\nexport async function base64ToArrayBuffer(b64: string): Promise<ArrayBuffer> {\n const bin = atob(b64);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes.buffer;\n}\n\nexport async function resolveSource(args: {\n fileUrl?: string;\n base64?: string;\n blob?: Blob;\n fileName?: string;\n fileType?: SupportedFileType;\n onProgress?: (loaded: number, total?: number) => void;\n}): Promise<{ fileType: SupportedFileType; fileName: string; arrayBuffer: ArrayBuffer; url?: string }>{\n const fileType = guessFileType(args.fileName, args.fileType);\n const fileName = args.fileName ?? `document.${fileType}`;\n\n if (args.blob) {\n const ab = await args.blob.arrayBuffer();\n const url = URL.createObjectURL(args.blob);\n return { fileType, fileName, arrayBuffer: ab, url };\n }\n\n if (args.base64) {\n const ab = await base64ToArrayBuffer(args.base64);\n return { fileType, fileName, arrayBuffer: ab };\n }\n\n if (!args.fileUrl) throw new Error('No file source provided. Use fileUrl, blob, or base64.');\n\n const res = await fetch(args.fileUrl);\n if (!res.ok) throw new Error(`Failed to fetch file (${res.status})`);\n\n const total = Number(res.headers.get('content-length') || '') || undefined;\n if (!res.body) {\n const ab = await res.arrayBuffer();\n args.onProgress?.(ab.byteLength, total);\n return { fileType, fileName, arrayBuffer: ab, url: args.fileUrl };\n }\n\n const reader = res.body.getReader();\n const chunks: Uint8Array[] = [];\n let loaded = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) {\n chunks.push(value);\n loaded += value.length;\n args.onProgress?.(loaded, total);\n }\n }\n const out = new Uint8Array(loaded);\n let offset = 0;\n for (const c of chunks) { out.set(c, offset); offset += c.length; }\n return { fileType, fileName, arrayBuffer: out.buffer, url: args.fileUrl };\n}\n","'use client';\n\nimport React from 'react';\nimport type { DocumentMode, PageLayout, SupportedFileType } from '../types';\n\nexport function Toolbar(props: {\n locale: Record<string, string>;\n mode: DocumentMode;\n fileType?: SupportedFileType;\n layout: PageLayout;\n onChangeLayout: (l: PageLayout) => void;\n showThumbnails: boolean;\n onToggleThumbnails: () => void;\n showSignatures: boolean;\n onToggleSignatures: () => void;\n allowSigning: boolean;\n signingDisabled: boolean;\n onSign: () => void;\n canSave: boolean;\n onSave: () => void;\n canExportPdf: boolean;\n onExportPdf: () => void;\n showHeaderFooterToggle: boolean;\n headerFooterEnabled: boolean;\n onToggleHeaderFooter: () => void;\n}) {\n const t = (k: string, fallback: string) => props.locale[k] ?? fallback;\n\n return (\n <div className=\"hv-toolbar\" role=\"toolbar\" aria-label={t('a11y.toolbar', 'Document toolbar')}>\n <div className=\"hv-toolbar__left\">\n <button type=\"button\" className=\"hv-btn\" onClick={props.onToggleThumbnails} aria-pressed={props.showThumbnails}>\n {t('toolbar.thumbs', 'Thumbnails')}\n </button>\n {props.mode !== 'create' && (\n <button type=\"button\" className=\"hv-btn\" onClick={props.onToggleSignatures} aria-pressed={props.showSignatures}>\n {t('toolbar.signatures', 'Signatures')}\n </button>\n )}\n <span className=\"hv-sep\" />\n <button type=\"button\" className={props.layout === 'single' ? 'hv-btn hv-btn--active' : 'hv-btn'} onClick={() => props.onChangeLayout('single')}>\n {t('toolbar.layout.single', 'Single')}\n </button>\n <button type=\"button\" className={props.layout === 'side-by-side' ? 'hv-btn hv-btn--active' : 'hv-btn'} onClick={() => props.onChangeLayout('side-by-side')}>\n {t('toolbar.layout.two', 'Two')}\n </button>\n </div>\n\n <div className=\"hv-toolbar__right\">\n {props.showHeaderFooterToggle && (\n <label className=\"hv-toggle\">\n <input type=\"checkbox\" checked={props.headerFooterEnabled} onChange={props.onToggleHeaderFooter} />\n <span>{t('toolbar.letterhead', 'Letterhead')}</span>\n </label>\n )}\n\n {props.allowSigning && (\n <button type=\"button\" className=\"hv-btn hv-btn--primary\" onClick={props.onSign} disabled={props.signingDisabled}>\n {t('toolbar.sign', 'Sign Document')}\n </button>\n )}\n\n {props.canExportPdf && (\n <button type=\"button\" className=\"hv-btn\" onClick={props.onExportPdf}>\n {t('toolbar.exportPdf', 'Export as PDF')}\n </button>\n )}\n {props.canSave && (\n <button type=\"button\" className=\"hv-btn hv-btn--primary\" onClick={props.onSave}>\n {t('toolbar.save', 'Save')}\n </button>\n )}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport React from 'react';\n\nexport type Thumbnail = {\n id: string;\n label: string;\n dataUrl?: string;\n};\n\nexport function ThumbnailsSidebar(props: {\n locale: Record<string, string>;\n thumbnails: Thumbnail[];\n currentPage: number;\n collapsed: boolean;\n onToggle: () => void;\n onSelectPage: (p: number) => void;\n}) {\n const t = props.locale['thumbnails.title'] ?? 'Thumbnails';\n return (\n <aside className={props.collapsed ? 'hv-thumbs hv-thumbs--collapsed' : 'hv-thumbs'} aria-label={t}>\n <div className=\"hv-thumbs__header\">\n <button type=\"button\" className=\"hv-icon\" onClick={props.onToggle} aria-label={props.collapsed ? (props.locale['thumbnails.open'] ?? 'Open thumbnails') : (props.locale['thumbnails.close'] ?? 'Close thumbnails')}\n >{props.collapsed ? '▸' : '▾'}</button>\n {!props.collapsed ? <div className=\"hv-thumbs__title\">{t}</div> : null}\n </div>\n {!props.collapsed ? (\n <div className=\"hv-thumbs__list\" role=\"list\">\n {props.thumbnails.map((th, idx) => {\n const p = idx + 1;\n const active = p === props.currentPage;\n return (\n <button\n key={th.id}\n type=\"button\"\n role=\"listitem\"\n className={active ? 'hv-thumb hv-thumb--active' : 'hv-thumb'}\n onClick={() => props.onSelectPage(p)}\n aria-current={active ? 'page' : undefined}\n >\n <div className=\"hv-thumb__img\" aria-hidden>\n {th.dataUrl ? <img src={th.dataUrl} alt=\"\" /> : <div className=\"hv-thumb__placeholder\" />}\n </div>\n <div className=\"hv-thumb__label\">{th.label}</div>\n </button>\n );\n })}\n </div>\n ) : null}\n </aside>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport type { Signature } from '../types';\n\nexport function SignaturePanel(props: {\n locale: Record<string, string>;\n signatures: Signature[];\n collapsed: boolean;\n onToggle: () => void;\n}) {\n const title = props.locale['signatures.title'] ?? 'Signatures';\n return (\n <aside className={props.collapsed ? 'hv-side hv-side--collapsed' : 'hv-side'} aria-label={title}>\n <div className=\"hv-sidebar-header\">\n <button type=\"button\" className=\"hv-icon\" onClick={props.onToggle} aria-label={props.locale['toolbar.signatures'] ?? 'Signatures'}>\n ✍\n </button>\n <div className=\"hv-sidebar-title\">{title}</div>\n </div>\n <div className=\"hv-sidebar-body\">\n {props.signatures.map((s, idx) => (\n <div key={`${s.signedBy}-${s.dateSigned}-${idx}`} className=\"hv-signature-card\">\n <img src={s.signatureImageUrl} alt={`Signature by ${s.signedBy}`} className=\"hv-signature-img\" />\n <div className=\"hv-signature-meta\">\n <div className=\"hv-signature-name\">{s.signedBy}</div>\n <div className=\"hv-signature-date\">{new Date(s.dateSigned).toLocaleString()}</div>\n {s.comment ? <div className=\"hv-signature-comment\">{s.comment}</div> : null}\n </div>\n </div>\n ))}\n </div>\n </aside>\n );\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { GlobalWorkerOptions, getDocument, type PDFDocumentProxy } from 'pdfjs-dist';\nimport type { PageLayout } from '../types';\n\nexport function PdfRenderer(props: {\n url?: string;\n arrayBuffer?: ArrayBuffer;\n layout: PageLayout;\n currentPage: number;\n onCurrentPageChange: (p: number) => void;\n onPageCount: (n: number) => void;\n onThumbs: (thumbs: (string | undefined)[]) => void;\n signatureStamp?: {\n imageUrl: string;\n armed: boolean;\n onPlaced: (placement: { page: number; x: number; y: number; w: number; h: number }) => void;\n };\n}) {\n const { url, arrayBuffer } = props;\n const [doc, setDoc] = useState<PDFDocumentProxy | null>(null);\n const [pageCount, setPageCount] = useState(0);\n const [rendered, setRendered] = useState<Map<number, HTMLCanvasElement>>(new Map());\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n const [size, setSize] = useState({ w: 840, h: 1188 });\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n try {\n GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString();\n } catch {}\n }, []);\n\n useEffect(() => {\n let cancel = false;\n (async () => {\n setDoc(null);\n setRendered(new Map());\n setThumbs([]);\n if (!url && !arrayBuffer) return;\n const task = getDocument(url ? { url, rangeChunkSize: 512 * 1024 } : { data: arrayBuffer! });\n const pdf = await task.promise;\n if (cancel) return;\n setDoc(pdf);\n setPageCount(pdf.numPages);\n props.onPageCount(pdf.numPages);\n setThumbs(Array.from({ length: pdf.numPages }));\n const p1 = await pdf.getPage(1);\n const base = p1.getViewport({ scale: 1 });\n const w = Math.min(980, Math.max(640, base.width));\n const s = w / base.width;\n const vp = p1.getViewport({ scale: s });\n setSize({ w: Math.round(vp.width), h: Math.round(vp.height) });\n })().catch(() => {\n // ignore; caller shows error\n });\n return () => { cancel = true; };\n }, [url, arrayBuffer]);\n\n useEffect(() => {\n props.onThumbs(thumbs);\n }, [thumbs]);\n\n const pagesToShow = useMemo(() => {\n if (props.layout === 'side-by-side') {\n const left = props.currentPage;\n const right = Math.min(pageCount || left + 1, left + 1);\n return [left, right];\n }\n return [props.currentPage];\n }, [props.currentPage, props.layout, pageCount]);\n\n useEffect(() => {\n if (!doc) return;\n let cancel = false;\n (async () => {\n for (const p of pagesToShow) {\n if (rendered.has(p)) continue;\n const page = await doc.getPage(p);\n if (cancel) return;\n const base = page.getViewport({ scale: 1 });\n const vp = page.getViewport({ scale: size.w / base.width });\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(vp.width);\n canvas.height = Math.round(vp.height);\n const ctx = canvas.getContext('2d', { alpha: false });\n if (!ctx) continue;\n await page.render({ canvasContext: ctx, viewport: vp }).promise;\n if (cancel) return;\n setRendered(prev => {\n const next = new Map(prev);\n next.set(p, canvas);\n return next;\n });\n try {\n const tw = 140;\n const th = Math.round(tw * (canvas.height / canvas.width));\n const t = document.createElement('canvas');\n t.width = tw; t.height = th;\n const tctx = t.getContext('2d');\n if (tctx) {\n tctx.drawImage(canvas, 0, 0, tw, th);\n const url = t.toDataURL('image/jpeg', 0.75);\n setThumbs(prev => {\n const next = prev.slice();\n next[p - 1] = url;\n return next;\n });\n }\n } catch {}\n }\n })();\n return () => { cancel = true; };\n }, [doc, pagesToShow, size.w, rendered]);\n\n function onWheel(e: React.WheelEvent) {\n if (!pageCount) return;\n if (Math.abs(e.deltaY) < 10) return;\n const dir = e.deltaY > 0 ? 1 : -1;\n const step = props.layout === 'side-by-side' ? 2 : 1;\n const next = Math.max(1, Math.min(pageCount, props.currentPage + dir * step));\n props.onCurrentPageChange(next);\n }\n\n function clickPlace(e: React.MouseEvent, page: number) {\n const stamp = props.signatureStamp;\n if (!stamp?.armed) return;\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const x = (e.clientX - rect.left) / rect.width;\n const y = (e.clientY - rect.top) / rect.height;\n stamp.onPlaced({ page, x, y, w: 0.22, h: 0.08 });\n }\n\n return (\n <div className=\"hv-doc\" ref={containerRef} onWheel={onWheel}>\n {!doc ? <div className=\"hv-loading\">Loading PDF…</div> : null}\n {doc ? (\n <div className={props.layout === 'side-by-side' ? 'hv-pages hv-pages--two' : 'hv-pages'}>\n {pagesToShow.map(p => {\n const c = rendered.get(p);\n return (\n <div key={p} className=\"hv-page\" style={{ width: size.w, height: size.h }} onClick={(e) => clickPlace(e, p)}>\n {c ? (\n <canvas\n className=\"hv-canvas\"\n width={c.width}\n height={c.height}\n ref={(node) => {\n if (!node) return;\n const ctx = node.getContext('2d');\n if (ctx) ctx.drawImage(c, 0, 0);\n }}\n />\n ) : <div className=\"hv-loading\">Rendering…</div>}\n </div>\n );\n })}\n </div>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\nimport React, {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport mammoth from \"mammoth\";\n// Do not statically import html-to-docx; use dynamic import for browser compatibility\nimport MarkdownIt from \"markdown-it\";\nimport html2canvas from \"html2canvas\";\nimport { sanitizeHtml } from \"../utils/sanitize\";\nimport { arrayBufferToBase64 } from \"../utils/fileSource\";\nimport type { DocumentMode, Signature, SupportedFileType } from \"../types\";\n\nconst PAGE_H = 1122; // virtual A4\n\nexport type RichTextEditorHandle = {\n save: (exportPdf?: boolean) => Promise<void>;\n requestThumbnail: (index: number) => Promise<string | undefined>;\n};\n\nexport const RichTextEditor = forwardRef<\n RichTextEditorHandle,\n {\n mode: DocumentMode;\n fileType: \"docx\" | \"md\" | \"txt\";\n fileName: string;\n arrayBuffer?: ArrayBuffer;\n locale: Record<string, string>;\n headerComponent?: React.ReactNode;\n footerComponent?: React.ReactNode;\n headerFooterEnabled: boolean;\n signatures: Signature[];\n signaturePlacements: {\n page: number;\n x: number;\n y: number;\n w: number;\n h: number;\n signatureImageUrl: string;\n }[];\n armedSignatureUrl: string | null;\n onPlaceSignature: (p: {\n page: number;\n x: number;\n y: number;\n w: number;\n h: number;\n }) => void;\n onSave: (\n b64: string,\n meta: {\n fileName: string;\n fileType: SupportedFileType;\n exportedAsPdf?: boolean;\n annotations?: unknown;\n },\n ) => void;\n onPageCount: (n: number) => void;\n }\n>((props, ref) => {\n const readOnly = props.mode === \"view\";\n const md = useMemo(\n () => new MarkdownIt({ html: false, linkify: true, breaks: true }),\n [],\n );\n const scrollerRef = useRef<HTMLDivElement | null>(null);\n const editorRef = useRef<HTMLDivElement | null>(null);\n const captureRef = useRef<HTMLDivElement | null>(null);\n\n const [html, setHtml] = useState(\"<p><br/></p>\");\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n if (props.mode === \"create\") {\n setHtml(\"<p><br/></p>\");\n return;\n }\n if (!props.arrayBuffer) return;\n if (props.fileType === \"docx\") {\n const res = await mammoth.convertToHtml({\n arrayBuffer: props.arrayBuffer,\n });\n if (!cancelled) setHtml(sanitizeHtml(res.value || \"<p><br/></p>\"));\n } else {\n const text = new TextDecoder().decode(props.arrayBuffer);\n if (props.fileType === \"md\") setHtml(sanitizeHtml(md.render(text)));\n else setHtml(`<pre>${escapeHtml(text)}</pre>`);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [props.arrayBuffer, props.fileType, props.mode, md]);\n\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return;\n const recompute = () =>\n props.onPageCount(Math.max(1, Math.ceil(el.scrollHeight / PAGE_H)));\n recompute();\n const ro = new ResizeObserver(recompute);\n ro.observe(el);\n return () => ro.disconnect();\n }, [html, props.headerFooterEnabled]);\n\n function exec(cmd: string) {\n if (readOnly) return;\n document.execCommand(cmd);\n }\n\n function onClick(e: React.MouseEvent<HTMLDivElement>) {\n if (!props.armedSignatureUrl) return;\n const scroller = scrollerRef.current;\n if (!scroller) return;\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const absY = scroller.scrollTop + (e.clientY - rect.top);\n const page = Math.max(1, Math.floor(absY / PAGE_H) + 1);\n const pageTop = (page - 1) * PAGE_H;\n const x = (e.clientX - rect.left) / rect.width;\n const y = (absY - pageTop) / PAGE_H;\n props.onPlaceSignature({ page, x, y, w: 0.25, h: 0.1 });\n }\n\n async function requestThumbnail(index: number): Promise<string | undefined> {\n const scroller = scrollerRef.current;\n const capture = captureRef.current;\n if (!scroller || !capture) return undefined;\n const old = scroller.scrollTop;\n scroller.scrollTop = index * PAGE_H;\n await new Promise((r) => requestAnimationFrame(() => r(null)));\n try {\n const canvas = await html2canvas(capture, {\n backgroundColor: null,\n scale: 0.25,\n useCORS: true,\n });\n return canvas.toDataURL(\"image/png\");\n } catch {\n return undefined;\n } finally {\n scroller.scrollTop = old;\n }\n }\n\n async function save(exportPdf?: boolean) {\n const inner = editorRef.current?.innerHTML ?? html;\n const stitched = `<!doctype html><html><head><meta charset=\"utf-8\" /></head><body>${inner}</body></html>`;\n\n if (exportPdf) {\n // client-side: return print-ready HTML as base64\n const b64 = btoa(unescape(encodeURIComponent(stitched)));\n props.onSave(b64, {\n fileName: replaceExt(props.fileName, \"html\"),\n fileType: \"txt\",\n exportedAsPdf: true,\n annotations: { signaturePlacements: props.signaturePlacements },\n });\n return;\n }\n\n if (props.fileType === \"docx\") {\n // Only attempt to import html-to-docx at runtime\n try {\n // @ts-ignore\n const htmlToDocx = (await import(\"html-to-docx\")).default;\n const blob = await htmlToDocx(stitched);\n const ab = await blob.arrayBuffer();\n props.onSave(arrayBufferToBase64(ab), {\n fileName: replaceExt(props.fileName, \"docx\"),\n fileType: \"docx\",\n annotations: { signaturePlacements: props.signaturePlacements },\n });\n } catch (err) {\n // Show a user-friendly error if running in the browser or import fails\n alert(\n \"DOCX export is not supported in this environment. Please use this feature in a Node.js/server context.\",\n );\n }\n return;\n }\n\n const text = editorRef.current?.innerText ?? \"\";\n const b64 = btoa(unescape(encodeURIComponent(text)));\n props.onSave(b64, {\n fileName: replaceExt(props.fileName, props.fileType),\n fileType: props.fileType,\n annotations: { signaturePlacements: props.signaturePlacements },\n });\n }\n\n useImperativeHandle(ref, () => ({ save, requestThumbnail }));\n\n return (\n <div className=\"hv-doc\">\n <div className=\"hv-ribbon\" role=\"toolbar\">\n <button\n className=\"hv-btn\"\n onClick={() => exec(\"bold\")}\n disabled={readOnly}\n >\n B\n </button>\n <button\n className=\"hv-btn\"\n onClick={() => exec(\"italic\")}\n disabled={readOnly}\n >\n I\n </button>\n <button\n className=\"hv-btn\"\n onClick={() => exec(\"underline\")}\n disabled={readOnly}\n >\n U\n </button>\n {props.armedSignatureUrl ? (\n <div className=\"hv-hint\">Click to place signature</div>\n ) : null}\n </div>\n\n <div className=\"hv-scroll\" ref={scrollerRef} onClick={onClick}>\n <div className=\"hv-pageStage\" ref={captureRef}>\n {props.headerFooterEnabled && props.headerComponent ? (\n <div className=\"hv-letterhead\">{props.headerComponent}</div>\n ) : null}\n\n <div\n ref={editorRef}\n className={readOnly ? \"hv-editor hv-editor--ro\" : \"hv-editor\"}\n contentEditable={!readOnly}\n suppressContentEditableWarning\n onInput={() => setHtml(editorRef.current?.innerHTML ?? \"\")}\n dangerouslySetInnerHTML={{ __html: html }}\n />\n\n {props.headerFooterEnabled && props.footerComponent ? (\n <div className=\"hv-letterhead hv-letterhead--footer\">\n {props.footerComponent}\n </div>\n ) : null}\n\n {props.mode === \"create\" && props.signatures.length ? (\n <div className=\"hv-signatures-inline\">\n {props.signatures.map((s, i) => (\n <div key={i} className=\"hv-sign-inline\">\n <img\n src={s.signatureImageUrl}\n alt=\"\"\n className=\"hv-sign-img\"\n />\n <div>\n <div className=\"hv-sign-name\">{s.signedBy}</div>\n <div className=\"hv-sign-date\">\n {new Date(s.dateSigned).toLocaleString()}\n </div>\n </div>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n </div>\n );\n});\n\nfunction replaceExt(name: string, ext: string) {\n const base = name.includes(\".\") ? name.slice(0, name.lastIndexOf(\".\")) : name;\n return `${base}.${ext}`;\n}\n\nfunction escapeHtml(s: string) {\n return s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n","import DOMPurify from 'dompurify';\n\nexport function sanitizeHtml(html: string): string {\n // DOMPurify is safe to call in the browser. For SSR, callers should only run after mount.\n return DOMPurify.sanitize(html, {\n USE_PROFILES: { html: true },\n ADD_ATTR: ['target', 'rel']\n });\n}\n","'use client';\n\nimport React, { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react';\nimport * as XLSX from 'xlsx';\nimport { arrayBufferToBase64 } from '../utils/fileSource';\nimport type { DocumentMode, SupportedFileType } from '../types';\n\nexport type SpreadsheetEditorHandle = {\n save: (exportPdf?: boolean) => Promise<void>;\n requestThumbnails: (index: number) => Promise<void>;\n};\n\nexport const SpreadsheetEditor = forwardRef<SpreadsheetEditorHandle, {\n mode: DocumentMode;\n fileName: string;\n arrayBuffer?: ArrayBuffer;\n locale: Record<string, string>;\n onSave: (base64: string, meta: { fileName: string; fileType: SupportedFileType; exportedAsPdf?: boolean }) => void;\n}>(function SpreadsheetEditor(props, ref) {\n const readonly = props.mode === 'view';\n const [grid, setGrid] = useState<string[][]>(() => Array.from({ length: 30 }, () => Array.from({ length: 12 }, () => '')));\n\n useEffect(() => {\n if (!props.arrayBuffer) return;\n try {\n const wb = XLSX.read(props.arrayBuffer, { type: 'array' });\n const name = wb.SheetNames[0];\n const ws = wb.Sheets[name];\n const aoa = XLSX.utils.sheet_to_json(ws, { header: 1, raw: true }) as any[][];\n const rows = Math.max(30, aoa.length);\n const cols = Math.max(12, Math.max(...aoa.map(r => (r?.length ?? 0)), 0));\n const next = Array.from({ length: rows }, (_, r) => Array.from({ length: cols }, (_, c) => {\n const v = aoa[r]?.[c];\n return v == null ? '' : String(v);\n }));\n setGrid(next);\n } catch {\n // ignore\n }\n }, [props.arrayBuffer]);\n\n async function save(exportPdf?: boolean) {\n const ws = XLSX.utils.aoa_to_sheet(grid);\n const wb = XLSX.utils.book_new();\n XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');\n const out = XLSX.write(wb, { type: 'array', bookType: 'xlsx' }) as ArrayBuffer;\n const b64 = arrayBufferToBase64(out);\n props.onSave(b64, { fileName: ensureExt(props.fileName, 'xlsx'), fileType: 'xlsx', exportedAsPdf: !!exportPdf });\n }\n\n useImperativeHandle(ref, () => ({\n save,\n requestThumbnails: async () => undefined\n }));\n\n const cols = useMemo(() => Array.from({ length: grid[0]?.length ?? 0 }, (_, i) => String.fromCharCode(65 + (i % 26))), [grid]);\n\n return (\n <div className=\"hv-sheet\">\n <div className=\"hv-sheetbar\">\n <div className=\"hv-sheetbar-title\">{props.fileName}</div>\n {!readonly ? <button className=\"hv-btn\" type=\"button\" onClick={() => void save(false)}>{props.locale['toolbar.save'] ?? 'Save'}</button> : null}\n </div>\n <div className=\"hv-sheetgrid\" role=\"table\" aria-label=\"Spreadsheet\">\n <div className=\"hv-sheetrow hv-sheetrow--header\" role=\"row\">\n <div className=\"hv-sheetcell hv-sheetcell--corner\" role=\"columnheader\" />\n {cols.map((c, i) => <div key={i} className=\"hv-sheetcell hv-sheetcell--header\" role=\"columnheader\">{c}</div>)}\n </div>\n {grid.map((row, r) => (\n <div key={r} className=\"hv-sheetrow\" role=\"row\">\n <div className=\"hv-sheetcell hv-sheetcell--header\" role=\"rowheader\">{r + 1}</div>\n {row.map((val, c) => (\n <div\n key={c}\n className=\"hv-sheetcell\"\n role=\"cell\"\n contentEditable={!readonly}\n suppressContentEditableWarning\n onInput={(e) => {\n const text = (e.currentTarget.textContent ?? '');\n setGrid((prev) => {\n const next = prev.map(rr => rr.slice());\n next[r][c] = text;\n return next;\n });\n }}\n >{val}</div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n});\n\nfunction ensureExt(name: string, ext: string) {\n const base = name.includes('.') ? name.slice(0, name.lastIndexOf('.')) : name;\n return `${base}.${ext}`;\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport type { SupportedFileType } from '../types';\n\nexport function ImageRenderer({ arrayBuffer, fileType, fileName }: { arrayBuffer?: ArrayBuffer; fileType: SupportedFileType; fileName: string }) {\n const [zoom, setZoom] = useState(1);\n const url = useMemo(() => {\n if (!arrayBuffer) return undefined;\n const mime = fileType === 'svg' ? 'image/svg+xml' : fileType === 'png' ? 'image/png' : 'image/jpeg';\n return URL.createObjectURL(new Blob([arrayBuffer], { type: mime }));\n }, [arrayBuffer, fileType]);\n\n useEffect(() => {\n return () => { if (url) URL.revokeObjectURL(url); };\n }, [url]);\n\n return (\n <div className=\"hv-doc\">\n <div className=\"hv-mini-toolbar\">\n <div className=\"hv-title\">{fileName}</div>\n <div className=\"hv-spacer\" />\n <button type=\"button\" className=\"hv-btn\" onClick={() => setZoom((z) => Math.max(0.25, z - 0.25))}>-</button>\n <div className=\"hv-zoom\">{Math.round(zoom * 100)}%</div>\n <button type=\"button\" className=\"hv-btn\" onClick={() => setZoom((z) => Math.min(4, z + 0.25))}>+</button>\n </div>\n <div className=\"hv-center\">\n {url ? <img src={url} alt={fileName} style={{ transform: `scale(${zoom})` }} className=\"hv-image\" /> : <div className=\"hv-loading\">Loading…</div>}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport JSZip from 'jszip';\nimport type { PageLayout } from '../types';\n\ntype Slide = { index: number; text: string };\n\nfunction decodeXml(s: string): string {\n return s\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\");\n}\n\nfunction extractText(xml: string) {\n return [...xml.matchAll(/<a:t>(.*?)<\\/a:t>/g)].map(m => decodeXml(m[1] || '')).join(' ').trim();\n}\n\nexport function PptxRenderer(props: {\n arrayBuffer?: ArrayBuffer;\n layout: PageLayout;\n currentPage: number;\n onCurrentPageChange: (p: number) => void;\n onSlideCount: (n: number) => void;\n onThumbs: (thumbs: (string|undefined)[]) => void;\n}) {\n const [slides, setSlides] = useState<Slide[]>([]);\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setSlides([]); setThumbs([]);\n if (!props.arrayBuffer) { props.onSlideCount(1); setSlides([{index:1,text:'No content'}]); return; }\n const zip = await JSZip.loadAsync(props.arrayBuffer);\n const files = Object.keys(zip.files).filter(p => /^ppt\\/slides\\/slide\\d+\\.xml$/.test(p)).sort((a,b)=>{\n const na = Number(a.match(/slide(\\d+)\\.xml/)?.[1]||0);\n const nb = Number(b.match(/slide(\\d+)\\.xml/)?.[1]||0);\n return na-nb;\n });\n const out: Slide[] = [];\n for (let i=0;i<files.length;i++) {\n const xml = await zip.file(files[i])!.async('string');\n out.push({ index:i+1, text: extractText(xml) });\n }\n if (cancelled) return;\n const count = Math.max(1,out.length);\n props.onSlideCount(count);\n setSlides(out.length?out:[{index:1,text:'(empty)'}]);\n setThumbs(Array.from({length:count}, (_,i)=>`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgThumb(i+1))}`));\n })().catch(()=>{\n props.onSlideCount(1);\n setSlides([{index:1,text:'Unable to render this .pptx in-browser.'}]);\n setThumbs([undefined]);\n });\n return ()=>{cancelled=true;};\n }, [props.arrayBuffer]);\n\n useEffect(()=>{ props.onThumbs(thumbs); }, [thumbs]);\n\n const pagesToShow = useMemo(()=>{\n if (props.layout==='side-by-side') return [props.currentPage, Math.min(slides.length||props.currentPage+1, props.currentPage+1)];\n return [props.currentPage];\n }, [props.currentPage, props.layout, slides.length]);\n\n return (\n <div className=\"hv-doc\">\n <div className={props.layout==='side-by-side' ? 'hv-pages hv-pages--two' : 'hv-pages'}>\n {pagesToShow.map(p=>{\n const s = slides[p-1];\n return (\n <div key={p} className=\"hv-slide\" tabIndex={0} onFocus={()=>props.onCurrentPageChange(p)}>\n <div className=\"hv-slide-title\">Slide {p}</div>\n <div className=\"hv-slide-text\">{s?.text || ''}</div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction svgThumb(n: number) {\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"180\" height=\"100\"><rect width=\"100%\" height=\"100%\" rx=\"12\" fill=\"#111827\"/><text x=\"50%\" y=\"54%\" font-size=\"18\" fill=\"#e5e7eb\" text-anchor=\"middle\">${n}</text></svg>`;\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","url","import_react","DOMPurify","import_jsx_runtime","MarkdownIt","mammoth","html2canvas","b64","import_react","import_jsx_runtime","SpreadsheetEditor","cols","_","import_react","import_jsx_runtime","import_react","import_jsx_runtime","JSZip","import_jsx_runtime","arrayBufferToBase64"]}
package/dist/index.js CHANGED
@@ -310,9 +310,15 @@ function PdfRenderer(props) {
310
310
  }
311
311
 
312
312
  // src/editors/RichTextEditor.tsx
313
- import { forwardRef, useEffect as useEffect2, useImperativeHandle, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
313
+ import {
314
+ forwardRef,
315
+ useEffect as useEffect2,
316
+ useImperativeHandle,
317
+ useMemo as useMemo2,
318
+ useRef as useRef2,
319
+ useState as useState2
320
+ } from "react";
314
321
  import mammoth from "mammoth";
315
- import htmlToDocx from "html-to-docx";
316
322
  import MarkdownIt from "markdown-it";
317
323
  import html2canvas from "html2canvas";
318
324
 
@@ -330,7 +336,10 @@ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
330
336
  var PAGE_H = 1122;
331
337
  var RichTextEditor = forwardRef((props, ref) => {
332
338
  const readOnly = props.mode === "view";
333
- const md = useMemo2(() => new MarkdownIt({ html: false, linkify: true, breaks: true }), []);
339
+ const md = useMemo2(
340
+ () => new MarkdownIt({ html: false, linkify: true, breaks: true }),
341
+ []
342
+ );
334
343
  const scrollerRef = useRef2(null);
335
344
  const editorRef = useRef2(null);
336
345
  const captureRef = useRef2(null);
@@ -344,7 +353,9 @@ var RichTextEditor = forwardRef((props, ref) => {
344
353
  }
345
354
  if (!props.arrayBuffer) return;
346
355
  if (props.fileType === "docx") {
347
- const res = await mammoth.convertToHtml({ arrayBuffer: props.arrayBuffer });
356
+ const res = await mammoth.convertToHtml({
357
+ arrayBuffer: props.arrayBuffer
358
+ });
348
359
  if (!cancelled) setHtml(sanitizeHtml(res.value || "<p><br/></p>"));
349
360
  } else {
350
361
  const text = new TextDecoder().decode(props.arrayBuffer);
@@ -389,7 +400,11 @@ var RichTextEditor = forwardRef((props, ref) => {
389
400
  scroller.scrollTop = index * PAGE_H;
390
401
  await new Promise((r) => requestAnimationFrame(() => r(null)));
391
402
  try {
392
- const canvas = await html2canvas(capture, { backgroundColor: null, scale: 0.25, useCORS: true });
403
+ const canvas = await html2canvas(capture, {
404
+ backgroundColor: null,
405
+ scale: 0.25,
406
+ useCORS: true
407
+ });
393
408
  return canvas.toDataURL("image/png");
394
409
  } catch {
395
410
  return void 0;
@@ -402,25 +417,69 @@ var RichTextEditor = forwardRef((props, ref) => {
402
417
  const stitched = `<!doctype html><html><head><meta charset="utf-8" /></head><body>${inner}</body></html>`;
403
418
  if (exportPdf) {
404
419
  const b642 = btoa(unescape(encodeURIComponent(stitched)));
405
- props.onSave(b642, { fileName: replaceExt(props.fileName, "html"), fileType: "txt", exportedAsPdf: true, annotations: { signaturePlacements: props.signaturePlacements } });
420
+ props.onSave(b642, {
421
+ fileName: replaceExt(props.fileName, "html"),
422
+ fileType: "txt",
423
+ exportedAsPdf: true,
424
+ annotations: { signaturePlacements: props.signaturePlacements }
425
+ });
406
426
  return;
407
427
  }
408
428
  if (props.fileType === "docx") {
409
- const blob = await htmlToDocx(stitched);
410
- const ab = await blob.arrayBuffer();
411
- props.onSave(arrayBufferToBase64(ab), { fileName: replaceExt(props.fileName, "docx"), fileType: "docx", annotations: { signaturePlacements: props.signaturePlacements } });
429
+ try {
430
+ const htmlToDocx = (await import("html-to-docx")).default;
431
+ const blob = await htmlToDocx(stitched);
432
+ const ab = await blob.arrayBuffer();
433
+ props.onSave(arrayBufferToBase64(ab), {
434
+ fileName: replaceExt(props.fileName, "docx"),
435
+ fileType: "docx",
436
+ annotations: { signaturePlacements: props.signaturePlacements }
437
+ });
438
+ } catch (err) {
439
+ alert(
440
+ "DOCX export is not supported in this environment. Please use this feature in a Node.js/server context."
441
+ );
442
+ }
412
443
  return;
413
444
  }
414
445
  const text = editorRef.current?.innerText ?? "";
415
446
  const b64 = btoa(unescape(encodeURIComponent(text)));
416
- props.onSave(b64, { fileName: replaceExt(props.fileName, props.fileType), fileType: props.fileType, annotations: { signaturePlacements: props.signaturePlacements } });
447
+ props.onSave(b64, {
448
+ fileName: replaceExt(props.fileName, props.fileType),
449
+ fileType: props.fileType,
450
+ annotations: { signaturePlacements: props.signaturePlacements }
451
+ });
417
452
  }
418
453
  useImperativeHandle(ref, () => ({ save, requestThumbnail }));
419
454
  return /* @__PURE__ */ jsxs5("div", { className: "hv-doc", children: [
420
455
  /* @__PURE__ */ jsxs5("div", { className: "hv-ribbon", role: "toolbar", children: [
421
- /* @__PURE__ */ jsx5("button", { className: "hv-btn", onClick: () => exec("bold"), disabled: readOnly, children: "B" }),
422
- /* @__PURE__ */ jsx5("button", { className: "hv-btn", onClick: () => exec("italic"), disabled: readOnly, children: "I" }),
423
- /* @__PURE__ */ jsx5("button", { className: "hv-btn", onClick: () => exec("underline"), disabled: readOnly, children: "U" }),
456
+ /* @__PURE__ */ jsx5(
457
+ "button",
458
+ {
459
+ className: "hv-btn",
460
+ onClick: () => exec("bold"),
461
+ disabled: readOnly,
462
+ children: "B"
463
+ }
464
+ ),
465
+ /* @__PURE__ */ jsx5(
466
+ "button",
467
+ {
468
+ className: "hv-btn",
469
+ onClick: () => exec("italic"),
470
+ disabled: readOnly,
471
+ children: "I"
472
+ }
473
+ ),
474
+ /* @__PURE__ */ jsx5(
475
+ "button",
476
+ {
477
+ className: "hv-btn",
478
+ onClick: () => exec("underline"),
479
+ disabled: readOnly,
480
+ children: "U"
481
+ }
482
+ ),
424
483
  props.armedSignatureUrl ? /* @__PURE__ */ jsx5("div", { className: "hv-hint", children: "Click to place signature" }) : null
425
484
  ] }),
426
485
  /* @__PURE__ */ jsx5("div", { className: "hv-scroll", ref: scrollerRef, onClick, children: /* @__PURE__ */ jsxs5("div", { className: "hv-pageStage", ref: captureRef, children: [
@@ -438,7 +497,14 @@ var RichTextEditor = forwardRef((props, ref) => {
438
497
  ),
439
498
  props.headerFooterEnabled && props.footerComponent ? /* @__PURE__ */ jsx5("div", { className: "hv-letterhead hv-letterhead--footer", children: props.footerComponent }) : null,
440
499
  props.mode === "create" && props.signatures.length ? /* @__PURE__ */ jsx5("div", { className: "hv-signatures-inline", children: props.signatures.map((s, i) => /* @__PURE__ */ jsxs5("div", { className: "hv-sign-inline", children: [
441
- /* @__PURE__ */ jsx5("img", { src: s.signatureImageUrl, alt: "", className: "hv-sign-img" }),
500
+ /* @__PURE__ */ jsx5(
501
+ "img",
502
+ {
503
+ src: s.signatureImageUrl,
504
+ alt: "",
505
+ className: "hv-sign-img"
506
+ }
507
+ ),
442
508
  /* @__PURE__ */ jsxs5("div", { children: [
443
509
  /* @__PURE__ */ jsx5("div", { className: "hv-sign-name", children: s.signedBy }),
444
510
  /* @__PURE__ */ jsx5("div", { className: "hv-sign-date", children: new Date(s.dateSigned).toLocaleString() })
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/DocumentViewer.tsx","../src/utils/locale.ts","../src/utils/fileSource.ts","../src/components/Toolbar.tsx","../src/components/ThumbnailsSidebar.tsx","../src/components/SignaturePanel.tsx","../src/renderers/PdfRenderer.tsx","../src/editors/RichTextEditor.tsx","../src/utils/sanitize.ts","../src/editors/SpreadsheetEditor.tsx","../src/renderers/ImageRenderer.tsx","../src/renderers/PptxRenderer.tsx"],"sourcesContent":["'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport type { DocumentMode, DocumentViewerProps, PageLayout, Signature, SupportedFileType } from '../types';\nimport { defaultLocale } from '../utils/locale';\nimport { resolveSource } from '../utils/fileSource';\nimport { Toolbar } from './Toolbar';\nimport { ThumbnailsSidebar, type Thumbnail } from './ThumbnailsSidebar';\nimport { SignaturePanel } from './SignaturePanel';\nimport { PdfRenderer } from '../renderers/PdfRenderer';\nimport { RichTextEditor, type RichTextEditorHandle } from '../editors/RichTextEditor';\nimport { SpreadsheetEditor, type SpreadsheetEditorHandle } from '../editors/SpreadsheetEditor';\nimport { ImageRenderer } from '../renderers/ImageRenderer';\nimport { PptxRenderer } from '../renderers/PptxRenderer';\n\ntype SigPlacement = { page: number; x: number; y: number; w: number; h: number; signatureImageUrl: string };\n\ntype EditorHandle = (RichTextEditorHandle | SpreadsheetEditorHandle) & { save: (exportPdf?: boolean) => Promise<void> };\n\nexport function DocumentViewer(props: DocumentViewerProps) {\n const mode: DocumentMode = props.mode ?? 'view';\n const theme = props.theme ?? 'light';\n const locale = useMemo(() => ({ ...defaultLocale, ...(props.locale ?? {}) }), [props.locale]);\n\n const [layout, setLayout] = useState<PageLayout>(props.defaultLayout ?? 'single');\n const [showThumbnails, setShowThumbnails] = useState(true);\n const [showSignatures, setShowSignatures] = useState(true);\n const [headerFooterEnabled, setHeaderFooterEnabled] = useState(true);\n\n const allowSigning = props.allowSigning ?? false;\n const [signingBusy, setSigningBusy] = useState(false);\n\n const [resolved, setResolved] = useState<{ fileType: SupportedFileType; fileName: string; url?: string; arrayBuffer?: ArrayBuffer } | null>(null);\n const [error, setError] = useState<string>('');\n const [pageCount, setPageCount] = useState(1);\n const [currentPage, setCurrentPage] = useState(1);\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n\n const [localSignatures, setLocalSignatures] = useState<Signature[]>(props.signatures ?? []);\n useEffect(() => setLocalSignatures(props.signatures ?? []), [props.signatures]);\n\n const [sigPlacements, setSigPlacements] = useState<SigPlacement[]>([]);\n const [armedSignatureUrl, setArmedSignatureUrl] = useState<string | null>(null);\n\n const editorRef = useRef<EditorHandle | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setError('');\n setResolved(null);\n setThumbs([]);\n setPageCount(1);\n setCurrentPage(1);\n setSigPlacements([]);\n setArmedSignatureUrl(null);\n\n if (mode === 'create') {\n const ft = (props.fileType ?? 'docx') as SupportedFileType;\n setResolved({ fileType: ft, fileName: props.fileName ?? `Untitled.${ft}` });\n return;\n }\n\n try {\n const res = await resolveSource({\n fileUrl: props.fileUrl,\n base64: props.base64,\n blob: props.blob,\n fileName: props.fileName,\n fileType: props.fileType\n });\n if (cancelled) return;\n setResolved({ fileType: res.fileType, fileName: res.fileName, url: res.url, arrayBuffer: res.arrayBuffer });\n } catch (e) {\n if (cancelled) return;\n setError(e instanceof Error ? e.message : String(e));\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [mode, props.fileUrl, props.base64, props.blob, props.fileName, props.fileType]);\n\n const thumbnails: Thumbnail[] = useMemo(() => {\n const n = Math.max(1, pageCount);\n return Array.from({ length: n }, (_, i) => ({\n id: `p-${i + 1}`,\n label: `${locale['thumbnails.page'] ?? 'Page'} ${i + 1}`,\n dataUrl: thumbs[i]\n }));\n }, [pageCount, thumbs, locale]);\n\n async function handleSignRequest() {\n if (!allowSigning || signingBusy || !props.onSignRequest) return;\n setSigningBusy(true);\n try {\n const sig = await props.onSignRequest();\n setLocalSignatures((prev: Signature[]) => [...prev, sig]);\n setArmedSignatureUrl(sig.signatureImageUrl);\n } finally {\n setSigningBusy(false);\n }\n }\n\n function placeSignature(p: { page: number; x: number; y: number; w: number; h: number }) {\n if (!armedSignatureUrl) return;\n setSigPlacements((prev: SigPlacement[]) => [...prev, { ...p, signatureImageUrl: armedSignatureUrl }]);\n setArmedSignatureUrl(null);\n }\n\n async function handleSave(exportPdf?: boolean) {\n if (editorRef.current) {\n await editorRef.current.save(!!exportPdf);\n return;\n }\n if (!resolved?.arrayBuffer) return;\n const b64 = arrayBufferToBase64(resolved.arrayBuffer);\n props.onSave?.(b64, { fileName: resolved.fileName, fileType: resolved.fileType, annotations: { sigPlacements } });\n }\n\n const canSave = mode === 'edit' || mode === 'create';\n const canExportPdf = (mode === 'edit' || mode === 'create') && (resolved?.fileType === 'docx' || resolved?.fileType === 'md' || resolved?.fileType === 'txt' || resolved?.fileType === 'xlsx');\n\n return (\n <div className={`hv-root`} data-hv-theme={theme}>\n <Toolbar\n locale={locale}\n mode={mode}\n fileType={resolved?.fileType}\n layout={layout}\n onChangeLayout={setLayout}\n showThumbnails={showThumbnails}\n onToggleThumbnails={() => setShowThumbnails((v: boolean) => !v)}\n showSignatures={showSignatures}\n onToggleSignatures={() => setShowSignatures((v: boolean) => !v)}\n onSign={() => void handleSignRequest()}\n allowSigning={allowSigning}\n signingDisabled={signingBusy || !props.onSignRequest}\n canSave={canSave}\n onSave={() => void handleSave(false)}\n canExportPdf={canExportPdf}\n onExportPdf={() => void handleSave(true)}\n headerFooterEnabled={headerFooterEnabled}\n showHeaderFooterToggle={(props.enableHeaderFooterToggle ?? true) && mode === 'create'}\n onToggleHeaderFooter={() => setHeaderFooterEnabled((v: boolean) => !v)}\n />\n\n {error ? (\n <div className=\"hv-error\" role=\"alert\">\n <div className=\"hv-error-title\">{locale['error.title'] ?? 'Error'}</div>\n <div className=\"hv-error-body\">{error}</div>\n </div>\n ) : null}\n\n {!resolved && !error ? <div className=\"hv-loading\" aria-busy=\"true\">{locale['loading'] ?? 'Loading…'}</div> : null}\n\n {resolved ? (\n <div className=\"hv-shell\">\n {mode !== 'create' ? (\n <ThumbnailsSidebar\n locale={locale}\n thumbnails={thumbnails}\n currentPage={currentPage}\n collapsed={!showThumbnails}\n onToggle={() => setShowThumbnails((v: boolean) => !v)}\n onSelectPage={setCurrentPage}\n />\n ) : null}\n\n <main className=\"hv-main\">\n {resolved.fileType === 'pdf' ? (\n <PdfRenderer\n url={resolved.url}\n arrayBuffer={resolved.arrayBuffer}\n layout={layout}\n currentPage={currentPage}\n onCurrentPageChange={setCurrentPage}\n onPageCount={(n) => {\n setPageCount(n);\n setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])));\n }}\n onThumbs={(t) => setThumbs(t)}\n signatureStamp={armedSignatureUrl ? { imageUrl: armedSignatureUrl, armed: true, onPlaced: placeSignature } : undefined}\n />\n ) : null}\n\n {resolved.fileType === 'docx' || resolved.fileType === 'md' || resolved.fileType === 'txt' ? (\n <RichTextEditor\n ref={editorRef as any}\n mode={mode}\n fileType={resolved.fileType}\n fileName={resolved.fileName}\n arrayBuffer={resolved.arrayBuffer}\n headerComponent={props.headerComponent}\n footerComponent={props.footerComponent}\n headerFooterEnabled={headerFooterEnabled}\n locale={locale}\n signatures={localSignatures}\n signaturePlacements={sigPlacements}\n onPageCount={(n) => { setPageCount(n); setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i]))); }}\n onSave={(b64, meta) => props.onSave?.(b64, meta)}\n armedSignatureUrl={armedSignatureUrl}\n onPlaceSignature={placeSignature}\n />\n ) : null}\n\n {resolved.fileType === 'xlsx' ? (\n <SpreadsheetEditor\n ref={editorRef as any}\n mode={mode}\n fileName={resolved.fileName}\n arrayBuffer={resolved.arrayBuffer}\n locale={locale}\n onSave={(b64, meta) => props.onSave?.(b64, meta)}\n />\n ) : null}\n\n {resolved.fileType === 'pptx' ? (\n <PptxRenderer\n arrayBuffer={resolved.arrayBuffer}\n layout={layout}\n currentPage={currentPage}\n onCurrentPageChange={setCurrentPage}\n onSlideCount={(n) => {\n setPageCount(n);\n setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])));\n }}\n onThumbs={(t) => setThumbs(t)}\n />\n ) : null}\n\n {resolved.fileType === 'png' || resolved.fileType === 'jpg' || resolved.fileType === 'svg' ? (\n <ImageRenderer arrayBuffer={resolved.arrayBuffer} fileType={resolved.fileType} fileName={resolved.fileName} />\n ) : null}\n </main>\n\n {mode !== 'create' && localSignatures.length ? (\n <SignaturePanel\n locale={locale}\n signatures={localSignatures}\n collapsed={!showSignatures}\n onToggle={() => setShowSignatures((v: boolean) => !v)}\n />\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction arrayBufferToBase64(ab: ArrayBuffer): string {\n const bytes = new Uint8Array(ab);\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n","export const defaultLocale: Record<string, string> = {\n 'loading': 'Loading…',\n 'error.title': 'Error',\n 'toolbar.layout.single': 'Single page',\n 'toolbar.layout.two': 'Side-by-side',\n 'toolbar.thumbs': 'Thumbnails',\n 'toolbar.signatures': 'Signatures',\n 'toolbar.sign': 'Sign Document',\n 'toolbar.save': 'Save',\n 'toolbar.exportPdf': 'Export as PDF',\n 'thumbnails.title': 'Thumbnails',\n 'thumbnails.page': 'Page',\n 'signatures.title': 'Signatures',\n 'signatures.empty': 'No signatures',\n 'signatures.placeHint': 'Click on the document to place the signature.',\n 'a11y.viewer': 'Document viewer',\n 'a11y.ribbon': 'Ribbon',\n 'a11y.editor': 'Document editor'\n};\n","import type { SupportedFileType } from '../types';\n\nexport function guessFileType(name?: string, explicit?: SupportedFileType): SupportedFileType {\n if (explicit) return explicit;\n const ext = (name?.split('.').pop() || '').toLowerCase();\n const allowed: SupportedFileType[] = ['pdf','md','docx','xlsx','pptx','txt','png','jpg','svg'];\n return (allowed as string[]).includes(ext) ? (ext as SupportedFileType) : 'txt';\n}\n\nexport function arrayBufferToBase64(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n\nexport async function base64ToArrayBuffer(b64: string): Promise<ArrayBuffer> {\n const bin = atob(b64);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes.buffer;\n}\n\nexport async function resolveSource(args: {\n fileUrl?: string;\n base64?: string;\n blob?: Blob;\n fileName?: string;\n fileType?: SupportedFileType;\n onProgress?: (loaded: number, total?: number) => void;\n}): Promise<{ fileType: SupportedFileType; fileName: string; arrayBuffer: ArrayBuffer; url?: string }>{\n const fileType = guessFileType(args.fileName, args.fileType);\n const fileName = args.fileName ?? `document.${fileType}`;\n\n if (args.blob) {\n const ab = await args.blob.arrayBuffer();\n const url = URL.createObjectURL(args.blob);\n return { fileType, fileName, arrayBuffer: ab, url };\n }\n\n if (args.base64) {\n const ab = await base64ToArrayBuffer(args.base64);\n return { fileType, fileName, arrayBuffer: ab };\n }\n\n if (!args.fileUrl) throw new Error('No file source provided. Use fileUrl, blob, or base64.');\n\n const res = await fetch(args.fileUrl);\n if (!res.ok) throw new Error(`Failed to fetch file (${res.status})`);\n\n const total = Number(res.headers.get('content-length') || '') || undefined;\n if (!res.body) {\n const ab = await res.arrayBuffer();\n args.onProgress?.(ab.byteLength, total);\n return { fileType, fileName, arrayBuffer: ab, url: args.fileUrl };\n }\n\n const reader = res.body.getReader();\n const chunks: Uint8Array[] = [];\n let loaded = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) {\n chunks.push(value);\n loaded += value.length;\n args.onProgress?.(loaded, total);\n }\n }\n const out = new Uint8Array(loaded);\n let offset = 0;\n for (const c of chunks) { out.set(c, offset); offset += c.length; }\n return { fileType, fileName, arrayBuffer: out.buffer, url: args.fileUrl };\n}\n","'use client';\n\nimport React from 'react';\nimport type { DocumentMode, PageLayout, SupportedFileType } from '../types';\n\nexport function Toolbar(props: {\n locale: Record<string, string>;\n mode: DocumentMode;\n fileType?: SupportedFileType;\n layout: PageLayout;\n onChangeLayout: (l: PageLayout) => void;\n showThumbnails: boolean;\n onToggleThumbnails: () => void;\n showSignatures: boolean;\n onToggleSignatures: () => void;\n allowSigning: boolean;\n signingDisabled: boolean;\n onSign: () => void;\n canSave: boolean;\n onSave: () => void;\n canExportPdf: boolean;\n onExportPdf: () => void;\n showHeaderFooterToggle: boolean;\n headerFooterEnabled: boolean;\n onToggleHeaderFooter: () => void;\n}) {\n const t = (k: string, fallback: string) => props.locale[k] ?? fallback;\n\n return (\n <div className=\"hv-toolbar\" role=\"toolbar\" aria-label={t('a11y.toolbar', 'Document toolbar')}>\n <div className=\"hv-toolbar__left\">\n <button type=\"button\" className=\"hv-btn\" onClick={props.onToggleThumbnails} aria-pressed={props.showThumbnails}>\n {t('toolbar.thumbs', 'Thumbnails')}\n </button>\n {props.mode !== 'create' && (\n <button type=\"button\" className=\"hv-btn\" onClick={props.onToggleSignatures} aria-pressed={props.showSignatures}>\n {t('toolbar.signatures', 'Signatures')}\n </button>\n )}\n <span className=\"hv-sep\" />\n <button type=\"button\" className={props.layout === 'single' ? 'hv-btn hv-btn--active' : 'hv-btn'} onClick={() => props.onChangeLayout('single')}>\n {t('toolbar.layout.single', 'Single')}\n </button>\n <button type=\"button\" className={props.layout === 'side-by-side' ? 'hv-btn hv-btn--active' : 'hv-btn'} onClick={() => props.onChangeLayout('side-by-side')}>\n {t('toolbar.layout.two', 'Two')}\n </button>\n </div>\n\n <div className=\"hv-toolbar__right\">\n {props.showHeaderFooterToggle && (\n <label className=\"hv-toggle\">\n <input type=\"checkbox\" checked={props.headerFooterEnabled} onChange={props.onToggleHeaderFooter} />\n <span>{t('toolbar.letterhead', 'Letterhead')}</span>\n </label>\n )}\n\n {props.allowSigning && (\n <button type=\"button\" className=\"hv-btn hv-btn--primary\" onClick={props.onSign} disabled={props.signingDisabled}>\n {t('toolbar.sign', 'Sign Document')}\n </button>\n )}\n\n {props.canExportPdf && (\n <button type=\"button\" className=\"hv-btn\" onClick={props.onExportPdf}>\n {t('toolbar.exportPdf', 'Export as PDF')}\n </button>\n )}\n {props.canSave && (\n <button type=\"button\" className=\"hv-btn hv-btn--primary\" onClick={props.onSave}>\n {t('toolbar.save', 'Save')}\n </button>\n )}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport React from 'react';\n\nexport type Thumbnail = {\n id: string;\n label: string;\n dataUrl?: string;\n};\n\nexport function ThumbnailsSidebar(props: {\n locale: Record<string, string>;\n thumbnails: Thumbnail[];\n currentPage: number;\n collapsed: boolean;\n onToggle: () => void;\n onSelectPage: (p: number) => void;\n}) {\n const t = props.locale['thumbnails.title'] ?? 'Thumbnails';\n return (\n <aside className={props.collapsed ? 'hv-thumbs hv-thumbs--collapsed' : 'hv-thumbs'} aria-label={t}>\n <div className=\"hv-thumbs__header\">\n <button type=\"button\" className=\"hv-icon\" onClick={props.onToggle} aria-label={props.collapsed ? (props.locale['thumbnails.open'] ?? 'Open thumbnails') : (props.locale['thumbnails.close'] ?? 'Close thumbnails')}\n >{props.collapsed ? '▸' : '▾'}</button>\n {!props.collapsed ? <div className=\"hv-thumbs__title\">{t}</div> : null}\n </div>\n {!props.collapsed ? (\n <div className=\"hv-thumbs__list\" role=\"list\">\n {props.thumbnails.map((th, idx) => {\n const p = idx + 1;\n const active = p === props.currentPage;\n return (\n <button\n key={th.id}\n type=\"button\"\n role=\"listitem\"\n className={active ? 'hv-thumb hv-thumb--active' : 'hv-thumb'}\n onClick={() => props.onSelectPage(p)}\n aria-current={active ? 'page' : undefined}\n >\n <div className=\"hv-thumb__img\" aria-hidden>\n {th.dataUrl ? <img src={th.dataUrl} alt=\"\" /> : <div className=\"hv-thumb__placeholder\" />}\n </div>\n <div className=\"hv-thumb__label\">{th.label}</div>\n </button>\n );\n })}\n </div>\n ) : null}\n </aside>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport type { Signature } from '../types';\n\nexport function SignaturePanel(props: {\n locale: Record<string, string>;\n signatures: Signature[];\n collapsed: boolean;\n onToggle: () => void;\n}) {\n const title = props.locale['signatures.title'] ?? 'Signatures';\n return (\n <aside className={props.collapsed ? 'hv-side hv-side--collapsed' : 'hv-side'} aria-label={title}>\n <div className=\"hv-sidebar-header\">\n <button type=\"button\" className=\"hv-icon\" onClick={props.onToggle} aria-label={props.locale['toolbar.signatures'] ?? 'Signatures'}>\n ✍\n </button>\n <div className=\"hv-sidebar-title\">{title}</div>\n </div>\n <div className=\"hv-sidebar-body\">\n {props.signatures.map((s, idx) => (\n <div key={`${s.signedBy}-${s.dateSigned}-${idx}`} className=\"hv-signature-card\">\n <img src={s.signatureImageUrl} alt={`Signature by ${s.signedBy}`} className=\"hv-signature-img\" />\n <div className=\"hv-signature-meta\">\n <div className=\"hv-signature-name\">{s.signedBy}</div>\n <div className=\"hv-signature-date\">{new Date(s.dateSigned).toLocaleString()}</div>\n {s.comment ? <div className=\"hv-signature-comment\">{s.comment}</div> : null}\n </div>\n </div>\n ))}\n </div>\n </aside>\n );\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { GlobalWorkerOptions, getDocument, type PDFDocumentProxy } from 'pdfjs-dist';\nimport type { PageLayout } from '../types';\n\nexport function PdfRenderer(props: {\n url?: string;\n arrayBuffer?: ArrayBuffer;\n layout: PageLayout;\n currentPage: number;\n onCurrentPageChange: (p: number) => void;\n onPageCount: (n: number) => void;\n onThumbs: (thumbs: (string | undefined)[]) => void;\n signatureStamp?: {\n imageUrl: string;\n armed: boolean;\n onPlaced: (placement: { page: number; x: number; y: number; w: number; h: number }) => void;\n };\n}) {\n const { url, arrayBuffer } = props;\n const [doc, setDoc] = useState<PDFDocumentProxy | null>(null);\n const [pageCount, setPageCount] = useState(0);\n const [rendered, setRendered] = useState<Map<number, HTMLCanvasElement>>(new Map());\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n const [size, setSize] = useState({ w: 840, h: 1188 });\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n try {\n GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString();\n } catch {}\n }, []);\n\n useEffect(() => {\n let cancel = false;\n (async () => {\n setDoc(null);\n setRendered(new Map());\n setThumbs([]);\n if (!url && !arrayBuffer) return;\n const task = getDocument(url ? { url, rangeChunkSize: 512 * 1024 } : { data: arrayBuffer! });\n const pdf = await task.promise;\n if (cancel) return;\n setDoc(pdf);\n setPageCount(pdf.numPages);\n props.onPageCount(pdf.numPages);\n setThumbs(Array.from({ length: pdf.numPages }));\n const p1 = await pdf.getPage(1);\n const base = p1.getViewport({ scale: 1 });\n const w = Math.min(980, Math.max(640, base.width));\n const s = w / base.width;\n const vp = p1.getViewport({ scale: s });\n setSize({ w: Math.round(vp.width), h: Math.round(vp.height) });\n })().catch(() => {\n // ignore; caller shows error\n });\n return () => { cancel = true; };\n }, [url, arrayBuffer]);\n\n useEffect(() => {\n props.onThumbs(thumbs);\n }, [thumbs]);\n\n const pagesToShow = useMemo(() => {\n if (props.layout === 'side-by-side') {\n const left = props.currentPage;\n const right = Math.min(pageCount || left + 1, left + 1);\n return [left, right];\n }\n return [props.currentPage];\n }, [props.currentPage, props.layout, pageCount]);\n\n useEffect(() => {\n if (!doc) return;\n let cancel = false;\n (async () => {\n for (const p of pagesToShow) {\n if (rendered.has(p)) continue;\n const page = await doc.getPage(p);\n if (cancel) return;\n const base = page.getViewport({ scale: 1 });\n const vp = page.getViewport({ scale: size.w / base.width });\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(vp.width);\n canvas.height = Math.round(vp.height);\n const ctx = canvas.getContext('2d', { alpha: false });\n if (!ctx) continue;\n await page.render({ canvasContext: ctx, viewport: vp }).promise;\n if (cancel) return;\n setRendered(prev => {\n const next = new Map(prev);\n next.set(p, canvas);\n return next;\n });\n try {\n const tw = 140;\n const th = Math.round(tw * (canvas.height / canvas.width));\n const t = document.createElement('canvas');\n t.width = tw; t.height = th;\n const tctx = t.getContext('2d');\n if (tctx) {\n tctx.drawImage(canvas, 0, 0, tw, th);\n const url = t.toDataURL('image/jpeg', 0.75);\n setThumbs(prev => {\n const next = prev.slice();\n next[p - 1] = url;\n return next;\n });\n }\n } catch {}\n }\n })();\n return () => { cancel = true; };\n }, [doc, pagesToShow, size.w, rendered]);\n\n function onWheel(e: React.WheelEvent) {\n if (!pageCount) return;\n if (Math.abs(e.deltaY) < 10) return;\n const dir = e.deltaY > 0 ? 1 : -1;\n const step = props.layout === 'side-by-side' ? 2 : 1;\n const next = Math.max(1, Math.min(pageCount, props.currentPage + dir * step));\n props.onCurrentPageChange(next);\n }\n\n function clickPlace(e: React.MouseEvent, page: number) {\n const stamp = props.signatureStamp;\n if (!stamp?.armed) return;\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const x = (e.clientX - rect.left) / rect.width;\n const y = (e.clientY - rect.top) / rect.height;\n stamp.onPlaced({ page, x, y, w: 0.22, h: 0.08 });\n }\n\n return (\n <div className=\"hv-doc\" ref={containerRef} onWheel={onWheel}>\n {!doc ? <div className=\"hv-loading\">Loading PDF…</div> : null}\n {doc ? (\n <div className={props.layout === 'side-by-side' ? 'hv-pages hv-pages--two' : 'hv-pages'}>\n {pagesToShow.map(p => {\n const c = rendered.get(p);\n return (\n <div key={p} className=\"hv-page\" style={{ width: size.w, height: size.h }} onClick={(e) => clickPlace(e, p)}>\n {c ? (\n <canvas\n className=\"hv-canvas\"\n width={c.width}\n height={c.height}\n ref={(node) => {\n if (!node) return;\n const ctx = node.getContext('2d');\n if (ctx) ctx.drawImage(c, 0, 0);\n }}\n />\n ) : <div className=\"hv-loading\">Rendering…</div>}\n </div>\n );\n })}\n </div>\n ) : null}\n </div>\n );\n}\n","'use client';\n\nimport React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';\nimport mammoth from 'mammoth';\nimport htmlToDocx from 'html-to-docx';\nimport MarkdownIt from 'markdown-it';\nimport html2canvas from 'html2canvas';\nimport { sanitizeHtml } from '../utils/sanitize';\nimport { arrayBufferToBase64 } from '../utils/fileSource';\nimport type { DocumentMode, Signature, SupportedFileType } from '../types';\n\nconst PAGE_H = 1122; // virtual A4\n\nexport type RichTextEditorHandle = {\n save: (exportPdf?: boolean) => Promise<void>;\n requestThumbnail: (index: number) => Promise<string | undefined>;\n};\n\nexport const RichTextEditor = forwardRef<RichTextEditorHandle, {\n mode: DocumentMode;\n fileType: 'docx' | 'md' | 'txt';\n fileName: string;\n arrayBuffer?: ArrayBuffer;\n locale: Record<string, string>;\n headerComponent?: React.ReactNode;\n footerComponent?: React.ReactNode;\n headerFooterEnabled: boolean;\n signatures: Signature[];\n signaturePlacements: { page: number; x: number; y: number; w: number; h: number; signatureImageUrl: string }[];\n armedSignatureUrl: string | null;\n onPlaceSignature: (p: { page: number; x: number; y: number; w: number; h: number }) => void;\n onSave: (b64: string, meta: { fileName: string; fileType: SupportedFileType; exportedAsPdf?: boolean; annotations?: unknown }) => void;\n onPageCount: (n: number) => void;\n}>((props, ref) => {\n const readOnly = props.mode === 'view';\n const md = useMemo(() => new MarkdownIt({ html: false, linkify: true, breaks: true }), []);\n const scrollerRef = useRef<HTMLDivElement | null>(null);\n const editorRef = useRef<HTMLDivElement | null>(null);\n const captureRef = useRef<HTMLDivElement | null>(null);\n\n const [html, setHtml] = useState('<p><br/></p>');\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n if (props.mode === 'create') {\n setHtml('<p><br/></p>');\n return;\n }\n if (!props.arrayBuffer) return;\n if (props.fileType === 'docx') {\n const res = await mammoth.convertToHtml({ arrayBuffer: props.arrayBuffer });\n if (!cancelled) setHtml(sanitizeHtml(res.value || '<p><br/></p>'));\n } else {\n const text = new TextDecoder().decode(props.arrayBuffer);\n if (props.fileType === 'md') setHtml(sanitizeHtml(md.render(text)));\n else setHtml(`<pre>${escapeHtml(text)}</pre>`);\n }\n })();\n return () => { cancelled = true; };\n }, [props.arrayBuffer, props.fileType, props.mode, md]);\n\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return;\n const recompute = () => props.onPageCount(Math.max(1, Math.ceil(el.scrollHeight / PAGE_H)));\n recompute();\n const ro = new ResizeObserver(recompute);\n ro.observe(el);\n return () => ro.disconnect();\n }, [html, props.headerFooterEnabled]);\n\n function exec(cmd: string) {\n if (readOnly) return;\n document.execCommand(cmd);\n }\n\n function onClick(e: React.MouseEvent<HTMLDivElement>) {\n if (!props.armedSignatureUrl) return;\n const scroller = scrollerRef.current;\n if (!scroller) return;\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const absY = scroller.scrollTop + (e.clientY - rect.top);\n const page = Math.max(1, Math.floor(absY / PAGE_H) + 1);\n const pageTop = (page - 1) * PAGE_H;\n const x = (e.clientX - rect.left) / rect.width;\n const y = (absY - pageTop) / PAGE_H;\n props.onPlaceSignature({ page, x, y, w: 0.25, h: 0.1 });\n }\n\n async function requestThumbnail(index: number): Promise<string | undefined> {\n const scroller = scrollerRef.current;\n const capture = captureRef.current;\n if (!scroller || !capture) return undefined;\n const old = scroller.scrollTop;\n scroller.scrollTop = index * PAGE_H;\n await new Promise((r) => requestAnimationFrame(() => r(null)));\n try {\n const canvas = await html2canvas(capture, { backgroundColor: null, scale: 0.25, useCORS: true });\n return canvas.toDataURL('image/png');\n } catch {\n return undefined;\n } finally {\n scroller.scrollTop = old;\n }\n }\n\n async function save(exportPdf?: boolean) {\n const inner = editorRef.current?.innerHTML ?? html;\n const stitched = `<!doctype html><html><head><meta charset=\"utf-8\" /></head><body>${inner}</body></html>`;\n\n if (exportPdf) {\n // client-side: return print-ready HTML as base64\n const b64 = btoa(unescape(encodeURIComponent(stitched)));\n props.onSave(b64, { fileName: replaceExt(props.fileName, 'html'), fileType: 'txt', exportedAsPdf: true, annotations: { signaturePlacements: props.signaturePlacements } });\n return;\n }\n\n if (props.fileType === 'docx') {\n const blob = await htmlToDocx(stitched);\n const ab = await blob.arrayBuffer();\n props.onSave(arrayBufferToBase64(ab), { fileName: replaceExt(props.fileName, 'docx'), fileType: 'docx', annotations: { signaturePlacements: props.signaturePlacements } });\n return;\n }\n\n const text = editorRef.current?.innerText ?? '';\n const b64 = btoa(unescape(encodeURIComponent(text)));\n props.onSave(b64, { fileName: replaceExt(props.fileName, props.fileType), fileType: props.fileType, annotations: { signaturePlacements: props.signaturePlacements } });\n }\n\n useImperativeHandle(ref, () => ({ save, requestThumbnail }));\n\n return (\n <div className=\"hv-doc\">\n <div className=\"hv-ribbon\" role=\"toolbar\">\n <button className=\"hv-btn\" onClick={() => exec('bold')} disabled={readOnly}>B</button>\n <button className=\"hv-btn\" onClick={() => exec('italic')} disabled={readOnly}>I</button>\n <button className=\"hv-btn\" onClick={() => exec('underline')} disabled={readOnly}>U</button>\n {props.armedSignatureUrl ? <div className=\"hv-hint\">Click to place signature</div> : null}\n </div>\n\n <div className=\"hv-scroll\" ref={scrollerRef} onClick={onClick}>\n <div className=\"hv-pageStage\" ref={captureRef}>\n {props.headerFooterEnabled && props.headerComponent ? <div className=\"hv-letterhead\">{props.headerComponent}</div> : null}\n\n <div\n ref={editorRef}\n className={readOnly ? 'hv-editor hv-editor--ro' : 'hv-editor'}\n contentEditable={!readOnly}\n suppressContentEditableWarning\n onInput={() => setHtml(editorRef.current?.innerHTML ?? '')}\n dangerouslySetInnerHTML={{ __html: html }}\n />\n\n {props.headerFooterEnabled && props.footerComponent ? <div className=\"hv-letterhead hv-letterhead--footer\">{props.footerComponent}</div> : null}\n\n {props.mode === 'create' && props.signatures.length ? (\n <div className=\"hv-signatures-inline\">\n {props.signatures.map((s, i) => (\n <div key={i} className=\"hv-sign-inline\">\n <img src={s.signatureImageUrl} alt=\"\" className=\"hv-sign-img\" />\n <div>\n <div className=\"hv-sign-name\">{s.signedBy}</div>\n <div className=\"hv-sign-date\">{new Date(s.dateSigned).toLocaleString()}</div>\n </div>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n </div>\n );\n});\n\nfunction replaceExt(name: string, ext: string) {\n const base = name.includes('.') ? name.slice(0, name.lastIndexOf('.')) : name;\n return `${base}.${ext}`;\n}\n\nfunction escapeHtml(s: string) {\n return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n}\n","import DOMPurify from 'dompurify';\n\nexport function sanitizeHtml(html: string): string {\n // DOMPurify is safe to call in the browser. For SSR, callers should only run after mount.\n return DOMPurify.sanitize(html, {\n USE_PROFILES: { html: true },\n ADD_ATTR: ['target', 'rel']\n });\n}\n","'use client';\n\nimport React, { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react';\nimport * as XLSX from 'xlsx';\nimport { arrayBufferToBase64 } from '../utils/fileSource';\nimport type { DocumentMode, SupportedFileType } from '../types';\n\nexport type SpreadsheetEditorHandle = {\n save: (exportPdf?: boolean) => Promise<void>;\n requestThumbnails: (index: number) => Promise<void>;\n};\n\nexport const SpreadsheetEditor = forwardRef<SpreadsheetEditorHandle, {\n mode: DocumentMode;\n fileName: string;\n arrayBuffer?: ArrayBuffer;\n locale: Record<string, string>;\n onSave: (base64: string, meta: { fileName: string; fileType: SupportedFileType; exportedAsPdf?: boolean }) => void;\n}>(function SpreadsheetEditor(props, ref) {\n const readonly = props.mode === 'view';\n const [grid, setGrid] = useState<string[][]>(() => Array.from({ length: 30 }, () => Array.from({ length: 12 }, () => '')));\n\n useEffect(() => {\n if (!props.arrayBuffer) return;\n try {\n const wb = XLSX.read(props.arrayBuffer, { type: 'array' });\n const name = wb.SheetNames[0];\n const ws = wb.Sheets[name];\n const aoa = XLSX.utils.sheet_to_json(ws, { header: 1, raw: true }) as any[][];\n const rows = Math.max(30, aoa.length);\n const cols = Math.max(12, Math.max(...aoa.map(r => (r?.length ?? 0)), 0));\n const next = Array.from({ length: rows }, (_, r) => Array.from({ length: cols }, (_, c) => {\n const v = aoa[r]?.[c];\n return v == null ? '' : String(v);\n }));\n setGrid(next);\n } catch {\n // ignore\n }\n }, [props.arrayBuffer]);\n\n async function save(exportPdf?: boolean) {\n const ws = XLSX.utils.aoa_to_sheet(grid);\n const wb = XLSX.utils.book_new();\n XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');\n const out = XLSX.write(wb, { type: 'array', bookType: 'xlsx' }) as ArrayBuffer;\n const b64 = arrayBufferToBase64(out);\n props.onSave(b64, { fileName: ensureExt(props.fileName, 'xlsx'), fileType: 'xlsx', exportedAsPdf: !!exportPdf });\n }\n\n useImperativeHandle(ref, () => ({\n save,\n requestThumbnails: async () => undefined\n }));\n\n const cols = useMemo(() => Array.from({ length: grid[0]?.length ?? 0 }, (_, i) => String.fromCharCode(65 + (i % 26))), [grid]);\n\n return (\n <div className=\"hv-sheet\">\n <div className=\"hv-sheetbar\">\n <div className=\"hv-sheetbar-title\">{props.fileName}</div>\n {!readonly ? <button className=\"hv-btn\" type=\"button\" onClick={() => void save(false)}>{props.locale['toolbar.save'] ?? 'Save'}</button> : null}\n </div>\n <div className=\"hv-sheetgrid\" role=\"table\" aria-label=\"Spreadsheet\">\n <div className=\"hv-sheetrow hv-sheetrow--header\" role=\"row\">\n <div className=\"hv-sheetcell hv-sheetcell--corner\" role=\"columnheader\" />\n {cols.map((c, i) => <div key={i} className=\"hv-sheetcell hv-sheetcell--header\" role=\"columnheader\">{c}</div>)}\n </div>\n {grid.map((row, r) => (\n <div key={r} className=\"hv-sheetrow\" role=\"row\">\n <div className=\"hv-sheetcell hv-sheetcell--header\" role=\"rowheader\">{r + 1}</div>\n {row.map((val, c) => (\n <div\n key={c}\n className=\"hv-sheetcell\"\n role=\"cell\"\n contentEditable={!readonly}\n suppressContentEditableWarning\n onInput={(e) => {\n const text = (e.currentTarget.textContent ?? '');\n setGrid((prev) => {\n const next = prev.map(rr => rr.slice());\n next[r][c] = text;\n return next;\n });\n }}\n >{val}</div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n});\n\nfunction ensureExt(name: string, ext: string) {\n const base = name.includes('.') ? name.slice(0, name.lastIndexOf('.')) : name;\n return `${base}.${ext}`;\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport type { SupportedFileType } from '../types';\n\nexport function ImageRenderer({ arrayBuffer, fileType, fileName }: { arrayBuffer?: ArrayBuffer; fileType: SupportedFileType; fileName: string }) {\n const [zoom, setZoom] = useState(1);\n const url = useMemo(() => {\n if (!arrayBuffer) return undefined;\n const mime = fileType === 'svg' ? 'image/svg+xml' : fileType === 'png' ? 'image/png' : 'image/jpeg';\n return URL.createObjectURL(new Blob([arrayBuffer], { type: mime }));\n }, [arrayBuffer, fileType]);\n\n useEffect(() => {\n return () => { if (url) URL.revokeObjectURL(url); };\n }, [url]);\n\n return (\n <div className=\"hv-doc\">\n <div className=\"hv-mini-toolbar\">\n <div className=\"hv-title\">{fileName}</div>\n <div className=\"hv-spacer\" />\n <button type=\"button\" className=\"hv-btn\" onClick={() => setZoom((z) => Math.max(0.25, z - 0.25))}>-</button>\n <div className=\"hv-zoom\">{Math.round(zoom * 100)}%</div>\n <button type=\"button\" className=\"hv-btn\" onClick={() => setZoom((z) => Math.min(4, z + 0.25))}>+</button>\n </div>\n <div className=\"hv-center\">\n {url ? <img src={url} alt={fileName} style={{ transform: `scale(${zoom})` }} className=\"hv-image\" /> : <div className=\"hv-loading\">Loading…</div>}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport JSZip from 'jszip';\nimport type { PageLayout } from '../types';\n\ntype Slide = { index: number; text: string };\n\nfunction decodeXml(s: string): string {\n return s\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\");\n}\n\nfunction extractText(xml: string) {\n return [...xml.matchAll(/<a:t>(.*?)<\\/a:t>/g)].map(m => decodeXml(m[1] || '')).join(' ').trim();\n}\n\nexport function PptxRenderer(props: {\n arrayBuffer?: ArrayBuffer;\n layout: PageLayout;\n currentPage: number;\n onCurrentPageChange: (p: number) => void;\n onSlideCount: (n: number) => void;\n onThumbs: (thumbs: (string|undefined)[]) => void;\n}) {\n const [slides, setSlides] = useState<Slide[]>([]);\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setSlides([]); setThumbs([]);\n if (!props.arrayBuffer) { props.onSlideCount(1); setSlides([{index:1,text:'No content'}]); return; }\n const zip = await JSZip.loadAsync(props.arrayBuffer);\n const files = Object.keys(zip.files).filter(p => /^ppt\\/slides\\/slide\\d+\\.xml$/.test(p)).sort((a,b)=>{\n const na = Number(a.match(/slide(\\d+)\\.xml/)?.[1]||0);\n const nb = Number(b.match(/slide(\\d+)\\.xml/)?.[1]||0);\n return na-nb;\n });\n const out: Slide[] = [];\n for (let i=0;i<files.length;i++) {\n const xml = await zip.file(files[i])!.async('string');\n out.push({ index:i+1, text: extractText(xml) });\n }\n if (cancelled) return;\n const count = Math.max(1,out.length);\n props.onSlideCount(count);\n setSlides(out.length?out:[{index:1,text:'(empty)'}]);\n setThumbs(Array.from({length:count}, (_,i)=>`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgThumb(i+1))}`));\n })().catch(()=>{\n props.onSlideCount(1);\n setSlides([{index:1,text:'Unable to render this .pptx in-browser.'}]);\n setThumbs([undefined]);\n });\n return ()=>{cancelled=true;};\n }, [props.arrayBuffer]);\n\n useEffect(()=>{ props.onThumbs(thumbs); }, [thumbs]);\n\n const pagesToShow = useMemo(()=>{\n if (props.layout==='side-by-side') return [props.currentPage, Math.min(slides.length||props.currentPage+1, props.currentPage+1)];\n return [props.currentPage];\n }, [props.currentPage, props.layout, slides.length]);\n\n return (\n <div className=\"hv-doc\">\n <div className={props.layout==='side-by-side' ? 'hv-pages hv-pages--two' : 'hv-pages'}>\n {pagesToShow.map(p=>{\n const s = slides[p-1];\n return (\n <div key={p} className=\"hv-slide\" tabIndex={0} onFocus={()=>props.onCurrentPageChange(p)}>\n <div className=\"hv-slide-title\">Slide {p}</div>\n <div className=\"hv-slide-text\">{s?.text || ''}</div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction svgThumb(n: number) {\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"180\" height=\"100\"><rect width=\"100%\" height=\"100%\" rx=\"12\" fill=\"#111827\"/><text x=\"50%\" y=\"54%\" font-size=\"18\" fill=\"#e5e7eb\" text-anchor=\"middle\">${n}</text></svg>`;\n}\n"],"mappings":"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","names":["useEffect","useMemo","useRef","useState","jsx","jsxs","jsx","jsxs","jsx","jsxs","url","useEffect","useMemo","useRef","useState","jsx","jsxs","useMemo","useRef","useState","useEffect","b64","forwardRef","useEffect","useImperativeHandle","useMemo","useState","jsx","jsxs","forwardRef","SpreadsheetEditor","useState","useEffect","cols","_","useImperativeHandle","useMemo","useEffect","useMemo","useState","jsx","jsxs","useEffect","useMemo","useState","jsx","jsxs","jsx","jsxs","useMemo","useState","useEffect","useRef","arrayBufferToBase64"]}
1
+ {"version":3,"sources":["../src/components/DocumentViewer.tsx","../src/utils/locale.ts","../src/utils/fileSource.ts","../src/components/Toolbar.tsx","../src/components/ThumbnailsSidebar.tsx","../src/components/SignaturePanel.tsx","../src/renderers/PdfRenderer.tsx","../src/editors/RichTextEditor.tsx","../src/utils/sanitize.ts","../src/editors/SpreadsheetEditor.tsx","../src/renderers/ImageRenderer.tsx","../src/renderers/PptxRenderer.tsx"],"sourcesContent":["'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport type { DocumentMode, DocumentViewerProps, PageLayout, Signature, SupportedFileType } from '../types';\nimport { defaultLocale } from '../utils/locale';\nimport { resolveSource } from '../utils/fileSource';\nimport { Toolbar } from './Toolbar';\nimport { ThumbnailsSidebar, type Thumbnail } from './ThumbnailsSidebar';\nimport { SignaturePanel } from './SignaturePanel';\nimport { PdfRenderer } from '../renderers/PdfRenderer';\nimport { RichTextEditor, type RichTextEditorHandle } from '../editors/RichTextEditor';\nimport { SpreadsheetEditor, type SpreadsheetEditorHandle } from '../editors/SpreadsheetEditor';\nimport { ImageRenderer } from '../renderers/ImageRenderer';\nimport { PptxRenderer } from '../renderers/PptxRenderer';\n\ntype SigPlacement = { page: number; x: number; y: number; w: number; h: number; signatureImageUrl: string };\n\ntype EditorHandle = (RichTextEditorHandle | SpreadsheetEditorHandle) & { save: (exportPdf?: boolean) => Promise<void> };\n\nexport function DocumentViewer(props: DocumentViewerProps) {\n const mode: DocumentMode = props.mode ?? 'view';\n const theme = props.theme ?? 'light';\n const locale = useMemo(() => ({ ...defaultLocale, ...(props.locale ?? {}) }), [props.locale]);\n\n const [layout, setLayout] = useState<PageLayout>(props.defaultLayout ?? 'single');\n const [showThumbnails, setShowThumbnails] = useState(true);\n const [showSignatures, setShowSignatures] = useState(true);\n const [headerFooterEnabled, setHeaderFooterEnabled] = useState(true);\n\n const allowSigning = props.allowSigning ?? false;\n const [signingBusy, setSigningBusy] = useState(false);\n\n const [resolved, setResolved] = useState<{ fileType: SupportedFileType; fileName: string; url?: string; arrayBuffer?: ArrayBuffer } | null>(null);\n const [error, setError] = useState<string>('');\n const [pageCount, setPageCount] = useState(1);\n const [currentPage, setCurrentPage] = useState(1);\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n\n const [localSignatures, setLocalSignatures] = useState<Signature[]>(props.signatures ?? []);\n useEffect(() => setLocalSignatures(props.signatures ?? []), [props.signatures]);\n\n const [sigPlacements, setSigPlacements] = useState<SigPlacement[]>([]);\n const [armedSignatureUrl, setArmedSignatureUrl] = useState<string | null>(null);\n\n const editorRef = useRef<EditorHandle | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setError('');\n setResolved(null);\n setThumbs([]);\n setPageCount(1);\n setCurrentPage(1);\n setSigPlacements([]);\n setArmedSignatureUrl(null);\n\n if (mode === 'create') {\n const ft = (props.fileType ?? 'docx') as SupportedFileType;\n setResolved({ fileType: ft, fileName: props.fileName ?? `Untitled.${ft}` });\n return;\n }\n\n try {\n const res = await resolveSource({\n fileUrl: props.fileUrl,\n base64: props.base64,\n blob: props.blob,\n fileName: props.fileName,\n fileType: props.fileType\n });\n if (cancelled) return;\n setResolved({ fileType: res.fileType, fileName: res.fileName, url: res.url, arrayBuffer: res.arrayBuffer });\n } catch (e) {\n if (cancelled) return;\n setError(e instanceof Error ? e.message : String(e));\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [mode, props.fileUrl, props.base64, props.blob, props.fileName, props.fileType]);\n\n const thumbnails: Thumbnail[] = useMemo(() => {\n const n = Math.max(1, pageCount);\n return Array.from({ length: n }, (_, i) => ({\n id: `p-${i + 1}`,\n label: `${locale['thumbnails.page'] ?? 'Page'} ${i + 1}`,\n dataUrl: thumbs[i]\n }));\n }, [pageCount, thumbs, locale]);\n\n async function handleSignRequest() {\n if (!allowSigning || signingBusy || !props.onSignRequest) return;\n setSigningBusy(true);\n try {\n const sig = await props.onSignRequest();\n setLocalSignatures((prev: Signature[]) => [...prev, sig]);\n setArmedSignatureUrl(sig.signatureImageUrl);\n } finally {\n setSigningBusy(false);\n }\n }\n\n function placeSignature(p: { page: number; x: number; y: number; w: number; h: number }) {\n if (!armedSignatureUrl) return;\n setSigPlacements((prev: SigPlacement[]) => [...prev, { ...p, signatureImageUrl: armedSignatureUrl }]);\n setArmedSignatureUrl(null);\n }\n\n async function handleSave(exportPdf?: boolean) {\n if (editorRef.current) {\n await editorRef.current.save(!!exportPdf);\n return;\n }\n if (!resolved?.arrayBuffer) return;\n const b64 = arrayBufferToBase64(resolved.arrayBuffer);\n props.onSave?.(b64, { fileName: resolved.fileName, fileType: resolved.fileType, annotations: { sigPlacements } });\n }\n\n const canSave = mode === 'edit' || mode === 'create';\n const canExportPdf = (mode === 'edit' || mode === 'create') && (resolved?.fileType === 'docx' || resolved?.fileType === 'md' || resolved?.fileType === 'txt' || resolved?.fileType === 'xlsx');\n\n return (\n <div className={`hv-root`} data-hv-theme={theme}>\n <Toolbar\n locale={locale}\n mode={mode}\n fileType={resolved?.fileType}\n layout={layout}\n onChangeLayout={setLayout}\n showThumbnails={showThumbnails}\n onToggleThumbnails={() => setShowThumbnails((v: boolean) => !v)}\n showSignatures={showSignatures}\n onToggleSignatures={() => setShowSignatures((v: boolean) => !v)}\n onSign={() => void handleSignRequest()}\n allowSigning={allowSigning}\n signingDisabled={signingBusy || !props.onSignRequest}\n canSave={canSave}\n onSave={() => void handleSave(false)}\n canExportPdf={canExportPdf}\n onExportPdf={() => void handleSave(true)}\n headerFooterEnabled={headerFooterEnabled}\n showHeaderFooterToggle={(props.enableHeaderFooterToggle ?? true) && mode === 'create'}\n onToggleHeaderFooter={() => setHeaderFooterEnabled((v: boolean) => !v)}\n />\n\n {error ? (\n <div className=\"hv-error\" role=\"alert\">\n <div className=\"hv-error-title\">{locale['error.title'] ?? 'Error'}</div>\n <div className=\"hv-error-body\">{error}</div>\n </div>\n ) : null}\n\n {!resolved && !error ? <div className=\"hv-loading\" aria-busy=\"true\">{locale['loading'] ?? 'Loading…'}</div> : null}\n\n {resolved ? (\n <div className=\"hv-shell\">\n {mode !== 'create' ? (\n <ThumbnailsSidebar\n locale={locale}\n thumbnails={thumbnails}\n currentPage={currentPage}\n collapsed={!showThumbnails}\n onToggle={() => setShowThumbnails((v: boolean) => !v)}\n onSelectPage={setCurrentPage}\n />\n ) : null}\n\n <main className=\"hv-main\">\n {resolved.fileType === 'pdf' ? (\n <PdfRenderer\n url={resolved.url}\n arrayBuffer={resolved.arrayBuffer}\n layout={layout}\n currentPage={currentPage}\n onCurrentPageChange={setCurrentPage}\n onPageCount={(n) => {\n setPageCount(n);\n setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])));\n }}\n onThumbs={(t) => setThumbs(t)}\n signatureStamp={armedSignatureUrl ? { imageUrl: armedSignatureUrl, armed: true, onPlaced: placeSignature } : undefined}\n />\n ) : null}\n\n {resolved.fileType === 'docx' || resolved.fileType === 'md' || resolved.fileType === 'txt' ? (\n <RichTextEditor\n ref={editorRef as any}\n mode={mode}\n fileType={resolved.fileType}\n fileName={resolved.fileName}\n arrayBuffer={resolved.arrayBuffer}\n headerComponent={props.headerComponent}\n footerComponent={props.footerComponent}\n headerFooterEnabled={headerFooterEnabled}\n locale={locale}\n signatures={localSignatures}\n signaturePlacements={sigPlacements}\n onPageCount={(n) => { setPageCount(n); setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i]))); }}\n onSave={(b64, meta) => props.onSave?.(b64, meta)}\n armedSignatureUrl={armedSignatureUrl}\n onPlaceSignature={placeSignature}\n />\n ) : null}\n\n {resolved.fileType === 'xlsx' ? (\n <SpreadsheetEditor\n ref={editorRef as any}\n mode={mode}\n fileName={resolved.fileName}\n arrayBuffer={resolved.arrayBuffer}\n locale={locale}\n onSave={(b64, meta) => props.onSave?.(b64, meta)}\n />\n ) : null}\n\n {resolved.fileType === 'pptx' ? (\n <PptxRenderer\n arrayBuffer={resolved.arrayBuffer}\n layout={layout}\n currentPage={currentPage}\n onCurrentPageChange={setCurrentPage}\n onSlideCount={(n) => {\n setPageCount(n);\n setThumbs((prev) => (prev.length === n ? prev : Array.from({ length: n }, (_, i) => prev[i])));\n }}\n onThumbs={(t) => setThumbs(t)}\n />\n ) : null}\n\n {resolved.fileType === 'png' || resolved.fileType === 'jpg' || resolved.fileType === 'svg' ? (\n <ImageRenderer arrayBuffer={resolved.arrayBuffer} fileType={resolved.fileType} fileName={resolved.fileName} />\n ) : null}\n </main>\n\n {mode !== 'create' && localSignatures.length ? (\n <SignaturePanel\n locale={locale}\n signatures={localSignatures}\n collapsed={!showSignatures}\n onToggle={() => setShowSignatures((v: boolean) => !v)}\n />\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction arrayBufferToBase64(ab: ArrayBuffer): string {\n const bytes = new Uint8Array(ab);\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n","export const defaultLocale: Record<string, string> = {\n 'loading': 'Loading…',\n 'error.title': 'Error',\n 'toolbar.layout.single': 'Single page',\n 'toolbar.layout.two': 'Side-by-side',\n 'toolbar.thumbs': 'Thumbnails',\n 'toolbar.signatures': 'Signatures',\n 'toolbar.sign': 'Sign Document',\n 'toolbar.save': 'Save',\n 'toolbar.exportPdf': 'Export as PDF',\n 'thumbnails.title': 'Thumbnails',\n 'thumbnails.page': 'Page',\n 'signatures.title': 'Signatures',\n 'signatures.empty': 'No signatures',\n 'signatures.placeHint': 'Click on the document to place the signature.',\n 'a11y.viewer': 'Document viewer',\n 'a11y.ribbon': 'Ribbon',\n 'a11y.editor': 'Document editor'\n};\n","import type { SupportedFileType } from '../types';\n\nexport function guessFileType(name?: string, explicit?: SupportedFileType): SupportedFileType {\n if (explicit) return explicit;\n const ext = (name?.split('.').pop() || '').toLowerCase();\n const allowed: SupportedFileType[] = ['pdf','md','docx','xlsx','pptx','txt','png','jpg','svg'];\n return (allowed as string[]).includes(ext) ? (ext as SupportedFileType) : 'txt';\n}\n\nexport function arrayBufferToBase64(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n\nexport async function base64ToArrayBuffer(b64: string): Promise<ArrayBuffer> {\n const bin = atob(b64);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes.buffer;\n}\n\nexport async function resolveSource(args: {\n fileUrl?: string;\n base64?: string;\n blob?: Blob;\n fileName?: string;\n fileType?: SupportedFileType;\n onProgress?: (loaded: number, total?: number) => void;\n}): Promise<{ fileType: SupportedFileType; fileName: string; arrayBuffer: ArrayBuffer; url?: string }>{\n const fileType = guessFileType(args.fileName, args.fileType);\n const fileName = args.fileName ?? `document.${fileType}`;\n\n if (args.blob) {\n const ab = await args.blob.arrayBuffer();\n const url = URL.createObjectURL(args.blob);\n return { fileType, fileName, arrayBuffer: ab, url };\n }\n\n if (args.base64) {\n const ab = await base64ToArrayBuffer(args.base64);\n return { fileType, fileName, arrayBuffer: ab };\n }\n\n if (!args.fileUrl) throw new Error('No file source provided. Use fileUrl, blob, or base64.');\n\n const res = await fetch(args.fileUrl);\n if (!res.ok) throw new Error(`Failed to fetch file (${res.status})`);\n\n const total = Number(res.headers.get('content-length') || '') || undefined;\n if (!res.body) {\n const ab = await res.arrayBuffer();\n args.onProgress?.(ab.byteLength, total);\n return { fileType, fileName, arrayBuffer: ab, url: args.fileUrl };\n }\n\n const reader = res.body.getReader();\n const chunks: Uint8Array[] = [];\n let loaded = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) {\n chunks.push(value);\n loaded += value.length;\n args.onProgress?.(loaded, total);\n }\n }\n const out = new Uint8Array(loaded);\n let offset = 0;\n for (const c of chunks) { out.set(c, offset); offset += c.length; }\n return { fileType, fileName, arrayBuffer: out.buffer, url: args.fileUrl };\n}\n","'use client';\n\nimport React from 'react';\nimport type { DocumentMode, PageLayout, SupportedFileType } from '../types';\n\nexport function Toolbar(props: {\n locale: Record<string, string>;\n mode: DocumentMode;\n fileType?: SupportedFileType;\n layout: PageLayout;\n onChangeLayout: (l: PageLayout) => void;\n showThumbnails: boolean;\n onToggleThumbnails: () => void;\n showSignatures: boolean;\n onToggleSignatures: () => void;\n allowSigning: boolean;\n signingDisabled: boolean;\n onSign: () => void;\n canSave: boolean;\n onSave: () => void;\n canExportPdf: boolean;\n onExportPdf: () => void;\n showHeaderFooterToggle: boolean;\n headerFooterEnabled: boolean;\n onToggleHeaderFooter: () => void;\n}) {\n const t = (k: string, fallback: string) => props.locale[k] ?? fallback;\n\n return (\n <div className=\"hv-toolbar\" role=\"toolbar\" aria-label={t('a11y.toolbar', 'Document toolbar')}>\n <div className=\"hv-toolbar__left\">\n <button type=\"button\" className=\"hv-btn\" onClick={props.onToggleThumbnails} aria-pressed={props.showThumbnails}>\n {t('toolbar.thumbs', 'Thumbnails')}\n </button>\n {props.mode !== 'create' && (\n <button type=\"button\" className=\"hv-btn\" onClick={props.onToggleSignatures} aria-pressed={props.showSignatures}>\n {t('toolbar.signatures', 'Signatures')}\n </button>\n )}\n <span className=\"hv-sep\" />\n <button type=\"button\" className={props.layout === 'single' ? 'hv-btn hv-btn--active' : 'hv-btn'} onClick={() => props.onChangeLayout('single')}>\n {t('toolbar.layout.single', 'Single')}\n </button>\n <button type=\"button\" className={props.layout === 'side-by-side' ? 'hv-btn hv-btn--active' : 'hv-btn'} onClick={() => props.onChangeLayout('side-by-side')}>\n {t('toolbar.layout.two', 'Two')}\n </button>\n </div>\n\n <div className=\"hv-toolbar__right\">\n {props.showHeaderFooterToggle && (\n <label className=\"hv-toggle\">\n <input type=\"checkbox\" checked={props.headerFooterEnabled} onChange={props.onToggleHeaderFooter} />\n <span>{t('toolbar.letterhead', 'Letterhead')}</span>\n </label>\n )}\n\n {props.allowSigning && (\n <button type=\"button\" className=\"hv-btn hv-btn--primary\" onClick={props.onSign} disabled={props.signingDisabled}>\n {t('toolbar.sign', 'Sign Document')}\n </button>\n )}\n\n {props.canExportPdf && (\n <button type=\"button\" className=\"hv-btn\" onClick={props.onExportPdf}>\n {t('toolbar.exportPdf', 'Export as PDF')}\n </button>\n )}\n {props.canSave && (\n <button type=\"button\" className=\"hv-btn hv-btn--primary\" onClick={props.onSave}>\n {t('toolbar.save', 'Save')}\n </button>\n )}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport React from 'react';\n\nexport type Thumbnail = {\n id: string;\n label: string;\n dataUrl?: string;\n};\n\nexport function ThumbnailsSidebar(props: {\n locale: Record<string, string>;\n thumbnails: Thumbnail[];\n currentPage: number;\n collapsed: boolean;\n onToggle: () => void;\n onSelectPage: (p: number) => void;\n}) {\n const t = props.locale['thumbnails.title'] ?? 'Thumbnails';\n return (\n <aside className={props.collapsed ? 'hv-thumbs hv-thumbs--collapsed' : 'hv-thumbs'} aria-label={t}>\n <div className=\"hv-thumbs__header\">\n <button type=\"button\" className=\"hv-icon\" onClick={props.onToggle} aria-label={props.collapsed ? (props.locale['thumbnails.open'] ?? 'Open thumbnails') : (props.locale['thumbnails.close'] ?? 'Close thumbnails')}\n >{props.collapsed ? '▸' : '▾'}</button>\n {!props.collapsed ? <div className=\"hv-thumbs__title\">{t}</div> : null}\n </div>\n {!props.collapsed ? (\n <div className=\"hv-thumbs__list\" role=\"list\">\n {props.thumbnails.map((th, idx) => {\n const p = idx + 1;\n const active = p === props.currentPage;\n return (\n <button\n key={th.id}\n type=\"button\"\n role=\"listitem\"\n className={active ? 'hv-thumb hv-thumb--active' : 'hv-thumb'}\n onClick={() => props.onSelectPage(p)}\n aria-current={active ? 'page' : undefined}\n >\n <div className=\"hv-thumb__img\" aria-hidden>\n {th.dataUrl ? <img src={th.dataUrl} alt=\"\" /> : <div className=\"hv-thumb__placeholder\" />}\n </div>\n <div className=\"hv-thumb__label\">{th.label}</div>\n </button>\n );\n })}\n </div>\n ) : null}\n </aside>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport type { Signature } from '../types';\n\nexport function SignaturePanel(props: {\n locale: Record<string, string>;\n signatures: Signature[];\n collapsed: boolean;\n onToggle: () => void;\n}) {\n const title = props.locale['signatures.title'] ?? 'Signatures';\n return (\n <aside className={props.collapsed ? 'hv-side hv-side--collapsed' : 'hv-side'} aria-label={title}>\n <div className=\"hv-sidebar-header\">\n <button type=\"button\" className=\"hv-icon\" onClick={props.onToggle} aria-label={props.locale['toolbar.signatures'] ?? 'Signatures'}>\n ✍\n </button>\n <div className=\"hv-sidebar-title\">{title}</div>\n </div>\n <div className=\"hv-sidebar-body\">\n {props.signatures.map((s, idx) => (\n <div key={`${s.signedBy}-${s.dateSigned}-${idx}`} className=\"hv-signature-card\">\n <img src={s.signatureImageUrl} alt={`Signature by ${s.signedBy}`} className=\"hv-signature-img\" />\n <div className=\"hv-signature-meta\">\n <div className=\"hv-signature-name\">{s.signedBy}</div>\n <div className=\"hv-signature-date\">{new Date(s.dateSigned).toLocaleString()}</div>\n {s.comment ? <div className=\"hv-signature-comment\">{s.comment}</div> : null}\n </div>\n </div>\n ))}\n </div>\n </aside>\n );\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { GlobalWorkerOptions, getDocument, type PDFDocumentProxy } from 'pdfjs-dist';\nimport type { PageLayout } from '../types';\n\nexport function PdfRenderer(props: {\n url?: string;\n arrayBuffer?: ArrayBuffer;\n layout: PageLayout;\n currentPage: number;\n onCurrentPageChange: (p: number) => void;\n onPageCount: (n: number) => void;\n onThumbs: (thumbs: (string | undefined)[]) => void;\n signatureStamp?: {\n imageUrl: string;\n armed: boolean;\n onPlaced: (placement: { page: number; x: number; y: number; w: number; h: number }) => void;\n };\n}) {\n const { url, arrayBuffer } = props;\n const [doc, setDoc] = useState<PDFDocumentProxy | null>(null);\n const [pageCount, setPageCount] = useState(0);\n const [rendered, setRendered] = useState<Map<number, HTMLCanvasElement>>(new Map());\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n const [size, setSize] = useState({ w: 840, h: 1188 });\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n try {\n GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString();\n } catch {}\n }, []);\n\n useEffect(() => {\n let cancel = false;\n (async () => {\n setDoc(null);\n setRendered(new Map());\n setThumbs([]);\n if (!url && !arrayBuffer) return;\n const task = getDocument(url ? { url, rangeChunkSize: 512 * 1024 } : { data: arrayBuffer! });\n const pdf = await task.promise;\n if (cancel) return;\n setDoc(pdf);\n setPageCount(pdf.numPages);\n props.onPageCount(pdf.numPages);\n setThumbs(Array.from({ length: pdf.numPages }));\n const p1 = await pdf.getPage(1);\n const base = p1.getViewport({ scale: 1 });\n const w = Math.min(980, Math.max(640, base.width));\n const s = w / base.width;\n const vp = p1.getViewport({ scale: s });\n setSize({ w: Math.round(vp.width), h: Math.round(vp.height) });\n })().catch(() => {\n // ignore; caller shows error\n });\n return () => { cancel = true; };\n }, [url, arrayBuffer]);\n\n useEffect(() => {\n props.onThumbs(thumbs);\n }, [thumbs]);\n\n const pagesToShow = useMemo(() => {\n if (props.layout === 'side-by-side') {\n const left = props.currentPage;\n const right = Math.min(pageCount || left + 1, left + 1);\n return [left, right];\n }\n return [props.currentPage];\n }, [props.currentPage, props.layout, pageCount]);\n\n useEffect(() => {\n if (!doc) return;\n let cancel = false;\n (async () => {\n for (const p of pagesToShow) {\n if (rendered.has(p)) continue;\n const page = await doc.getPage(p);\n if (cancel) return;\n const base = page.getViewport({ scale: 1 });\n const vp = page.getViewport({ scale: size.w / base.width });\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(vp.width);\n canvas.height = Math.round(vp.height);\n const ctx = canvas.getContext('2d', { alpha: false });\n if (!ctx) continue;\n await page.render({ canvasContext: ctx, viewport: vp }).promise;\n if (cancel) return;\n setRendered(prev => {\n const next = new Map(prev);\n next.set(p, canvas);\n return next;\n });\n try {\n const tw = 140;\n const th = Math.round(tw * (canvas.height / canvas.width));\n const t = document.createElement('canvas');\n t.width = tw; t.height = th;\n const tctx = t.getContext('2d');\n if (tctx) {\n tctx.drawImage(canvas, 0, 0, tw, th);\n const url = t.toDataURL('image/jpeg', 0.75);\n setThumbs(prev => {\n const next = prev.slice();\n next[p - 1] = url;\n return next;\n });\n }\n } catch {}\n }\n })();\n return () => { cancel = true; };\n }, [doc, pagesToShow, size.w, rendered]);\n\n function onWheel(e: React.WheelEvent) {\n if (!pageCount) return;\n if (Math.abs(e.deltaY) < 10) return;\n const dir = e.deltaY > 0 ? 1 : -1;\n const step = props.layout === 'side-by-side' ? 2 : 1;\n const next = Math.max(1, Math.min(pageCount, props.currentPage + dir * step));\n props.onCurrentPageChange(next);\n }\n\n function clickPlace(e: React.MouseEvent, page: number) {\n const stamp = props.signatureStamp;\n if (!stamp?.armed) return;\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const x = (e.clientX - rect.left) / rect.width;\n const y = (e.clientY - rect.top) / rect.height;\n stamp.onPlaced({ page, x, y, w: 0.22, h: 0.08 });\n }\n\n return (\n <div className=\"hv-doc\" ref={containerRef} onWheel={onWheel}>\n {!doc ? <div className=\"hv-loading\">Loading PDF…</div> : null}\n {doc ? (\n <div className={props.layout === 'side-by-side' ? 'hv-pages hv-pages--two' : 'hv-pages'}>\n {pagesToShow.map(p => {\n const c = rendered.get(p);\n return (\n <div key={p} className=\"hv-page\" style={{ width: size.w, height: size.h }} onClick={(e) => clickPlace(e, p)}>\n {c ? (\n <canvas\n className=\"hv-canvas\"\n width={c.width}\n height={c.height}\n ref={(node) => {\n if (!node) return;\n const ctx = node.getContext('2d');\n if (ctx) ctx.drawImage(c, 0, 0);\n }}\n />\n ) : <div className=\"hv-loading\">Rendering…</div>}\n </div>\n );\n })}\n </div>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\nimport React, {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport mammoth from \"mammoth\";\n// Do not statically import html-to-docx; use dynamic import for browser compatibility\nimport MarkdownIt from \"markdown-it\";\nimport html2canvas from \"html2canvas\";\nimport { sanitizeHtml } from \"../utils/sanitize\";\nimport { arrayBufferToBase64 } from \"../utils/fileSource\";\nimport type { DocumentMode, Signature, SupportedFileType } from \"../types\";\n\nconst PAGE_H = 1122; // virtual A4\n\nexport type RichTextEditorHandle = {\n save: (exportPdf?: boolean) => Promise<void>;\n requestThumbnail: (index: number) => Promise<string | undefined>;\n};\n\nexport const RichTextEditor = forwardRef<\n RichTextEditorHandle,\n {\n mode: DocumentMode;\n fileType: \"docx\" | \"md\" | \"txt\";\n fileName: string;\n arrayBuffer?: ArrayBuffer;\n locale: Record<string, string>;\n headerComponent?: React.ReactNode;\n footerComponent?: React.ReactNode;\n headerFooterEnabled: boolean;\n signatures: Signature[];\n signaturePlacements: {\n page: number;\n x: number;\n y: number;\n w: number;\n h: number;\n signatureImageUrl: string;\n }[];\n armedSignatureUrl: string | null;\n onPlaceSignature: (p: {\n page: number;\n x: number;\n y: number;\n w: number;\n h: number;\n }) => void;\n onSave: (\n b64: string,\n meta: {\n fileName: string;\n fileType: SupportedFileType;\n exportedAsPdf?: boolean;\n annotations?: unknown;\n },\n ) => void;\n onPageCount: (n: number) => void;\n }\n>((props, ref) => {\n const readOnly = props.mode === \"view\";\n const md = useMemo(\n () => new MarkdownIt({ html: false, linkify: true, breaks: true }),\n [],\n );\n const scrollerRef = useRef<HTMLDivElement | null>(null);\n const editorRef = useRef<HTMLDivElement | null>(null);\n const captureRef = useRef<HTMLDivElement | null>(null);\n\n const [html, setHtml] = useState(\"<p><br/></p>\");\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n if (props.mode === \"create\") {\n setHtml(\"<p><br/></p>\");\n return;\n }\n if (!props.arrayBuffer) return;\n if (props.fileType === \"docx\") {\n const res = await mammoth.convertToHtml({\n arrayBuffer: props.arrayBuffer,\n });\n if (!cancelled) setHtml(sanitizeHtml(res.value || \"<p><br/></p>\"));\n } else {\n const text = new TextDecoder().decode(props.arrayBuffer);\n if (props.fileType === \"md\") setHtml(sanitizeHtml(md.render(text)));\n else setHtml(`<pre>${escapeHtml(text)}</pre>`);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [props.arrayBuffer, props.fileType, props.mode, md]);\n\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return;\n const recompute = () =>\n props.onPageCount(Math.max(1, Math.ceil(el.scrollHeight / PAGE_H)));\n recompute();\n const ro = new ResizeObserver(recompute);\n ro.observe(el);\n return () => ro.disconnect();\n }, [html, props.headerFooterEnabled]);\n\n function exec(cmd: string) {\n if (readOnly) return;\n document.execCommand(cmd);\n }\n\n function onClick(e: React.MouseEvent<HTMLDivElement>) {\n if (!props.armedSignatureUrl) return;\n const scroller = scrollerRef.current;\n if (!scroller) return;\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const absY = scroller.scrollTop + (e.clientY - rect.top);\n const page = Math.max(1, Math.floor(absY / PAGE_H) + 1);\n const pageTop = (page - 1) * PAGE_H;\n const x = (e.clientX - rect.left) / rect.width;\n const y = (absY - pageTop) / PAGE_H;\n props.onPlaceSignature({ page, x, y, w: 0.25, h: 0.1 });\n }\n\n async function requestThumbnail(index: number): Promise<string | undefined> {\n const scroller = scrollerRef.current;\n const capture = captureRef.current;\n if (!scroller || !capture) return undefined;\n const old = scroller.scrollTop;\n scroller.scrollTop = index * PAGE_H;\n await new Promise((r) => requestAnimationFrame(() => r(null)));\n try {\n const canvas = await html2canvas(capture, {\n backgroundColor: null,\n scale: 0.25,\n useCORS: true,\n });\n return canvas.toDataURL(\"image/png\");\n } catch {\n return undefined;\n } finally {\n scroller.scrollTop = old;\n }\n }\n\n async function save(exportPdf?: boolean) {\n const inner = editorRef.current?.innerHTML ?? html;\n const stitched = `<!doctype html><html><head><meta charset=\"utf-8\" /></head><body>${inner}</body></html>`;\n\n if (exportPdf) {\n // client-side: return print-ready HTML as base64\n const b64 = btoa(unescape(encodeURIComponent(stitched)));\n props.onSave(b64, {\n fileName: replaceExt(props.fileName, \"html\"),\n fileType: \"txt\",\n exportedAsPdf: true,\n annotations: { signaturePlacements: props.signaturePlacements },\n });\n return;\n }\n\n if (props.fileType === \"docx\") {\n // Only attempt to import html-to-docx at runtime\n try {\n // @ts-ignore\n const htmlToDocx = (await import(\"html-to-docx\")).default;\n const blob = await htmlToDocx(stitched);\n const ab = await blob.arrayBuffer();\n props.onSave(arrayBufferToBase64(ab), {\n fileName: replaceExt(props.fileName, \"docx\"),\n fileType: \"docx\",\n annotations: { signaturePlacements: props.signaturePlacements },\n });\n } catch (err) {\n // Show a user-friendly error if running in the browser or import fails\n alert(\n \"DOCX export is not supported in this environment. Please use this feature in a Node.js/server context.\",\n );\n }\n return;\n }\n\n const text = editorRef.current?.innerText ?? \"\";\n const b64 = btoa(unescape(encodeURIComponent(text)));\n props.onSave(b64, {\n fileName: replaceExt(props.fileName, props.fileType),\n fileType: props.fileType,\n annotations: { signaturePlacements: props.signaturePlacements },\n });\n }\n\n useImperativeHandle(ref, () => ({ save, requestThumbnail }));\n\n return (\n <div className=\"hv-doc\">\n <div className=\"hv-ribbon\" role=\"toolbar\">\n <button\n className=\"hv-btn\"\n onClick={() => exec(\"bold\")}\n disabled={readOnly}\n >\n B\n </button>\n <button\n className=\"hv-btn\"\n onClick={() => exec(\"italic\")}\n disabled={readOnly}\n >\n I\n </button>\n <button\n className=\"hv-btn\"\n onClick={() => exec(\"underline\")}\n disabled={readOnly}\n >\n U\n </button>\n {props.armedSignatureUrl ? (\n <div className=\"hv-hint\">Click to place signature</div>\n ) : null}\n </div>\n\n <div className=\"hv-scroll\" ref={scrollerRef} onClick={onClick}>\n <div className=\"hv-pageStage\" ref={captureRef}>\n {props.headerFooterEnabled && props.headerComponent ? (\n <div className=\"hv-letterhead\">{props.headerComponent}</div>\n ) : null}\n\n <div\n ref={editorRef}\n className={readOnly ? \"hv-editor hv-editor--ro\" : \"hv-editor\"}\n contentEditable={!readOnly}\n suppressContentEditableWarning\n onInput={() => setHtml(editorRef.current?.innerHTML ?? \"\")}\n dangerouslySetInnerHTML={{ __html: html }}\n />\n\n {props.headerFooterEnabled && props.footerComponent ? (\n <div className=\"hv-letterhead hv-letterhead--footer\">\n {props.footerComponent}\n </div>\n ) : null}\n\n {props.mode === \"create\" && props.signatures.length ? (\n <div className=\"hv-signatures-inline\">\n {props.signatures.map((s, i) => (\n <div key={i} className=\"hv-sign-inline\">\n <img\n src={s.signatureImageUrl}\n alt=\"\"\n className=\"hv-sign-img\"\n />\n <div>\n <div className=\"hv-sign-name\">{s.signedBy}</div>\n <div className=\"hv-sign-date\">\n {new Date(s.dateSigned).toLocaleString()}\n </div>\n </div>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n </div>\n );\n});\n\nfunction replaceExt(name: string, ext: string) {\n const base = name.includes(\".\") ? name.slice(0, name.lastIndexOf(\".\")) : name;\n return `${base}.${ext}`;\n}\n\nfunction escapeHtml(s: string) {\n return s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n","import DOMPurify from 'dompurify';\n\nexport function sanitizeHtml(html: string): string {\n // DOMPurify is safe to call in the browser. For SSR, callers should only run after mount.\n return DOMPurify.sanitize(html, {\n USE_PROFILES: { html: true },\n ADD_ATTR: ['target', 'rel']\n });\n}\n","'use client';\n\nimport React, { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react';\nimport * as XLSX from 'xlsx';\nimport { arrayBufferToBase64 } from '../utils/fileSource';\nimport type { DocumentMode, SupportedFileType } from '../types';\n\nexport type SpreadsheetEditorHandle = {\n save: (exportPdf?: boolean) => Promise<void>;\n requestThumbnails: (index: number) => Promise<void>;\n};\n\nexport const SpreadsheetEditor = forwardRef<SpreadsheetEditorHandle, {\n mode: DocumentMode;\n fileName: string;\n arrayBuffer?: ArrayBuffer;\n locale: Record<string, string>;\n onSave: (base64: string, meta: { fileName: string; fileType: SupportedFileType; exportedAsPdf?: boolean }) => void;\n}>(function SpreadsheetEditor(props, ref) {\n const readonly = props.mode === 'view';\n const [grid, setGrid] = useState<string[][]>(() => Array.from({ length: 30 }, () => Array.from({ length: 12 }, () => '')));\n\n useEffect(() => {\n if (!props.arrayBuffer) return;\n try {\n const wb = XLSX.read(props.arrayBuffer, { type: 'array' });\n const name = wb.SheetNames[0];\n const ws = wb.Sheets[name];\n const aoa = XLSX.utils.sheet_to_json(ws, { header: 1, raw: true }) as any[][];\n const rows = Math.max(30, aoa.length);\n const cols = Math.max(12, Math.max(...aoa.map(r => (r?.length ?? 0)), 0));\n const next = Array.from({ length: rows }, (_, r) => Array.from({ length: cols }, (_, c) => {\n const v = aoa[r]?.[c];\n return v == null ? '' : String(v);\n }));\n setGrid(next);\n } catch {\n // ignore\n }\n }, [props.arrayBuffer]);\n\n async function save(exportPdf?: boolean) {\n const ws = XLSX.utils.aoa_to_sheet(grid);\n const wb = XLSX.utils.book_new();\n XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');\n const out = XLSX.write(wb, { type: 'array', bookType: 'xlsx' }) as ArrayBuffer;\n const b64 = arrayBufferToBase64(out);\n props.onSave(b64, { fileName: ensureExt(props.fileName, 'xlsx'), fileType: 'xlsx', exportedAsPdf: !!exportPdf });\n }\n\n useImperativeHandle(ref, () => ({\n save,\n requestThumbnails: async () => undefined\n }));\n\n const cols = useMemo(() => Array.from({ length: grid[0]?.length ?? 0 }, (_, i) => String.fromCharCode(65 + (i % 26))), [grid]);\n\n return (\n <div className=\"hv-sheet\">\n <div className=\"hv-sheetbar\">\n <div className=\"hv-sheetbar-title\">{props.fileName}</div>\n {!readonly ? <button className=\"hv-btn\" type=\"button\" onClick={() => void save(false)}>{props.locale['toolbar.save'] ?? 'Save'}</button> : null}\n </div>\n <div className=\"hv-sheetgrid\" role=\"table\" aria-label=\"Spreadsheet\">\n <div className=\"hv-sheetrow hv-sheetrow--header\" role=\"row\">\n <div className=\"hv-sheetcell hv-sheetcell--corner\" role=\"columnheader\" />\n {cols.map((c, i) => <div key={i} className=\"hv-sheetcell hv-sheetcell--header\" role=\"columnheader\">{c}</div>)}\n </div>\n {grid.map((row, r) => (\n <div key={r} className=\"hv-sheetrow\" role=\"row\">\n <div className=\"hv-sheetcell hv-sheetcell--header\" role=\"rowheader\">{r + 1}</div>\n {row.map((val, c) => (\n <div\n key={c}\n className=\"hv-sheetcell\"\n role=\"cell\"\n contentEditable={!readonly}\n suppressContentEditableWarning\n onInput={(e) => {\n const text = (e.currentTarget.textContent ?? '');\n setGrid((prev) => {\n const next = prev.map(rr => rr.slice());\n next[r][c] = text;\n return next;\n });\n }}\n >{val}</div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n});\n\nfunction ensureExt(name: string, ext: string) {\n const base = name.includes('.') ? name.slice(0, name.lastIndexOf('.')) : name;\n return `${base}.${ext}`;\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport type { SupportedFileType } from '../types';\n\nexport function ImageRenderer({ arrayBuffer, fileType, fileName }: { arrayBuffer?: ArrayBuffer; fileType: SupportedFileType; fileName: string }) {\n const [zoom, setZoom] = useState(1);\n const url = useMemo(() => {\n if (!arrayBuffer) return undefined;\n const mime = fileType === 'svg' ? 'image/svg+xml' : fileType === 'png' ? 'image/png' : 'image/jpeg';\n return URL.createObjectURL(new Blob([arrayBuffer], { type: mime }));\n }, [arrayBuffer, fileType]);\n\n useEffect(() => {\n return () => { if (url) URL.revokeObjectURL(url); };\n }, [url]);\n\n return (\n <div className=\"hv-doc\">\n <div className=\"hv-mini-toolbar\">\n <div className=\"hv-title\">{fileName}</div>\n <div className=\"hv-spacer\" />\n <button type=\"button\" className=\"hv-btn\" onClick={() => setZoom((z) => Math.max(0.25, z - 0.25))}>-</button>\n <div className=\"hv-zoom\">{Math.round(zoom * 100)}%</div>\n <button type=\"button\" className=\"hv-btn\" onClick={() => setZoom((z) => Math.min(4, z + 0.25))}>+</button>\n </div>\n <div className=\"hv-center\">\n {url ? <img src={url} alt={fileName} style={{ transform: `scale(${zoom})` }} className=\"hv-image\" /> : <div className=\"hv-loading\">Loading…</div>}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport JSZip from 'jszip';\nimport type { PageLayout } from '../types';\n\ntype Slide = { index: number; text: string };\n\nfunction decodeXml(s: string): string {\n return s\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\");\n}\n\nfunction extractText(xml: string) {\n return [...xml.matchAll(/<a:t>(.*?)<\\/a:t>/g)].map(m => decodeXml(m[1] || '')).join(' ').trim();\n}\n\nexport function PptxRenderer(props: {\n arrayBuffer?: ArrayBuffer;\n layout: PageLayout;\n currentPage: number;\n onCurrentPageChange: (p: number) => void;\n onSlideCount: (n: number) => void;\n onThumbs: (thumbs: (string|undefined)[]) => void;\n}) {\n const [slides, setSlides] = useState<Slide[]>([]);\n const [thumbs, setThumbs] = useState<(string | undefined)[]>([]);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setSlides([]); setThumbs([]);\n if (!props.arrayBuffer) { props.onSlideCount(1); setSlides([{index:1,text:'No content'}]); return; }\n const zip = await JSZip.loadAsync(props.arrayBuffer);\n const files = Object.keys(zip.files).filter(p => /^ppt\\/slides\\/slide\\d+\\.xml$/.test(p)).sort((a,b)=>{\n const na = Number(a.match(/slide(\\d+)\\.xml/)?.[1]||0);\n const nb = Number(b.match(/slide(\\d+)\\.xml/)?.[1]||0);\n return na-nb;\n });\n const out: Slide[] = [];\n for (let i=0;i<files.length;i++) {\n const xml = await zip.file(files[i])!.async('string');\n out.push({ index:i+1, text: extractText(xml) });\n }\n if (cancelled) return;\n const count = Math.max(1,out.length);\n props.onSlideCount(count);\n setSlides(out.length?out:[{index:1,text:'(empty)'}]);\n setThumbs(Array.from({length:count}, (_,i)=>`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgThumb(i+1))}`));\n })().catch(()=>{\n props.onSlideCount(1);\n setSlides([{index:1,text:'Unable to render this .pptx in-browser.'}]);\n setThumbs([undefined]);\n });\n return ()=>{cancelled=true;};\n }, [props.arrayBuffer]);\n\n useEffect(()=>{ props.onThumbs(thumbs); }, [thumbs]);\n\n const pagesToShow = useMemo(()=>{\n if (props.layout==='side-by-side') return [props.currentPage, Math.min(slides.length||props.currentPage+1, props.currentPage+1)];\n return [props.currentPage];\n }, [props.currentPage, props.layout, slides.length]);\n\n return (\n <div className=\"hv-doc\">\n <div className={props.layout==='side-by-side' ? 'hv-pages hv-pages--two' : 'hv-pages'}>\n {pagesToShow.map(p=>{\n const s = slides[p-1];\n return (\n <div key={p} className=\"hv-slide\" tabIndex={0} onFocus={()=>props.onCurrentPageChange(p)}>\n <div className=\"hv-slide-title\">Slide {p}</div>\n <div className=\"hv-slide-text\">{s?.text || ''}</div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction svgThumb(n: number) {\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"180\" height=\"100\"><rect width=\"100%\" height=\"100%\" rx=\"12\" fill=\"#111827\"/><text x=\"50%\" y=\"54%\" font-size=\"18\" fill=\"#e5e7eb\" text-anchor=\"middle\">${n}</text></svg>`;\n}\n"],"mappings":"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","names":["useEffect","useMemo","useRef","useState","jsx","jsxs","jsx","jsxs","jsx","jsxs","url","useEffect","useMemo","useRef","useState","jsx","jsxs","useMemo","useRef","useState","useEffect","b64","forwardRef","useEffect","useImperativeHandle","useMemo","useState","jsx","jsxs","forwardRef","SpreadsheetEditor","useState","useEffect","cols","_","useImperativeHandle","useMemo","useEffect","useMemo","useState","jsx","jsxs","useEffect","useMemo","useState","jsx","jsxs","jsx","jsxs","useMemo","useState","useEffect","useRef","arrayBufferToBase64"]}
package/dist/index.mjs CHANGED
@@ -310,9 +310,15 @@ function PdfRenderer(props) {
310
310
  }
311
311
 
312
312
  // src/editors/RichTextEditor.tsx
313
- import { forwardRef, useEffect as useEffect2, useImperativeHandle, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
313
+ import {
314
+ forwardRef,
315
+ useEffect as useEffect2,
316
+ useImperativeHandle,
317
+ useMemo as useMemo2,
318
+ useRef as useRef2,
319
+ useState as useState2
320
+ } from "react";
314
321
  import mammoth from "mammoth";
315
- import htmlToDocx from "html-to-docx";
316
322
  import MarkdownIt from "markdown-it";
317
323
  import html2canvas from "html2canvas";
318
324
 
@@ -330,7 +336,10 @@ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
330
336
  var PAGE_H = 1122;
331
337
  var RichTextEditor = forwardRef((props, ref) => {
332
338
  const readOnly = props.mode === "view";
333
- const md = useMemo2(() => new MarkdownIt({ html: false, linkify: true, breaks: true }), []);
339
+ const md = useMemo2(
340
+ () => new MarkdownIt({ html: false, linkify: true, breaks: true }),
341
+ []
342
+ );
334
343
  const scrollerRef = useRef2(null);
335
344
  const editorRef = useRef2(null);
336
345
  const captureRef = useRef2(null);
@@ -344,7 +353,9 @@ var RichTextEditor = forwardRef((props, ref) => {
344
353
  }
345
354
  if (!props.arrayBuffer) return;
346
355
  if (props.fileType === "docx") {
347
- const res = await mammoth.convertToHtml({ arrayBuffer: props.arrayBuffer });
356
+ const res = await mammoth.convertToHtml({
357
+ arrayBuffer: props.arrayBuffer
358
+ });
348
359
  if (!cancelled) setHtml(sanitizeHtml(res.value || "<p><br/></p>"));
349
360
  } else {
350
361
  const text = new TextDecoder().decode(props.arrayBuffer);
@@ -389,7 +400,11 @@ var RichTextEditor = forwardRef((props, ref) => {
389
400
  scroller.scrollTop = index * PAGE_H;
390
401
  await new Promise((r) => requestAnimationFrame(() => r(null)));
391
402
  try {
392
- const canvas = await html2canvas(capture, { backgroundColor: null, scale: 0.25, useCORS: true });
403
+ const canvas = await html2canvas(capture, {
404
+ backgroundColor: null,
405
+ scale: 0.25,
406
+ useCORS: true
407
+ });
393
408
  return canvas.toDataURL("image/png");
394
409
  } catch {
395
410
  return void 0;
@@ -402,25 +417,69 @@ var RichTextEditor = forwardRef((props, ref) => {
402
417
  const stitched = `<!doctype html><html><head><meta charset="utf-8" /></head><body>${inner}</body></html>`;
403
418
  if (exportPdf) {
404
419
  const b642 = btoa(unescape(encodeURIComponent(stitched)));
405
- props.onSave(b642, { fileName: replaceExt(props.fileName, "html"), fileType: "txt", exportedAsPdf: true, annotations: { signaturePlacements: props.signaturePlacements } });
420
+ props.onSave(b642, {
421
+ fileName: replaceExt(props.fileName, "html"),
422
+ fileType: "txt",
423
+ exportedAsPdf: true,
424
+ annotations: { signaturePlacements: props.signaturePlacements }
425
+ });
406
426
  return;
407
427
  }
408
428
  if (props.fileType === "docx") {
409
- const blob = await htmlToDocx(stitched);
410
- const ab = await blob.arrayBuffer();
411
- props.onSave(arrayBufferToBase64(ab), { fileName: replaceExt(props.fileName, "docx"), fileType: "docx", annotations: { signaturePlacements: props.signaturePlacements } });
429
+ try {
430
+ const htmlToDocx = (await import("html-to-docx")).default;
431
+ const blob = await htmlToDocx(stitched);
432
+ const ab = await blob.arrayBuffer();
433
+ props.onSave(arrayBufferToBase64(ab), {
434
+ fileName: replaceExt(props.fileName, "docx"),
435
+ fileType: "docx",
436
+ annotations: { signaturePlacements: props.signaturePlacements }
437
+ });
438
+ } catch (err) {
439
+ alert(
440
+ "DOCX export is not supported in this environment. Please use this feature in a Node.js/server context."
441
+ );
442
+ }
412
443
  return;
413
444
  }
414
445
  const text = editorRef.current?.innerText ?? "";
415
446
  const b64 = btoa(unescape(encodeURIComponent(text)));
416
- props.onSave(b64, { fileName: replaceExt(props.fileName, props.fileType), fileType: props.fileType, annotations: { signaturePlacements: props.signaturePlacements } });
447
+ props.onSave(b64, {
448
+ fileName: replaceExt(props.fileName, props.fileType),
449
+ fileType: props.fileType,
450
+ annotations: { signaturePlacements: props.signaturePlacements }
451
+ });
417
452
  }
418
453
  useImperativeHandle(ref, () => ({ save, requestThumbnail }));
419
454
  return /* @__PURE__ */ jsxs5("div", { className: "hv-doc", children: [
420
455
  /* @__PURE__ */ jsxs5("div", { className: "hv-ribbon", role: "toolbar", children: [
421
- /* @__PURE__ */ jsx5("button", { className: "hv-btn", onClick: () => exec("bold"), disabled: readOnly, children: "B" }),
422
- /* @__PURE__ */ jsx5("button", { className: "hv-btn", onClick: () => exec("italic"), disabled: readOnly, children: "I" }),
423
- /* @__PURE__ */ jsx5("button", { className: "hv-btn", onClick: () => exec("underline"), disabled: readOnly, children: "U" }),
456
+ /* @__PURE__ */ jsx5(
457
+ "button",
458
+ {
459
+ className: "hv-btn",
460
+ onClick: () => exec("bold"),
461
+ disabled: readOnly,
462
+ children: "B"
463
+ }
464
+ ),
465
+ /* @__PURE__ */ jsx5(
466
+ "button",
467
+ {
468
+ className: "hv-btn",
469
+ onClick: () => exec("italic"),
470
+ disabled: readOnly,
471
+ children: "I"
472
+ }
473
+ ),
474
+ /* @__PURE__ */ jsx5(
475
+ "button",
476
+ {
477
+ className: "hv-btn",
478
+ onClick: () => exec("underline"),
479
+ disabled: readOnly,
480
+ children: "U"
481
+ }
482
+ ),
424
483
  props.armedSignatureUrl ? /* @__PURE__ */ jsx5("div", { className: "hv-hint", children: "Click to place signature" }) : null
425
484
  ] }),
426
485
  /* @__PURE__ */ jsx5("div", { className: "hv-scroll", ref: scrollerRef, onClick, children: /* @__PURE__ */ jsxs5("div", { className: "hv-pageStage", ref: captureRef, children: [
@@ -438,7 +497,14 @@ var RichTextEditor = forwardRef((props, ref) => {
438
497
  ),
439
498
  props.headerFooterEnabled && props.footerComponent ? /* @__PURE__ */ jsx5("div", { className: "hv-letterhead hv-letterhead--footer", children: props.footerComponent }) : null,
440
499
  props.mode === "create" && props.signatures.length ? /* @__PURE__ */ jsx5("div", { className: "hv-signatures-inline", children: props.signatures.map((s, i) => /* @__PURE__ */ jsxs5("div", { className: "hv-sign-inline", children: [
441
- /* @__PURE__ */ jsx5("img", { src: s.signatureImageUrl, alt: "", className: "hv-sign-img" }),
500
+ /* @__PURE__ */ jsx5(
501
+ "img",
502
+ {
503
+ src: s.signatureImageUrl,
504
+ alt: "",
505
+ className: "hv-sign-img"
506
+ }
507
+ ),
442
508
  /* @__PURE__ */ jsxs5("div", { children: [
443
509
  /* @__PURE__ */ jsx5("div", { className: "hv-sign-name", children: s.signedBy }),
444
510
  /* @__PURE__ */ jsx5("div", { className: "hv-sign-date", children: new Date(s.dateSigned).toLocaleString() })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerohive/hive-viewer",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",