@drvillo/react-browser-e-signing 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -59,6 +59,11 @@ pnpm demo
59
59
  - `SIGNATURE_FONTS`
60
60
  - `sha256`
61
61
 
62
+ ### Configuration
63
+
64
+ - `configure(options)` — PDF worker URL, signature font mode (`network` | `local-only`), optional `fontUrlResolver`, optional `onWarning` callback
65
+ - Types: `ESigningConfig`, `SignatureFontWarning`
66
+
62
67
  ### Types
63
68
 
64
69
  - `FieldPlacement`
@@ -123,10 +128,87 @@ pnpm typecheck
123
128
 
124
129
  ## Notes
125
130
 
126
- - `PdfViewer` sets `react-pdf` worker from CDN by default using the runtime PDF.js version.
131
+ - **PDF worker:** the package does **not** inject a third-party worker URL. Set `configure({ pdfWorkerSrc })` and/or `<PdfViewer workerSrc="..." />` so PDF.js can load a worker (recommended for production). See **Production hardening** below.
127
132
  - Browser test config skips execution when Playwright Chromium is not available in the environment.
128
133
  - Demo theme switcher (`default` / `custom`) shows how a container app can fully re-theme the same components.
129
134
 
135
+ ## Production hardening
136
+
137
+ Runtime calls to external CDNs (PDF.js worker, Google Fonts) often fail in real apps: **CSP** (`worker-src`, `connect-src`, `font-src`), ad blockers, corporate proxies, or offline users. They also add noisy console errors (`Failed to fetch`) even when the rest of the UI works. This library defaults to **no injected worker URL** and lets you control loading explicitly.
138
+
139
+ ### Self-hosted PDF.js worker (recommended)
140
+
141
+ Copy the worker file that matches your installed `pdfjs-dist` (same major/minor as `react-pdf` / PDF.js):
142
+
143
+ ```bash
144
+ cp node_modules/pdfjs-dist/build/pdf.worker.min.mjs public/pdf.worker.min.mjs
145
+ ```
146
+
147
+ Then configure once (e.g. in your app entry or root layout client component):
148
+
149
+ ```tsx
150
+ import { configure } from '@drvillo/react-browser-e-signing'
151
+
152
+ configure({ pdfWorkerSrc: '/pdf.worker.min.mjs' })
153
+ ```
154
+
155
+ Or per viewer:
156
+
157
+ ```tsx
158
+ <PdfViewer workerSrc="/pdf.worker.min.mjs" {...pdfViewerProps} />
159
+ ```
160
+
161
+ `workerSrc` on `PdfViewer` overrides `configure({ pdfWorkerSrc })`.
162
+
163
+ ### Typed signatures: local-only fonts (no network)
164
+
165
+ Skip all font fetches (handwriting fonts won’t load from Google; the browser uses whatever faces are already available, with sensible fallback):
166
+
167
+ ```tsx
168
+ configure({ fontMode: 'local-only' })
169
+ ```
170
+
171
+ Default is `fontMode: 'network'`, which keeps the previous Google Fonts behavior but **does not throw** on failure; failures are reported via `onWarning` when set.
172
+
173
+ ### Custom font URLs (self-hosted woff/woff2)
174
+
175
+ ```tsx
176
+ configure({
177
+ fontUrlResolver: (family) => `/fonts/${family.replace(/\s+/g, '-')}.woff2`,
178
+ })
179
+ ```
180
+
181
+ Return `null` to fall back to Google Fonts for that family (when `fontMode` is `'network'`).
182
+
183
+ ### Observability
184
+
185
+ ```tsx
186
+ configure({
187
+ onWarning: (w) => {
188
+ console.warn(`[react-browser-e-signing] ${w.code}: ${w.message}`)
189
+ },
190
+ })
191
+ ```
192
+
193
+ Warnings are non-throwing; signing flow should remain usable.
194
+
195
+ ### CSP-oriented example
196
+
197
+ If everything is same-origin:
198
+
199
+ ```
200
+ Content-Security-Policy: worker-src 'self'; script-src 'self'; connect-src 'self'; font-src 'self';
201
+ ```
202
+
203
+ Adjust `connect-src` / `font-src` if you still use Google Fonts or a CDN for the worker.
204
+
205
+ ### Migration from v0.1.2 and earlier
206
+
207
+ Previously, `PdfViewer` set the worker to unpkg at module load, and typed fonts fetched Google Fonts CSS + files at runtime.
208
+
209
+ - **Worker:** to restore the old CDN behavior (not recommended for production), set `pdfWorkerSrc` to the unpkg URL for your PDF.js version, e.g. `https://unpkg.com/pdfjs-dist@<version>/build/pdf.worker.min.mjs` (match `pdfjs.version` from `react-pdf` / `pdfjs-dist`).
210
+ - **Fonts:** behavior is unchanged when you omit `configure()` except that network failures no longer surface as thrown errors from `loadSignatureFont`; use `fontMode: 'local-only'` for strict no-network deployments.
211
+
130
212
  ## Limitations
131
213
 
132
214
  - Single signer workflow in v0.1
package/dist/index.d.ts CHANGED
@@ -2,6 +2,25 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ReactNode } from 'react';
4
4
 
5
+ declare const SIGNATURE_FONTS: readonly ["Caveat", "Homemade Apple", "Reenie Beanie", "Mr Dafoe", "Pacifico", "Qwitcher Grypen"];
6
+ declare function loadSignatureFont(fontFamily: string): Promise<void>;
7
+
8
+ interface SignatureFontWarning {
9
+ code: string;
10
+ message: string;
11
+ }
12
+ interface ESigningConfig {
13
+ /** PDF.js worker script URL (e.g. self-hosted `/pdf.worker.min.mjs`). When unset, `PdfViewer` does not set `GlobalWorkerOptions.workerSrc`. */
14
+ pdfWorkerSrc?: string;
15
+ /** `network`: fetch Google Fonts when loading typed signature fonts (default). `local-only`: no fetches; browser uses available/system fonts. */
16
+ fontMode?: 'network' | 'local-only';
17
+ /** Return a woff/woff2 URL for a font family, or `null` to fall back to Google Fonts (when `fontMode` is `network`). */
18
+ fontUrlResolver?: (fontFamily: string) => string | null;
19
+ /** Non-throwing callback for recoverable issues (font/worker setup). */
20
+ onWarning?: (warning: SignatureFontWarning) => void;
21
+ }
22
+ declare function configure(options: ESigningConfig): void;
23
+
5
24
  interface PdfViewerProps {
6
25
  pdfData: ArrayBuffer | null;
7
26
  numPages: number;
@@ -15,8 +34,10 @@ interface PdfViewerProps {
15
34
  }) => void;
16
35
  renderOverlay?: (pageIndex: number) => ReactNode;
17
36
  className?: string;
37
+ /** PDF.js worker script URL. Overrides `configure({ pdfWorkerSrc })`. When neither is set, worker URL is left unset (no CDN injection). */
38
+ workerSrc?: string;
18
39
  }
19
- declare function PdfViewer({ pdfData, numPages, scale, onScaleChange, onDocumentLoadSuccess, onPageDimensions, renderOverlay, className, }: PdfViewerProps): react_jsx_runtime.JSX.Element;
40
+ declare function PdfViewer({ pdfData, numPages, scale, onScaleChange, onDocumentLoadSuccess, onPageDimensions, renderOverlay, className, workerSrc, }: PdfViewerProps): react_jsx_runtime.JSX.Element;
20
41
 
21
42
  type FieldType = 'signature' | 'fullName' | 'title' | 'date';
