@josephomills/esign 0.3.0 → 0.5.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/{ports-DtICqgEf.d.cts → ports-DM0-2hQd.d.cts} +65 -3
- package/dist/{ports-DtICqgEf.d.ts → ports-DM0-2hQd.d.ts} +65 -3
- package/dist/prisma/index.cjs +9 -2
- package/dist/prisma/index.cjs.map +1 -1
- package/dist/prisma/index.d.cts +1 -1
- package/dist/prisma/index.d.ts +1 -1
- package/dist/prisma/index.js +9 -2
- package/dist/prisma/index.js.map +1 -1
- package/dist/server/index.cjs +37 -29
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +8 -7
- package/dist/server/index.d.ts +8 -7
- package/dist/server/index.js +36 -30
- package/dist/server/index.js.map +1 -1
- package/dist/ui/index.cjs +377 -7
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.cts +30 -5
- package/dist/ui/index.d.ts +30 -5
- package/dist/ui/index.js +378 -9
- package/dist/ui/index.js.map +1 -1
- package/package.json +1 -1
package/dist/ui/index.d.cts
CHANGED
|
@@ -38,8 +38,8 @@ interface ViewerPlacement {
|
|
|
38
38
|
interface PdfViewerProps {
|
|
39
39
|
/** Token-gated source PDF URL. */
|
|
40
40
|
url: string;
|
|
41
|
-
/**
|
|
42
|
-
|
|
41
|
+
/** Signature-box hints, each drawn on its page at normalized coords. */
|
|
42
|
+
placements?: ViewerPlacement[];
|
|
43
43
|
/** Override the pdf.js worker (defaults to the unpkg .mjs for the bundled version). */
|
|
44
44
|
workerSrc?: string;
|
|
45
45
|
primaryColor?: string;
|
|
@@ -49,7 +49,32 @@ interface PdfViewerProps {
|
|
|
49
49
|
* box overlaid where the manager placed it. Falls back to an <iframe> + download
|
|
50
50
|
* link if pdf.js fails to load — so the document is always readable.
|
|
51
51
|
*/
|
|
52
|
-
declare function PdfViewer({ url,
|
|
52
|
+
declare function PdfViewer({ url, placements, workerSrc, primaryColor }: PdfViewerProps): react.JSX.Element;
|
|
53
|
+
|
|
54
|
+
interface DesignerPlacement {
|
|
55
|
+
id: string;
|
|
56
|
+
label: string;
|
|
57
|
+
page: number;
|
|
58
|
+
x: number;
|
|
59
|
+
y: number;
|
|
60
|
+
w: number;
|
|
61
|
+
h: number;
|
|
62
|
+
}
|
|
63
|
+
interface FieldDesignerProps {
|
|
64
|
+
/** The chosen PDF's bytes (read client-side before upload). */
|
|
65
|
+
pdfData: Uint8Array;
|
|
66
|
+
value: DesignerPlacement[];
|
|
67
|
+
onChange: (fields: DesignerPlacement[]) => void;
|
|
68
|
+
workerSrc?: string;
|
|
69
|
+
primaryColor?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Place + edit one or more named signature fields on a pdf.js-rendered page.
|
|
73
|
+
* Touch + mouse (Pointer Events): drag empty space to add a field, drag a field
|
|
74
|
+
* to move, drag a corner to resize, × to remove. Fields are listed and renameable
|
|
75
|
+
* on the side (and wrap below on narrow screens). Each box shows its name.
|
|
76
|
+
*/
|
|
77
|
+
declare function FieldDesigner({ pdfData, value, onChange, workerSrc, primaryColor, }: FieldDesignerProps): react.JSX.Element;
|
|
53
78
|
|
|
54
79
|
interface SigningBranding {
|
|
55
80
|
appName?: string;
|
|
@@ -62,7 +87,7 @@ interface SigningExperienceProps {
|
|
|
62
87
|
/** Submit endpoint (POST /sign/<token>/submit). */
|
|
63
88
|
submitUrl: string;
|
|
64
89
|
documentTitle: string;
|
|
65
|
-
|
|
90
|
+
placements?: ViewerPlacement[];
|
|
66
91
|
branding?: SigningBranding;
|
|
67
92
|
/** Called after a successful signature submit (host navigates to /done). */
|
|
68
93
|
onSigned?: () => void;
|
|
@@ -75,4 +100,4 @@ interface SigningExperienceProps {
|
|
|
75
100
|
*/
|
|
76
101
|
declare function SigningExperience(props: SigningExperienceProps): react.JSX.Element;
|
|
77
102
|
|
|
78
|
-
export { ConsentBlock, type ConsentBlockProps, type ConsentValue, PdfViewer, type PdfViewerProps, SignaturePad, type SignaturePadProps, type SigningBranding, SigningExperience, type SigningExperienceProps, type ViewerPlacement };
|
|
103
|
+
export { ConsentBlock, type ConsentBlockProps, type ConsentValue, type DesignerPlacement, FieldDesigner, type FieldDesignerProps, PdfViewer, type PdfViewerProps, SignaturePad, type SignaturePadProps, type SigningBranding, SigningExperience, type SigningExperienceProps, type ViewerPlacement };
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -38,8 +38,8 @@ interface ViewerPlacement {
|
|
|
38
38
|
interface PdfViewerProps {
|
|
39
39
|
/** Token-gated source PDF URL. */
|
|
40
40
|
url: string;
|
|
41
|
-
/**
|
|
42
|
-
|
|
41
|
+
/** Signature-box hints, each drawn on its page at normalized coords. */
|
|
42
|
+
placements?: ViewerPlacement[];
|
|
43
43
|
/** Override the pdf.js worker (defaults to the unpkg .mjs for the bundled version). */
|
|
44
44
|
workerSrc?: string;
|
|
45
45
|
primaryColor?: string;
|
|
@@ -49,7 +49,32 @@ interface PdfViewerProps {
|
|
|
49
49
|
* box overlaid where the manager placed it. Falls back to an <iframe> + download
|
|
50
50
|
* link if pdf.js fails to load — so the document is always readable.
|
|
51
51
|
*/
|
|
52
|
-
declare function PdfViewer({ url,
|
|
52
|
+
declare function PdfViewer({ url, placements, workerSrc, primaryColor }: PdfViewerProps): react.JSX.Element;
|
|
53
|
+
|
|
54
|
+
interface DesignerPlacement {
|
|
55
|
+
id: string;
|
|
56
|
+
label: string;
|
|
57
|
+
page: number;
|
|
58
|
+
x: number;
|
|
59
|
+
y: number;
|
|
60
|
+
w: number;
|
|
61
|
+
h: number;
|
|
62
|
+
}
|
|
63
|
+
interface FieldDesignerProps {
|
|
64
|
+
/** The chosen PDF's bytes (read client-side before upload). */
|
|
65
|
+
pdfData: Uint8Array;
|
|
66
|
+
value: DesignerPlacement[];
|
|
67
|
+
onChange: (fields: DesignerPlacement[]) => void;
|
|
68
|
+
workerSrc?: string;
|
|
69
|
+
primaryColor?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Place + edit one or more named signature fields on a pdf.js-rendered page.
|
|
73
|
+
* Touch + mouse (Pointer Events): drag empty space to add a field, drag a field
|
|
74
|
+
* to move, drag a corner to resize, × to remove. Fields are listed and renameable
|
|
75
|
+
* on the side (and wrap below on narrow screens). Each box shows its name.
|
|
76
|
+
*/
|
|
77
|
+
declare function FieldDesigner({ pdfData, value, onChange, workerSrc, primaryColor, }: FieldDesignerProps): react.JSX.Element;
|
|
53
78
|
|
|
54
79
|
interface SigningBranding {
|
|
55
80
|
appName?: string;
|
|
@@ -62,7 +87,7 @@ interface SigningExperienceProps {
|
|
|
62
87
|
/** Submit endpoint (POST /sign/<token>/submit). */
|
|
63
88
|
submitUrl: string;
|
|
64
89
|
documentTitle: string;
|
|
65
|
-
|
|
90
|
+
placements?: ViewerPlacement[];
|
|
66
91
|
branding?: SigningBranding;
|
|
67
92
|
/** Called after a successful signature submit (host navigates to /done). */
|
|
68
93
|
onSigned?: () => void;
|
|
@@ -75,4 +100,4 @@ interface SigningExperienceProps {
|
|
|
75
100
|
*/
|
|
76
101
|
declare function SigningExperience(props: SigningExperienceProps): react.JSX.Element;
|
|
77
102
|
|
|
78
|
-
export { ConsentBlock, type ConsentBlockProps, type ConsentValue, PdfViewer, type PdfViewerProps, SignaturePad, type SignaturePadProps, type SigningBranding, SigningExperience, type SigningExperienceProps, type ViewerPlacement };
|
|
103
|
+
export { ConsentBlock, type ConsentBlockProps, type ConsentValue, type DesignerPlacement, FieldDesigner, type FieldDesignerProps, PdfViewer, type PdfViewerProps, SignaturePad, type SignaturePadProps, type SigningBranding, SigningExperience, type SigningExperienceProps, type ViewerPlacement };
|
package/dist/ui/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import SignaturePadLib from 'signature_pad';
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
// src/ui/SignaturePad.tsx
|
|
7
7
|
function SignaturePad({ primaryColor = "#4f46e5", onChange }) {
|
|
@@ -165,7 +165,7 @@ function ConsentBlock({ value, onChange, primaryColor = "#4f46e5" }) {
|
|
|
165
165
|
] })
|
|
166
166
|
] });
|
|
167
167
|
}
|
|
168
|
-
function PdfViewer({ url,
|
|
168
|
+
function PdfViewer({ url, placements, workerSrc, primaryColor = "#4f46e5" }) {
|
|
169
169
|
const containerRef = useRef(null);
|
|
170
170
|
const [failed, setFailed] = useState(false);
|
|
171
171
|
useEffect(() => {
|
|
@@ -196,12 +196,13 @@ function PdfViewer({ url, placement, workerSrc, primaryColor = "#4f46e5" }) {
|
|
|
196
196
|
wrap.style.marginBottom = "14px";
|
|
197
197
|
wrap.style.boxShadow = "0 1px 4px rgba(0,0,0,0.12)";
|
|
198
198
|
wrap.appendChild(canvas);
|
|
199
|
-
|
|
199
|
+
for (const pl of placements ?? []) {
|
|
200
|
+
if (pl.page !== p) continue;
|
|
200
201
|
const box = document.createElement("div");
|
|
201
|
-
box.style.cssText = `position:absolute;left:${
|
|
202
|
+
box.style.cssText = `position:absolute;left:${pl.x * 100}%;top:${pl.y * 100}%;width:${pl.w * 100}%;height:${pl.h * 100}%;border:2px dashed ${primaryColor};background:${primaryColor}1a;border-radius:4px;pointer-events:none;display:flex;align-items:center;justify-content:center;overflow:hidden;`;
|
|
202
203
|
const label = document.createElement("span");
|
|
203
|
-
label.textContent = "
|
|
204
|
-
label.style.cssText = `
|
|
204
|
+
label.textContent = "\u270D Sign here";
|
|
205
|
+
label.style.cssText = `font-size:11px;font-weight:600;color:${primaryColor};opacity:0.85;white-space:nowrap;`;
|
|
205
206
|
box.appendChild(label);
|
|
206
207
|
wrap.appendChild(box);
|
|
207
208
|
}
|
|
@@ -218,7 +219,7 @@ function PdfViewer({ url, placement, workerSrc, primaryColor = "#4f46e5" }) {
|
|
|
218
219
|
return () => {
|
|
219
220
|
cancelled = true;
|
|
220
221
|
};
|
|
221
|
-
}, [url,
|
|
222
|
+
}, [url, placements, workerSrc, primaryColor]);
|
|
222
223
|
if (failed) {
|
|
223
224
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
224
225
|
/* @__PURE__ */ jsx(
|
|
@@ -234,6 +235,374 @@ function PdfViewer({ url, placement, workerSrc, primaryColor = "#4f46e5" }) {
|
|
|
234
235
|
}
|
|
235
236
|
return /* @__PURE__ */ jsx("div", { ref: containerRef, style: { width: "100%" } });
|
|
236
237
|
}
|
|
238
|
+
var clamp = (v, min, max) => Math.min(Math.max(v, min), max);
|
|
239
|
+
var MIN_W = 0.04;
|
|
240
|
+
var MIN_H = 0.02;
|
|
241
|
+
var newId = () => typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2);
|
|
242
|
+
function FieldDesigner({
|
|
243
|
+
pdfData,
|
|
244
|
+
value,
|
|
245
|
+
onChange,
|
|
246
|
+
workerSrc,
|
|
247
|
+
primaryColor = "#4f46e5"
|
|
248
|
+
}) {
|
|
249
|
+
const [numPages, setNumPages] = useState(0);
|
|
250
|
+
const [page, setPage] = useState(value[0]?.page ?? 1);
|
|
251
|
+
const [failed, setFailed] = useState(false);
|
|
252
|
+
const [selectedId, setSelectedId] = useState(value[0]?.id ?? null);
|
|
253
|
+
const [drag, setDrag] = useState(null);
|
|
254
|
+
const [live, setLive] = useState(null);
|
|
255
|
+
const stageRef = useRef(null);
|
|
256
|
+
const canvasRef = useRef(null);
|
|
257
|
+
const docRef = useRef(null);
|
|
258
|
+
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
|
+
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 || 480;
|
|
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 r = stageRef.current.getBoundingClientRect();
|
|
304
|
+
return {
|
|
305
|
+
x: clamp((e.clientX - r.left) / r.width, 0, 1),
|
|
306
|
+
y: clamp((e.clientY - r.top) / r.height, 0, 1)
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function onPointerMove(e) {
|
|
310
|
+
if (!drag) return;
|
|
311
|
+
const p = rel(e);
|
|
312
|
+
let b;
|
|
313
|
+
if (drag.mode === "new") {
|
|
314
|
+
b = {
|
|
315
|
+
x: Math.min(drag.start.x, p.x),
|
|
316
|
+
y: Math.min(drag.start.y, p.y),
|
|
317
|
+
w: Math.abs(p.x - drag.start.x),
|
|
318
|
+
h: Math.abs(p.y - drag.start.y)
|
|
319
|
+
};
|
|
320
|
+
} else if (drag.mode === "move") {
|
|
321
|
+
const dx = p.x - drag.start.x;
|
|
322
|
+
const dy = p.y - drag.start.y;
|
|
323
|
+
b = {
|
|
324
|
+
x: clamp(drag.orig.x + dx, 0, 1 - drag.orig.w),
|
|
325
|
+
y: clamp(drag.orig.y + dy, 0, 1 - drag.orig.h),
|
|
326
|
+
w: drag.orig.w,
|
|
327
|
+
h: drag.orig.h
|
|
328
|
+
};
|
|
329
|
+
} else {
|
|
330
|
+
let x1 = drag.orig.x;
|
|
331
|
+
let y1 = drag.orig.y;
|
|
332
|
+
let x2 = drag.orig.x + drag.orig.w;
|
|
333
|
+
let y2 = drag.orig.y + drag.orig.h;
|
|
334
|
+
if (drag.handle[0] === "n") y1 = p.y;
|
|
335
|
+
else y2 = p.y;
|
|
336
|
+
if (drag.handle[1] === "w") x1 = p.x;
|
|
337
|
+
else x2 = p.x;
|
|
338
|
+
b = { x: Math.min(x1, x2), y: Math.min(y1, y2), w: Math.abs(x2 - x1), h: Math.abs(y2 - y1) };
|
|
339
|
+
}
|
|
340
|
+
setLive(b);
|
|
341
|
+
}
|
|
342
|
+
function onPointerUp() {
|
|
343
|
+
if (drag && live && live.w >= MIN_W && live.h >= MIN_H) {
|
|
344
|
+
if (drag.mode === "new") {
|
|
345
|
+
const f = {
|
|
346
|
+
id: newId(),
|
|
347
|
+
label: value.length === 0 ? "Signature" : `Signature ${value.length + 1}`,
|
|
348
|
+
page,
|
|
349
|
+
...live
|
|
350
|
+
};
|
|
351
|
+
onChange([...value, f]);
|
|
352
|
+
setSelectedId(f.id);
|
|
353
|
+
} else {
|
|
354
|
+
onChange(value.map((x) => x.id === drag.id ? { ...x, ...live } : x));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
setDrag(null);
|
|
358
|
+
setLive(null);
|
|
359
|
+
}
|
|
360
|
+
function removeField(id) {
|
|
361
|
+
onChange(value.filter((f) => f.id !== id));
|
|
362
|
+
if (selectedId === id) setSelectedId(null);
|
|
363
|
+
}
|
|
364
|
+
function rename(id, label) {
|
|
365
|
+
onChange(value.map((f) => f.id === id ? { ...f, label } : f));
|
|
366
|
+
}
|
|
367
|
+
const handle = (id, geom, c) => {
|
|
368
|
+
const cx = c[1] === "w" ? geom.x : geom.x + geom.w;
|
|
369
|
+
const cy = c[0] === "n" ? geom.y : geom.y + geom.h;
|
|
370
|
+
const cursor = c === "nw" || c === "se" ? "nwse-resize" : "nesw-resize";
|
|
371
|
+
return /* @__PURE__ */ jsx(
|
|
372
|
+
"div",
|
|
373
|
+
{
|
|
374
|
+
onPointerDown: (e) => {
|
|
375
|
+
e.stopPropagation();
|
|
376
|
+
setDrag({ mode: "resize", id, handle: c, orig: geom });
|
|
377
|
+
},
|
|
378
|
+
style: {
|
|
379
|
+
position: "absolute",
|
|
380
|
+
left: `${cx * 100}%`,
|
|
381
|
+
top: `${cy * 100}%`,
|
|
382
|
+
width: 13,
|
|
383
|
+
height: 13,
|
|
384
|
+
marginLeft: -7,
|
|
385
|
+
marginTop: -7,
|
|
386
|
+
background: "#fff",
|
|
387
|
+
border: `2px solid ${primaryColor}`,
|
|
388
|
+
borderRadius: 2,
|
|
389
|
+
cursor,
|
|
390
|
+
touchAction: "none"
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
c
|
|
394
|
+
);
|
|
395
|
+
};
|
|
396
|
+
if (failed) {
|
|
397
|
+
return /* @__PURE__ */ jsx("div", { style: { color: "#b91c1c", fontSize: 14 }, children: "Could not render this PDF for placement. Please check the file is a valid, unencrypted PDF." });
|
|
398
|
+
}
|
|
399
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: 16, alignItems: "flex-start" }, children: [
|
|
400
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: "1 1 340px", minWidth: 260 }, children: [
|
|
401
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }, children: [
|
|
402
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 13, color: "#6b7280" }, children: "Drag a box where a signature goes." }),
|
|
403
|
+
numPages > 1 ? /* @__PURE__ */ jsxs("label", { style: { marginLeft: "auto", fontSize: 13, color: "#374151" }, children: [
|
|
404
|
+
"Page",
|
|
405
|
+
" ",
|
|
406
|
+
/* @__PURE__ */ jsx("select", { value: page, onChange: (e) => setPage(Number(e.target.value)), children: Array.from({ length: numPages }, (_, i) => /* @__PURE__ */ jsx("option", { value: i + 1, children: i + 1 }, i)) })
|
|
407
|
+
] }) : null
|
|
408
|
+
] }),
|
|
409
|
+
/* @__PURE__ */ jsxs(
|
|
410
|
+
"div",
|
|
411
|
+
{
|
|
412
|
+
ref: stageRef,
|
|
413
|
+
onPointerDown: (e) => setDrag({ mode: "new", start: rel(e) }),
|
|
414
|
+
onPointerMove,
|
|
415
|
+
onPointerUp,
|
|
416
|
+
onPointerLeave: onPointerUp,
|
|
417
|
+
style: {
|
|
418
|
+
position: "relative",
|
|
419
|
+
cursor: "crosshair",
|
|
420
|
+
userSelect: "none",
|
|
421
|
+
touchAction: "none",
|
|
422
|
+
border: "1px solid #e5e7eb",
|
|
423
|
+
borderRadius: 6,
|
|
424
|
+
overflow: "hidden"
|
|
425
|
+
},
|
|
426
|
+
children: [
|
|
427
|
+
/* @__PURE__ */ jsx("canvas", { ref: canvasRef }),
|
|
428
|
+
value.filter((f) => f.page === page).map((f) => {
|
|
429
|
+
const dragging = drag && drag.mode !== "new" && drag.id === f.id;
|
|
430
|
+
const geom = dragging && live ? live : f;
|
|
431
|
+
const isSel = f.id === selectedId;
|
|
432
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
433
|
+
/* @__PURE__ */ jsx(
|
|
434
|
+
"div",
|
|
435
|
+
{
|
|
436
|
+
onPointerDown: (e) => {
|
|
437
|
+
e.stopPropagation();
|
|
438
|
+
setSelectedId(f.id);
|
|
439
|
+
setDrag({ mode: "move", id: f.id, start: rel(e), orig: geom });
|
|
440
|
+
},
|
|
441
|
+
style: {
|
|
442
|
+
position: "absolute",
|
|
443
|
+
left: `${geom.x * 100}%`,
|
|
444
|
+
top: `${geom.y * 100}%`,
|
|
445
|
+
width: `${geom.w * 100}%`,
|
|
446
|
+
height: `${geom.h * 100}%`,
|
|
447
|
+
border: `2px ${isSel ? "solid" : "dashed"} ${primaryColor}`,
|
|
448
|
+
background: `${primaryColor}${isSel ? "22" : "14"}`,
|
|
449
|
+
borderRadius: 3,
|
|
450
|
+
cursor: "move",
|
|
451
|
+
display: "flex",
|
|
452
|
+
alignItems: "center",
|
|
453
|
+
justifyContent: "center",
|
|
454
|
+
overflow: "hidden",
|
|
455
|
+
touchAction: "none"
|
|
456
|
+
},
|
|
457
|
+
children: /* @__PURE__ */ jsxs(
|
|
458
|
+
"span",
|
|
459
|
+
{
|
|
460
|
+
style: {
|
|
461
|
+
fontSize: 12,
|
|
462
|
+
fontWeight: 600,
|
|
463
|
+
color: primaryColor,
|
|
464
|
+
opacity: 0.85,
|
|
465
|
+
whiteSpace: "nowrap",
|
|
466
|
+
padding: "0 4px"
|
|
467
|
+
},
|
|
468
|
+
children: [
|
|
469
|
+
"\u270D ",
|
|
470
|
+
f.label || "Signature"
|
|
471
|
+
]
|
|
472
|
+
}
|
|
473
|
+
)
|
|
474
|
+
}
|
|
475
|
+
),
|
|
476
|
+
isSel ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
477
|
+
["nw", "ne", "sw", "se"].map((c) => handle(f.id, geom, c)),
|
|
478
|
+
/* @__PURE__ */ jsx(
|
|
479
|
+
"button",
|
|
480
|
+
{
|
|
481
|
+
type: "button",
|
|
482
|
+
"aria-label": `Remove ${f.label}`,
|
|
483
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
484
|
+
onClick: (e) => {
|
|
485
|
+
e.stopPropagation();
|
|
486
|
+
removeField(f.id);
|
|
487
|
+
},
|
|
488
|
+
style: {
|
|
489
|
+
position: "absolute",
|
|
490
|
+
left: `${(geom.x + geom.w) * 100}%`,
|
|
491
|
+
top: `${geom.y * 100}%`,
|
|
492
|
+
transform: "translate(-50%, -50%)",
|
|
493
|
+
marginTop: -18,
|
|
494
|
+
width: 22,
|
|
495
|
+
height: 22,
|
|
496
|
+
borderRadius: "50%",
|
|
497
|
+
background: primaryColor,
|
|
498
|
+
color: "#fff",
|
|
499
|
+
border: "2px solid #fff",
|
|
500
|
+
boxShadow: "0 1px 3px rgba(0,0,0,0.3)",
|
|
501
|
+
fontSize: 14,
|
|
502
|
+
lineHeight: "16px",
|
|
503
|
+
cursor: "pointer",
|
|
504
|
+
padding: 0,
|
|
505
|
+
touchAction: "none"
|
|
506
|
+
},
|
|
507
|
+
children: "\xD7"
|
|
508
|
+
}
|
|
509
|
+
)
|
|
510
|
+
] }) : null
|
|
511
|
+
] }, f.id);
|
|
512
|
+
}),
|
|
513
|
+
drag?.mode === "new" && live ? /* @__PURE__ */ jsx(
|
|
514
|
+
"div",
|
|
515
|
+
{
|
|
516
|
+
style: {
|
|
517
|
+
position: "absolute",
|
|
518
|
+
left: `${live.x * 100}%`,
|
|
519
|
+
top: `${live.y * 100}%`,
|
|
520
|
+
width: `${live.w * 100}%`,
|
|
521
|
+
height: `${live.h * 100}%`,
|
|
522
|
+
border: `2px dashed ${primaryColor}`,
|
|
523
|
+
background: `${primaryColor}22`,
|
|
524
|
+
borderRadius: 3,
|
|
525
|
+
pointerEvents: "none"
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
) : null
|
|
529
|
+
]
|
|
530
|
+
}
|
|
531
|
+
)
|
|
532
|
+
] }),
|
|
533
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: "1 1 200px", minWidth: 180, maxWidth: 300 }, children: [
|
|
534
|
+
/* @__PURE__ */ jsxs("p", { style: { fontSize: 13, fontWeight: 600, color: "#374151", margin: "0 0 8px" }, children: [
|
|
535
|
+
"Signature fields (",
|
|
536
|
+
value.length,
|
|
537
|
+
")"
|
|
538
|
+
] }),
|
|
539
|
+
value.length === 0 ? /* @__PURE__ */ jsx("p", { style: { fontSize: 13, color: "#6b7280" }, children: "Draw a box on the page to add a field. Add as many as you need." }) : /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: value.map((f) => /* @__PURE__ */ jsxs(
|
|
540
|
+
"div",
|
|
541
|
+
{
|
|
542
|
+
onClick: () => {
|
|
543
|
+
setSelectedId(f.id);
|
|
544
|
+
setPage(f.page);
|
|
545
|
+
},
|
|
546
|
+
style: {
|
|
547
|
+
display: "flex",
|
|
548
|
+
alignItems: "center",
|
|
549
|
+
gap: 6,
|
|
550
|
+
padding: "6px 8px",
|
|
551
|
+
borderRadius: 8,
|
|
552
|
+
border: `1px solid ${f.id === selectedId ? primaryColor : "#e5e7eb"}`,
|
|
553
|
+
background: f.id === selectedId ? `${primaryColor}0f` : "#fff",
|
|
554
|
+
cursor: "pointer"
|
|
555
|
+
},
|
|
556
|
+
children: [
|
|
557
|
+
/* @__PURE__ */ jsx(
|
|
558
|
+
"input",
|
|
559
|
+
{
|
|
560
|
+
value: f.label,
|
|
561
|
+
onClick: (e) => e.stopPropagation(),
|
|
562
|
+
onChange: (e) => rename(f.id, e.target.value),
|
|
563
|
+
placeholder: "Field name",
|
|
564
|
+
style: {
|
|
565
|
+
flex: 1,
|
|
566
|
+
minWidth: 0,
|
|
567
|
+
border: "none",
|
|
568
|
+
outline: "none",
|
|
569
|
+
background: "transparent",
|
|
570
|
+
fontSize: 13
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
),
|
|
574
|
+
/* @__PURE__ */ jsxs("span", { style: { fontSize: 11, color: "#9ca3af" }, children: [
|
|
575
|
+
"p",
|
|
576
|
+
f.page
|
|
577
|
+
] }),
|
|
578
|
+
/* @__PURE__ */ jsx(
|
|
579
|
+
"button",
|
|
580
|
+
{
|
|
581
|
+
type: "button",
|
|
582
|
+
"aria-label": `Remove ${f.label}`,
|
|
583
|
+
onClick: (e) => {
|
|
584
|
+
e.stopPropagation();
|
|
585
|
+
removeField(f.id);
|
|
586
|
+
},
|
|
587
|
+
style: {
|
|
588
|
+
border: "none",
|
|
589
|
+
background: "transparent",
|
|
590
|
+
color: "#9ca3af",
|
|
591
|
+
cursor: "pointer",
|
|
592
|
+
fontSize: 16,
|
|
593
|
+
lineHeight: 1,
|
|
594
|
+
padding: 0
|
|
595
|
+
},
|
|
596
|
+
children: "\xD7"
|
|
597
|
+
}
|
|
598
|
+
)
|
|
599
|
+
]
|
|
600
|
+
},
|
|
601
|
+
f.id
|
|
602
|
+
)) })
|
|
603
|
+
] })
|
|
604
|
+
] });
|
|
605
|
+
}
|
|
237
606
|
function SigningExperience(props) {
|
|
238
607
|
const primary = props.branding?.primaryColor ?? "#4f46e5";
|
|
239
608
|
const [signaturePng, setSignaturePng] = useState(null);
|
|
@@ -287,7 +656,7 @@ function SigningExperience(props) {
|
|
|
287
656
|
PdfViewer,
|
|
288
657
|
{
|
|
289
658
|
url: props.sourceUrl,
|
|
290
|
-
|
|
659
|
+
placements: props.placements,
|
|
291
660
|
workerSrc: props.workerSrc,
|
|
292
661
|
primaryColor: primary
|
|
293
662
|
}
|
|
@@ -337,6 +706,6 @@ function SigningExperience(props) {
|
|
|
337
706
|
);
|
|
338
707
|
}
|
|
339
708
|
|
|
340
|
-
export { ConsentBlock, PdfViewer, SignaturePad, SigningExperience };
|
|
709
|
+
export { ConsentBlock, FieldDesigner, PdfViewer, SignaturePad, SigningExperience };
|
|
341
710
|
//# sourceMappingURL=index.js.map
|
|
342
711
|
//# sourceMappingURL=index.js.map
|