@embedpdf/plugin-signature 2.15.0 → 3.0.0-next.13
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/LICENSE +192 -21
- package/README.md +38 -0
- package/dist/contract-BvHa9Zl_.d.cts +176 -0
- package/dist/contract-C3nQtwGf.js +14 -0
- package/dist/contract-C3nQtwGf.js.map +1 -0
- package/dist/contract-CojqGdMH.cjs +43 -0
- package/dist/contract-CojqGdMH.cjs.map +1 -0
- package/dist/contract-Dg50puf7.d.ts +176 -0
- package/dist/contract.cjs +7 -0
- package/dist/contract.d.cts +2 -0
- package/dist/contract.d.ts +2 -0
- package/dist/contract.js +2 -0
- package/dist/index.cjs +498 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -0
- package/dist/index.d.ts +35 -1
- package/dist/index.js +450 -511
- package/dist/index.js.map +1 -1
- package/package.json +28 -58
- package/dist/lib/actions.d.ts +0 -14
- package/dist/lib/handlers/signature-ink.handler.d.ts +0 -4
- package/dist/lib/handlers/signature-stamp.handler.d.ts +0 -4
- package/dist/lib/index.d.ts +0 -12
- package/dist/lib/manifest.d.ts +0 -4
- package/dist/lib/reducer.d.ts +0 -5
- package/dist/lib/serialization.d.ts +0 -30
- package/dist/lib/signature-plugin.d.ts +0 -27
- package/dist/lib/tools.d.ts +0 -113
- package/dist/lib/types.d.ts +0 -114
- package/dist/preact/adapter.d.ts +0 -5
- package/dist/preact/annotation.d.ts +0 -1
- package/dist/preact/core.d.ts +0 -1
- package/dist/preact/index.cjs +0 -2
- package/dist/preact/index.cjs.map +0 -1
- package/dist/preact/index.d.ts +0 -1
- package/dist/preact/index.js +0 -464
- package/dist/preact/index.js.map +0 -1
- package/dist/react/adapter.d.ts +0 -2
- package/dist/react/annotation.d.ts +0 -1
- package/dist/react/core.d.ts +0 -1
- package/dist/react/index.cjs +0 -2
- package/dist/react/index.cjs.map +0 -1
- package/dist/react/index.d.ts +0 -1
- package/dist/react/index.js +0 -463
- package/dist/react/index.js.map +0 -1
- package/dist/shared/components/crop-canvas.d.ts +0 -14
- package/dist/shared/components/index.d.ts +0 -2
- package/dist/shared/components/signature-draw-pad.d.ts +0 -12
- package/dist/shared/components/signature-type-pad.d.ts +0 -14
- package/dist/shared/hooks/index.d.ts +0 -2
- package/dist/shared/hooks/use-signature-upload.d.ts +0 -21
- package/dist/shared/hooks/use-signature.d.ts +0 -16
- package/dist/shared/index.d.ts +0 -4
- package/dist/shared-preact/components/crop-canvas.d.ts +0 -14
- package/dist/shared-preact/components/index.d.ts +0 -2
- package/dist/shared-preact/components/signature-draw-pad.d.ts +0 -12
- package/dist/shared-preact/components/signature-type-pad.d.ts +0 -14
- package/dist/shared-preact/hooks/index.d.ts +0 -2
- package/dist/shared-preact/hooks/use-signature-upload.d.ts +0 -21
- package/dist/shared-preact/hooks/use-signature.d.ts +0 -16
- package/dist/shared-preact/index.d.ts +0 -4
- package/dist/shared-react/components/crop-canvas.d.ts +0 -14
- package/dist/shared-react/components/index.d.ts +0 -2
- package/dist/shared-react/components/signature-draw-pad.d.ts +0 -12
- package/dist/shared-react/components/signature-type-pad.d.ts +0 -14
- package/dist/shared-react/hooks/index.d.ts +0 -2
- package/dist/shared-react/hooks/use-signature-upload.d.ts +0 -21
- package/dist/shared-react/hooks/use-signature.d.ts +0 -16
- package/dist/shared-react/index.d.ts +0 -4
- package/dist/shared-vue/components/crop-canvas.d.ts +0 -14
- package/dist/svelte/components/SignatureDrawPad.svelte.d.ts +0 -12
- package/dist/svelte/components/SignatureTypePad.svelte.d.ts +0 -14
- package/dist/svelte/components/index.d.ts +0 -2
- package/dist/svelte/hooks/index.d.ts +0 -2
- package/dist/svelte/hooks/use-signature-upload.svelte.d.ts +0 -21
- package/dist/svelte/hooks/use-signature.svelte.d.ts +0 -17
- package/dist/svelte/index.cjs +0 -2
- package/dist/svelte/index.cjs.map +0 -1
- package/dist/svelte/index.d.ts +0 -4
- package/dist/svelte/index.js +0 -415
- package/dist/svelte/index.js.map +0 -1
- package/dist/vue/components/SignatureDrawPad.vue.d.ts +0 -15
- package/dist/vue/components/SignatureTypePad.vue.d.ts +0 -19
- package/dist/vue/components/index.d.ts +0 -2
- package/dist/vue/hooks/index.d.ts +0 -2
- package/dist/vue/hooks/use-signature-upload.d.ts +0 -20
- package/dist/vue/hooks/use-signature.d.ts +0 -176
- package/dist/vue/index.cjs +0 -2
- package/dist/vue/index.cjs.map +0 -1
- package/dist/vue/index.d.ts +0 -4
- package/dist/vue/index.js +0 -453
- package/dist/vue/index.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,498 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_contract = require("./contract-CojqGdMH.cjs");
|
|
3
|
+
let _embedpdf_core = require("@embedpdf/core");
|
|
4
|
+
let _embedpdf_plugin_form_contract = require("@embedpdf/plugin-form/contract");
|
|
5
|
+
let _embedpdf_plugin_interaction_contract = require("@embedpdf/plugin-interaction/contract");
|
|
6
|
+
let _embedpdf_plugin_stamp_contract = require("@embedpdf/plugin-stamp/contract");
|
|
7
|
+
let _embedpdf_plugin_annotation_contract = require("@embedpdf/plugin-annotation/contract");
|
|
8
|
+
let _embedpdf_core_signature = require("@embedpdf/core-signature");
|
|
9
|
+
let _embedpdf_engine_core_runtime = require("@embedpdf/engine-core/runtime");
|
|
10
|
+
//#region src/blank-page.ts
|
|
11
|
+
const OBJECTS = [
|
|
12
|
+
"<< /Type /Catalog /Pages 2 0 R >>",
|
|
13
|
+
"<< /Type /Pages /Kids [3 0 R] /Count 1 >>",
|
|
14
|
+
"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 60] /Contents 4 0 R /Resources << >> >>",
|
|
15
|
+
`<< /Length 3 >>\nstream\nq Q\nendstream`
|
|
16
|
+
];
|
|
17
|
+
let cached = null;
|
|
18
|
+
function blankPagePdf() {
|
|
19
|
+
if (cached) return new Uint8Array(cached);
|
|
20
|
+
let body = "%PDF-1.7\n";
|
|
21
|
+
const offsets = [];
|
|
22
|
+
OBJECTS.forEach((object, index) => {
|
|
23
|
+
offsets.push(body.length);
|
|
24
|
+
body += `${index + 1} 0 obj\n${object}\nendobj\n`;
|
|
25
|
+
});
|
|
26
|
+
const xref = body.length;
|
|
27
|
+
body += `xref\n0 ${OBJECTS.length + 1}\n0000000000 65535 f \n`;
|
|
28
|
+
for (const offset of offsets) body += `${String(offset).padStart(10, "0")} 00000 n \n`;
|
|
29
|
+
body += `trailer\n<< /Size ${OBJECTS.length + 1} /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`;
|
|
30
|
+
cached = new TextEncoder().encode(body);
|
|
31
|
+
return new Uint8Array(cached);
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/capability.ts
|
|
35
|
+
const sameRef = (a, b) => a.kind === "objectNumber" && b.kind === "objectNumber" ? a.fieldObjectNumber === b.fieldObjectNumber : a.kind === "fqn" && b.kind === "fqn" ? a.name === b.name : false;
|
|
36
|
+
const sameProtection = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
37
|
+
function createSignatureCapability(ctx, config = {}) {
|
|
38
|
+
const form = ctx.get(_embedpdf_plugin_form_contract.FormToken);
|
|
39
|
+
const changed = (0, _embedpdf_core.createEventHook)((error) => globalThis.console?.error("[signature] listener failed:", error));
|
|
40
|
+
ctx.cleanup(() => changed.dispose());
|
|
41
|
+
const state = () => ctx.getState();
|
|
42
|
+
const requireDoc = () => {
|
|
43
|
+
const doc = ctx.doc;
|
|
44
|
+
if (!doc) throw new Error("[signature] no document bound");
|
|
45
|
+
return doc;
|
|
46
|
+
};
|
|
47
|
+
const requireSignatures = () => {
|
|
48
|
+
const doc = requireDoc();
|
|
49
|
+
if (!doc.signatures) throw new Error("[signature] this engine does not implement signatures");
|
|
50
|
+
return {
|
|
51
|
+
doc,
|
|
52
|
+
signatures: doc.signatures
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const stamp = () => ctx.tryGet(_embedpdf_plugin_stamp_contract.StampToken);
|
|
56
|
+
const documentId = () => {
|
|
57
|
+
const id = ctx.documentId;
|
|
58
|
+
if (!id) throw new Error("[signature] no document id");
|
|
59
|
+
return id;
|
|
60
|
+
};
|
|
61
|
+
const mode = () => config.mode ?? (config.signer ? "sign" : "visual");
|
|
62
|
+
const resolveSigner = async () => {
|
|
63
|
+
const signer = config.signer;
|
|
64
|
+
if (!signer) throw new Error("[signature] no signer configured (mode \"sign\" needs one)");
|
|
65
|
+
return typeof signer === "function" ? signer() : signer;
|
|
66
|
+
};
|
|
67
|
+
const allows = (cap) => ctx.doc?.security.allows(cap) ?? false;
|
|
68
|
+
const refresh = async () => {
|
|
69
|
+
const doc = ctx.doc;
|
|
70
|
+
if (!doc?.signatures) {
|
|
71
|
+
ctx.dispatch({
|
|
72
|
+
type: "SNAPSHOT",
|
|
73
|
+
snapshot: null
|
|
74
|
+
});
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const before = state().snapshot?.protection ?? null;
|
|
78
|
+
const snapshot = await doc.signatures.list();
|
|
79
|
+
ctx.dispatch({
|
|
80
|
+
type: "SNAPSHOT",
|
|
81
|
+
snapshot
|
|
82
|
+
});
|
|
83
|
+
if (!sameProtection(before, snapshot.protection)) changed.emit({
|
|
84
|
+
type: "protectionChanged",
|
|
85
|
+
protection: snapshot.protection
|
|
86
|
+
});
|
|
87
|
+
return snapshot;
|
|
88
|
+
};
|
|
89
|
+
const validate = async (opts) => {
|
|
90
|
+
const doc = ctx.doc;
|
|
91
|
+
if (!doc?.signatures) return [];
|
|
92
|
+
const verdicts = await (0, _embedpdf_core_signature.validateSignatures)(doc, {
|
|
93
|
+
trust: config.trust ?? null,
|
|
94
|
+
at: opts?.at,
|
|
95
|
+
until: opts?.until ?? "working-copy"
|
|
96
|
+
});
|
|
97
|
+
const before = state().verdicts;
|
|
98
|
+
ctx.dispatch({
|
|
99
|
+
type: "VERDICTS",
|
|
100
|
+
verdicts
|
|
101
|
+
});
|
|
102
|
+
changed.emit({
|
|
103
|
+
type: "validated",
|
|
104
|
+
verdicts
|
|
105
|
+
});
|
|
106
|
+
for (const v of verdicts) {
|
|
107
|
+
if (v.modifications.basis !== "working-copy" || v.summary !== "invalid") continue;
|
|
108
|
+
const was = before?.find((b) => b.signature.index === v.signature.index);
|
|
109
|
+
if (was && was.summary === "invalid") continue;
|
|
110
|
+
changed.emit({
|
|
111
|
+
type: "invalidating",
|
|
112
|
+
field: v.signature.field,
|
|
113
|
+
detail: v.modifications.detail ?? ""
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return verdicts;
|
|
117
|
+
};
|
|
118
|
+
let revalidateTimer = null;
|
|
119
|
+
const revalidateSoon = () => {
|
|
120
|
+
if (!state().snapshot?.signatures.some((s) => s.signed)) return;
|
|
121
|
+
if (revalidateTimer) clearTimeout(revalidateTimer);
|
|
122
|
+
revalidateTimer = setTimeout(() => {
|
|
123
|
+
revalidateTimer = null;
|
|
124
|
+
validate().catch((error) => globalThis.console?.error("[signature] re-validation failed:", error));
|
|
125
|
+
}, 300);
|
|
126
|
+
};
|
|
127
|
+
ctx.cleanup(() => {
|
|
128
|
+
if (revalidateTimer) clearTimeout(revalidateTimer);
|
|
129
|
+
});
|
|
130
|
+
const analyze = (input) => requireSignatures().signatures.analyze(input);
|
|
131
|
+
const signatureOf = (field) => {
|
|
132
|
+
const snapshot = state().snapshot;
|
|
133
|
+
if (!snapshot) return null;
|
|
134
|
+
if ("annotObjectNumber" in field) {
|
|
135
|
+
const byWidget = snapshot.signatures.find((s) => s.widget?.annotObjectNumber === field.annotObjectNumber);
|
|
136
|
+
if (byWidget) return byWidget;
|
|
137
|
+
const owner = form.fieldForWidget(field.annotObjectNumber);
|
|
138
|
+
return owner ? signatureOf(owner.ref) : null;
|
|
139
|
+
}
|
|
140
|
+
return snapshot.signatures.find((s) => field.kind === "fqn" ? s.fieldName === field.name : sameRef(s.field, field)) ?? null;
|
|
141
|
+
};
|
|
142
|
+
const verdictOf = (field) => {
|
|
143
|
+
const signature = signatureOf(field);
|
|
144
|
+
if (!signature) return null;
|
|
145
|
+
return state().verdicts?.find((v) => v.signature.index === signature.index) ?? null;
|
|
146
|
+
};
|
|
147
|
+
const bytesOf = async (source) => new Uint8Array((await (0, _embedpdf_engine_core_runtime.resolveBinarySource)(source)).bytes);
|
|
148
|
+
const markBytes = async (mark) => {
|
|
149
|
+
if ("assetId" in mark) {
|
|
150
|
+
const bytes = stamp()?.assetBytes(mark.assetId);
|
|
151
|
+
if (!bytes) throw new Error(`[signature] unknown mark '${mark.assetId}'`);
|
|
152
|
+
return bytes;
|
|
153
|
+
}
|
|
154
|
+
return bytesOf(mark.source);
|
|
155
|
+
};
|
|
156
|
+
const withBusy = async (work) => {
|
|
157
|
+
ctx.dispatch({
|
|
158
|
+
type: "BUSY",
|
|
159
|
+
busy: true
|
|
160
|
+
});
|
|
161
|
+
try {
|
|
162
|
+
return await work();
|
|
163
|
+
} finally {
|
|
164
|
+
ctx.dispatch({
|
|
165
|
+
type: "BUSY",
|
|
166
|
+
busy: false
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const signField = (input) => withBusy(async () => {
|
|
171
|
+
const { doc } = requireSignatures();
|
|
172
|
+
const signer = await resolveSigner();
|
|
173
|
+
const subject = signer.kind === "raw" && signer.certificateChain[0] ? (0, _embedpdf_core_signature.certificateCommonName)(signer.certificateChain[0]) : null;
|
|
174
|
+
const attribution = {
|
|
175
|
+
...subject ? { name: subject } : {},
|
|
176
|
+
...input.attribution
|
|
177
|
+
};
|
|
178
|
+
const appearance = input.appearance ? await bytesOf(input.appearance) : await markBytes(input.mark);
|
|
179
|
+
const result = await (0, _embedpdf_core_signature.sign)(doc, {
|
|
180
|
+
field: input.field,
|
|
181
|
+
signer,
|
|
182
|
+
attribution,
|
|
183
|
+
certify: input.certify,
|
|
184
|
+
lock: input.lock,
|
|
185
|
+
appearance: {
|
|
186
|
+
pdf: appearance,
|
|
187
|
+
pageIndex: 0
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
if (state().target && sameRef(state().target, input.field)) setTarget(null);
|
|
191
|
+
await refresh();
|
|
192
|
+
validate().catch((error) => globalThis.console?.error("[signature] validation after signing failed:", error));
|
|
193
|
+
changed.emit({
|
|
194
|
+
type: "signed",
|
|
195
|
+
field: input.field,
|
|
196
|
+
result
|
|
197
|
+
});
|
|
198
|
+
return result;
|
|
199
|
+
});
|
|
200
|
+
const setAppearance = async (field, pdf) => {
|
|
201
|
+
const doc = requireDoc();
|
|
202
|
+
if (!doc.forms.setSignatureAppearance) throw new Error("[signature] this engine cannot draw into a signature field");
|
|
203
|
+
const signature = signatureOf(field);
|
|
204
|
+
if (signature?.signed) throw new Error(`[signature] '${signature.fieldName}' is signed`);
|
|
205
|
+
await doc.forms.setSignatureAppearance(field, {
|
|
206
|
+
pdf,
|
|
207
|
+
pageIndex: 0
|
|
208
|
+
});
|
|
209
|
+
await form.refresh();
|
|
210
|
+
};
|
|
211
|
+
const fillField = (field, mark) => withBusy(async () => {
|
|
212
|
+
await setAppearance(field, await markBytes(mark));
|
|
213
|
+
if (state().target && sameRef(state().target, field)) setTarget(null);
|
|
214
|
+
changed.emit({
|
|
215
|
+
type: "filled",
|
|
216
|
+
field
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
const clearField = (field) => withBusy(async () => {
|
|
220
|
+
await setAppearance(field, blankPagePdf());
|
|
221
|
+
changed.emit({
|
|
222
|
+
type: "cleared",
|
|
223
|
+
field
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
const placeMark = async (mark, target) => {
|
|
227
|
+
if (!("field" in target)) {
|
|
228
|
+
if ("assetId" in mark) {
|
|
229
|
+
const library = stamp();
|
|
230
|
+
if (!library) throw new Error("[signature] no stamp plugin to place an asset");
|
|
231
|
+
await library.placeAsset(documentId(), mark.assetId, target);
|
|
232
|
+
} else await ctx.get(_embedpdf_plugin_annotation_contract.AnnotationToken).placeStamp({ source: mark.source }, target);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
switch (mode()) {
|
|
236
|
+
case "sign":
|
|
237
|
+
if (config.allowCertify && !state().snapshot?.signatures.some((s) => s.signed)) {
|
|
238
|
+
changed.emit({
|
|
239
|
+
type: "ask",
|
|
240
|
+
field: target.field,
|
|
241
|
+
mark
|
|
242
|
+
});
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
await signField({
|
|
246
|
+
field: target.field,
|
|
247
|
+
mark
|
|
248
|
+
});
|
|
249
|
+
return;
|
|
250
|
+
case "visual":
|
|
251
|
+
await fillField(target.field, mark);
|
|
252
|
+
return;
|
|
253
|
+
case "ask":
|
|
254
|
+
changed.emit({
|
|
255
|
+
type: "ask",
|
|
256
|
+
field: target.field,
|
|
257
|
+
mark
|
|
258
|
+
});
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
const setTarget = (field) => {
|
|
263
|
+
const current = state().target;
|
|
264
|
+
if (current === field || current && field && sameRef(current, field)) return;
|
|
265
|
+
ctx.dispatch({
|
|
266
|
+
type: "TARGET",
|
|
267
|
+
field
|
|
268
|
+
});
|
|
269
|
+
changed.emit({
|
|
270
|
+
type: "target",
|
|
271
|
+
field
|
|
272
|
+
});
|
|
273
|
+
};
|
|
274
|
+
const doc = ctx.doc;
|
|
275
|
+
if (doc) {
|
|
276
|
+
const unsubscribe = doc.events.subscribe((event) => {
|
|
277
|
+
switch (event.type) {
|
|
278
|
+
case "signature.prepared":
|
|
279
|
+
ctx.dispatch({
|
|
280
|
+
type: "PENDING",
|
|
281
|
+
pending: {
|
|
282
|
+
signingId: event.signingId,
|
|
283
|
+
field: event.field
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
return;
|
|
287
|
+
case "signature.aborted":
|
|
288
|
+
ctx.dispatch({
|
|
289
|
+
type: "PENDING",
|
|
290
|
+
pending: null
|
|
291
|
+
});
|
|
292
|
+
return;
|
|
293
|
+
case "signature.completed":
|
|
294
|
+
ctx.dispatch({
|
|
295
|
+
type: "PENDING",
|
|
296
|
+
pending: null
|
|
297
|
+
});
|
|
298
|
+
return;
|
|
299
|
+
case "document.versioned":
|
|
300
|
+
case "stream.desynced":
|
|
301
|
+
refresh().then(() => validate()).catch((error) => globalThis.console?.error("[signature] refresh failed:", error));
|
|
302
|
+
return;
|
|
303
|
+
case "form.fieldCreated":
|
|
304
|
+
case "form.fieldDeleted":
|
|
305
|
+
case "form.widgetAttached":
|
|
306
|
+
case "form.widgetDetached":
|
|
307
|
+
case "form.imported":
|
|
308
|
+
case "form.repaired":
|
|
309
|
+
refresh().then(() => revalidateSoon()).catch((error) => globalThis.console?.error("[signature] refresh failed:", error));
|
|
310
|
+
return;
|
|
311
|
+
case "annotation.created":
|
|
312
|
+
case "annotation.updated":
|
|
313
|
+
case "annotation.deleted":
|
|
314
|
+
case "annotation.moved":
|
|
315
|
+
case "form.valueChanged":
|
|
316
|
+
case "form.fieldUpdated":
|
|
317
|
+
case "form.effectsApplied":
|
|
318
|
+
revalidateSoon();
|
|
319
|
+
return;
|
|
320
|
+
default: return;
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
ctx.cleanup(unsubscribe);
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
snapshot: () => state().snapshot,
|
|
327
|
+
verdicts: () => state().verdicts,
|
|
328
|
+
protection: () => state().snapshot?.protection ?? null,
|
|
329
|
+
pending: () => state().pending,
|
|
330
|
+
target: () => state().target,
|
|
331
|
+
busy: () => state().busy,
|
|
332
|
+
mode,
|
|
333
|
+
signatureOf,
|
|
334
|
+
verdictOf,
|
|
335
|
+
canSign: () => allows("doc.sign") && config.signer != null,
|
|
336
|
+
canFill: () => allows("doc.forms.fill") && ctx.doc?.forms.setSignatureAppearance != null,
|
|
337
|
+
canCertify: () => config.allowCertify === true && allows("doc.sign.certify"),
|
|
338
|
+
signField,
|
|
339
|
+
fillField,
|
|
340
|
+
clearField,
|
|
341
|
+
placeMark,
|
|
342
|
+
setTarget,
|
|
343
|
+
inspect: (field) => changed.emit({
|
|
344
|
+
type: "inspect",
|
|
345
|
+
field
|
|
346
|
+
}),
|
|
347
|
+
refresh,
|
|
348
|
+
validate,
|
|
349
|
+
analyze,
|
|
350
|
+
revisionBytes: (revisionIndex) => requireSignatures().signatures.revisionBytes(revisionIndex),
|
|
351
|
+
onChanged: changed.on
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/handler.ts
|
|
356
|
+
/**
|
|
357
|
+
* The armed mark over a field. The annotation plugin places an armed stamp
|
|
358
|
+
* on click (`annotation-place`, priority 95) and selects an existing
|
|
359
|
+
* annotation under the pointer before that (`annotation-edit`, 100 — a
|
|
360
|
+
* widget is an annotation). This handler sits above BOTH, enabled for the
|
|
361
|
+
* armed stamp's tool only, and captures exactly when the armed asset is a
|
|
362
|
+
* person's mark (a library of kind `signatures`) and the pointer is over a
|
|
363
|
+
* signature field: then the destination decides — the mark goes INTO the
|
|
364
|
+
* field (`placeMark` by mode) instead of onto the page. Everywhere else it
|
|
365
|
+
* declines and the click stays a stamp placement, as in Preview.
|
|
366
|
+
*/
|
|
367
|
+
function createArmedMarkHandler(documentId, signature, form, stamp) {
|
|
368
|
+
return {
|
|
369
|
+
id: "signature:armed-mark-on-field",
|
|
370
|
+
priority: _embedpdf_plugin_annotation_contract.ANNOTATION_EDIT_PRIORITY + 1,
|
|
371
|
+
enabledFor: (tool) => tool.id === _embedpdf_plugin_annotation_contract.ARMED_STAMP_TOOL_ID,
|
|
372
|
+
onDown: (sample) => {
|
|
373
|
+
if (!sample.page) return false;
|
|
374
|
+
const armed = stamp.armedAsset(documentId);
|
|
375
|
+
if (!armed || stamp.library(armed.libraryId)?.kind !== "signatures") return false;
|
|
376
|
+
const hit = form.widgetAt(sample.page.pon, sample.page.point);
|
|
377
|
+
if (!hit || hit.field.family !== "signature") return false;
|
|
378
|
+
if (signature.signatureOf(hit.field.ref)?.signed || hit.field.valueEntry.kind !== "none") return true;
|
|
379
|
+
stamp.disarm(documentId);
|
|
380
|
+
signature.placeMark({ assetId: armed.id }, { field: hit.field.ref }).catch((error) => globalThis.console?.error("[signature] placing the mark failed:", error));
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
//#endregion
|
|
386
|
+
//#region src/reducer.ts
|
|
387
|
+
const initialSignatureState = () => ({
|
|
388
|
+
snapshot: null,
|
|
389
|
+
verdicts: null,
|
|
390
|
+
target: null,
|
|
391
|
+
pending: null,
|
|
392
|
+
busy: false
|
|
393
|
+
});
|
|
394
|
+
function signatureReducer(state, action) {
|
|
395
|
+
switch (action.type) {
|
|
396
|
+
case "SNAPSHOT": return {
|
|
397
|
+
...state,
|
|
398
|
+
snapshot: action.snapshot
|
|
399
|
+
};
|
|
400
|
+
case "VERDICTS": return {
|
|
401
|
+
...state,
|
|
402
|
+
verdicts: action.verdicts
|
|
403
|
+
};
|
|
404
|
+
case "TARGET": return {
|
|
405
|
+
...state,
|
|
406
|
+
target: action.field
|
|
407
|
+
};
|
|
408
|
+
case "PENDING": return {
|
|
409
|
+
...state,
|
|
410
|
+
pending: action.pending
|
|
411
|
+
};
|
|
412
|
+
case "BUSY": return {
|
|
413
|
+
...state,
|
|
414
|
+
busy: action.busy
|
|
415
|
+
};
|
|
416
|
+
default: return state;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
//#endregion
|
|
420
|
+
//#region src/signature.plugin.ts
|
|
421
|
+
/**
|
|
422
|
+
* The signature plugin — the ACT of signing, document-scoped. It owns no
|
|
423
|
+
* mark: marks are stamp-library assets (or bytes the embedder brings), and
|
|
424
|
+
* the mark IS the appearance the engine draws into the field. Signing goes
|
|
425
|
+
* through `@embedpdf/core-signature` with the configured signer port; the
|
|
426
|
+
* engine seals; on the cloud the server publishes the new version.
|
|
427
|
+
*
|
|
428
|
+
* With the interaction hub and the stamp plugin present, an armed mark from
|
|
429
|
+
* a `signatures` library dropped over an unsigned signature field goes into
|
|
430
|
+
* the field (sign / visual fill / ask, by mode) instead of onto the page.
|
|
431
|
+
*/
|
|
432
|
+
const signaturePlugin = (config = {}) => (0, _embedpdf_core.definePlugin)({
|
|
433
|
+
id: "signature",
|
|
434
|
+
token: require_contract.SignatureToken,
|
|
435
|
+
scope: "document",
|
|
436
|
+
requires: [_embedpdf_plugin_form_contract.FormToken],
|
|
437
|
+
optional: [
|
|
438
|
+
_embedpdf_plugin_interaction_contract.InteractionToken,
|
|
439
|
+
_embedpdf_plugin_stamp_contract.StampToken,
|
|
440
|
+
_embedpdf_plugin_annotation_contract.AnnotationToken
|
|
441
|
+
],
|
|
442
|
+
initialState: initialSignatureState,
|
|
443
|
+
reduce: signatureReducer,
|
|
444
|
+
capability: (ctx) => createSignatureCapability(ctx, config),
|
|
445
|
+
init: (ctx) => {
|
|
446
|
+
const signature = ctx.get(require_contract.SignatureToken);
|
|
447
|
+
signature.refresh().then((snapshot) => snapshot?.signatures.some((s) => s.signed) ? signature.validate() : null).catch((error) => globalThis.console?.error("[signature] initial read failed:", error));
|
|
448
|
+
const interaction = ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken);
|
|
449
|
+
const stamp = ctx.tryGet(_embedpdf_plugin_stamp_contract.StampToken);
|
|
450
|
+
if (interaction && stamp && ctx.documentId) ctx.cleanup(interaction.registerHandler(createArmedMarkHandler(ctx.documentId, signature, ctx.get(_embedpdf_plugin_form_contract.FormToken), stamp)));
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
//#endregion
|
|
454
|
+
exports.INITIALS_MARK_NAME = require_contract.INITIALS_MARK_NAME;
|
|
455
|
+
exports.SIGNATURES_LIBRARY_KIND = require_contract.SIGNATURES_LIBRARY_KIND;
|
|
456
|
+
exports.SIGNATURE_MARK_NAME = require_contract.SIGNATURE_MARK_NAME;
|
|
457
|
+
exports.SignatureToken = require_contract.SignatureToken;
|
|
458
|
+
exports.createArmedMarkHandler = createArmedMarkHandler;
|
|
459
|
+
Object.defineProperty(exports, "createTestSigner", {
|
|
460
|
+
enumerable: true,
|
|
461
|
+
get: function() {
|
|
462
|
+
return _embedpdf_core_signature.createTestSigner;
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
Object.defineProperty(exports, "indexedDbKeyStore", {
|
|
466
|
+
enumerable: true,
|
|
467
|
+
get: function() {
|
|
468
|
+
return _embedpdf_core_signature.indexedDbKeyStore;
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
exports.markRoleOf = require_contract.markRoleOf;
|
|
472
|
+
Object.defineProperty(exports, "memoryKeyStore", {
|
|
473
|
+
enumerable: true,
|
|
474
|
+
get: function() {
|
|
475
|
+
return _embedpdf_core_signature.memoryKeyStore;
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
Object.defineProperty(exports, "personalSigner", {
|
|
479
|
+
enumerable: true,
|
|
480
|
+
get: function() {
|
|
481
|
+
return _embedpdf_core_signature.personalSigner;
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
Object.defineProperty(exports, "remoteSigner", {
|
|
485
|
+
enumerable: true,
|
|
486
|
+
get: function() {
|
|
487
|
+
return _embedpdf_core_signature.remoteSigner;
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
exports.signaturePlugin = signaturePlugin;
|
|
491
|
+
Object.defineProperty(exports, "webCryptoSigner", {
|
|
492
|
+
enumerable: true,
|
|
493
|
+
get: function() {
|
|
494
|
+
return _embedpdf_core_signature.webCryptoSigner;
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
//# sourceMappingURL=index.cjs.map
|