22
43
  interface FieldPlacement {
@@ -186,9 +207,6 @@ declare function modifyPdf({ pdfBytes, fields, signer, signatureDataUrl, pageDim
186
207
  declare function mapToPoints(field: FieldPlacement, page: PdfPageDimensions): PointRect;
187
208
  declare function mapFromPoints(rect: PointRect, page: PdfPageDimensions): Pick<FieldPlacement, 'xPercent' | 'yPercent' | 'widthPercent' | 'heightPercent'>;
188
209
 
189
- declare const SIGNATURE_FONTS: readonly ["Dancing Script", "Great Vibes", "Sacramento", "Alex Brush"];
190
- declare function loadSignatureFont(fontFamily: string): Promise<void>;
191
-
192
210
  declare function sha256(data: Uint8Array): Promise<string>;
193
211
 
194
212
  declare const SLOTS: {
@@ -243,9 +261,9 @@ declare const SLOTS: {
243
261
  };
244
262
 
245
263
  declare const defaults: {
246
- readonly SIGNATURE_FONTS: readonly ["Dancing Script", "Great Vibes", "Sacramento", "Alex Brush"];
264
+ readonly SIGNATURE_FONTS: readonly ["Caveat", "Homemade Apple", "Reenie Beanie", "Mr Dafoe", "Pacifico", "Qwitcher Grypen"];
247
265
  readonly DEFAULT_FIELD_WIDTH_PERCENT: 25;
248
266
  readonly DEFAULT_FIELD_HEIGHT_PERCENT: 5;
249
267
  };
250
268
 
251
- export { FieldOverlay, FieldPalette, type FieldPlacement, type FieldType, type PdfPageDimensions, PdfViewer, SIGNATURE_FONTS, SLOTS, SignatureField, type SignatureFieldPreview, SignaturePad, SignaturePreview, type SignatureStyle, SignerDetailsPanel, type SignerInfo, SigningComplete, type SigningResult, defaults, loadSignatureFont, mapFromPoints, mapToPoints, modifyPdf, sha256, useFieldPlacement, usePdfDocument, useSignatureRenderer };
269
+ export { type ESigningConfig, FieldOverlay, FieldPalette, type FieldPlacement, type FieldType, type PdfPageDimensions, PdfViewer, SIGNATURE_FONTS, SLOTS, SignatureField, type SignatureFieldPreview, type SignatureFontWarning, SignaturePad, SignaturePreview, type SignatureStyle, SignerDetailsPanel, type SignerInfo, SigningComplete, type SigningResult, configure, defaults, loadSignatureFont, mapFromPoints, mapToPoints, modifyPdf, sha256, useFieldPlacement, usePdfDocument, useSignatureRenderer };
package/dist/index.js CHANGED
@@ -1,19 +1,95 @@
1
1
  import { pdfjs, Document, Page } from 'react-pdf';
2
+ import { useEffect, useRef, useMemo, useState, useCallback } from 'react';
2
3
  import { jsx, jsxs } from 'react/jsx-runtime';
3
- import { useRef, useEffect, useMemo, useState, useCallback } from 'react';
4
4
  import SignaturePadLibrary from 'signature_pad';
5
5
  import fontkit from '@pdf-lib/fontkit';
6
6
  import { PDFDocument, StandardFonts } from 'pdf-lib';
7
7
 
8
- // src/components/pdf-viewer.tsx
8
+ // src/lib/config.ts
9
+ var _config = {};
10
+ function configure(options) {
11
+ _config = { ..._config, ...options };
12
+ }
13
+ function getConfig() {
14
+ return _config;
15
+ }
16
+
17
+ // src/lib/signature-fonts.ts
18
+ var loadedFonts = /* @__PURE__ */ new Set();
19
+ var SIGNATURE_FONTS = [
20
+ "Caveat",
21
+ "Homemade Apple",
22
+ "Reenie Beanie",
23
+ "Mr Dafoe",
24
+ "Pacifico",
25
+ "Qwitcher Grypen"
26
+ ];
27
+ function buildGoogleFontsCssUrl(family) {
28
+ const encoded = family.trim().replace(/\s+/g, "+");
29
+ return `https://fonts.googleapis.com/css2?family=${encoded}&display=swap`;
30
+ }
31
+ async function loadCssFromGoogleFonts(url) {
32
+ const response = await fetch(url);
33
+ if (!response.ok) throw new Error(`Unable to load font css from ${url}`);
34
+ return response.text();
35
+ }
36
+ function extractFontSource(cssText) {
37
+ const sourceMatch = cssText.match(/src:\s*url\(([^)]+)\)\s*format\(['"]?([^'")]+)['"]?\)/i);
38
+ if (!sourceMatch) return null;
39
+ return sourceMatch[1].replace(/['"]/g, "");
40
+ }
41
+ function warnFontLoad(message) {
42
+ try {
43
+ getConfig().onWarning?.({ code: "FONT_LOAD_FAILED", message });
44
+ } catch {
45
+ }
46
+ }
47
+ async function loadFontFaceFromUrl(fontFamily, url) {
48
+ if (typeof FontFace === "undefined" || typeof document === "undefined") return;
49
+ const fontFace = new FontFace(fontFamily, `url(${url})`);
50
+ await fontFace.load();
51
+ const fontSet = document.fonts;
52
+ fontSet.add(fontFace);
53
+ }
54
+ async function loadSignatureFont(fontFamily) {
55
+ if (loadedFonts.has(fontFamily)) return;
56
+ if (typeof document === "undefined") return;
57
+ if (typeof FontFace === "undefined") return;
58
+ const { fontMode = "network", fontUrlResolver } = getConfig();
59
+ if (fontMode === "local-only") {
60
+ loadedFonts.add(fontFamily);
61
+ return;
62
+ }
63
+ const tryLoadFromGoogle = async () => {
64
+ try {
65
+ const cssUrl = buildGoogleFontsCssUrl(fontFamily);
66
+ const cssText = await loadCssFromGoogleFonts(cssUrl);
67
+ const fontSource = extractFontSource(cssText);
68
+ if (!fontSource) throw new Error(`Unable to extract font source for ${fontFamily}`);
69
+ await loadFontFaceFromUrl(fontFamily, fontSource);
70
+ } catch (error) {
71
+ const detail = error instanceof Error ? error.message : String(error);
72
+ warnFontLoad(`Google Fonts load failed for "${fontFamily}": ${detail}`);
73
+ }
74
+ };
75
+ if (fontUrlResolver) {
76
+ try {
77
+ const resolved = fontUrlResolver(fontFamily);
78
+ if (resolved) await loadFontFaceFromUrl(fontFamily, resolved);
79
+ else await tryLoadFromGoogle();
80
+ } catch (error) {
81
+ const detail = error instanceof Error ? error.message : String(error);
82
+ warnFontLoad(`Custom font load failed for "${fontFamily}": ${detail}`);
83
+ await tryLoadFromGoogle();
84
+ }
85
+ } else await tryLoadFromGoogle();
86
+ loadedFonts.add(fontFamily);
87
+ }
9
88
 
10
89
  // src/lib/cn.ts
11
90
  function cn(...values) {
12
91
  return values.filter(Boolean).join(" ");
13
92
  }
14
- if (typeof window !== "undefined") {
15
- pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
16
- }
17
93
  var MIN_SCALE = 0.5;
18
94
  var MAX_SCALE = 2;
19
95
  var SCALE_STEP = 0.1;
@@ -25,8 +101,15 @@ function PdfViewer({
25
101
  onDocumentLoadSuccess,
26
102
  onPageDimensions,
27
103
  renderOverlay,
28
- className
104
+ className,
105
+ workerSrc
29
106
  }) {
107
+ useEffect(() => {
108
+ if (typeof window === "undefined") return;
109
+ const fromConfig = getConfig().pdfWorkerSrc;
110
+ const next = workerSrc ?? fromConfig;
111
+ if (next) pdfjs.GlobalWorkerOptions.workerSrc = next;
112
+ }, [workerSrc]);
30
113
  if (!pdfData)
31
114
  return /* @__PURE__ */ jsx("div", { "data-slot": "pdf-viewer-empty", className: cn(className), children: "Upload a PDF to begin" });
32
115
  return /* @__PURE__ */ jsxs("div", { "data-slot": "pdf-viewer", className: cn(className), children: [
@@ -207,7 +290,7 @@ function SignatureField({ field, onUpdateField, onRemoveField, preview, classNam
207
290
  display: "flex",
208
291
  height: "100%",
209
292
  width: "100%",
210
- alignItems: "flex-start",
293
+ alignItems: "stretch",
211
294
  justifyContent: "space-between"
212
295
  },
213
296
  children: [
@@ -381,38 +464,6 @@ function SignerDetailsPanel({ signerInfo, onSignerInfoChange, className }) {
381
464
  ] })
382
465
  ] });
383
466
  }
384
-
385
- // src/lib/signature-fonts.ts
386
- var loadedFonts = /* @__PURE__ */ new Set();
387
- var SIGNATURE_FONTS = ["Dancing Script", "Great Vibes", "Sacramento", "Alex Brush"];
388
- function buildGoogleFontsCssUrl(family) {
389
- const encoded = family.trim().replace(/\s+/g, "+");
390
- return `https://fonts.googleapis.com/css2?family=${encoded}&display=swap`;
391
- }
392
- async function loadCssFromGoogleFonts(url) {
393
- const response = await fetch(url);
394
- if (!response.ok) throw new Error(`Unable to load font css from ${url}`);
395
- return response.text();
396
- }
397
- function extractFontSource(cssText) {
398
- const sourceMatch = cssText.match(/src:\s*url\(([^)]+)\)\s*format\(['"]?([^'")]+)['"]?\)/i);
399
- if (!sourceMatch) return null;
400
- return sourceMatch[1].replace(/['"]/g, "");
401
- }
402
- async function loadSignatureFont(fontFamily) {
403
- if (loadedFonts.has(fontFamily)) return;
404
- if (typeof document === "undefined") return;
405
- if (typeof FontFace === "undefined") return;
406
- const cssUrl = buildGoogleFontsCssUrl(fontFamily);
407
- const cssText = await loadCssFromGoogleFonts(cssUrl);
408
- const fontSource = extractFontSource(cssText);
409
- if (!fontSource) throw new Error(`Unable to extract font source for ${fontFamily}`);
410
- const fontFace = new FontFace(fontFamily, `url(${fontSource})`);
411
- await fontFace.load();
412
- const fontSet = document.fonts;
413
- fontSet.add(fontFace);
414
- loadedFonts.add(fontFamily);
415
- }
416
467
  function SignaturePad({ onDrawn, className }) {
417
468
  const canvasRef = useRef(null);
418
469
  const signaturePadRef = useRef(null);
@@ -709,6 +760,41 @@ function useFieldPlacement(options = {}) {
709
760
  function buildCanvas() {
710
761
  return document.createElement("canvas");
711
762
  }
763
+ function hashString(s) {
764
+ let h = 2166136261;
765
+ for (let i = 0; i < s.length; i++) {
766
+ h ^= s.charCodeAt(i);
767
+ h = Math.imul(h, 16777619);
768
+ }
769
+ return h >>> 0;
770
+ }
771
+ function mulberry32(seed) {
772
+ return function() {
773
+ let t = seed += 1831565813;
774
+ t = Math.imul(t ^ t >>> 15, t | 1);
775
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
776
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
777
+ };
778
+ }
779
+ function layoutTypedGlyphs({
780
+ signerName,
781
+ fontFamily,
782
+ fontSize,
783
+ context
784
+ }) {
785
+ const rng = mulberry32(hashString(`${signerName}\0${fontFamily}`));
786
+ context.font = `${fontSize}px "${fontFamily}"`;
787
+ const chars = Array.from(signerName);
788
+ const layouts = [];
789
+ for (let i = 0; i < chars.length; i++) {
790
+ const char = chars[i];
791
+ const width = context.measureText(char).width;
792
+ const rotation = (rng() * 2 - 1) * 0.07;
793
+ const gapAfter = i < chars.length - 1 ? (rng() * 2 - 1) * 1.25 : 0;
794
+ layouts.push({ char, width, rotation, gapAfter });
795
+ }
796
+ return layouts;
797
+ }
712
798
  function drawTypedSignature({
713
799
  signerName,
714
800
  fontFamily
@@ -718,15 +804,27 @@ function drawTypedSignature({
718
804
  if (!context) return "";
719
805
  const padding = 16;
720
806
  const fontSize = 56;
721
- context.font = `${fontSize}px "${fontFamily}"`;
722
- const metrics = context.measureText(signerName);
723
- canvas.width = Math.max(240, Math.ceil(metrics.width + padding * 2));
807
+ const baselineY = 50;
808
+ const glyphs = layoutTypedGlyphs({ signerName, fontFamily, fontSize, context });
809
+ const textWidth = glyphs.reduce((sum, g) => sum + g.width + g.gapAfter, 0);
810
+ canvas.width = Math.max(240, Math.ceil(textWidth + padding * 2));
724
811
  canvas.height = 100;
725
812
  context.clearRect(0, 0, canvas.width, canvas.height);
726
813
  context.font = `${fontSize}px "${fontFamily}"`;
727
814
  context.fillStyle = "#111827";
815
+ context.textAlign = "center";
728
816
  context.textBaseline = "middle";
729
- context.fillText(signerName, padding, canvas.height / 2);
817
+ let x = padding;
818
+ for (const glyph of glyphs) {
819
+ const { char, width, rotation, gapAfter } = glyph;
820
+ const cx = x + width / 2;
821
+ context.save();
822
+ context.translate(cx, baselineY);
823
+ context.rotate(rotation);
824
+ context.fillText(char, 0, 0);
825
+ context.restore();
826
+ x += width + gapAfter;
827
+ }
730
828
  return canvas.toDataURL("image/png");
731
829
  }
732
830
  function useSignatureRenderer({ signerName, style }) {
@@ -750,7 +848,8 @@ function useSignatureRenderer({ signerName, style }) {
750
848
  setSignatureDataUrl(dataUrl || null);
751
849
  }).catch(() => {
752
850
  if (!isActive) return;
753
- setSignatureDataUrl(null);
851
+ const dataUrl = drawTypedSignature({ signerName: normalizedName, fontFamily: style.fontFamily });
852
+ setSignatureDataUrl(dataUrl || null);
754
853
  }).finally(() => {
755
854
  if (!isActive) return;
756
855
  setIsRendering(false);
@@ -912,11 +1011,11 @@ var SLOTS = {
912
1011
 
913
1012
  // src/index.ts
914
1013
  var defaults = {
915
- SIGNATURE_FONTS: ["Dancing Script", "Great Vibes", "Sacramento", "Alex Brush"],
1014
+ SIGNATURE_FONTS: [...SIGNATURE_FONTS],
916
1015
  DEFAULT_FIELD_WIDTH_PERCENT: 25,
917
1016
  DEFAULT_FIELD_HEIGHT_PERCENT: 5
918
1017
  };
919
1018
 
920
- export { FieldOverlay, FieldPalette, PdfViewer, SIGNATURE_FONTS, SLOTS, SignatureField, SignaturePad, SignaturePreview, SignerDetailsPanel, SigningComplete, defaults, loadSignatureFont, mapFromPoints, mapToPoints, modifyPdf, sha256, useFieldPlacement, usePdfDocument, useSignatureRenderer };
1019
+ export { FieldOverlay, FieldPalette, PdfViewer, SIGNATURE_FONTS, SLOTS, SignatureField, SignaturePad, SignaturePreview, SignerDetailsPanel, SigningComplete, configure, defaults, loadSignatureFont, mapFromPoints, mapToPoints, modifyPdf, sha256, useFieldPlacement, usePdfDocument, useSignatureRenderer };
921
1020
  //# sourceMappingURL=index.js.map
922
1021
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/cn.ts","../src/components/pdf-viewer.tsx","../src/components/signature-field.tsx","../src/components/field-overlay.tsx","../src/components/field-palette.tsx","../src/components/signer-details-panel.tsx","../src/lib/signature-fonts.ts","../src/components/signature-pad.tsx","../src/components/signature-preview.tsx","../src/components/signing-complete.tsx","../src/hooks/use-pdf-document.ts","../src/hooks/use-field-placement.ts","../src/hooks/use-signature-renderer.ts","../src/lib/coordinate-mapper.ts","../src/lib/pdf-modifier.ts","../src/lib/hash.ts","../src/lib/slots.ts","../src/index.ts"],"names":["jsxs","jsx","useRef","useEffect","useMemo","clampPercent","useState"],"mappings":"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","file":"index.js","sourcesContent":["export function cn(...values: Array<string | false | null | undefined>): string {\n return values.filter(Boolean).join(' ')\n}\n","import { Document, Page, pdfjs } from 'react-pdf'\nimport type { ReactNode } from 'react'\nimport { cn } from '../lib/cn'\n\nif (typeof window !== 'undefined') {\n pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`\n}\n\ninterface PdfViewerProps {\n pdfData: ArrayBuffer | null\n numPages: number\n scale: number\n onScaleChange: (nextScale: number) => void\n onDocumentLoadSuccess: (numPages: number) => void\n onPageDimensions: (input: { pageIndex: number; widthPt: number; heightPt: number }) => void\n renderOverlay?: (pageIndex: number) => ReactNode\n className?: string\n}\n\nconst MIN_SCALE = 0.5\nconst MAX_SCALE = 2\nconst SCALE_STEP = 0.1\n\nexport function PdfViewer({\n pdfData,\n numPages,\n scale,\n onScaleChange,\n onDocumentLoadSuccess,\n onPageDimensions,\n renderOverlay,\n className,\n}: PdfViewerProps) {\n if (!pdfData)\n return (\n <div data-slot=\"pdf-viewer-empty\" className={cn(className)}>\n Upload a PDF to begin\n </div>\n )\n\n return (\n <div data-slot=\"pdf-viewer\" className={cn(className)}>\n <div data-slot=\"pdf-viewer-toolbar\">\n <div data-slot=\"pdf-viewer-page-count\">Pages: {numPages || '—'}</div>\n <div data-slot=\"pdf-viewer-zoom\">\n <button\n type=\"button\"\n data-slot=\"pdf-viewer-zoom-button\"\n onClick={() => onScaleChange(Math.max(MIN_SCALE, Number((scale - SCALE_STEP).toFixed(2))))}\n >\n -\n </button>\n <span data-slot=\"pdf-viewer-zoom-value\">{Math.round(scale * 100)}%</span>\n <button\n type=\"button\"\n data-slot=\"pdf-viewer-zoom-button\"\n onClick={() => onScaleChange(Math.min(MAX_SCALE, Number((scale + SCALE_STEP).toFixed(2))))}\n >\n +\n </button>\n </div>\n </div>\n\n <Document\n file={pdfData}\n onLoadSuccess={(loadedPdf) => onDocumentLoadSuccess(loadedPdf.numPages)}\n loading={<div data-slot=\"pdf-viewer-loading\">Loading PDF...</div>}\n error={<div data-slot=\"pdf-viewer-error\">Unable to render this PDF.</div>}\n >\n <div data-slot=\"pdf-viewer-pages\">\n {Array.from({ length: numPages }, (_, pageIndex) => (\n <div\n key={`pdf-page-${pageIndex}`}\n data-slot=\"pdf-viewer-page\"\n style={{ position: 'relative', margin: '0 auto', width: 'fit-content' }}\n >\n <Page\n pageNumber={pageIndex + 1}\n scale={scale}\n renderTextLayer={false}\n renderAnnotationLayer={false}\n onLoadSuccess={(page) =>\n onPageDimensions({\n pageIndex,\n widthPt: page.view[2],\n heightPt: page.view[3],\n })\n }\n />\n {renderOverlay?.(pageIndex)}\n </div>\n ))}\n </div>\n </Document>\n </div>\n )\n}\n","import { useRef } from 'react'\nimport type { FieldPlacement, SignatureFieldPreview } from '../types'\nimport type { PointerEvent } from 'react'\nimport { cn } from '../lib/cn'\n\ninterface SignatureFieldProps {\n field: FieldPlacement\n onUpdateField: (fieldId: string, partial: Partial<FieldPlacement>) => void\n onRemoveField: (fieldId: string) => void\n preview: SignatureFieldPreview\n className?: string\n}\n\ninterface DragState {\n startClientX: number\n startClientY: number\n startXPercent: number\n startYPercent: number\n}\n\ninterface ResizeState {\n startClientX: number\n startClientY: number\n startWidthPercent: number\n startHeightPercent: number\n}\n\nconst MIN_WIDTH_PERCENT = 8\nconst MIN_HEIGHT_PERCENT = 3\n\nfunction clampPercent(value: number): number {\n if (value < 0) return 0\n if (value > 100) return 100\n return value\n}\n\nfunction getFieldPreviewText(field: FieldPlacement, preview: SignatureFieldPreview): string {\n if (field.type === 'fullName') return preview.fullName\n if (field.type === 'title') return preview.title\n if (field.type === 'date') return preview.dateText\n return ''\n}\n\nexport function SignatureField({ field, onUpdateField, onRemoveField, preview, className }: SignatureFieldProps) {\n const rootRef = useRef<HTMLDivElement | null>(null)\n const dragStateRef = useRef<DragState | null>(null)\n const resizeStateRef = useRef<ResizeState | null>(null)\n\n function handleDragPointerDown(event: PointerEvent<HTMLDivElement>): void {\n event.stopPropagation()\n if (event.button !== 0) return\n if (!rootRef.current?.parentElement) return\n\n dragStateRef.current = {\n startClientX: event.clientX,\n startClientY: event.clientY,\n startXPercent: field.xPercent,\n startYPercent: field.yPercent,\n }\n\n event.currentTarget.setPointerCapture(event.pointerId)\n }\n\n function handleDragPointerMove(event: PointerEvent<HTMLDivElement>): void {\n if (!dragStateRef.current) return\n const parentElement = rootRef.current?.parentElement\n if (!parentElement) return\n\n const deltaX = event.clientX - dragStateRef.current.startClientX\n const deltaY = event.clientY - dragStateRef.current.startClientY\n const deltaXPercent = (deltaX / parentElement.clientWidth) * 100\n const deltaYPercent = (deltaY / parentElement.clientHeight) * 100\n const maxX = 100 - field.widthPercent\n const maxY = 100 - field.heightPercent\n\n onUpdateField(field.id, {\n xPercent: clampPercent(Math.min(maxX, dragStateRef.current.startXPercent + deltaXPercent)),\n yPercent: clampPercent(Math.min(maxY, dragStateRef.current.startYPercent + deltaYPercent)),\n })\n }\n\n function handleDragPointerUp(event: PointerEvent<HTMLDivElement>): void {\n dragStateRef.current = null\n if (event.currentTarget.hasPointerCapture(event.pointerId))\n event.currentTarget.releasePointerCapture(event.pointerId)\n }\n\n function handleResizePointerDown(event: PointerEvent<HTMLDivElement>): void {\n event.stopPropagation()\n if (event.button !== 0) return\n\n resizeStateRef.current = {\n startClientX: event.clientX,\n startClientY: event.clientY,\n startWidthPercent: field.widthPercent,\n startHeightPercent: field.heightPercent,\n }\n\n event.currentTarget.setPointerCapture(event.pointerId)\n }\n\n function handleResizePointerMove(event: PointerEvent<HTMLDivElement>): void {\n if (!resizeStateRef.current) return\n const parentElement = rootRef.current?.parentElement\n if (!parentElement) return\n\n const deltaX = event.clientX - resizeStateRef.current.startClientX\n const deltaY = event.clientY - resizeStateRef.current.startClientY\n const deltaWidthPercent = (deltaX / parentElement.clientWidth) * 100\n const deltaHeightPercent = (deltaY / parentElement.clientHeight) * 100\n\n const maxWidth = 100 - field.xPercent\n const maxHeight = 100 - field.yPercent\n const widthPercent = clampPercent(\n Math.min(maxWidth, Math.max(MIN_WIDTH_PERCENT, resizeStateRef.current.startWidthPercent + deltaWidthPercent))\n )\n const heightPercent = clampPercent(\n Math.min(maxHeight, Math.max(MIN_HEIGHT_PERCENT, resizeStateRef.current.startHeightPercent + deltaHeightPercent))\n )\n\n onUpdateField(field.id, { widthPercent, heightPercent })\n }\n\n function handleResizePointerUp(event: PointerEvent<HTMLDivElement>): void {\n resizeStateRef.current = null\n if (event.currentTarget.hasPointerCapture(event.pointerId))\n event.currentTarget.releasePointerCapture(event.pointerId)\n }\n\n const previewText = getFieldPreviewText(field, preview)\n\n return (\n <div\n ref={rootRef}\n data-slot=\"signature-field\"\n data-field-type={field.type}\n className={cn(className)}\n style={{\n position: 'absolute',\n left: `${field.xPercent}%`,\n top: `${field.yPercent}%`,\n width: `${field.widthPercent}%`,\n height: `${field.heightPercent}%`,\n userSelect: 'none',\n }}\n onPointerDown={handleDragPointerDown}\n onPointerMove={handleDragPointerMove}\n onPointerUp={handleDragPointerUp}\n >\n <div\n data-slot=\"signature-field-content\"\n style={{\n display: 'flex',\n height: '100%',\n width: '100%',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n }}\n >\n <div data-slot=\"signature-field-preview\">\n <div data-slot=\"signature-field-label\">{field.type}</div>\n {field.type === 'signature' && preview.signatureDataUrl ? (\n <img\n data-slot=\"signature-field-preview-image\"\n src={preview.signatureDataUrl}\n alt=\"signature preview\"\n draggable={false}\n />\n ) : (\n <div data-slot=\"signature-field-preview-text\">{previewText || '—'}</div>\n )}\n </div>\n <button\n type=\"button\"\n data-slot=\"signature-field-remove\"\n onPointerDown={(event) => event.stopPropagation()}\n onClick={(event) => {\n event.stopPropagation()\n onRemoveField(field.id)\n }}\n aria-label=\"Remove field\"\n >\n ×\n </button>\n </div>\n\n <div\n data-slot=\"signature-field-resize\"\n style={{\n position: 'absolute',\n right: '-0.375rem',\n bottom: '-0.375rem',\n width: '0.75rem',\n height: '0.75rem',\n cursor: 'nwse-resize',\n }}\n onPointerDown={handleResizePointerDown}\n onPointerMove={handleResizePointerMove}\n onPointerUp={handleResizePointerUp}\n />\n </div>\n )\n}\n","import type { FieldPlacement, FieldType, SignatureFieldPreview } from '../types'\nimport { SignatureField } from './signature-field'\nimport type { PointerEvent } from 'react'\nimport { cn } from '../lib/cn'\n\ninterface FieldOverlayProps {\n pageIndex: number\n fields: FieldPlacement[]\n selectedFieldType: FieldType | null\n onAddField: (input: { pageIndex: number; type: FieldType; xPercent: number; yPercent: number }) => void\n onUpdateField: (fieldId: string, partial: Partial<FieldPlacement>) => void\n onRemoveField: (fieldId: string) => void\n preview: SignatureFieldPreview\n className?: string\n}\n\nexport function FieldOverlay({\n pageIndex,\n fields,\n selectedFieldType,\n onAddField,\n onUpdateField,\n onRemoveField,\n preview,\n className,\n}: FieldOverlayProps) {\n function handleOverlayPointerDown(event: PointerEvent<HTMLDivElement>): void {\n if (!selectedFieldType) return\n if (event.button !== 0) return\n if (event.target !== event.currentTarget) return\n const rect = event.currentTarget.getBoundingClientRect()\n const xPercent = ((event.clientX - rect.left) / rect.width) * 100\n const yPercent = ((event.clientY - rect.top) / rect.height) * 100\n onAddField({\n pageIndex,\n type: selectedFieldType,\n xPercent,\n yPercent,\n })\n }\n\n const pageFields = fields.filter((field) => field.pageIndex === pageIndex)\n\n return (\n <div\n data-slot=\"field-overlay\"\n data-state={selectedFieldType ? 'placing' : 'idle'}\n className={cn(className)}\n style={{\n position: 'absolute',\n inset: 0,\n zIndex: 20,\n cursor: selectedFieldType ? 'crosshair' : 'default',\n }}\n onPointerDown={handleOverlayPointerDown}\n aria-label={`Field overlay page ${pageIndex + 1}`}\n >\n {pageFields.map((field) => (\n <SignatureField\n key={field.id}\n field={field}\n onUpdateField={onUpdateField}\n onRemoveField={onRemoveField}\n preview={preview}\n />\n ))}\n </div>\n )\n}\n","import type { FieldType } from '../types'\nimport { cn } from '../lib/cn'\n\ninterface FieldPaletteProps {\n selectedFieldType: FieldType | null\n onSelectFieldType: (fieldType: FieldType | null) => void\n className?: string\n}\n\nconst FIELD_LABELS: Record<FieldType, string> = {\n signature: 'Signature',\n fullName: 'Full Name',\n title: 'Title',\n date: 'Date',\n}\n\nconst FIELD_TYPES: FieldType[] = ['signature', 'fullName', 'title', 'date']\n\nexport function FieldPalette({ selectedFieldType, onSelectFieldType, className }: FieldPaletteProps) {\n return (\n <div data-slot=\"field-palette\" className={cn(className)}>\n {FIELD_TYPES.map((fieldType) => {\n const isSelected = selectedFieldType === fieldType\n return (\n <button\n key={fieldType}\n type=\"button\"\n data-slot=\"field-palette-button\"\n data-state={isSelected ? 'selected' : 'idle'}\n onClick={() => onSelectFieldType(isSelected ? null : fieldType)}\n aria-pressed={isSelected}\n >\n {FIELD_LABELS[fieldType]}\n </button>\n )\n })}\n </div>\n )\n}\n","import type { SignerInfo } from '../types'\nimport { cn } from '../lib/cn'\n\ninterface SignerDetailsPanelProps {\n signerInfo: SignerInfo\n onSignerInfoChange: (nextSignerInfo: SignerInfo) => void\n className?: string\n}\n\nexport function SignerDetailsPanel({ signerInfo, onSignerInfoChange, className }: SignerDetailsPanelProps) {\n function handleInputChange(fieldName: keyof SignerInfo, fieldValue: string): void {\n onSignerInfoChange({\n ...signerInfo,\n [fieldName]: fieldValue,\n })\n }\n\n return (\n <div data-slot=\"signer-panel\" className={cn(className)}>\n <h2 data-slot=\"signer-panel-heading\">Signer Details</h2>\n\n <label data-slot=\"signer-panel-label\">\n First Name\n <input\n data-slot=\"signer-panel-input\"\n value={signerInfo.firstName}\n onChange={(event) => handleInputChange('firstName', event.target.value)}\n />\n </label>\n\n <label data-slot=\"signer-panel-label\">\n Last Name\n <input\n data-slot=\"signer-panel-input\"\n value={signerInfo.lastName}\n onChange={(event) => handleInputChange('lastName', event.target.value)}\n />\n </label>\n\n <label data-slot=\"signer-panel-label\">\n Title\n <input\n data-slot=\"signer-panel-input\"\n value={signerInfo.title}\n onChange={(event) => handleInputChange('title', event.target.value)}\n />\n </label>\n </div>\n )\n}\n","const loadedFonts = new Set<string>()\n\nexport const SIGNATURE_FONTS = ['Dancing Script', 'Great Vibes', 'Sacramento', 'Alex Brush'] as const\n\nfunction buildGoogleFontsCssUrl(family: string): string {\n const encoded = family.trim().replace(/\\s+/g, '+')\n return `https://fonts.googleapis.com/css2?family=${encoded}&display=swap`\n}\n\nasync function loadCssFromGoogleFonts(url: string): Promise<string> {\n const response = await fetch(url)\n if (!response.ok) throw new Error(`Unable to load font css from ${url}`)\n return response.text()\n}\n\nfunction extractFontSource(cssText: string): string | null {\n const sourceMatch = cssText.match(/src:\\s*url\\(([^)]+)\\)\\s*format\\(['\"]?([^'\")]+)['\"]?\\)/i)\n if (!sourceMatch) return null\n return sourceMatch[1].replace(/['\"]/g, '')\n}\n\nexport async function loadSignatureFont(fontFamily: string): Promise<void> {\n if (loadedFonts.has(fontFamily)) return\n if (typeof document === 'undefined') return\n if (typeof FontFace === 'undefined') return\n\n const cssUrl = buildGoogleFontsCssUrl(fontFamily)\n const cssText = await loadCssFromGoogleFonts(cssUrl)\n const fontSource = extractFontSource(cssText)\n if (!fontSource) throw new Error(`Unable to extract font source for ${fontFamily}`)\n\n const fontFace = new FontFace(fontFamily, `url(${fontSource})`)\n await fontFace.load()\n const fontSet = document.fonts as unknown as { add: (font: FontFace) => void }\n fontSet.add(fontFace)\n loadedFonts.add(fontFamily)\n}\n\nexport function buildSignatureFontCssUrl(fontFamily: string): string {\n return buildGoogleFontsCssUrl(fontFamily)\n}\n","import SignaturePadLibrary from 'signature_pad'\nimport { useEffect, useRef } from 'react'\nimport { cn } from '../lib/cn'\n\ninterface SignaturePadProps {\n onDrawn: (signatureDataUrl: string) => void\n className?: string\n}\n\nexport function SignaturePad({ onDrawn, className }: SignaturePadProps) {\n const canvasRef = useRef<HTMLCanvasElement | null>(null)\n const signaturePadRef = useRef<SignaturePadLibrary | null>(null)\n\n useEffect(() => {\n if (!canvasRef.current) return\n\n const signaturePad = new SignaturePadLibrary(canvasRef.current, {\n minWidth: 1,\n maxWidth: 2.5,\n penColor: '#111827',\n backgroundColor: 'rgba(255,255,255,0)',\n })\n\n signaturePadRef.current = signaturePad\n\n function emitSignatureIfNotEmpty(): void {\n if (signaturePad.isEmpty()) return\n onDrawn(signaturePad.toDataURL('image/png'))\n }\n\n signaturePad.addEventListener('endStroke', emitSignatureIfNotEmpty)\n\n return () => {\n signaturePad.removeEventListener('endStroke', emitSignatureIfNotEmpty)\n signaturePad.off()\n signaturePadRef.current = null\n }\n }, [onDrawn])\n\n function handleClear(): void {\n signaturePadRef.current?.clear()\n onDrawn('')\n }\n\n return (\n <div data-slot=\"signature-pad\" className={cn(className)}>\n <canvas data-slot=\"signature-pad-canvas\" ref={canvasRef} width={420} height={140} />\n <div data-slot=\"signature-pad-actions\">\n <button\n type=\"button\"\n data-slot=\"signature-pad-clear\"\n onClick={handleClear}\n >\n Clear\n </button>\n </div>\n </div>\n )\n}\n","import { useMemo } from 'react'\nimport { SIGNATURE_FONTS } from '../lib/signature-fonts'\nimport type { SignatureStyle } from '../types'\nimport { SignaturePad } from './signature-pad'\nimport { cn } from '../lib/cn'\n\ninterface SignaturePreviewProps {\n signerName: string\n style: SignatureStyle\n signatureDataUrl: string | null\n isRendering: boolean\n onStyleChange: (nextStyle: SignatureStyle) => void\n className?: string\n}\n\nexport function SignaturePreview({\n signerName,\n style,\n signatureDataUrl,\n isRendering,\n onStyleChange,\n className,\n}: SignaturePreviewProps) {\n const canShowPreview = useMemo(() => signerName.trim().length > 0, [signerName])\n\n return (\n <div data-slot=\"signature-preview\" className={cn(className)}>\n <h2 data-slot=\"signature-preview-heading\">Signature</h2>\n\n <div data-slot=\"signature-preview-mode-toggle\">\n <button\n type=\"button\"\n data-slot=\"signature-preview-mode-button\"\n data-mode=\"typed\"\n data-state={style.mode === 'typed' ? 'active' : 'idle'}\n onClick={() => onStyleChange({ mode: 'typed', fontFamily: style.mode === 'typed' ? style.fontFamily : SIGNATURE_FONTS[0] })}\n >\n Typed\n </button>\n <button\n type=\"button\"\n data-slot=\"signature-preview-mode-button\"\n data-mode=\"drawn\"\n data-state={style.mode === 'drawn' ? 'active' : 'idle'}\n onClick={() => onStyleChange({ mode: 'drawn', dataUrl: style.mode === 'drawn' ? style.dataUrl : '' })}\n >\n Drawn\n </button>\n </div>\n\n {style.mode === 'typed' ? (\n <label data-slot=\"signature-preview-font-label\">\n Font\n <select\n data-slot=\"signature-preview-font-select\"\n value={style.fontFamily}\n onChange={(event) => onStyleChange({ mode: 'typed', fontFamily: event.target.value })}\n >\n {SIGNATURE_FONTS.map((fontFamily) => (\n <option key={fontFamily} value={fontFamily}>\n {fontFamily}\n </option>\n ))}\n </select>\n </label>\n ) : (\n <SignaturePad onDrawn={(dataUrl) => onStyleChange({ mode: 'drawn', dataUrl })} />\n )}\n\n <div\n data-slot=\"signature-preview-display\"\n data-state={\n !canShowPreview ? 'empty' : isRendering ? 'rendering' : signatureDataUrl ? 'ready' : 'missing-signature'\n }\n >\n {!canShowPreview ? (\n <p data-slot=\"signature-preview-placeholder\">Enter signer first and last name to render a signature.</p>\n ) : isRendering ? (\n <p data-slot=\"signature-preview-placeholder\">Rendering signature...</p>\n ) : signatureDataUrl ? (\n <img data-slot=\"signature-preview-image\" src={signatureDataUrl} alt=\"Signature preview\" />\n ) : (\n <p data-slot=\"signature-preview-placeholder\">No signature available yet.</p>\n )}\n </div>\n </div>\n )\n}\n","import { cn } from '../lib/cn'\n\ninterface SigningCompleteProps {\n signerName: string\n fieldCount: number\n signedAt: string\n documentHash: string\n downloadUrl: string\n fileName?: string\n onReset: () => void\n className?: string\n}\n\nexport function SigningComplete({\n signerName,\n fieldCount,\n signedAt,\n documentHash,\n downloadUrl,\n fileName = 'signed-document.pdf',\n onReset,\n className,\n}: SigningCompleteProps) {\n return (\n <div data-slot=\"signing-complete\" className={cn(className)}>\n <h2 data-slot=\"signing-complete-heading\">Document Signed</h2>\n <div data-slot=\"signing-complete-details\">\n <p>Signer: {signerName || 'Unknown'}</p>\n <p>Fields applied: {fieldCount}</p>\n <p>Signed at: {signedAt}</p>\n </div>\n\n <div data-slot=\"signing-complete-hash\">\n <p data-slot=\"signing-complete-hash-label\">SHA-256</p>\n <p data-slot=\"signing-complete-hash-value\">{documentHash}</p>\n </div>\n\n <div data-slot=\"signing-complete-actions\">\n <a\n href={downloadUrl}\n download={fileName}\n data-slot=\"signing-complete-download\"\n >\n Download Signed PDF\n </a>\n <button\n type=\"button\"\n data-slot=\"signing-complete-reset\"\n onClick={onReset}\n >\n Sign Another\n </button>\n </div>\n </div>\n )\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport type { PdfPageDimensions } from '../types'\n\nexport type PdfInput = File | Blob | ArrayBuffer | Uint8Array | null\n\nfunction isArrayBuffer(value: unknown): value is ArrayBuffer {\n return value instanceof ArrayBuffer\n}\n\nfunction isUint8Array(value: unknown): value is Uint8Array {\n return value instanceof Uint8Array\n}\n\nasync function convertPdfInputToArrayBuffer(pdfInput: Exclude<PdfInput, null>): Promise<ArrayBuffer> {\n if (isArrayBuffer(pdfInput)) return pdfInput\n if (isUint8Array(pdfInput)) {\n const copy = new Uint8Array(pdfInput.byteLength)\n copy.set(pdfInput)\n return copy.buffer\n }\n return pdfInput.arrayBuffer()\n}\n\nexport function usePdfDocument(pdfInput: PdfInput) {\n const [pdfData, setPdfData] = useState<ArrayBuffer | null>(null)\n const [numPages, setNumPages] = useState(0)\n const [scale, setScale] = useState(1)\n const [pageDimensions, setPageDimensions] = useState<PdfPageDimensions[]>([])\n const [errorMessage, setErrorMessage] = useState<string | null>(null)\n const [isLoading, setIsLoading] = useState(false)\n\n useEffect(() => {\n if (!pdfInput) {\n setPdfData(null)\n setNumPages(0)\n setPageDimensions([])\n setErrorMessage(null)\n return\n }\n\n let isMounted = true\n\n setIsLoading(true)\n setErrorMessage(null)\n convertPdfInputToArrayBuffer(pdfInput)\n .then((arrayBuffer) => {\n if (!isMounted) return\n setPdfData(arrayBuffer)\n })\n .catch((error: unknown) => {\n if (!isMounted) return\n const message = error instanceof Error ? error.message : 'Unable to read PDF data'\n setErrorMessage(message)\n setPdfData(null)\n })\n .finally(() => {\n if (!isMounted) return\n setIsLoading(false)\n })\n\n return () => {\n isMounted = false\n }\n }, [pdfInput])\n\n function handleDocumentLoadSuccess(loadedPages: number): void {\n setNumPages(loadedPages)\n setPageDimensions((previousDimensions) =>\n previousDimensions\n .filter((dimension) => dimension.pageIndex < loadedPages)\n .sort((left, right) => left.pageIndex - right.pageIndex)\n )\n }\n\n function setPageDimension(pageIndex: number, widthPt: number, heightPt: number): void {\n setPageDimensions((previousDimensions) => {\n const nextDimensions = previousDimensions.filter((entry) => entry.pageIndex !== pageIndex)\n nextDimensions.push({ pageIndex, widthPt, heightPt })\n nextDimensions.sort((left, right) => left.pageIndex - right.pageIndex)\n return nextDimensions\n })\n }\n\n const hasPdf = useMemo(() => pdfData !== null, [pdfData])\n\n return {\n pdfData,\n numPages,\n scale,\n setScale,\n pageDimensions,\n setPageDimension,\n handleDocumentLoadSuccess,\n hasPdf,\n isLoading,\n errorMessage,\n }\n}\n","import { useCallback, useMemo, useState } from 'react'\nimport type { FieldPlacement, FieldType } from '../types'\n\ninterface UseFieldPlacementOptions {\n defaultWidthPercent?: number\n defaultHeightPercent?: number\n}\n\ninterface AddFieldInput {\n pageIndex: number\n type: FieldType\n xPercent: number\n yPercent: number\n}\n\nfunction clampPercent(value: number): number {\n if (Number.isNaN(value)) return 0\n if (value < 0) return 0\n if (value > 100) return 100\n return value\n}\n\nfunction buildFieldId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n\n return `field-${Date.now()}-${Math.random().toString(16).slice(2)}`\n}\n\nexport function useFieldPlacement(options: UseFieldPlacementOptions = {}) {\n const defaultWidthPercent = options.defaultWidthPercent ?? 25\n const defaultHeightPercent = options.defaultHeightPercent ?? 5\n const [fields, setFields] = useState<FieldPlacement[]>([])\n\n const addField = useCallback(\n ({ pageIndex, type, xPercent, yPercent }: AddFieldInput) => {\n const field: FieldPlacement = {\n id: buildFieldId(),\n pageIndex,\n type,\n xPercent: clampPercent(xPercent),\n yPercent: clampPercent(yPercent),\n widthPercent: clampPercent(defaultWidthPercent),\n heightPercent: clampPercent(defaultHeightPercent),\n }\n setFields((previousFields) => [...previousFields, field])\n return field\n },\n [defaultHeightPercent, defaultWidthPercent]\n )\n\n const updateField = useCallback((id: string, partial: Partial<FieldPlacement>) => {\n setFields((previousFields) =>\n previousFields.map((field) => {\n if (field.id !== id) return field\n return {\n ...field,\n ...partial,\n xPercent: partial.xPercent === undefined ? field.xPercent : clampPercent(partial.xPercent),\n yPercent: partial.yPercent === undefined ? field.yPercent : clampPercent(partial.yPercent),\n widthPercent:\n partial.widthPercent === undefined ? field.widthPercent : clampPercent(partial.widthPercent),\n heightPercent:\n partial.heightPercent === undefined ? field.heightPercent : clampPercent(partial.heightPercent),\n }\n })\n )\n }, [])\n\n const removeField = useCallback((id: string) => {\n setFields((previousFields) => previousFields.filter((field) => field.id !== id))\n }, [])\n\n const clearFields = useCallback(() => {\n setFields([])\n }, [])\n\n const fieldActions = useMemo(\n () => ({\n addField,\n updateField,\n removeField,\n clearFields,\n }),\n [addField, clearFields, removeField, updateField]\n )\n\n return {\n fields,\n ...fieldActions,\n }\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport { loadSignatureFont } from '../lib/signature-fonts'\nimport type { SignatureStyle } from '../types'\n\ninterface UseSignatureRendererInput {\n signerName: string\n style: SignatureStyle\n}\n\nfunction buildCanvas(): HTMLCanvasElement {\n return document.createElement('canvas')\n}\n\nfunction drawTypedSignature({\n signerName,\n fontFamily,\n}: {\n signerName: string\n fontFamily: string\n}): string {\n const canvas = buildCanvas()\n const context = canvas.getContext('2d')\n if (!context) return ''\n\n const padding = 16\n const fontSize = 56\n context.font = `${fontSize}px \"${fontFamily}\"`\n const metrics = context.measureText(signerName)\n\n canvas.width = Math.max(240, Math.ceil(metrics.width + padding * 2))\n canvas.height = 100\n\n context.clearRect(0, 0, canvas.width, canvas.height)\n context.font = `${fontSize}px \"${fontFamily}\"`\n context.fillStyle = '#111827'\n context.textBaseline = 'middle'\n context.fillText(signerName, padding, canvas.height / 2)\n\n return canvas.toDataURL('image/png')\n}\n\nexport function useSignatureRenderer({ signerName, style }: UseSignatureRendererInput) {\n const [signatureDataUrl, setSignatureDataUrl] = useState<string | null>(null)\n const [isRendering, setIsRendering] = useState(false)\n\n const normalizedName = useMemo(() => signerName.trim(), [signerName])\n\n useEffect(() => {\n if (!normalizedName) {\n setSignatureDataUrl(null)\n return\n }\n\n if (style.mode === 'drawn') {\n setSignatureDataUrl(style.dataUrl || null)\n return\n }\n\n let isActive = true\n setIsRendering(true)\n\n loadSignatureFont(style.fontFamily)\n .then(() => {\n if (!isActive) return\n const dataUrl = drawTypedSignature({ signerName: normalizedName, fontFamily: style.fontFamily })\n setSignatureDataUrl(dataUrl || null)\n })\n .catch(() => {\n if (!isActive) return\n setSignatureDataUrl(null)\n })\n .finally(() => {\n if (!isActive) return\n setIsRendering(false)\n })\n\n return () => {\n isActive = false\n }\n }, [normalizedName, style])\n\n return {\n signatureDataUrl,\n isRendering,\n }\n}\n","import type { FieldPlacement, PdfPageDimensions, PointRect } from '../types'\n\nfunction clampPercent(value: number): number {\n if (Number.isNaN(value)) return 0\n if (value < 0) return 0\n if (value > 100) return 100\n return value\n}\n\nexport function mapToPoints(field: FieldPlacement, page: PdfPageDimensions): PointRect {\n const xPercent = clampPercent(field.xPercent)\n const yPercent = clampPercent(field.yPercent)\n const widthPercent = clampPercent(field.widthPercent)\n const heightPercent = clampPercent(field.heightPercent)\n\n const width = (widthPercent / 100) * page.widthPt\n const height = (heightPercent / 100) * page.heightPt\n const x = (xPercent / 100) * page.widthPt\n const y = page.heightPt - (yPercent / 100) * page.heightPt - height\n\n return { x, y, width, height }\n}\n\nexport function mapFromPoints(\n rect: PointRect,\n page: PdfPageDimensions\n): Pick<FieldPlacement, 'xPercent' | 'yPercent' | 'widthPercent' | 'heightPercent'> {\n const widthPercent = (rect.width / page.widthPt) * 100\n const heightPercent = (rect.height / page.heightPt) * 100\n const xPercent = (rect.x / page.widthPt) * 100\n const yPercent = ((page.heightPt - rect.y - rect.height) / page.heightPt) * 100\n\n return {\n xPercent: clampPercent(xPercent),\n yPercent: clampPercent(yPercent),\n widthPercent: clampPercent(widthPercent),\n heightPercent: clampPercent(heightPercent),\n }\n}\n","import fontkit from '@pdf-lib/fontkit'\nimport { PDFDocument, StandardFonts } from 'pdf-lib'\nimport { mapToPoints } from './coordinate-mapper'\nimport type { FieldPlacement, PdfPageDimensions, SignerInfo } from '../types'\n\ninterface ModifyPdfInput {\n pdfBytes: Uint8Array\n fields: FieldPlacement[]\n signer: SignerInfo\n signatureDataUrl: string\n pageDimensions: PdfPageDimensions[]\n dateText?: string\n}\n\nfunction fullNameFromSigner(signer: SignerInfo): string {\n return [signer.firstName, signer.lastName].filter(Boolean).join(' ').trim()\n}\n\nfunction dataUrlToBytes(dataUrl: string): Uint8Array {\n const base64 = dataUrl.split(',')[1]\n if (!base64) throw new Error('Invalid signature data URL')\n const binary =\n typeof atob === 'function'\n ? atob(base64)\n : Buffer.from(base64, 'base64').toString('binary')\n const bytes = new Uint8Array(binary.length)\n for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index)\n return bytes\n}\n\nexport async function modifyPdf({\n pdfBytes,\n fields,\n signer,\n signatureDataUrl,\n pageDimensions,\n dateText,\n}: ModifyPdfInput): Promise<Uint8Array> {\n const pdfDocument = await PDFDocument.load(pdfBytes)\n pdfDocument.registerFontkit(fontkit)\n const pages = pdfDocument.getPages()\n const helveticaFont = await pdfDocument.embedFont(StandardFonts.Helvetica)\n\n const signatureImageBytes = signatureDataUrl ? dataUrlToBytes(signatureDataUrl) : null\n const signatureImage = signatureImageBytes ? await pdfDocument.embedPng(signatureImageBytes) : null\n const resolvedDateText = dateText || new Date().toLocaleDateString()\n\n for (const field of fields) {\n const page = pages[field.pageIndex]\n const pageDimension = pageDimensions.find((entry) => entry.pageIndex === field.pageIndex)\n if (!page || !pageDimension) continue\n\n const pointRect = mapToPoints(field, pageDimension)\n if (field.type === 'signature' && signatureImage) {\n page.drawImage(signatureImage, {\n x: pointRect.x,\n y: pointRect.y,\n width: pointRect.width,\n height: pointRect.height,\n })\n continue\n }\n\n const textValue =\n field.type === 'fullName'\n ? fullNameFromSigner(signer)\n : field.type === 'title'\n ? signer.title\n : field.type === 'date'\n ? resolvedDateText\n : ''\n if (!textValue) continue\n\n const textSize = Math.max(9, Math.min(16, pointRect.height * 0.6))\n page.drawText(textValue, {\n x: pointRect.x + 2,\n y: pointRect.y + Math.max(0, (pointRect.height - textSize) / 2),\n size: textSize,\n font: helveticaFont,\n })\n }\n\n return pdfDocument.save()\n}\n","export async function sha256(data: Uint8Array): Promise<string> {\n const dataBuffer = new Uint8Array(data.byteLength)\n dataBuffer.set(data)\n const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer)\n return Array.from(new Uint8Array(hashBuffer))\n .map((byte) => byte.toString(16).padStart(2, '0'))\n .join('')\n}\n","export const SLOTS = {\n pdfViewer: 'pdf-viewer',\n pdfViewerEmpty: 'pdf-viewer-empty',\n pdfViewerToolbar: 'pdf-viewer-toolbar',\n pdfViewerPageCount: 'pdf-viewer-page-count',\n pdfViewerZoom: 'pdf-viewer-zoom',\n pdfViewerZoomButton: 'pdf-viewer-zoom-button',\n pdfViewerZoomValue: 'pdf-viewer-zoom-value',\n pdfViewerPages: 'pdf-viewer-pages',\n pdfViewerPage: 'pdf-viewer-page',\n pdfViewerLoading: 'pdf-viewer-loading',\n pdfViewerError: 'pdf-viewer-error',\n fieldOverlay: 'field-overlay',\n signatureField: 'signature-field',\n signatureFieldContent: 'signature-field-content',\n signatureFieldLabel: 'signature-field-label',\n signatureFieldPreview: 'signature-field-preview',\n signatureFieldPreviewImage: 'signature-field-preview-image',\n signatureFieldPreviewText: 'signature-field-preview-text',\n signatureFieldRemove: 'signature-field-remove',\n signatureFieldResize: 'signature-field-resize',\n fieldPalette: 'field-palette',\n fieldPaletteButton: 'field-palette-button',\n signerPanel: 'signer-panel',\n signerPanelHeading: 'signer-panel-heading',\n signerPanelLabel: 'signer-panel-label',\n signerPanelInput: 'signer-panel-input',\n signaturePreview: 'signature-preview',\n signaturePreviewHeading: 'signature-preview-heading',\n signaturePreviewModeToggle: 'signature-preview-mode-toggle',\n signaturePreviewModeButton: 'signature-preview-mode-button',\n signaturePreviewFontLabel: 'signature-preview-font-label',\n signaturePreviewFontSelect: 'signature-preview-font-select',\n signaturePreviewDisplay: 'signature-preview-display',\n signaturePreviewImage: 'signature-preview-image',\n signaturePreviewPlaceholder: 'signature-preview-placeholder',\n signaturePad: 'signature-pad',\n signaturePadCanvas: 'signature-pad-canvas',\n signaturePadActions: 'signature-pad-actions',\n signaturePadClear: 'signature-pad-clear',\n signingComplete: 'signing-complete',\n signingCompleteHeading: 'signing-complete-heading',\n signingCompleteDetails: 'signing-complete-details',\n signingCompleteHash: 'signing-complete-hash',\n signingCompleteHashLabel: 'signing-complete-hash-label',\n signingCompleteHashValue: 'signing-complete-hash-value',\n signingCompleteActions: 'signing-complete-actions',\n signingCompleteDownload: 'signing-complete-download',\n signingCompleteReset: 'signing-complete-reset',\n} as const\n","export { PdfViewer } from './components/pdf-viewer'\nexport { FieldOverlay } from './components/field-overlay'\nexport { SignatureField } from './components/signature-field'\nexport { FieldPalette } from './components/field-palette'\nexport { SignerDetailsPanel } from './components/signer-details-panel'\nexport { SignaturePreview } from './components/signature-preview'\nexport { SignaturePad } from './components/signature-pad'\nexport { SigningComplete } from './components/signing-complete'\n\nexport { usePdfDocument } from './hooks/use-pdf-document'\nexport { useFieldPlacement } from './hooks/use-field-placement'\nexport { useSignatureRenderer } from './hooks/use-signature-renderer'\n\nexport { modifyPdf } from './lib/pdf-modifier'\nexport { mapToPoints, mapFromPoints } from './lib/coordinate-mapper'\nexport { loadSignatureFont, SIGNATURE_FONTS } from './lib/signature-fonts'\nexport { sha256 } from './lib/hash'\nexport { SLOTS } from './lib/slots'\n\nexport type {\n FieldPlacement,\n FieldType,\n SignerInfo,\n SignatureStyle,\n SigningResult,\n PdfPageDimensions,\n SignatureFieldPreview,\n} from './types'\n\nexport const defaults = {\n SIGNATURE_FONTS: ['Dancing Script', 'Great Vibes', 'Sacramento', 'Alex Brush'],\n DEFAULT_FIELD_WIDTH_PERCENT: 25,\n DEFAULT_FIELD_HEIGHT_PERCENT: 5,\n} as const\n"]}
1
+ {"version":3,"sources":["../src/lib/config.ts","../src/lib/signature-fonts.ts","../src/lib/cn.ts","../src/components/pdf-viewer.tsx","../src/components/signature-field.tsx","../src/components/field-overlay.tsx","../src/components/field-palette.tsx","../src/components/signer-details-panel.tsx","../src/components/signature-pad.tsx","../src/components/signature-preview.tsx","../src/components/signing-complete.tsx","../src/hooks/use-pdf-document.ts","../src/hooks/use-field-placement.ts","../src/hooks/use-signature-renderer.ts","../src/lib/coordinate-mapper.ts","../src/lib/pdf-modifier.ts","../src/lib/hash.ts","../src/lib/slots.ts","../src/index.ts"],"names":["jsxs","jsx","useRef","useEffect","useMemo","clampPercent","useState"],"mappings":"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","file":"index.js","sourcesContent":["export interface SignatureFontWarning {\n code: string\n message: string\n}\n\nexport interface ESigningConfig {\n /** PDF.js worker script URL (e.g. self-hosted `/pdf.worker.min.mjs`). When unset, `PdfViewer` does not set `GlobalWorkerOptions.workerSrc`. */\n pdfWorkerSrc?: string\n /** `network`: fetch Google Fonts when loading typed signature fonts (default). `local-only`: no fetches; browser uses available/system fonts. */\n fontMode?: 'network' | 'local-only'\n /** Return a woff/woff2 URL for a font family, or `null` to fall back to Google Fonts (when `fontMode` is `network`). */\n fontUrlResolver?: (fontFamily: string) => string | null\n /** Non-throwing callback for recoverable issues (font/worker setup). */\n onWarning?: (warning: SignatureFontWarning) => void\n}\n\nlet _config: ESigningConfig = {}\n\nexport function configure(options: ESigningConfig): void {\n _config = { ..._config, ...options }\n}\n\nexport function getConfig(): Readonly<ESigningConfig> {\n return _config\n}\n\n/** @internal Reset for tests */\nexport function resetConfig(): void {\n _config = {}\n}\n","import { getConfig } from './config'\n\nconst loadedFonts = new Set<string>()\n\nexport const SIGNATURE_FONTS = [\n 'Caveat',\n 'Homemade Apple',\n 'Reenie Beanie',\n 'Mr Dafoe',\n 'Pacifico',\n 'Qwitcher Grypen',\n] as const\n\nfunction buildGoogleFontsCssUrl(family: string): string {\n const encoded = family.trim().replace(/\\s+/g, '+')\n return `https://fonts.googleapis.com/css2?family=${encoded}&display=swap`\n}\n\nasync function loadCssFromGoogleFonts(url: string): Promise<string> {\n const response = await fetch(url)\n if (!response.ok) throw new Error(`Unable to load font css from ${url}`)\n return response.text()\n}\n\nfunction extractFontSource(cssText: string): string | null {\n const sourceMatch = cssText.match(/src:\\s*url\\(([^)]+)\\)\\s*format\\(['\"]?([^'\")]+)['\"]?\\)/i)\n if (!sourceMatch) return null\n return sourceMatch[1].replace(/['\"]/g, '')\n}\n\nfunction warnFontLoad(message: string): void {\n try {\n getConfig().onWarning?.({ code: 'FONT_LOAD_FAILED', message })\n } catch {\n // never throw from observability hook\n }\n}\n\nasync function loadFontFaceFromUrl(fontFamily: string, url: string): Promise<void> {\n if (typeof FontFace === 'undefined' || typeof document === 'undefined') return\n const fontFace = new FontFace(fontFamily, `url(${url})`)\n await fontFace.load()\n const fontSet = document.fonts as unknown as { add: (font: FontFace) => void }\n fontSet.add(fontFace)\n}\n\nexport async function loadSignatureFont(fontFamily: string): Promise<void> {\n if (loadedFonts.has(fontFamily)) return\n if (typeof document === 'undefined') return\n if (typeof FontFace === 'undefined') return\n\n const { fontMode = 'network', fontUrlResolver } = getConfig()\n\n if (fontMode === 'local-only') {\n loadedFonts.add(fontFamily)\n return\n }\n\n const tryLoadFromGoogle = async (): Promise<void> => {\n try {\n const cssUrl = buildGoogleFontsCssUrl(fontFamily)\n const cssText = await loadCssFromGoogleFonts(cssUrl)\n const fontSource = extractFontSource(cssText)\n if (!fontSource) throw new Error(`Unable to extract font source for ${fontFamily}`)\n await loadFontFaceFromUrl(fontFamily, fontSource)\n } catch (error: unknown) {\n const detail = error instanceof Error ? error.message : String(error)\n warnFontLoad(`Google Fonts load failed for \"${fontFamily}\": ${detail}`)\n }\n }\n\n if (fontUrlResolver) {\n try {\n const resolved = fontUrlResolver(fontFamily)\n if (resolved) await loadFontFaceFromUrl(fontFamily, resolved)\n else await tryLoadFromGoogle()\n } catch (error: unknown) {\n const detail = error instanceof Error ? error.message : String(error)\n warnFontLoad(`Custom font load failed for \"${fontFamily}\": ${detail}`)\n await tryLoadFromGoogle()\n }\n } else await tryLoadFromGoogle()\n\n loadedFonts.add(fontFamily)\n}\n\n/** @internal Clears loaded-font bookkeeping (for unit tests). */\nexport function resetSignatureFontCache(): void {\n loadedFonts.clear()\n}\n\nexport function buildSignatureFontCssUrl(fontFamily: string): string {\n return buildGoogleFontsCssUrl(fontFamily)\n}\n","export function cn(...values: Array<string | false | null | undefined>): string {\n return values.filter(Boolean).join(' ')\n}\n","import { Document, Page, pdfjs } from 'react-pdf'\nimport { useEffect } from 'react'\nimport type { ReactNode } from 'react'\nimport { getConfig } from '../lib/config'\nimport { cn } from '../lib/cn'\n\ninterface PdfViewerProps {\n pdfData: ArrayBuffer | null\n numPages: number\n scale: number\n onScaleChange: (nextScale: number) => void\n onDocumentLoadSuccess: (numPages: number) => void\n onPageDimensions: (input: { pageIndex: number; widthPt: number; heightPt: number }) => void\n renderOverlay?: (pageIndex: number) => ReactNode\n className?: string\n /** PDF.js worker script URL. Overrides `configure({ pdfWorkerSrc })`. When neither is set, worker URL is left unset (no CDN injection). */\n workerSrc?: string\n}\n\nconst MIN_SCALE = 0.5\nconst MAX_SCALE = 2\nconst SCALE_STEP = 0.1\n\nexport function PdfViewer({\n pdfData,\n numPages,\n scale,\n onScaleChange,\n onDocumentLoadSuccess,\n onPageDimensions,\n renderOverlay,\n className,\n workerSrc,\n}: PdfViewerProps) {\n useEffect(() => {\n if (typeof window === 'undefined') return\n const fromConfig = getConfig().pdfWorkerSrc\n const next = workerSrc ?? fromConfig\n if (next) pdfjs.GlobalWorkerOptions.workerSrc = next\n }, [workerSrc])\n\n if (!pdfData)\n return (\n <div data-slot=\"pdf-viewer-empty\" className={cn(className)}>\n Upload a PDF to begin\n </div>\n )\n\n return (\n <div data-slot=\"pdf-viewer\" className={cn(className)}>\n <div data-slot=\"pdf-viewer-toolbar\">\n <div data-slot=\"pdf-viewer-page-count\">Pages: {numPages || '—'}</div>\n <div data-slot=\"pdf-viewer-zoom\">\n <button\n type=\"button\"\n data-slot=\"pdf-viewer-zoom-button\"\n onClick={() => onScaleChange(Math.max(MIN_SCALE, Number((scale - SCALE_STEP).toFixed(2))))}\n >\n -\n </button>\n <span data-slot=\"pdf-viewer-zoom-value\">{Math.round(scale * 100)}%</span>\n <button\n type=\"button\"\n data-slot=\"pdf-viewer-zoom-button\"\n onClick={() => onScaleChange(Math.min(MAX_SCALE, Number((scale + SCALE_STEP).toFixed(2))))}\n >\n +\n </button>\n </div>\n </div>\n\n <Document\n file={pdfData}\n onLoadSuccess={(loadedPdf) => onDocumentLoadSuccess(loadedPdf.numPages)}\n loading={<div data-slot=\"pdf-viewer-loading\">Loading PDF...</div>}\n error={<div data-slot=\"pdf-viewer-error\">Unable to render this PDF.</div>}\n >\n <div data-slot=\"pdf-viewer-pages\">\n {Array.from({ length: numPages }, (_, pageIndex) => (\n <div\n key={`pdf-page-${pageIndex}`}\n data-slot=\"pdf-viewer-page\"\n style={{ position: 'relative', margin: '0 auto', width: 'fit-content' }}\n >\n <Page\n pageNumber={pageIndex + 1}\n scale={scale}\n renderTextLayer={false}\n renderAnnotationLayer={false}\n onLoadSuccess={(page) =>\n onPageDimensions({\n pageIndex,\n widthPt: page.view[2],\n heightPt: page.view[3],\n })\n }\n />\n {renderOverlay?.(pageIndex)}\n </div>\n ))}\n </div>\n </Document>\n </div>\n )\n}\n","import { useRef } from 'react'\nimport type { FieldPlacement, SignatureFieldPreview } from '../types'\nimport type { PointerEvent } from 'react'\nimport { cn } from '../lib/cn'\n\ninterface SignatureFieldProps {\n field: FieldPlacement\n onUpdateField: (fieldId: string, partial: Partial<FieldPlacement>) => void\n onRemoveField: (fieldId: string) => void\n preview: SignatureFieldPreview\n className?: string\n}\n\ninterface DragState {\n startClientX: number\n startClientY: number\n startXPercent: number\n startYPercent: number\n}\n\ninterface ResizeState {\n startClientX: number\n startClientY: number\n startWidthPercent: number\n startHeightPercent: number\n}\n\nconst MIN_WIDTH_PERCENT = 8\nconst MIN_HEIGHT_PERCENT = 3\n\nfunction clampPercent(value: number): number {\n if (value < 0) return 0\n if (value > 100) return 100\n return value\n}\n\nfunction getFieldPreviewText(field: FieldPlacement, preview: SignatureFieldPreview): string {\n if (field.type === 'fullName') return preview.fullName\n if (field.type === 'title') return preview.title\n if (field.type === 'date') return preview.dateText\n return ''\n}\n\nexport function SignatureField({ field, onUpdateField, onRemoveField, preview, className }: SignatureFieldProps) {\n const rootRef = useRef<HTMLDivElement | null>(null)\n const dragStateRef = useRef<DragState | null>(null)\n const resizeStateRef = useRef<ResizeState | null>(null)\n\n function handleDragPointerDown(event: PointerEvent<HTMLDivElement>): void {\n event.stopPropagation()\n if (event.button !== 0) return\n if (!rootRef.current?.parentElement) return\n\n dragStateRef.current = {\n startClientX: event.clientX,\n startClientY: event.clientY,\n startXPercent: field.xPercent,\n startYPercent: field.yPercent,\n }\n\n event.currentTarget.setPointerCapture(event.pointerId)\n }\n\n function handleDragPointerMove(event: PointerEvent<HTMLDivElement>): void {\n if (!dragStateRef.current) return\n const parentElement = rootRef.current?.parentElement\n if (!parentElement) return\n\n const deltaX = event.clientX - dragStateRef.current.startClientX\n const deltaY = event.clientY - dragStateRef.current.startClientY\n const deltaXPercent = (deltaX / parentElement.clientWidth) * 100\n const deltaYPercent = (deltaY / parentElement.clientHeight) * 100\n const maxX = 100 - field.widthPercent\n const maxY = 100 - field.heightPercent\n\n onUpdateField(field.id, {\n xPercent: clampPercent(Math.min(maxX, dragStateRef.current.startXPercent + deltaXPercent)),\n yPercent: clampPercent(Math.min(maxY, dragStateRef.current.startYPercent + deltaYPercent)),\n })\n }\n\n function handleDragPointerUp(event: PointerEvent<HTMLDivElement>): void {\n dragStateRef.current = null\n if (event.currentTarget.hasPointerCapture(event.pointerId))\n event.currentTarget.releasePointerCapture(event.pointerId)\n }\n\n function handleResizePointerDown(event: PointerEvent<HTMLDivElement>): void {\n event.stopPropagation()\n if (event.button !== 0) return\n\n resizeStateRef.current = {\n startClientX: event.clientX,\n startClientY: event.clientY,\n startWidthPercent: field.widthPercent,\n startHeightPercent: field.heightPercent,\n }\n\n event.currentTarget.setPointerCapture(event.pointerId)\n }\n\n function handleResizePointerMove(event: PointerEvent<HTMLDivElement>): void {\n if (!resizeStateRef.current) return\n const parentElement = rootRef.current?.parentElement\n if (!parentElement) return\n\n const deltaX = event.clientX - resizeStateRef.current.startClientX\n const deltaY = event.clientY - resizeStateRef.current.startClientY\n const deltaWidthPercent = (deltaX / parentElement.clientWidth) * 100\n const deltaHeightPercent = (deltaY / parentElement.clientHeight) * 100\n\n const maxWidth = 100 - field.xPercent\n const maxHeight = 100 - field.yPercent\n const widthPercent = clampPercent(\n Math.min(maxWidth, Math.max(MIN_WIDTH_PERCENT, resizeStateRef.current.startWidthPercent + deltaWidthPercent))\n )\n const heightPercent = clampPercent(\n Math.min(maxHeight, Math.max(MIN_HEIGHT_PERCENT, resizeStateRef.current.startHeightPercent + deltaHeightPercent))\n )\n\n onUpdateField(field.id, { widthPercent, heightPercent })\n }\n\n function handleResizePointerUp(event: PointerEvent<HTMLDivElement>): void {\n resizeStateRef.current = null\n if (event.currentTarget.hasPointerCapture(event.pointerId))\n event.currentTarget.releasePointerCapture(event.pointerId)\n }\n\n const previewText = getFieldPreviewText(field, preview)\n\n return (\n <div\n ref={rootRef}\n data-slot=\"signature-field\"\n data-field-type={field.type}\n className={cn(className)}\n style={{\n position: 'absolute',\n left: `${field.xPercent}%`,\n top: `${field.yPercent}%`,\n width: `${field.widthPercent}%`,\n height: `${field.heightPercent}%`,\n userSelect: 'none',\n }}\n onPointerDown={handleDragPointerDown}\n onPointerMove={handleDragPointerMove}\n onPointerUp={handleDragPointerUp}\n >\n <div\n data-slot=\"signature-field-content\"\n style={{\n display: 'flex',\n height: '100%',\n width: '100%',\n alignItems: 'stretch',\n justifyContent: 'space-between',\n }}\n >\n <div data-slot=\"signature-field-preview\">\n <div data-slot=\"signature-field-label\">{field.type}</div>\n {field.type === 'signature' && preview.signatureDataUrl ? (\n <img\n data-slot=\"signature-field-preview-image\"\n src={preview.signatureDataUrl}\n alt=\"signature preview\"\n draggable={false}\n />\n ) : (\n <div data-slot=\"signature-field-preview-text\">{previewText || '—'}</div>\n )}\n </div>\n <button\n type=\"button\"\n data-slot=\"signature-field-remove\"\n onPointerDown={(event) => event.stopPropagation()}\n onClick={(event) => {\n event.stopPropagation()\n onRemoveField(field.id)\n }}\n aria-label=\"Remove field\"\n >\n ×\n </button>\n </div>\n\n <div\n data-slot=\"signature-field-resize\"\n style={{\n position: 'absolute',\n right: '-0.375rem',\n bottom: '-0.375rem',\n width: '0.75rem',\n height: '0.75rem',\n cursor: 'nwse-resize',\n }}\n onPointerDown={handleResizePointerDown}\n onPointerMove={handleResizePointerMove}\n onPointerUp={handleResizePointerUp}\n />\n </div>\n )\n}\n","import type { FieldPlacement, FieldType, SignatureFieldPreview } from '../types'\nimport { SignatureField } from './signature-field'\nimport type { PointerEvent } from 'react'\nimport { cn } from '../lib/cn'\n\ninterface FieldOverlayProps {\n pageIndex: number\n fields: FieldPlacement[]\n selectedFieldType: FieldType | null\n onAddField: (input: { pageIndex: number; type: FieldType; xPercent: number; yPercent: number }) => void\n onUpdateField: (fieldId: string, partial: Partial<FieldPlacement>) => void\n onRemoveField: (fieldId: string) => void\n preview: SignatureFieldPreview\n className?: string\n}\n\nexport function FieldOverlay({\n pageIndex,\n fields,\n selectedFieldType,\n onAddField,\n onUpdateField,\n onRemoveField,\n preview,\n className,\n}: FieldOverlayProps) {\n function handleOverlayPointerDown(event: PointerEvent<HTMLDivElement>): void {\n if (!selectedFieldType) return\n if (event.button !== 0) return\n if (event.target !== event.currentTarget) return\n const rect = event.currentTarget.getBoundingClientRect()\n const xPercent = ((event.clientX - rect.left) / rect.width) * 100\n const yPercent = ((event.clientY - rect.top) / rect.height) * 100\n onAddField({\n pageIndex,\n type: selectedFieldType,\n xPercent,\n yPercent,\n })\n }\n\n const pageFields = fields.filter((field) => field.pageIndex === pageIndex)\n\n return (\n <div\n data-slot=\"field-overlay\"\n data-state={selectedFieldType ? 'placing' : 'idle'}\n className={cn(className)}\n style={{\n position: 'absolute',\n inset: 0,\n zIndex: 20,\n cursor: selectedFieldType ? 'crosshair' : 'default',\n }}\n onPointerDown={handleOverlayPointerDown}\n aria-label={`Field overlay page ${pageIndex + 1}`}\n >\n {pageFields.map((field) => (\n <SignatureField\n key={field.id}\n field={field}\n onUpdateField={onUpdateField}\n onRemoveField={onRemoveField}\n preview={preview}\n />\n ))}\n </div>\n )\n}\n","import type { FieldType } from '../types'\nimport { cn } from '../lib/cn'\n\ninterface FieldPaletteProps {\n selectedFieldType: FieldType | null\n onSelectFieldType: (fieldType: FieldType | null) => void\n className?: string\n}\n\nconst FIELD_LABELS: Record<FieldType, string> = {\n signature: 'Signature',\n fullName: 'Full Name',\n title: 'Title',\n date: 'Date',\n}\n\nconst FIELD_TYPES: FieldType[] = ['signature', 'fullName', 'title', 'date']\n\nexport function FieldPalette({ selectedFieldType, onSelectFieldType, className }: FieldPaletteProps) {\n return (\n <div data-slot=\"field-palette\" className={cn(className)}>\n {FIELD_TYPES.map((fieldType) => {\n const isSelected = selectedFieldType === fieldType\n return (\n <button\n key={fieldType}\n type=\"button\"\n data-slot=\"field-palette-button\"\n data-state={isSelected ? 'selected' : 'idle'}\n onClick={() => onSelectFieldType(isSelected ? null : fieldType)}\n aria-pressed={isSelected}\n >\n {FIELD_LABELS[fieldType]}\n </button>\n )\n })}\n </div>\n )\n}\n","import type { SignerInfo } from '../types'\nimport { cn } from '../lib/cn'\n\ninterface SignerDetailsPanelProps {\n signerInfo: SignerInfo\n onSignerInfoChange: (nextSignerInfo: SignerInfo) => void\n className?: string\n}\n\nexport function SignerDetailsPanel({ signerInfo, onSignerInfoChange, className }: SignerDetailsPanelProps) {\n function handleInputChange(fieldName: keyof SignerInfo, fieldValue: string): void {\n onSignerInfoChange({\n ...signerInfo,\n [fieldName]: fieldValue,\n })\n }\n\n return (\n <div data-slot=\"signer-panel\" className={cn(className)}>\n <h2 data-slot=\"signer-panel-heading\">Signer Details</h2>\n\n <label data-slot=\"signer-panel-label\">\n First Name\n <input\n data-slot=\"signer-panel-input\"\n value={signerInfo.firstName}\n onChange={(event) => handleInputChange('firstName', event.target.value)}\n />\n </label>\n\n <label data-slot=\"signer-panel-label\">\n Last Name\n <input\n data-slot=\"signer-panel-input\"\n value={signerInfo.lastName}\n onChange={(event) => handleInputChange('lastName', event.target.value)}\n />\n </label>\n\n <label data-slot=\"signer-panel-label\">\n Title\n <input\n data-slot=\"signer-panel-input\"\n value={signerInfo.title}\n onChange={(event) => handleInputChange('title', event.target.value)}\n />\n </label>\n </div>\n )\n}\n","import SignaturePadLibrary from 'signature_pad'\nimport { useEffect, useRef } from 'react'\nimport { cn } from '../lib/cn'\n\ninterface SignaturePadProps {\n onDrawn: (signatureDataUrl: string) => void\n className?: string\n}\n\nexport function SignaturePad({ onDrawn, className }: SignaturePadProps) {\n const canvasRef = useRef<HTMLCanvasElement | null>(null)\n const signaturePadRef = useRef<SignaturePadLibrary | null>(null)\n\n useEffect(() => {\n if (!canvasRef.current) return\n\n const signaturePad = new SignaturePadLibrary(canvasRef.current, {\n minWidth: 1,\n maxWidth: 2.5,\n penColor: '#111827',\n backgroundColor: 'rgba(255,255,255,0)',\n })\n\n signaturePadRef.current = signaturePad\n\n function emitSignatureIfNotEmpty(): void {\n if (signaturePad.isEmpty()) return\n onDrawn(signaturePad.toDataURL('image/png'))\n }\n\n signaturePad.addEventListener('endStroke', emitSignatureIfNotEmpty)\n\n return () => {\n signaturePad.removeEventListener('endStroke', emitSignatureIfNotEmpty)\n signaturePad.off()\n signaturePadRef.current = null\n }\n }, [onDrawn])\n\n function handleClear(): void {\n signaturePadRef.current?.clear()\n onDrawn('')\n }\n\n return (\n <div data-slot=\"signature-pad\" className={cn(className)}>\n <canvas data-slot=\"signature-pad-canvas\" ref={canvasRef} width={420} height={140} />\n <div data-slot=\"signature-pad-actions\">\n <button\n type=\"button\"\n data-slot=\"signature-pad-clear\"\n onClick={handleClear}\n >\n Clear\n </button>\n </div>\n </div>\n )\n}\n","import { useMemo } from 'react'\nimport { SIGNATURE_FONTS } from '../lib/signature-fonts'\nimport type { SignatureStyle } from '../types'\nimport { SignaturePad } from './signature-pad'\nimport { cn } from '../lib/cn'\n\ninterface SignaturePreviewProps {\n signerName: string\n style: SignatureStyle\n signatureDataUrl: string | null\n isRendering: boolean\n onStyleChange: (nextStyle: SignatureStyle) => void\n className?: string\n}\n\nexport function SignaturePreview({\n signerName,\n style,\n signatureDataUrl,\n isRendering,\n onStyleChange,\n className,\n}: SignaturePreviewProps) {\n const canShowPreview = useMemo(() => signerName.trim().length > 0, [signerName])\n\n return (\n <div data-slot=\"signature-preview\" className={cn(className)}>\n <h2 data-slot=\"signature-preview-heading\">Signature</h2>\n\n <div data-slot=\"signature-preview-mode-toggle\">\n <button\n type=\"button\"\n data-slot=\"signature-preview-mode-button\"\n data-mode=\"typed\"\n data-state={style.mode === 'typed' ? 'active' : 'idle'}\n onClick={() => onStyleChange({ mode: 'typed', fontFamily: style.mode === 'typed' ? style.fontFamily : SIGNATURE_FONTS[0] })}\n >\n Typed\n </button>\n <button\n type=\"button\"\n data-slot=\"signature-preview-mode-button\"\n data-mode=\"drawn\"\n data-state={style.mode === 'drawn' ? 'active' : 'idle'}\n onClick={() => onStyleChange({ mode: 'drawn', dataUrl: style.mode === 'drawn' ? style.dataUrl : '' })}\n >\n Drawn\n </button>\n </div>\n\n {style.mode === 'typed' ? (\n <label data-slot=\"signature-preview-font-label\">\n Font\n <select\n data-slot=\"signature-preview-font-select\"\n value={style.fontFamily}\n onChange={(event) => onStyleChange({ mode: 'typed', fontFamily: event.target.value })}\n >\n {SIGNATURE_FONTS.map((fontFamily) => (\n <option key={fontFamily} value={fontFamily}>\n {fontFamily}\n </option>\n ))}\n </select>\n </label>\n ) : (\n <SignaturePad onDrawn={(dataUrl) => onStyleChange({ mode: 'drawn', dataUrl })} />\n )}\n\n <div\n data-slot=\"signature-preview-display\"\n data-state={\n !canShowPreview ? 'empty' : isRendering ? 'rendering' : signatureDataUrl ? 'ready' : 'missing-signature'\n }\n >\n {!canShowPreview ? (\n <p data-slot=\"signature-preview-placeholder\">Enter signer first and last name to render a signature.</p>\n ) : isRendering ? (\n <p data-slot=\"signature-preview-placeholder\">Rendering signature...</p>\n ) : signatureDataUrl ? (\n <img data-slot=\"signature-preview-image\" src={signatureDataUrl} alt=\"Signature preview\" />\n ) : (\n <p data-slot=\"signature-preview-placeholder\">No signature available yet.</p>\n )}\n </div>\n </div>\n )\n}\n","import { cn } from '../lib/cn'\n\ninterface SigningCompleteProps {\n signerName: string\n fieldCount: number\n signedAt: string\n documentHash: string\n downloadUrl: string\n fileName?: string\n onReset: () => void\n className?: string\n}\n\nexport function SigningComplete({\n signerName,\n fieldCount,\n signedAt,\n documentHash,\n downloadUrl,\n fileName = 'signed-document.pdf',\n onReset,\n className,\n}: SigningCompleteProps) {\n return (\n <div data-slot=\"signing-complete\" className={cn(className)}>\n <h2 data-slot=\"signing-complete-heading\">Document Signed</h2>\n <div data-slot=\"signing-complete-details\">\n <p>Signer: {signerName || 'Unknown'}</p>\n <p>Fields applied: {fieldCount}</p>\n <p>Signed at: {signedAt}</p>\n </div>\n\n <div data-slot=\"signing-complete-hash\">\n <p data-slot=\"signing-complete-hash-label\">SHA-256</p>\n <p data-slot=\"signing-complete-hash-value\">{documentHash}</p>\n </div>\n\n <div data-slot=\"signing-complete-actions\">\n <a\n href={downloadUrl}\n download={fileName}\n data-slot=\"signing-complete-download\"\n >\n Download Signed PDF\n </a>\n <button\n type=\"button\"\n data-slot=\"signing-complete-reset\"\n onClick={onReset}\n >\n Sign Another\n </button>\n </div>\n </div>\n )\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport type { PdfPageDimensions } from '../types'\n\nexport type PdfInput = File | Blob | ArrayBuffer | Uint8Array | null\n\nfunction isArrayBuffer(value: unknown): value is ArrayBuffer {\n return value instanceof ArrayBuffer\n}\n\nfunction isUint8Array(value: unknown): value is Uint8Array {\n return value instanceof Uint8Array\n}\n\nasync function convertPdfInputToArrayBuffer(pdfInput: Exclude<PdfInput, null>): Promise<ArrayBuffer> {\n if (isArrayBuffer(pdfInput)) return pdfInput\n if (isUint8Array(pdfInput)) {\n const copy = new Uint8Array(pdfInput.byteLength)\n copy.set(pdfInput)\n return copy.buffer\n }\n return pdfInput.arrayBuffer()\n}\n\nexport function usePdfDocument(pdfInput: PdfInput) {\n const [pdfData, setPdfData] = useState<ArrayBuffer | null>(null)\n const [numPages, setNumPages] = useState(0)\n const [scale, setScale] = useState(1)\n const [pageDimensions, setPageDimensions] = useState<PdfPageDimensions[]>([])\n const [errorMessage, setErrorMessage] = useState<string | null>(null)\n const [isLoading, setIsLoading] = useState(false)\n\n useEffect(() => {\n if (!pdfInput) {\n setPdfData(null)\n setNumPages(0)\n setPageDimensions([])\n setErrorMessage(null)\n return\n }\n\n let isMounted = true\n\n setIsLoading(true)\n setErrorMessage(null)\n convertPdfInputToArrayBuffer(pdfInput)\n .then((arrayBuffer) => {\n if (!isMounted) return\n setPdfData(arrayBuffer)\n })\n .catch((error: unknown) => {\n if (!isMounted) return\n const message = error instanceof Error ? error.message : 'Unable to read PDF data'\n setErrorMessage(message)\n setPdfData(null)\n })\n .finally(() => {\n if (!isMounted) return\n setIsLoading(false)\n })\n\n return () => {\n isMounted = false\n }\n }, [pdfInput])\n\n function handleDocumentLoadSuccess(loadedPages: number): void {\n setNumPages(loadedPages)\n setPageDimensions((previousDimensions) =>\n previousDimensions\n .filter((dimension) => dimension.pageIndex < loadedPages)\n .sort((left, right) => left.pageIndex - right.pageIndex)\n )\n }\n\n function setPageDimension(pageIndex: number, widthPt: number, heightPt: number): void {\n setPageDimensions((previousDimensions) => {\n const nextDimensions = previousDimensions.filter((entry) => entry.pageIndex !== pageIndex)\n nextDimensions.push({ pageIndex, widthPt, heightPt })\n nextDimensions.sort((left, right) => left.pageIndex - right.pageIndex)\n return nextDimensions\n })\n }\n\n const hasPdf = useMemo(() => pdfData !== null, [pdfData])\n\n return {\n pdfData,\n numPages,\n scale,\n setScale,\n pageDimensions,\n setPageDimension,\n handleDocumentLoadSuccess,\n hasPdf,\n isLoading,\n errorMessage,\n }\n}\n","import { useCallback, useMemo, useState } from 'react'\nimport type { FieldPlacement, FieldType } from '../types'\n\ninterface UseFieldPlacementOptions {\n defaultWidthPercent?: number\n defaultHeightPercent?: number\n}\n\ninterface AddFieldInput {\n pageIndex: number\n type: FieldType\n xPercent: number\n yPercent: number\n}\n\nfunction clampPercent(value: number): number {\n if (Number.isNaN(value)) return 0\n if (value < 0) return 0\n if (value > 100) return 100\n return value\n}\n\nfunction buildFieldId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n\n return `field-${Date.now()}-${Math.random().toString(16).slice(2)}`\n}\n\nexport function useFieldPlacement(options: UseFieldPlacementOptions = {}) {\n const defaultWidthPercent = options.defaultWidthPercent ?? 25\n const defaultHeightPercent = options.defaultHeightPercent ?? 5\n const [fields, setFields] = useState<FieldPlacement[]>([])\n\n const addField = useCallback(\n ({ pageIndex, type, xPercent, yPercent }: AddFieldInput) => {\n const field: FieldPlacement = {\n id: buildFieldId(),\n pageIndex,\n type,\n xPercent: clampPercent(xPercent),\n yPercent: clampPercent(yPercent),\n widthPercent: clampPercent(defaultWidthPercent),\n heightPercent: clampPercent(defaultHeightPercent),\n }\n setFields((previousFields) => [...previousFields, field])\n return field\n },\n [defaultHeightPercent, defaultWidthPercent]\n )\n\n const updateField = useCallback((id: string, partial: Partial<FieldPlacement>) => {\n setFields((previousFields) =>\n previousFields.map((field) => {\n if (field.id !== id) return field\n return {\n ...field,\n ...partial,\n xPercent: partial.xPercent === undefined ? field.xPercent : clampPercent(partial.xPercent),\n yPercent: partial.yPercent === undefined ? field.yPercent : clampPercent(partial.yPercent),\n widthPercent:\n partial.widthPercent === undefined ? field.widthPercent : clampPercent(partial.widthPercent),\n heightPercent:\n partial.heightPercent === undefined ? field.heightPercent : clampPercent(partial.heightPercent),\n }\n })\n )\n }, [])\n\n const removeField = useCallback((id: string) => {\n setFields((previousFields) => previousFields.filter((field) => field.id !== id))\n }, [])\n\n const clearFields = useCallback(() => {\n setFields([])\n }, [])\n\n const fieldActions = useMemo(\n () => ({\n addField,\n updateField,\n removeField,\n clearFields,\n }),\n [addField, clearFields, removeField, updateField]\n )\n\n return {\n fields,\n ...fieldActions,\n }\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport { loadSignatureFont } from '../lib/signature-fonts'\nimport type { SignatureStyle } from '../types'\n\ninterface UseSignatureRendererInput {\n signerName: string\n style: SignatureStyle\n}\n\nfunction buildCanvas(): HTMLCanvasElement {\n return document.createElement('canvas')\n}\n\nfunction hashString(s: string): number {\n let h = 2166136261\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i)\n h = Math.imul(h, 16777619)\n }\n return h >>> 0\n}\n\nfunction mulberry32(seed: number): () => number {\n return function () {\n let t = (seed += 0x6d2b79f5)\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\ninterface GlyphLayout {\n char: string\n width: number\n rotation: number\n gapAfter: number\n}\n\nfunction layoutTypedGlyphs({\n signerName,\n fontFamily,\n fontSize,\n context,\n}: {\n signerName: string\n fontFamily: string\n fontSize: number\n context: CanvasRenderingContext2D\n}): GlyphLayout[] {\n const rng = mulberry32(hashString(`${signerName}\\0${fontFamily}`))\n context.font = `${fontSize}px \"${fontFamily}\"`\n const chars = Array.from(signerName)\n const layouts: GlyphLayout[] = []\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i]\n const width = context.measureText(char).width\n const rotation = (rng() * 2 - 1) * 0.07\n const gapAfter = i < chars.length - 1 ? (rng() * 2 - 1) * 1.25 : 0\n layouts.push({ char, width, rotation, gapAfter })\n }\n return layouts\n}\n\nfunction drawTypedSignature({\n signerName,\n fontFamily,\n}: {\n signerName: string\n fontFamily: string\n}): string {\n const canvas = buildCanvas()\n const context = canvas.getContext('2d')\n if (!context) return ''\n\n const padding = 16\n const fontSize = 56\n const baselineY = 50\n\n const glyphs = layoutTypedGlyphs({ signerName, fontFamily, fontSize, context })\n const textWidth = glyphs.reduce((sum, g) => sum + g.width + g.gapAfter, 0)\n\n canvas.width = Math.max(240, Math.ceil(textWidth + padding * 2))\n canvas.height = 100\n\n context.clearRect(0, 0, canvas.width, canvas.height)\n context.font = `${fontSize}px \"${fontFamily}\"`\n context.fillStyle = '#111827'\n context.textAlign = 'center'\n context.textBaseline = 'middle'\n\n let x = padding\n for (const glyph of glyphs) {\n const { char, width, rotation, gapAfter } = glyph\n const cx = x + width / 2\n context.save()\n context.translate(cx, baselineY)\n context.rotate(rotation)\n context.fillText(char, 0, 0)\n context.restore()\n x += width + gapAfter\n }\n\n return canvas.toDataURL('image/png')\n}\n\nexport function useSignatureRenderer({ signerName, style }: UseSignatureRendererInput) {\n const [signatureDataUrl, setSignatureDataUrl] = useState<string | null>(null)\n const [isRendering, setIsRendering] = useState(false)\n\n const normalizedName = useMemo(() => signerName.trim(), [signerName])\n\n useEffect(() => {\n if (!normalizedName) {\n setSignatureDataUrl(null)\n return\n }\n\n if (style.mode === 'drawn') {\n setSignatureDataUrl(style.dataUrl || null)\n return\n }\n\n let isActive = true\n setIsRendering(true)\n\n loadSignatureFont(style.fontFamily)\n .then(() => {\n if (!isActive) return\n const dataUrl = drawTypedSignature({ signerName: normalizedName, fontFamily: style.fontFamily })\n setSignatureDataUrl(dataUrl || null)\n })\n .catch(() => {\n if (!isActive) return\n // Defensive: `loadSignatureFont` should not throw; still render with browser fallback glyphs\n const dataUrl = drawTypedSignature({ signerName: normalizedName, fontFamily: style.fontFamily })\n setSignatureDataUrl(dataUrl || null)\n })\n .finally(() => {\n if (!isActive) return\n setIsRendering(false)\n })\n\n return () => {\n isActive = false\n }\n }, [normalizedName, style])\n\n return {\n signatureDataUrl,\n isRendering,\n }\n}\n","import type { FieldPlacement, PdfPageDimensions, PointRect } from '../types'\n\nfunction clampPercent(value: number): number {\n if (Number.isNaN(value)) return 0\n if (value < 0) return 0\n if (value > 100) return 100\n return value\n}\n\nexport function mapToPoints(field: FieldPlacement, page: PdfPageDimensions): PointRect {\n const xPercent = clampPercent(field.xPercent)\n const yPercent = clampPercent(field.yPercent)\n const widthPercent = clampPercent(field.widthPercent)\n const heightPercent = clampPercent(field.heightPercent)\n\n const width = (widthPercent / 100) * page.widthPt\n const height = (heightPercent / 100) * page.heightPt\n const x = (xPercent / 100) * page.widthPt\n const y = page.heightPt - (yPercent / 100) * page.heightPt - height\n\n return { x, y, width, height }\n}\n\nexport function mapFromPoints(\n rect: PointRect,\n page: PdfPageDimensions\n): Pick<FieldPlacement, 'xPercent' | 'yPercent' | 'widthPercent' | 'heightPercent'> {\n const widthPercent = (rect.width / page.widthPt) * 100\n const heightPercent = (rect.height / page.heightPt) * 100\n const xPercent = (rect.x / page.widthPt) * 100\n const yPercent = ((page.heightPt - rect.y - rect.height) / page.heightPt) * 100\n\n return {\n xPercent: clampPercent(xPercent),\n yPercent: clampPercent(yPercent),\n widthPercent: clampPercent(widthPercent),\n heightPercent: clampPercent(heightPercent),\n }\n}\n","import fontkit from '@pdf-lib/fontkit'\nimport { PDFDocument, StandardFonts } from 'pdf-lib'\nimport { mapToPoints } from './coordinate-mapper'\nimport type { FieldPlacement, PdfPageDimensions, SignerInfo } from '../types'\n\ninterface ModifyPdfInput {\n pdfBytes: Uint8Array\n fields: FieldPlacement[]\n signer: SignerInfo\n signatureDataUrl: string\n pageDimensions: PdfPageDimensions[]\n dateText?: string\n}\n\nfunction fullNameFromSigner(signer: SignerInfo): string {\n return [signer.firstName, signer.lastName].filter(Boolean).join(' ').trim()\n}\n\nfunction dataUrlToBytes(dataUrl: string): Uint8Array {\n const base64 = dataUrl.split(',')[1]\n if (!base64) throw new Error('Invalid signature data URL')\n const binary =\n typeof atob === 'function'\n ? atob(base64)\n : Buffer.from(base64, 'base64').toString('binary')\n const bytes = new Uint8Array(binary.length)\n for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index)\n return bytes\n}\n\nexport async function modifyPdf({\n pdfBytes,\n fields,\n signer,\n signatureDataUrl,\n pageDimensions,\n dateText,\n}: ModifyPdfInput): Promise<Uint8Array> {\n const pdfDocument = await PDFDocument.load(pdfBytes)\n pdfDocument.registerFontkit(fontkit)\n const pages = pdfDocument.getPages()\n const helveticaFont = await pdfDocument.embedFont(StandardFonts.Helvetica)\n\n const signatureImageBytes = signatureDataUrl ? dataUrlToBytes(signatureDataUrl) : null\n const signatureImage = signatureImageBytes ? await pdfDocument.embedPng(signatureImageBytes) : null\n const resolvedDateText = dateText || new Date().toLocaleDateString()\n\n for (const field of fields) {\n const page = pages[field.pageIndex]\n const pageDimension = pageDimensions.find((entry) => entry.pageIndex === field.pageIndex)\n if (!page || !pageDimension) continue\n\n const pointRect = mapToPoints(field, pageDimension)\n if (field.type === 'signature' && signatureImage) {\n page.drawImage(signatureImage, {\n x: pointRect.x,\n y: pointRect.y,\n width: pointRect.width,\n height: pointRect.height,\n })\n continue\n }\n\n const textValue =\n field.type === 'fullName'\n ? fullNameFromSigner(signer)\n : field.type === 'title'\n ? signer.title\n : field.type === 'date'\n ? resolvedDateText\n : ''\n if (!textValue) continue\n\n const textSize = Math.max(9, Math.min(16, pointRect.height * 0.6))\n page.drawText(textValue, {\n x: pointRect.x + 2,\n y: pointRect.y + Math.max(0, (pointRect.height - textSize) / 2),\n size: textSize,\n font: helveticaFont,\n })\n }\n\n return pdfDocument.save()\n}\n","export async function sha256(data: Uint8Array): Promise<string> {\n const dataBuffer = new Uint8Array(data.byteLength)\n dataBuffer.set(data)\n const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer)\n return Array.from(new Uint8Array(hashBuffer))\n .map((byte) => byte.toString(16).padStart(2, '0'))\n .join('')\n}\n","export const SLOTS = {\n pdfViewer: 'pdf-viewer',\n pdfViewerEmpty: 'pdf-viewer-empty',\n pdfViewerToolbar: 'pdf-viewer-toolbar',\n pdfViewerPageCount: 'pdf-viewer-page-count',\n pdfViewerZoom: 'pdf-viewer-zoom',\n pdfViewerZoomButton: 'pdf-viewer-zoom-button',\n pdfViewerZoomValue: 'pdf-viewer-zoom-value',\n pdfViewerPages: 'pdf-viewer-pages',\n pdfViewerPage: 'pdf-viewer-page',\n pdfViewerLoading: 'pdf-viewer-loading',\n pdfViewerError: 'pdf-viewer-error',\n fieldOverlay: 'field-overlay',\n signatureField: 'signature-field',\n signatureFieldContent: 'signature-field-content',\n signatureFieldLabel: 'signature-field-label',\n signatureFieldPreview: 'signature-field-preview',\n signatureFieldPreviewImage: 'signature-field-preview-image',\n signatureFieldPreviewText: 'signature-field-preview-text',\n signatureFieldRemove: 'signature-field-remove',\n signatureFieldResize: 'signature-field-resize',\n fieldPalette: 'field-palette',\n fieldPaletteButton: 'field-palette-button',\n signerPanel: 'signer-panel',\n signerPanelHeading: 'signer-panel-heading',\n signerPanelLabel: 'signer-panel-label',\n signerPanelInput: 'signer-panel-input',\n signaturePreview: 'signature-preview',\n signaturePreviewHeading: 'signature-preview-heading',\n signaturePreviewModeToggle: 'signature-preview-mode-toggle',\n signaturePreviewModeButton: 'signature-preview-mode-button',\n signaturePreviewFontLabel: 'signature-preview-font-label',\n signaturePreviewFontSelect: 'signature-preview-font-select',\n signaturePreviewDisplay: 'signature-preview-display',\n signaturePreviewImage: 'signature-preview-image',\n signaturePreviewPlaceholder: 'signature-preview-placeholder',\n signaturePad: 'signature-pad',\n signaturePadCanvas: 'signature-pad-canvas',\n signaturePadActions: 'signature-pad-actions',\n signaturePadClear: 'signature-pad-clear',\n signingComplete: 'signing-complete',\n signingCompleteHeading: 'signing-complete-heading',\n signingCompleteDetails: 'signing-complete-details',\n signingCompleteHash: 'signing-complete-hash',\n signingCompleteHashLabel: 'signing-complete-hash-label',\n signingCompleteHashValue: 'signing-complete-hash-value',\n signingCompleteActions: 'signing-complete-actions',\n signingCompleteDownload: 'signing-complete-download',\n signingCompleteReset: 'signing-complete-reset',\n} as const\n","import { loadSignatureFont, SIGNATURE_FONTS } from './lib/signature-fonts'\n\nexport { configure } from './lib/config'\nexport type { ESigningConfig, SignatureFontWarning } from './lib/config'\n\nexport { PdfViewer } from './components/pdf-viewer'\nexport { FieldOverlay } from './components/field-overlay'\nexport { SignatureField } from './components/signature-field'\nexport { FieldPalette } from './components/field-palette'\nexport { SignerDetailsPanel } from './components/signer-details-panel'\nexport { SignaturePreview } from './components/signature-preview'\nexport { SignaturePad } from './components/signature-pad'\nexport { SigningComplete } from './components/signing-complete'\n\nexport { usePdfDocument } from './hooks/use-pdf-document'\nexport { useFieldPlacement } from './hooks/use-field-placement'\nexport { useSignatureRenderer } from './hooks/use-signature-renderer'\n\nexport { modifyPdf } from './lib/pdf-modifier'\nexport { mapToPoints, mapFromPoints } from './lib/coordinate-mapper'\nexport { loadSignatureFont, SIGNATURE_FONTS }\nexport { sha256 } from './lib/hash'\nexport { SLOTS } from './lib/slots'\n\nexport type {\n FieldPlacement,\n FieldType,\n SignerInfo,\n SignatureStyle,\n SigningResult,\n PdfPageDimensions,\n SignatureFieldPreview,\n} from './types'\n\nexport const defaults = {\n SIGNATURE_FONTS: [...SIGNATURE_FONTS],\n DEFAULT_FIELD_WIDTH_PERCENT: 25,\n DEFAULT_FIELD_HEIGHT_PERCENT: 5,\n} as const\n"]}
package/dist/styles.css CHANGED
@@ -253,6 +253,7 @@
253
253
  border-radius: 0.375rem;
254
254
  background: rgba(239, 246, 255, 0.8);
255
255
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.15);
256
+ overflow: hidden;
256
257
  }
257
258
 
258
259
  [data-slot='signature-field-content'] {
@@ -263,7 +264,11 @@
263
264
  }
264
265
 
265
266
  [data-slot='signature-field-preview'] {
267
+ display: flex;
268
+ flex-direction: column;
269
+ height: 100%;
266
270
  min-width: 0;
271
+ min-height: 0;
267
272
  flex: 1;
268
273
  overflow: hidden;
269
274
  }
@@ -279,8 +284,9 @@
279
284
  [data-slot='signature-field-preview-image'] {
280
285
  margin-top: 0.25rem;
281
286
  display: block;
282
- height: calc(100% - 18px);
283
- max-height: 100%;
287
+ flex: 1 1 auto;
288
+ min-height: 0;
289
+ height: 100%;
284
290
  width: 100%;
285
291
  object-fit: contain;
286
292
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drvillo/react-browser-e-signing",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "React PDF e-signing in the browser — fields, handwriting, pdf-lib",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,20 +24,6 @@
24
24
  "files": [
25
25
  "dist"
26
26
  ],
27
- "scripts": {
28
- "postinstall": "pnpm run install:browsers",
29
- "install:browsers": "playwright install chromium",
30
- "build": "tsup",
31
- "dev": "tsup --watch",
32
- "demo": "vite",
33
- "demo:build": "vite build",
34
- "test": "pnpm run test:unit && pnpm run test:browser",
35
- "test:unit": "vitest run --config vitest.config.ts",
36
- "test:browser": "vitest run --config vitest.browser.config.ts",
37
- "typecheck": "tsc --noEmit",
38
- "prepublishOnly": "npm run build",
39
- "publish:npm": "npm publish"
40
- },
41
27
  "keywords": [
42
28
  "e-signature",
43
29
  "pdf",
@@ -66,6 +52,7 @@
66
52
  "@vitejs/plugin-react": "^5.0.2",
67
53
  "@vitest/browser-playwright": "^4.0.0",
68
54
  "happy-dom": "^20.0.0",
55
+ "pdfjs-dist": "4.8.69",
69
56
  "playwright": "^1.55.0",
70
57
  "react": "^19.1.1",
71
58
  "react-dom": "^19.1.1",
@@ -74,5 +61,18 @@
74
61
  "typescript": "^5.9.2",
75
62
  "vite": "^7.1.5",
76
63
  "vitest": "^4.0.0"
64
+ },
65
+ "scripts": {
66
+ "postinstall": "pnpm run install:browsers",
67
+ "install:browsers": "playwright install chromium",
68
+ "build": "tsup",
69
+ "dev": "tsup --watch",
70
+ "demo": "vite",
71
+ "demo:build": "vite build",
72
+ "test": "pnpm run test:unit && pnpm run test:browser",
73
+ "test:unit": "vitest run --config vitest.config.ts",
74
+ "test:browser": "vitest run --config vitest.browser.config.ts",
75
+ "typecheck": "tsc --noEmit",
76
+ "publish:npm": "npm publish"
77
77
  }
78
- }
78
+ }