@josephomills/esign 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ui/index.cjs +487 -0
- package/dist/ui/index.cjs.map +1 -0
- package/dist/ui/index.d.cts +100 -0
- package/dist/ui/index.d.ts +100 -0
- package/dist/ui/index.js +477 -0
- package/dist/ui/index.js.map +1 -0
- package/package.json +12 -1
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var SignaturePadLib = require('signature_pad');
|
|
5
|
+
var react = require('react');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
|
|
8
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
|
|
10
|
+
var SignaturePadLib__default = /*#__PURE__*/_interopDefault(SignaturePadLib);
|
|
11
|
+
|
|
12
|
+
// src/ui/SignaturePad.tsx
|
|
13
|
+
function SignaturePad({ primaryColor = "#4f46e5", onChange }) {
|
|
14
|
+
const [mode, setMode] = react.useState("draw");
|
|
15
|
+
const [typed, setTyped] = react.useState("");
|
|
16
|
+
const canvasRef = react.useRef(null);
|
|
17
|
+
const padRef = react.useRef(null);
|
|
18
|
+
react.useEffect(() => {
|
|
19
|
+
if (mode !== "draw") return;
|
|
20
|
+
const canvas = canvasRef.current;
|
|
21
|
+
if (!canvas) return;
|
|
22
|
+
const pad = new SignaturePadLib__default.default(canvas, { penColor: "#111827", minWidth: 0.8, maxWidth: 2.2 });
|
|
23
|
+
padRef.current = pad;
|
|
24
|
+
const resize = () => {
|
|
25
|
+
const ratio = Math.max(window.devicePixelRatio || 1, 1);
|
|
26
|
+
const rect = canvas.getBoundingClientRect();
|
|
27
|
+
canvas.width = Math.floor(rect.width * ratio);
|
|
28
|
+
canvas.height = Math.floor(rect.height * ratio);
|
|
29
|
+
canvas.getContext("2d")?.scale(ratio, ratio);
|
|
30
|
+
pad.clear();
|
|
31
|
+
onChange(null);
|
|
32
|
+
};
|
|
33
|
+
pad.addEventListener(
|
|
34
|
+
"endStroke",
|
|
35
|
+
() => onChange(pad.isEmpty() ? null : pad.toDataURL("image/png"))
|
|
36
|
+
);
|
|
37
|
+
resize();
|
|
38
|
+
window.addEventListener("resize", resize);
|
|
39
|
+
return () => {
|
|
40
|
+
window.removeEventListener("resize", resize);
|
|
41
|
+
pad.off();
|
|
42
|
+
padRef.current = null;
|
|
43
|
+
};
|
|
44
|
+
}, [mode, onChange]);
|
|
45
|
+
react.useEffect(() => {
|
|
46
|
+
if (mode !== "type") return;
|
|
47
|
+
const name = typed.trim();
|
|
48
|
+
if (!name) {
|
|
49
|
+
onChange(null);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const c = document.createElement("canvas");
|
|
53
|
+
c.width = 720;
|
|
54
|
+
c.height = 200;
|
|
55
|
+
const ctx = c.getContext("2d");
|
|
56
|
+
if (!ctx) return;
|
|
57
|
+
ctx.fillStyle = "#111827";
|
|
58
|
+
ctx.font = "72px 'Segoe Script', 'Brush Script MT', cursive";
|
|
59
|
+
ctx.textBaseline = "middle";
|
|
60
|
+
ctx.fillText(name, 24, 110);
|
|
61
|
+
onChange(c.toDataURL("image/png"));
|
|
62
|
+
}, [mode, typed, onChange]);
|
|
63
|
+
const tab = (m, label) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
64
|
+
"button",
|
|
65
|
+
{
|
|
66
|
+
type: "button",
|
|
67
|
+
onClick: () => {
|
|
68
|
+
setMode(m);
|
|
69
|
+
onChange(null);
|
|
70
|
+
},
|
|
71
|
+
style: {
|
|
72
|
+
flex: 1,
|
|
73
|
+
padding: "8px 12px",
|
|
74
|
+
border: "none",
|
|
75
|
+
borderBottom: mode === m ? `2px solid ${primaryColor}` : "2px solid transparent",
|
|
76
|
+
background: "transparent",
|
|
77
|
+
fontWeight: mode === m ? 600 : 400,
|
|
78
|
+
color: mode === m ? primaryColor : "#6b7280",
|
|
79
|
+
cursor: "pointer"
|
|
80
|
+
},
|
|
81
|
+
children: label
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { border: "1px solid #e5e7eb", borderRadius: 12, overflow: "hidden" }, children: [
|
|
85
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", borderBottom: "1px solid #f3f4f6" }, children: [
|
|
86
|
+
tab("draw", "Draw"),
|
|
87
|
+
tab("type", "Type")
|
|
88
|
+
] }),
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", background: "#fff" }, children: [
|
|
90
|
+
mode === "draw" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
91
|
+
"canvas",
|
|
92
|
+
{
|
|
93
|
+
ref: canvasRef,
|
|
94
|
+
style: { width: "100%", height: 180, touchAction: "none", display: "block" }
|
|
95
|
+
}
|
|
96
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 16 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
97
|
+
"input",
|
|
98
|
+
{
|
|
99
|
+
value: typed,
|
|
100
|
+
onChange: (e) => setTyped(e.target.value),
|
|
101
|
+
placeholder: "Type your name",
|
|
102
|
+
style: {
|
|
103
|
+
width: "100%",
|
|
104
|
+
fontSize: 40,
|
|
105
|
+
fontFamily: "'Segoe Script', 'Brush Script MT', cursive",
|
|
106
|
+
border: "none",
|
|
107
|
+
borderBottom: "1px solid #e5e7eb",
|
|
108
|
+
outline: "none",
|
|
109
|
+
padding: "8px 0"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
) }),
|
|
113
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
114
|
+
"button",
|
|
115
|
+
{
|
|
116
|
+
type: "button",
|
|
117
|
+
onClick: () => {
|
|
118
|
+
padRef.current?.clear();
|
|
119
|
+
setTyped("");
|
|
120
|
+
onChange(null);
|
|
121
|
+
},
|
|
122
|
+
style: {
|
|
123
|
+
position: "absolute",
|
|
124
|
+
top: 8,
|
|
125
|
+
right: 8,
|
|
126
|
+
fontSize: 12,
|
|
127
|
+
color: "#6b7280",
|
|
128
|
+
background: "rgba(255,255,255,0.8)",
|
|
129
|
+
border: "1px solid #e5e7eb",
|
|
130
|
+
borderRadius: 6,
|
|
131
|
+
padding: "2px 8px",
|
|
132
|
+
cursor: "pointer"
|
|
133
|
+
},
|
|
134
|
+
children: "Clear"
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
] })
|
|
138
|
+
] });
|
|
139
|
+
}
|
|
140
|
+
function ConsentBlock({ value, onChange, primaryColor = "#4f46e5" }) {
|
|
141
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
|
|
142
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
|
|
143
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 13, fontWeight: 600, color: "#374151" }, children: "Full legal name" }),
|
|
144
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
145
|
+
"input",
|
|
146
|
+
{
|
|
147
|
+
value: value.signerName,
|
|
148
|
+
onChange: (e) => onChange({ ...value, signerName: e.target.value }),
|
|
149
|
+
placeholder: "e.g. Ada Lovelace",
|
|
150
|
+
style: {
|
|
151
|
+
padding: "10px 12px",
|
|
152
|
+
border: "1px solid #d1d5db",
|
|
153
|
+
borderRadius: 8,
|
|
154
|
+
fontSize: 15,
|
|
155
|
+
outline: "none"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
] }),
|
|
160
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "flex", gap: 10, alignItems: "flex-start", cursor: "pointer" }, children: [
|
|
161
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
162
|
+
"input",
|
|
163
|
+
{
|
|
164
|
+
type: "checkbox",
|
|
165
|
+
checked: value.consent,
|
|
166
|
+
onChange: (e) => onChange({ ...value, consent: e.target.checked }),
|
|
167
|
+
style: { marginTop: 3, accentColor: primaryColor, width: 16, height: 16 }
|
|
168
|
+
}
|
|
169
|
+
),
|
|
170
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 13, color: "#4b5563", lineHeight: 1.5 }, children: "I agree to sign this document electronically. I understand my electronic signature is legally binding and that an audit record (time, IP, and a tamper-evident hash) is kept with the signed document." })
|
|
171
|
+
] })
|
|
172
|
+
] });
|
|
173
|
+
}
|
|
174
|
+
function PdfViewer({ url, placement, workerSrc, primaryColor = "#4f46e5" }) {
|
|
175
|
+
const containerRef = react.useRef(null);
|
|
176
|
+
const [failed, setFailed] = react.useState(false);
|
|
177
|
+
react.useEffect(() => {
|
|
178
|
+
let cancelled = false;
|
|
179
|
+
void (async () => {
|
|
180
|
+
try {
|
|
181
|
+
const pdfjs = await import('pdfjs-dist');
|
|
182
|
+
pdfjs.GlobalWorkerOptions.workerSrc = workerSrc ?? `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
183
|
+
const doc = await pdfjs.getDocument({ url }).promise;
|
|
184
|
+
const container = containerRef.current;
|
|
185
|
+
if (!container || cancelled) return;
|
|
186
|
+
container.innerHTML = "";
|
|
187
|
+
const width = container.clientWidth || 640;
|
|
188
|
+
const ratio = Math.max(window.devicePixelRatio || 1, 1);
|
|
189
|
+
for (let p = 1; p <= doc.numPages; p++) {
|
|
190
|
+
const page = await doc.getPage(p);
|
|
191
|
+
if (cancelled) return;
|
|
192
|
+
const base = page.getViewport({ scale: 1 });
|
|
193
|
+
const viewport = page.getViewport({ scale: width / base.width });
|
|
194
|
+
const canvas = document.createElement("canvas");
|
|
195
|
+
canvas.width = Math.floor(viewport.width * ratio);
|
|
196
|
+
canvas.height = Math.floor(viewport.height * ratio);
|
|
197
|
+
canvas.style.width = "100%";
|
|
198
|
+
canvas.style.display = "block";
|
|
199
|
+
canvas.style.borderRadius = "4px";
|
|
200
|
+
const wrap = document.createElement("div");
|
|
201
|
+
wrap.style.position = "relative";
|
|
202
|
+
wrap.style.marginBottom = "14px";
|
|
203
|
+
wrap.style.boxShadow = "0 1px 4px rgba(0,0,0,0.12)";
|
|
204
|
+
wrap.appendChild(canvas);
|
|
205
|
+
if (placement && placement.page === p) {
|
|
206
|
+
const box = document.createElement("div");
|
|
207
|
+
box.style.cssText = `position:absolute;left:${placement.x * 100}%;top:${placement.y * 100}%;width:${placement.w * 100}%;height:${placement.h * 100}%;border:2px dashed ${primaryColor};background:${primaryColor}1a;border-radius:4px;pointer-events:none;`;
|
|
208
|
+
const label = document.createElement("span");
|
|
209
|
+
label.textContent = "Signature";
|
|
210
|
+
label.style.cssText = `position:absolute;top:-18px;left:0;font-size:11px;font-weight:600;color:${primaryColor};`;
|
|
211
|
+
box.appendChild(label);
|
|
212
|
+
wrap.appendChild(box);
|
|
213
|
+
}
|
|
214
|
+
container.appendChild(wrap);
|
|
215
|
+
const ctx = canvas.getContext("2d");
|
|
216
|
+
if (!ctx) continue;
|
|
217
|
+
ctx.scale(ratio, ratio);
|
|
218
|
+
await page.render({ canvasContext: ctx, viewport, canvas }).promise;
|
|
219
|
+
}
|
|
220
|
+
} catch {
|
|
221
|
+
if (!cancelled) setFailed(true);
|
|
222
|
+
}
|
|
223
|
+
})();
|
|
224
|
+
return () => {
|
|
225
|
+
cancelled = true;
|
|
226
|
+
};
|
|
227
|
+
}, [url, placement, workerSrc, primaryColor]);
|
|
228
|
+
if (failed) {
|
|
229
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
230
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
231
|
+
"iframe",
|
|
232
|
+
{
|
|
233
|
+
src: `${url}#toolbar=0`,
|
|
234
|
+
title: "Document",
|
|
235
|
+
style: { width: "100%", height: 520, border: "1px solid #e5e7eb", borderRadius: 8 }
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { href: url, target: "_blank", rel: "noreferrer", style: { fontSize: 13, color: primaryColor }, children: "Download to read" })
|
|
239
|
+
] });
|
|
240
|
+
}
|
|
241
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, style: { width: "100%" } });
|
|
242
|
+
}
|
|
243
|
+
function FieldDesigner({
|
|
244
|
+
pdfData,
|
|
245
|
+
value,
|
|
246
|
+
onChange,
|
|
247
|
+
workerSrc,
|
|
248
|
+
primaryColor = "#4f46e5"
|
|
249
|
+
}) {
|
|
250
|
+
const [numPages, setNumPages] = react.useState(0);
|
|
251
|
+
const [page, setPage] = react.useState(value?.page ?? 1);
|
|
252
|
+
const [failed, setFailed] = react.useState(false);
|
|
253
|
+
const stageRef = react.useRef(null);
|
|
254
|
+
const canvasRef = react.useRef(null);
|
|
255
|
+
const docRef = react.useRef(null);
|
|
256
|
+
const [drag, setDrag] = react.useState(null);
|
|
257
|
+
const startRef = react.useRef(null);
|
|
258
|
+
react.useEffect(() => {
|
|
259
|
+
let cancelled = false;
|
|
260
|
+
void (async () => {
|
|
261
|
+
try {
|
|
262
|
+
const pdfjs = await import('pdfjs-dist');
|
|
263
|
+
pdfjs.GlobalWorkerOptions.workerSrc = workerSrc ?? `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
264
|
+
const doc = await pdfjs.getDocument({ data: pdfData.slice() }).promise;
|
|
265
|
+
if (cancelled) return;
|
|
266
|
+
docRef.current = doc;
|
|
267
|
+
setNumPages(doc.numPages);
|
|
268
|
+
setPage((p) => Math.min(p, doc.numPages));
|
|
269
|
+
} catch {
|
|
270
|
+
if (!cancelled) setFailed(true);
|
|
271
|
+
}
|
|
272
|
+
})();
|
|
273
|
+
return () => {
|
|
274
|
+
cancelled = true;
|
|
275
|
+
};
|
|
276
|
+
}, [pdfData, workerSrc]);
|
|
277
|
+
react.useEffect(() => {
|
|
278
|
+
let cancelled = false;
|
|
279
|
+
void (async () => {
|
|
280
|
+
const doc = docRef.current;
|
|
281
|
+
const canvas = canvasRef.current;
|
|
282
|
+
if (!doc || !canvas) return;
|
|
283
|
+
const pageObj = await doc.getPage(page);
|
|
284
|
+
if (cancelled) return;
|
|
285
|
+
const width = stageRef.current?.clientWidth || 640;
|
|
286
|
+
const base = pageObj.getViewport({ scale: 1 });
|
|
287
|
+
const viewport = pageObj.getViewport({ scale: width / base.width });
|
|
288
|
+
const ratio = Math.max(window.devicePixelRatio || 1, 1);
|
|
289
|
+
canvas.width = Math.floor(viewport.width * ratio);
|
|
290
|
+
canvas.height = Math.floor(viewport.height * ratio);
|
|
291
|
+
canvas.style.width = "100%";
|
|
292
|
+
canvas.style.display = "block";
|
|
293
|
+
const ctx = canvas.getContext("2d");
|
|
294
|
+
if (!ctx) return;
|
|
295
|
+
ctx.scale(ratio, ratio);
|
|
296
|
+
await pageObj.render({ canvasContext: ctx, viewport, canvas }).promise;
|
|
297
|
+
})();
|
|
298
|
+
return () => {
|
|
299
|
+
cancelled = true;
|
|
300
|
+
};
|
|
301
|
+
}, [page, numPages]);
|
|
302
|
+
function rel(e) {
|
|
303
|
+
const rect = stageRef.current.getBoundingClientRect();
|
|
304
|
+
return {
|
|
305
|
+
x: Math.min(Math.max((e.clientX - rect.left) / rect.width, 0), 1),
|
|
306
|
+
y: Math.min(Math.max((e.clientY - rect.top) / rect.height, 0), 1)
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function onDown(e) {
|
|
310
|
+
startRef.current = rel(e);
|
|
311
|
+
setDrag({ ...startRef.current, w: 0, h: 0 });
|
|
312
|
+
}
|
|
313
|
+
function onMove(e) {
|
|
314
|
+
if (!startRef.current) return;
|
|
315
|
+
const p = rel(e);
|
|
316
|
+
const s = startRef.current;
|
|
317
|
+
setDrag({ x: Math.min(s.x, p.x), y: Math.min(s.y, p.y), w: Math.abs(p.x - s.x), h: Math.abs(p.y - s.y) });
|
|
318
|
+
}
|
|
319
|
+
function onUp() {
|
|
320
|
+
if (drag && drag.w > 0.02 && drag.h > 0.01) {
|
|
321
|
+
onChange({ page, x: drag.x, y: drag.y, w: drag.w, h: drag.h });
|
|
322
|
+
}
|
|
323
|
+
startRef.current = null;
|
|
324
|
+
setDrag(null);
|
|
325
|
+
}
|
|
326
|
+
const box = drag ?? (value?.page === page ? value : null);
|
|
327
|
+
if (failed) {
|
|
328
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#b91c1c", fontSize: 14 }, children: "Could not render this PDF for placement. Please check the file is a valid, unencrypted PDF." });
|
|
329
|
+
}
|
|
330
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
331
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }, children: [
|
|
332
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 13, color: "#6b7280" }, children: "Drag a box where the signature goes." }),
|
|
333
|
+
numPages > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { marginLeft: "auto", fontSize: 13, color: "#374151" }, children: [
|
|
334
|
+
"Page",
|
|
335
|
+
" ",
|
|
336
|
+
/* @__PURE__ */ jsxRuntime.jsx("select", { value: page, onChange: (e) => setPage(Number(e.target.value)), children: Array.from({ length: numPages }, (_, i) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: i + 1, children: i + 1 }, i)) })
|
|
337
|
+
] }) : null
|
|
338
|
+
] }),
|
|
339
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
340
|
+
"div",
|
|
341
|
+
{
|
|
342
|
+
ref: stageRef,
|
|
343
|
+
onMouseDown: onDown,
|
|
344
|
+
onMouseMove: onMove,
|
|
345
|
+
onMouseUp: onUp,
|
|
346
|
+
onMouseLeave: onUp,
|
|
347
|
+
style: {
|
|
348
|
+
position: "relative",
|
|
349
|
+
cursor: "crosshair",
|
|
350
|
+
userSelect: "none",
|
|
351
|
+
border: "1px solid #e5e7eb",
|
|
352
|
+
borderRadius: 6,
|
|
353
|
+
overflow: "hidden"
|
|
354
|
+
},
|
|
355
|
+
children: [
|
|
356
|
+
/* @__PURE__ */ jsxRuntime.jsx("canvas", { ref: canvasRef }),
|
|
357
|
+
box ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
358
|
+
"div",
|
|
359
|
+
{
|
|
360
|
+
style: {
|
|
361
|
+
position: "absolute",
|
|
362
|
+
left: `${box.x * 100}%`,
|
|
363
|
+
top: `${box.y * 100}%`,
|
|
364
|
+
width: `${box.w * 100}%`,
|
|
365
|
+
height: `${box.h * 100}%`,
|
|
366
|
+
border: `2px solid ${primaryColor}`,
|
|
367
|
+
background: `${primaryColor}22`,
|
|
368
|
+
borderRadius: 3,
|
|
369
|
+
pointerEvents: "none"
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
) : null
|
|
373
|
+
]
|
|
374
|
+
}
|
|
375
|
+
)
|
|
376
|
+
] });
|
|
377
|
+
}
|
|
378
|
+
function SigningExperience(props) {
|
|
379
|
+
const primary = props.branding?.primaryColor ?? "#4f46e5";
|
|
380
|
+
const [signaturePng, setSignaturePng] = react.useState(null);
|
|
381
|
+
const [consent, setConsent] = react.useState({ signerName: "", consent: false });
|
|
382
|
+
const [submitting, setSubmitting] = react.useState(false);
|
|
383
|
+
const [error, setError] = react.useState(null);
|
|
384
|
+
const canSubmit = !!signaturePng && consent.consent && consent.signerName.trim().length > 0 && !submitting;
|
|
385
|
+
async function submit() {
|
|
386
|
+
if (!canSubmit) return;
|
|
387
|
+
setSubmitting(true);
|
|
388
|
+
setError(null);
|
|
389
|
+
try {
|
|
390
|
+
const res = await fetch(props.submitUrl, {
|
|
391
|
+
method: "POST",
|
|
392
|
+
headers: { "content-type": "application/json" },
|
|
393
|
+
body: JSON.stringify({
|
|
394
|
+
signaturePng,
|
|
395
|
+
signerName: consent.signerName.trim(),
|
|
396
|
+
consent: true
|
|
397
|
+
})
|
|
398
|
+
});
|
|
399
|
+
if (!res.ok) {
|
|
400
|
+
const body = await res.json().catch(() => null);
|
|
401
|
+
throw new Error(body?.error?.message ?? "Could not submit your signature.");
|
|
402
|
+
}
|
|
403
|
+
props.onSigned?.();
|
|
404
|
+
} catch (e) {
|
|
405
|
+
setError(e instanceof Error ? e.message : "Something went wrong.");
|
|
406
|
+
} finally {
|
|
407
|
+
setSubmitting(false);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
411
|
+
"div",
|
|
412
|
+
{
|
|
413
|
+
style: {
|
|
414
|
+
maxWidth: 760,
|
|
415
|
+
margin: "0 auto",
|
|
416
|
+
padding: "24px 16px 64px",
|
|
417
|
+
fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif",
|
|
418
|
+
color: "#111827"
|
|
419
|
+
},
|
|
420
|
+
children: [
|
|
421
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { style: { display: "flex", alignItems: "center", gap: 12, marginBottom: 8 }, children: [
|
|
422
|
+
props.branding?.logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: props.branding.logoUrl, alt: "", style: { height: 32 } }) : null,
|
|
423
|
+
props.branding?.appName ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, color: "#374151" }, children: props.branding.appName }) : null
|
|
424
|
+
] }),
|
|
425
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: 22, margin: "8px 0 4px" }, children: props.documentTitle }),
|
|
426
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#6b7280", fontSize: 14, marginTop: 0 }, children: "Review the document below, then sign \u2014 no account or login needed." }),
|
|
427
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { style: { margin: "16px 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
428
|
+
PdfViewer,
|
|
429
|
+
{
|
|
430
|
+
url: props.sourceUrl,
|
|
431
|
+
placement: props.placement,
|
|
432
|
+
workerSrc: props.workerSrc,
|
|
433
|
+
primaryColor: primary
|
|
434
|
+
}
|
|
435
|
+
) }),
|
|
436
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
438
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: 13, fontWeight: 600, color: "#374151" }, children: "Your signature" }),
|
|
439
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 6 }, children: /* @__PURE__ */ jsxRuntime.jsx(SignaturePad, { primaryColor: primary, onChange: setSignaturePng }) })
|
|
440
|
+
] }),
|
|
441
|
+
/* @__PURE__ */ jsxRuntime.jsx(ConsentBlock, { value: consent, onChange: setConsent, primaryColor: primary }),
|
|
442
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
443
|
+
"div",
|
|
444
|
+
{
|
|
445
|
+
style: {
|
|
446
|
+
background: "#fef2f2",
|
|
447
|
+
border: "1px solid #fecaca",
|
|
448
|
+
color: "#b91c1c",
|
|
449
|
+
borderRadius: 8,
|
|
450
|
+
padding: "10px 12px",
|
|
451
|
+
fontSize: 14
|
|
452
|
+
},
|
|
453
|
+
children: error
|
|
454
|
+
}
|
|
455
|
+
) : null,
|
|
456
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
457
|
+
"button",
|
|
458
|
+
{
|
|
459
|
+
type: "button",
|
|
460
|
+
onClick: submit,
|
|
461
|
+
disabled: !canSubmit,
|
|
462
|
+
style: {
|
|
463
|
+
padding: "14px 16px",
|
|
464
|
+
borderRadius: 10,
|
|
465
|
+
border: "none",
|
|
466
|
+
background: canSubmit ? primary : "#c7c9d1",
|
|
467
|
+
color: "#fff",
|
|
468
|
+
fontSize: 16,
|
|
469
|
+
fontWeight: 600,
|
|
470
|
+
cursor: canSubmit ? "pointer" : "not-allowed"
|
|
471
|
+
},
|
|
472
|
+
children: submitting ? "Signing\u2026" : "Sign document"
|
|
473
|
+
}
|
|
474
|
+
)
|
|
475
|
+
] })
|
|
476
|
+
]
|
|
477
|
+
}
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
exports.ConsentBlock = ConsentBlock;
|
|
482
|
+
exports.FieldDesigner = FieldDesigner;
|
|
483
|
+
exports.PdfViewer = PdfViewer;
|
|
484
|
+
exports.SignaturePad = SignaturePad;
|
|
485
|
+
exports.SigningExperience = SigningExperience;
|
|
486
|
+
//# sourceMappingURL=index.cjs.map
|
|
487
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/ui/SignaturePad.tsx","../../src/ui/ConsentBlock.tsx","../../src/ui/PdfViewer.tsx","../../src/ui/FieldDesigner.tsx","../../src/ui/SigningExperience.tsx"],"names":["useState","useRef","useEffect","SignaturePadLib","jsx","jsxs"],"mappings":"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","file":"index.cjs","sourcesContent":["import SignaturePadLib from \"signature_pad\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport interface SignaturePadProps {\n primaryColor?: string;\n /** Emits a PNG data URL of the current signature, or null when empty. */\n onChange: (pngDataUrl: string | null) => void;\n}\n\n/**\n * Capture a signature by drawing (signature_pad, touch + mouse, DPI-aware) or by\n * typing a name rendered in a script font. Both yield the same PNG data URL that\n * the seal step stamps onto the document.\n */\nexport function SignaturePad({ primaryColor = \"#4f46e5\", onChange }: SignaturePadProps) {\n const [mode, setMode] = useState<\"draw\" | \"type\">(\"draw\");\n const [typed, setTyped] = useState(\"\");\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const padRef = useRef<SignaturePadLib | null>(null);\n\n useEffect(() => {\n if (mode !== \"draw\") return;\n const canvas = canvasRef.current;\n if (!canvas) return;\n const pad = new SignaturePadLib(canvas, { penColor: \"#111827\", minWidth: 0.8, maxWidth: 2.2 });\n padRef.current = pad;\n const resize = () => {\n const ratio = Math.max(window.devicePixelRatio || 1, 1);\n const rect = canvas.getBoundingClientRect();\n canvas.width = Math.floor(rect.width * ratio);\n canvas.height = Math.floor(rect.height * ratio);\n canvas.getContext(\"2d\")?.scale(ratio, ratio);\n pad.clear();\n onChange(null);\n };\n pad.addEventListener(\"endStroke\", () =>\n onChange(pad.isEmpty() ? null : pad.toDataURL(\"image/png\")),\n );\n resize();\n window.addEventListener(\"resize\", resize);\n return () => {\n window.removeEventListener(\"resize\", resize);\n pad.off();\n padRef.current = null;\n };\n }, [mode, onChange]);\n\n useEffect(() => {\n if (mode !== \"type\") return;\n const name = typed.trim();\n if (!name) {\n onChange(null);\n return;\n }\n const c = document.createElement(\"canvas\");\n c.width = 720;\n c.height = 200;\n const ctx = c.getContext(\"2d\");\n if (!ctx) return;\n ctx.fillStyle = \"#111827\";\n ctx.font = \"72px 'Segoe Script', 'Brush Script MT', cursive\";\n ctx.textBaseline = \"middle\";\n ctx.fillText(name, 24, 110);\n onChange(c.toDataURL(\"image/png\"));\n }, [mode, typed, onChange]);\n\n const tab = (m: \"draw\" | \"type\", label: string) => (\n <button\n type=\"button\"\n onClick={() => {\n setMode(m);\n onChange(null);\n }}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n border: \"none\",\n borderBottom: mode === m ? `2px solid ${primaryColor}` : \"2px solid transparent\",\n background: \"transparent\",\n fontWeight: mode === m ? 600 : 400,\n color: mode === m ? primaryColor : \"#6b7280\",\n cursor: \"pointer\",\n }}\n >\n {label}\n </button>\n );\n\n return (\n <div style={{ border: \"1px solid #e5e7eb\", borderRadius: 12, overflow: \"hidden\" }}>\n <div style={{ display: \"flex\", borderBottom: \"1px solid #f3f4f6\" }}>\n {tab(\"draw\", \"Draw\")}\n {tab(\"type\", \"Type\")}\n </div>\n <div style={{ position: \"relative\", background: \"#fff\" }}>\n {mode === \"draw\" ? (\n <canvas\n ref={canvasRef}\n style={{ width: \"100%\", height: 180, touchAction: \"none\", display: \"block\" }}\n />\n ) : (\n <div style={{ padding: 16 }}>\n <input\n value={typed}\n onChange={(e) => setTyped(e.target.value)}\n placeholder=\"Type your name\"\n style={{\n width: \"100%\",\n fontSize: 40,\n fontFamily: \"'Segoe Script', 'Brush Script MT', cursive\",\n border: \"none\",\n borderBottom: \"1px solid #e5e7eb\",\n outline: \"none\",\n padding: \"8px 0\",\n }}\n />\n </div>\n )}\n <button\n type=\"button\"\n onClick={() => {\n padRef.current?.clear();\n setTyped(\"\");\n onChange(null);\n }}\n style={{\n position: \"absolute\",\n top: 8,\n right: 8,\n fontSize: 12,\n color: \"#6b7280\",\n background: \"rgba(255,255,255,0.8)\",\n border: \"1px solid #e5e7eb\",\n borderRadius: 6,\n padding: \"2px 8px\",\n cursor: \"pointer\",\n }}\n >\n Clear\n </button>\n </div>\n </div>\n );\n}\n","export interface ConsentValue {\n signerName: string;\n consent: boolean;\n}\n\nexport interface ConsentBlockProps {\n value: ConsentValue;\n onChange: (value: ConsentValue) => void;\n primaryColor?: string;\n}\n\n/**\n * The electronic-signature intent record: a typed full legal name + an explicit\n * consent checkbox. Together with the audit trail this is what makes the simple\n * e-signature legally valid.\n */\nexport function ConsentBlock({ value, onChange, primaryColor = \"#4f46e5\" }: ConsentBlockProps) {\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n <label style={{ display: \"flex\", flexDirection: \"column\", gap: 4 }}>\n <span style={{ fontSize: 13, fontWeight: 600, color: \"#374151\" }}>Full legal name</span>\n <input\n value={value.signerName}\n onChange={(e) => onChange({ ...value, signerName: e.target.value })}\n placeholder=\"e.g. Ada Lovelace\"\n style={{\n padding: \"10px 12px\",\n border: \"1px solid #d1d5db\",\n borderRadius: 8,\n fontSize: 15,\n outline: \"none\",\n }}\n />\n </label>\n <label style={{ display: \"flex\", gap: 10, alignItems: \"flex-start\", cursor: \"pointer\" }}>\n <input\n type=\"checkbox\"\n checked={value.consent}\n onChange={(e) => onChange({ ...value, consent: e.target.checked })}\n style={{ marginTop: 3, accentColor: primaryColor, width: 16, height: 16 }}\n />\n <span style={{ fontSize: 13, color: \"#4b5563\", lineHeight: 1.5 }}>\n I agree to sign this document electronically. I understand my electronic\n signature is legally binding and that an audit record (time, IP, and a\n tamper-evident hash) is kept with the signed document.\n </span>\n </label>\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nexport interface ViewerPlacement {\n page: number;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface PdfViewerProps {\n /** Token-gated source PDF URL. */\n url: string;\n /** Optional signature-box hint, drawn on its page at normalized coords. */\n placement?: ViewerPlacement;\n /** Override the pdf.js worker (defaults to the unpkg .mjs for the bundled version). */\n workerSrc?: string;\n primaryColor?: string;\n}\n\n/**\n * Render the PDF to canvases (pdf.js, responsive, DPI-aware) with the signature\n * box overlaid where the manager placed it. Falls back to an <iframe> + download\n * link if pdf.js fails to load — so the document is always readable.\n */\nexport function PdfViewer({ url, placement, workerSrc, primaryColor = \"#4f46e5\" }: PdfViewerProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const [failed, setFailed] = useState(false);\n\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n try {\n const pdfjs = await import(\"pdfjs-dist\");\n pdfjs.GlobalWorkerOptions.workerSrc =\n workerSrc ?? `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;\n const doc = await pdfjs.getDocument({ url }).promise;\n const container = containerRef.current;\n if (!container || cancelled) return;\n container.innerHTML = \"\";\n const width = container.clientWidth || 640;\n const ratio = Math.max(window.devicePixelRatio || 1, 1);\n\n for (let p = 1; p <= doc.numPages; p++) {\n const page = await doc.getPage(p);\n if (cancelled) return;\n const base = page.getViewport({ scale: 1 });\n const viewport = page.getViewport({ scale: width / base.width });\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = Math.floor(viewport.width * ratio);\n canvas.height = Math.floor(viewport.height * ratio);\n canvas.style.width = \"100%\";\n canvas.style.display = \"block\";\n canvas.style.borderRadius = \"4px\";\n\n const wrap = document.createElement(\"div\");\n wrap.style.position = \"relative\";\n wrap.style.marginBottom = \"14px\";\n wrap.style.boxShadow = \"0 1px 4px rgba(0,0,0,0.12)\";\n wrap.appendChild(canvas);\n\n if (placement && placement.page === p) {\n const box = document.createElement(\"div\");\n box.style.cssText = `position:absolute;left:${placement.x * 100}%;top:${\n placement.y * 100\n }%;width:${placement.w * 100}%;height:${placement.h * 100}%;border:2px dashed ${primaryColor};background:${primaryColor}1a;border-radius:4px;pointer-events:none;`;\n const label = document.createElement(\"span\");\n label.textContent = \"Signature\";\n label.style.cssText = `position:absolute;top:-18px;left:0;font-size:11px;font-weight:600;color:${primaryColor};`;\n box.appendChild(label);\n wrap.appendChild(box);\n }\n\n container.appendChild(wrap);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) continue;\n ctx.scale(ratio, ratio);\n await page.render({ canvasContext: ctx, viewport, canvas }).promise;\n }\n } catch {\n if (!cancelled) setFailed(true);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [url, placement, workerSrc, primaryColor]);\n\n if (failed) {\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n <iframe\n src={`${url}#toolbar=0`}\n title=\"Document\"\n style={{ width: \"100%\", height: 520, border: \"1px solid #e5e7eb\", borderRadius: 8 }}\n />\n <a href={url} target=\"_blank\" rel=\"noreferrer\" style={{ fontSize: 13, color: primaryColor }}>\n Download to read\n </a>\n </div>\n );\n }\n\n return <div ref={containerRef} style={{ width: \"100%\" }} />;\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nexport interface DesignerPlacement {\n page: number;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface FieldDesignerProps {\n /** The chosen PDF's bytes (read client-side before upload). */\n pdfData: Uint8Array;\n value: DesignerPlacement | null;\n onChange: (placement: DesignerPlacement) => void;\n workerSrc?: string;\n primaryColor?: string;\n}\n\ninterface DragBox {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/**\n * Drag a signature box onto a pdf.js-rendered page. Emits a normalized\n * placement `{ page, x, y, w, h }` (0–1 fractions, top-left origin) that the seal\n * step converts to pdf coordinates — so it stays accurate at any size.\n */\nexport function FieldDesigner({\n pdfData,\n value,\n onChange,\n workerSrc,\n primaryColor = \"#4f46e5\",\n}: FieldDesignerProps) {\n const [numPages, setNumPages] = useState(0);\n const [page, setPage] = useState(value?.page ?? 1);\n const [failed, setFailed] = useState(false);\n const stageRef = useRef<HTMLDivElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const docRef = useRef<any>(null);\n const [drag, setDrag] = useState<DragBox | null>(null);\n const startRef = useRef<{ x: number; y: number } | null>(null);\n\n // Load the document once.\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n try {\n const pdfjs = await import(\"pdfjs-dist\");\n pdfjs.GlobalWorkerOptions.workerSrc =\n workerSrc ?? `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;\n const doc = await pdfjs.getDocument({ data: pdfData.slice() }).promise;\n if (cancelled) return;\n docRef.current = doc;\n setNumPages(doc.numPages);\n setPage((p) => Math.min(p, doc.numPages));\n } catch {\n if (!cancelled) setFailed(true);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [pdfData, workerSrc]);\n\n // Render the current page.\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n const doc = docRef.current;\n const canvas = canvasRef.current;\n if (!doc || !canvas) return;\n const pageObj = await doc.getPage(page);\n if (cancelled) return;\n const width = stageRef.current?.clientWidth || 640;\n const base = pageObj.getViewport({ scale: 1 });\n const viewport = pageObj.getViewport({ scale: width / base.width });\n const ratio = Math.max(window.devicePixelRatio || 1, 1);\n canvas.width = Math.floor(viewport.width * ratio);\n canvas.height = Math.floor(viewport.height * ratio);\n canvas.style.width = \"100%\";\n canvas.style.display = \"block\";\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n ctx.scale(ratio, ratio);\n await pageObj.render({ canvasContext: ctx, viewport, canvas }).promise;\n })();\n return () => {\n cancelled = true;\n };\n }, [page, numPages]);\n\n function rel(e: React.MouseEvent): { x: number; y: number } {\n const rect = stageRef.current!.getBoundingClientRect();\n return {\n x: Math.min(Math.max((e.clientX - rect.left) / rect.width, 0), 1),\n y: Math.min(Math.max((e.clientY - rect.top) / rect.height, 0), 1),\n };\n }\n\n function onDown(e: React.MouseEvent) {\n startRef.current = rel(e);\n setDrag({ ...startRef.current, w: 0, h: 0 });\n }\n function onMove(e: React.MouseEvent) {\n if (!startRef.current) return;\n const p = rel(e);\n const s = startRef.current;\n setDrag({ x: Math.min(s.x, p.x), y: Math.min(s.y, p.y), w: Math.abs(p.x - s.x), h: Math.abs(p.y - s.y) });\n }\n function onUp() {\n if (drag && drag.w > 0.02 && drag.h > 0.01) {\n onChange({ page, x: drag.x, y: drag.y, w: drag.w, h: drag.h });\n }\n startRef.current = null;\n setDrag(null);\n }\n\n const box = drag ?? (value?.page === page ? value : null);\n\n if (failed) {\n return (\n <div style={{ color: \"#b91c1c\", fontSize: 14 }}>\n Could not render this PDF for placement. Please check the file is a valid, unencrypted PDF.\n </div>\n );\n }\n\n return (\n <div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginBottom: 8 }}>\n <span style={{ fontSize: 13, color: \"#6b7280\" }}>Drag a box where the signature goes.</span>\n {numPages > 1 ? (\n <label style={{ marginLeft: \"auto\", fontSize: 13, color: \"#374151\" }}>\n Page{\" \"}\n <select value={page} onChange={(e) => setPage(Number(e.target.value))}>\n {Array.from({ length: numPages }, (_, i) => (\n <option key={i} value={i + 1}>\n {i + 1}\n </option>\n ))}\n </select>\n </label>\n ) : null}\n </div>\n <div\n ref={stageRef}\n onMouseDown={onDown}\n onMouseMove={onMove}\n onMouseUp={onUp}\n onMouseLeave={onUp}\n style={{\n position: \"relative\",\n cursor: \"crosshair\",\n userSelect: \"none\",\n border: \"1px solid #e5e7eb\",\n borderRadius: 6,\n overflow: \"hidden\",\n }}\n >\n <canvas ref={canvasRef} />\n {box ? (\n <div\n style={{\n position: \"absolute\",\n left: `${box.x * 100}%`,\n top: `${box.y * 100}%`,\n width: `${box.w * 100}%`,\n height: `${box.h * 100}%`,\n border: `2px solid ${primaryColor}`,\n background: `${primaryColor}22`,\n borderRadius: 3,\n pointerEvents: \"none\",\n }}\n />\n ) : null}\n </div>\n </div>\n );\n}\n","import { useState } from \"react\";\n\nimport { ConsentBlock, type ConsentValue } from \"./ConsentBlock\";\nimport { PdfViewer, type ViewerPlacement } from \"./PdfViewer\";\nimport { SignaturePad } from \"./SignaturePad\";\n\nexport interface SigningBranding {\n appName?: string;\n logoUrl?: string;\n primaryColor?: string;\n}\n\nexport interface SigningExperienceProps {\n /** Token-gated source PDF URL (GET /api/esign/source/<token>). */\n sourceUrl: string;\n /** Submit endpoint (POST /sign/<token>/submit). */\n submitUrl: string;\n documentTitle: string;\n placement?: ViewerPlacement;\n branding?: SigningBranding;\n /** Called after a successful signature submit (host navigates to /done). */\n onSigned?: () => void;\n workerSrc?: string;\n}\n\n/**\n * The full host-branded signer page body: read the PDF (placement highlighted),\n * draw/type a signature, consent, and submit. Self-contained styling so it sits\n * cleanly inside any host shell.\n */\nexport function SigningExperience(props: SigningExperienceProps) {\n const primary = props.branding?.primaryColor ?? \"#4f46e5\";\n const [signaturePng, setSignaturePng] = useState<string | null>(null);\n const [consent, setConsent] = useState<ConsentValue>({ signerName: \"\", consent: false });\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const canSubmit =\n !!signaturePng && consent.consent && consent.signerName.trim().length > 0 && !submitting;\n\n async function submit() {\n if (!canSubmit) return;\n setSubmitting(true);\n setError(null);\n try {\n const res = await fetch(props.submitUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n signaturePng,\n signerName: consent.signerName.trim(),\n consent: true,\n }),\n });\n if (!res.ok) {\n const body = (await res.json().catch(() => null)) as {\n error?: { message?: string };\n } | null;\n throw new Error(body?.error?.message ?? \"Could not submit your signature.\");\n }\n props.onSigned?.();\n } catch (e) {\n setError(e instanceof Error ? e.message : \"Something went wrong.\");\n } finally {\n setSubmitting(false);\n }\n }\n\n return (\n <div\n style={{\n maxWidth: 760,\n margin: \"0 auto\",\n padding: \"24px 16px 64px\",\n fontFamily:\n \"system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif\",\n color: \"#111827\",\n }}\n >\n <header style={{ display: \"flex\", alignItems: \"center\", gap: 12, marginBottom: 8 }}>\n {props.branding?.logoUrl ? (\n <img src={props.branding.logoUrl} alt=\"\" style={{ height: 32 }} />\n ) : null}\n {props.branding?.appName ? (\n <span style={{ fontWeight: 600, color: \"#374151\" }}>{props.branding.appName}</span>\n ) : null}\n </header>\n\n <h1 style={{ fontSize: 22, margin: \"8px 0 4px\" }}>{props.documentTitle}</h1>\n <p style={{ color: \"#6b7280\", fontSize: 14, marginTop: 0 }}>\n Review the document below, then sign — no account or login needed.\n </p>\n\n <section style={{ margin: \"16px 0\" }}>\n <PdfViewer\n url={props.sourceUrl}\n placement={props.placement}\n workerSrc={props.workerSrc}\n primaryColor={primary}\n />\n </section>\n\n <section style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n <div>\n <label style={{ fontSize: 13, fontWeight: 600, color: \"#374151\" }}>Your signature</label>\n <div style={{ marginTop: 6 }}>\n <SignaturePad primaryColor={primary} onChange={setSignaturePng} />\n </div>\n </div>\n\n <ConsentBlock value={consent} onChange={setConsent} primaryColor={primary} />\n\n {error ? (\n <div\n style={{\n background: \"#fef2f2\",\n border: \"1px solid #fecaca\",\n color: \"#b91c1c\",\n borderRadius: 8,\n padding: \"10px 12px\",\n fontSize: 14,\n }}\n >\n {error}\n </div>\n ) : null}\n\n <button\n type=\"button\"\n onClick={submit}\n disabled={!canSubmit}\n style={{\n padding: \"14px 16px\",\n borderRadius: 10,\n border: \"none\",\n background: canSubmit ? primary : \"#c7c9d1\",\n color: \"#fff\",\n fontSize: 16,\n fontWeight: 600,\n cursor: canSubmit ? \"pointer\" : \"not-allowed\",\n }}\n >\n {submitting ? \"Signing…\" : \"Sign document\"}\n </button>\n </section>\n </div>\n );\n}\n"]}
|