@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.
Files changed (92) hide show
  1. package/LICENSE +192 -21
  2. package/README.md +38 -0
  3. package/dist/contract-BvHa9Zl_.d.cts +176 -0
  4. package/dist/contract-C3nQtwGf.js +14 -0
  5. package/dist/contract-C3nQtwGf.js.map +1 -0
  6. package/dist/contract-CojqGdMH.cjs +43 -0
  7. package/dist/contract-CojqGdMH.cjs.map +1 -0
  8. package/dist/contract-Dg50puf7.d.ts +176 -0
  9. package/dist/contract.cjs +7 -0
  10. package/dist/contract.d.cts +2 -0
  11. package/dist/contract.d.ts +2 -0
  12. package/dist/contract.js +2 -0
  13. package/dist/index.cjs +498 -2
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +35 -0
  16. package/dist/index.d.ts +35 -1
  17. package/dist/index.js +450 -511
  18. package/dist/index.js.map +1 -1
  19. package/package.json +28 -58
  20. package/dist/lib/actions.d.ts +0 -14
  21. package/dist/lib/handlers/signature-ink.handler.d.ts +0 -4
  22. package/dist/lib/handlers/signature-stamp.handler.d.ts +0 -4
  23. package/dist/lib/index.d.ts +0 -12
  24. package/dist/lib/manifest.d.ts +0 -4
  25. package/dist/lib/reducer.d.ts +0 -5
  26. package/dist/lib/serialization.d.ts +0 -30
  27. package/dist/lib/signature-plugin.d.ts +0 -27
  28. package/dist/lib/tools.d.ts +0 -113
  29. package/dist/lib/types.d.ts +0 -114
  30. package/dist/preact/adapter.d.ts +0 -5
  31. package/dist/preact/annotation.d.ts +0 -1
  32. package/dist/preact/core.d.ts +0 -1
  33. package/dist/preact/index.cjs +0 -2
  34. package/dist/preact/index.cjs.map +0 -1
  35. package/dist/preact/index.d.ts +0 -1
  36. package/dist/preact/index.js +0 -464
  37. package/dist/preact/index.js.map +0 -1
  38. package/dist/react/adapter.d.ts +0 -2
  39. package/dist/react/annotation.d.ts +0 -1
  40. package/dist/react/core.d.ts +0 -1
  41. package/dist/react/index.cjs +0 -2
  42. package/dist/react/index.cjs.map +0 -1
  43. package/dist/react/index.d.ts +0 -1
  44. package/dist/react/index.js +0 -463
  45. package/dist/react/index.js.map +0 -1
  46. package/dist/shared/components/crop-canvas.d.ts +0 -14
  47. package/dist/shared/components/index.d.ts +0 -2
  48. package/dist/shared/components/signature-draw-pad.d.ts +0 -12
  49. package/dist/shared/components/signature-type-pad.d.ts +0 -14
  50. package/dist/shared/hooks/index.d.ts +0 -2
  51. package/dist/shared/hooks/use-signature-upload.d.ts +0 -21
  52. package/dist/shared/hooks/use-signature.d.ts +0 -16
  53. package/dist/shared/index.d.ts +0 -4
  54. package/dist/shared-preact/components/crop-canvas.d.ts +0 -14
  55. package/dist/shared-preact/components/index.d.ts +0 -2
  56. package/dist/shared-preact/components/signature-draw-pad.d.ts +0 -12
  57. package/dist/shared-preact/components/signature-type-pad.d.ts +0 -14
  58. package/dist/shared-preact/hooks/index.d.ts +0 -2
  59. package/dist/shared-preact/hooks/use-signature-upload.d.ts +0 -21
  60. package/dist/shared-preact/hooks/use-signature.d.ts +0 -16
  61. package/dist/shared-preact/index.d.ts +0 -4
  62. package/dist/shared-react/components/crop-canvas.d.ts +0 -14
  63. package/dist/shared-react/components/index.d.ts +0 -2
  64. package/dist/shared-react/components/signature-draw-pad.d.ts +0 -12
  65. package/dist/shared-react/components/signature-type-pad.d.ts +0 -14
  66. package/dist/shared-react/hooks/index.d.ts +0 -2
  67. package/dist/shared-react/hooks/use-signature-upload.d.ts +0 -21
  68. package/dist/shared-react/hooks/use-signature.d.ts +0 -16
  69. package/dist/shared-react/index.d.ts +0 -4
  70. package/dist/shared-vue/components/crop-canvas.d.ts +0 -14
  71. package/dist/svelte/components/SignatureDrawPad.svelte.d.ts +0 -12
  72. package/dist/svelte/components/SignatureTypePad.svelte.d.ts +0 -14
  73. package/dist/svelte/components/index.d.ts +0 -2
  74. package/dist/svelte/hooks/index.d.ts +0 -2
  75. package/dist/svelte/hooks/use-signature-upload.svelte.d.ts +0 -21
  76. package/dist/svelte/hooks/use-signature.svelte.d.ts +0 -17
  77. package/dist/svelte/index.cjs +0 -2
  78. package/dist/svelte/index.cjs.map +0 -1
  79. package/dist/svelte/index.d.ts +0 -4
  80. package/dist/svelte/index.js +0 -415
  81. package/dist/svelte/index.js.map +0 -1
  82. package/dist/vue/components/SignatureDrawPad.vue.d.ts +0 -15
  83. package/dist/vue/components/SignatureTypePad.vue.d.ts +0 -19
  84. package/dist/vue/components/index.d.ts +0 -2
  85. package/dist/vue/hooks/index.d.ts +0 -2
  86. package/dist/vue/hooks/use-signature-upload.d.ts +0 -20
  87. package/dist/vue/hooks/use-signature.d.ts +0 -176
  88. package/dist/vue/index.cjs +0 -2
  89. package/dist/vue/index.cjs.map +0 -1
  90. package/dist/vue/index.d.ts +0 -4
  91. package/dist/vue/index.js +0 -453
  92. package/dist/vue/index.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,2 +1,498 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core"),e=require("@embedpdf/models"),i=require("@embedpdf/plugin-annotation");var n=(t=>(t.SignatureOnly="signature-only",t.SignatureAndInitials="signature-and-initials",t))(n||{}),a=(t=>(t.Draw="draw",t.Type="type",t.Upload="upload",t))(a||{}),r=(t=>(t.Signature="signature",t.Initials="initials",t))(r||{});const o="signature",s={id:o,name:"Signature Plugin",version:"1.0.0",provides:["signature"],requires:["annotation"],optional:[],defaultConfig:{mode:n.SignatureOnly}},l="SIGNATURE/ADD_ENTRY",h="SIGNATURE/REMOVE_ENTRY";function c(t){return{type:l,payload:t}}function u(t){return{type:h,payload:t}}const g={annotationType:e.PdfAnnotationSubtype.STAMP,create(t){const{onPreview:n,onCommit:a,getTool:r,pageSize:o,pageRotation:s,getToolContext:l}=t;return{onPointerMove:t=>{const i=l();if(!(null==i?void 0:i.targetSize))return;const{width:a,height:r}=i.targetSize;n({type:e.PdfAnnotationSubtype.STAMP,bounds:{origin:{x:t.x-a/2,y:t.y-r/2},size:{width:a,height:r}},data:{rect:{origin:{x:t.x-a/2,y:t.y-r/2},size:{width:a,height:r}},ghostUrl:i.ghostUrl,pageRotation:s}})},onPointerDown:h=>{var c;const u=r(),g=l();if(!u||!(null==g?void 0:g.targetSize))return;const{width:d,height:p}=g.targetSize,m={origin:{x:h.x-d/2,y:h.y-p/2},size:{width:d,height:p}};let y={...u.defaults,rect:m,type:e.PdfAnnotationSubtype.STAMP,name:e.PdfAnnotationName.Custom,subject:"Signature",flags:u.defaults.flags??["print"],pageIndex:t.pageIndex,id:e.uuidV4(),created:new Date};(null==(c=u.behavior)?void 0:c.insertUpright)&&(y=i.applyInsertUpright(y,s,!1)),y=i.clampAnnotationToPage(y,o),a(y,{data:g.imageData}),n(null)},onPointerLeave:()=>{n(null)}}}};function d(t,e,i){const n=e.width/t.size.width,a=e.height/t.size.height,r=Math.min(n,a),o=t.size.width*r,s=t.size.height*r,l=i.x-o/2,h=i.y-s/2;return{inkList:t.inkList.map(t=>({points:t.points.map(t=>({x:t.x*r+l,y:t.y*r+h}))})),strokeWidth:Math.round(t.strokeWidth*r*10)/10}}const p={annotationType:e.PdfAnnotationSubtype.INK,create(t){const{onPreview:n,onCommit:a,getTool:r,pageSize:o,getToolContext:s}=t;return{onPointerMove:t=>{const i=s();if(!(null==i?void 0:i.inkData)||!(null==i?void 0:i.targetSize))return;const{inkList:a,strokeWidth:r}=d(i.inkData,i.targetSize,t),o=a.flatMap(t=>t.points);if(0===o.length)return;const l=e.expandRect({origin:{x:Math.min(...o.map(t=>t.x)),y:Math.min(...o.map(t=>t.y))},size:{width:Math.max(...o.map(t=>t.x))-Math.min(...o.map(t=>t.x)),height:Math.max(...o.map(t=>t.y))-Math.min(...o.map(t=>t.y))}},r/2);n({type:e.PdfAnnotationSubtype.INK,bounds:l,data:{rect:l,inkList:a,strokeWidth:r,strokeColor:i.inkData.strokeColor,opacity:.5}})},onPointerDown:l=>{const h=r(),c=s();if(!h||!(null==c?void 0:c.inkData)||!(null==c?void 0:c.targetSize))return;const{inkList:u,strokeWidth:g}=d(c.inkData,c.targetSize,l),p=u.flatMap(t=>t.points);if(0===p.length)return;const m=e.expandRect({origin:{x:Math.min(...p.map(t=>t.x)),y:Math.min(...p.map(t=>t.y))},size:{width:Math.max(...p.map(t=>t.x))-Math.min(...p.map(t=>t.x)),height:Math.max(...p.map(t=>t.y))-Math.min(...p.map(t=>t.y))}},g/2);let y={...h.defaults,inkList:u,rect:m,strokeWidth:g,strokeColor:c.inkData.strokeColor,opacity:1,type:e.PdfAnnotationSubtype.INK,subject:"Signature",flags:h.defaults.flags??["print"],pageIndex:t.pageIndex,id:e.uuidV4(),created:new Date};const f=y.rect;y=i.clampAnnotationToPage(y,o);const S=y.rect.origin.x-f.origin.x,v=y.rect.origin.y-f.origin.y;0===S&&0===v||(y={...y,inkList:y.inkList.map(t=>({points:t.points.map(t=>({x:t.x+S,y:t.y+v}))}))}),a(y),n(null)},onPointerLeave:()=>{n(null)}}}},m="signatureStamp",y="signatureInk",f=[i.defineAnnotationTool({id:m,name:"Signature Stamp",labelKey:"signature.stamp",categories:["annotation","signature","insert"],matchScore:()=>0,interaction:{exclusive:!0,cursor:"copy",isDraggable:!0,isResizable:!0,isRotatable:!1,lockAspectRatio:!0,isGroupDraggable:!0,isGroupResizable:!1,isGroupRotatable:!1},defaults:{type:e.PdfAnnotationSubtype.STAMP},behavior:{deactivateToolAfterCreate:!0,selectAfterCreate:!0,insertUpright:!0,useAppearanceStream:!0},pointerHandler:g}),i.defineAnnotationTool({id:y,name:"Signature Ink",labelKey:"signature.ink",categories:["annotation","signature","insert"],matchScore:t=>t.type===e.PdfAnnotationSubtype.INK&&"Signature"===t.subject?20:0,interaction:{exclusive:!0,cursor:"copy",isDraggable:!0,isResizable:!0,isRotatable:!1,lockAspectRatio:!0,isGroupDraggable:!0,isGroupResizable:!1,isGroupRotatable:!1},defaults:{type:e.PdfAnnotationSubtype.INK},behavior:{deactivateToolAfterCreate:!0,selectAfterCreate:!0},transform:i.patching.patchInk,pointerHandler:p})],S=class extends t.BasePlugin{constructor(e,i,n){var a;if(super(e,i),this.config=n,this.entries=new Map,this.entriesChange$=t.createEmitter(),this.activePlacement$=t.createScopedEmitter((t,e)=>({documentId:t,activePlacement:e})),this.annotation=null,this.toolChangeUnsubscribe=null,this.currentGhostUrl=null,this.annotation=(null==(a=i.getPlugin("annotation"))?void 0:a.provides())??null,this.annotation){for(const t of f)this.annotation.addTool(t);this.toolChangeUnsubscribe=this.annotation.onActiveToolChange(({documentId:t,tool:e})=>{(null==e?void 0:e.id)!==m&&(null==e?void 0:e.id)!==y&&(this.revokeGhostUrl(),this.activePlacement$.emit(t,null))})}}async initialize(){}buildCapability(){return{mode:this.config.mode,getEntries:()=>this.getEntries(),addEntry:t=>this.addEntry(t),removeEntry:t=>this.removeEntry(t),loadEntries:t=>this.loadEntries(t),exportEntries:()=>this.exportEntries(),onEntriesChange:this.entriesChange$.on,forDocument:t=>this.createSignatureScope(t),onActivePlacementChange:this.activePlacement$.onGlobal}}getEntries(){return Array.from(this.entries.values())}addEntry(t){const i=e.uuidV4(),n={...t,id:i,createdAt:Date.now()};return this.entries.set(i,n),this.dispatch(c(i)),this.emitEntriesChange(),i}removeEntry(t){this.entries.has(t)&&(this.entries.delete(t),this.dispatch(u(t)),this.emitEntriesChange())}loadEntries(t){for(const e of t)this.entries.set(e.id,e),this.dispatch(c(e.id));this.emitEntriesChange()}exportEntries(){return this.getEntries()}createSignatureScope(t){return{activateSignaturePlacement:e=>this.activatePlacement(t,e,r.Signature),activateInitialsPlacement:e=>this.activatePlacement(t,e,r.Initials),deactivatePlacement:()=>this.deactivatePlacement(t),getActivePlacement:()=>this.activePlacement$.getValue(t)??null,onActivePlacementChange:this.activePlacement$.forScope(t)}}activatePlacement(t,e,i){const n=this.entries.get(e);if(!n||!this.annotation)return;const o=i===r.Initials?n.initials:n.signature;if(o){if(this.revokeGhostUrl(),o.creationType===a.Draw){if(n.signature.creationType!==a.Draw)return;const t=this.config.defaultSize??{width:150,height:50},r=n.signature.inkData.size,s=Math.min(t.width/r.width,t.height/r.height),l={width:o.inkData.size.width*s,height:o.inkData.size.height*s};this.annotation.setActiveTool(y,{inkData:o.inkData,targetSize:l,entryId:e,kind:i})}else{if(!o.imageData)return;const t=URL.createObjectURL(new Blob([o.imageData],{type:o.imageMimeType??"image/png"}));this.currentGhostUrl=t;const r=this.config.defaultSize??{width:150,height:50};let s=r;if(o.imageSize){const t=n.signature.creationType!==a.Draw?n.signature.imageSize??o.imageSize:o.imageSize,e=Math.min(r.width/t.width,r.height/t.height);s={width:o.imageSize.width*e,height:o.imageSize.height*e}}this.annotation.setActiveTool(m,{imageData:o.imageData,ghostUrl:t,targetSize:s,entryId:e,kind:i})}this.activePlacement$.emit(t,{entryId:e,kind:i})}}deactivatePlacement(t){this.annotation&&(this.annotation.setActiveTool(null),this.revokeGhostUrl(),this.activePlacement$.emit(t,null))}revokeGhostUrl(){this.currentGhostUrl&&(URL.revokeObjectURL(this.currentGhostUrl),this.currentGhostUrl=null)}emitEntriesChange(){this.entriesChange$.emit(this.getEntries())}async destroy(){var t;this.revokeGhostUrl(),null==(t=this.toolChangeUnsubscribe)||t.call(this),this.entries.clear()}};S.id=o;let v=S;const x={entryIds:[]},A=(t=x,e)=>{switch(e.type){case l:return{...t,entryIds:[...t.entryIds,e.payload]};case h:return{...t,entryIds:t.entryIds.filter(t=>t!==e.payload)};default:return t}};function P(t){const e=new Uint8Array(t);let i="";for(let n=0;n<e.length;n++)i+=String.fromCharCode(e[n]);return btoa(i)}function b(t){const e=atob(t),i=new Uint8Array(e.length);for(let n=0;n<e.length;n++)i[n]=e.charCodeAt(n);return i.buffer}function k(t){if(t.creationType===a.Draw)return t;const{imageData:e,...i}=t;return{...i,imageData:e?P(e):void 0}}function T(t){if(t.creationType===a.Draw)return t;const{imageData:e,...i}=t;return{...i,imageData:e?b(e):void 0}}const D={manifest:s,create:(t,e)=>new v(o,t,e),reducer:A,initialState:x};exports.ADD_SIGNATURE_ENTRY=l,exports.REMOVE_SIGNATURE_ENTRY=h,exports.SIGNATURE_INK_TOOL_ID=y,exports.SIGNATURE_PLUGIN_ID=o,exports.SIGNATURE_STAMP_TOOL_ID=m,exports.SignatureCreationType=a,exports.SignatureFieldKind=r,exports.SignatureMode=n,exports.SignaturePlugin=v,exports.SignaturePluginPackage=D,exports.addSignatureEntry=c,exports.deserializeEntries=function(t){return t.map(t=>({id:t.id,createdAt:t.createdAt,signature:T(t.signature),...t.initials&&{initials:T(t.initials)}}))},exports.initialState=x,exports.manifest=s,exports.removeSignatureEntry=u,exports.serializeEntries=function(t){return t.map(t=>({id:t.id,createdAt:t.createdAt,signature:k(t.signature),...t.initials&&{initials:k(t.initials)}}))},exports.signatureReducer=A;
2
- //# sourceMappingURL=index.cjs.map
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