@docuseal/signature-maker-js 1.0.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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 DocuSeal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ <p align="center">
2
+ <a href="https://www.docuseal.co/online-signature" target="_blank">
3
+ <img width="600" height="356" src='https://github.com/user-attachments/assets/305904a9-291f-416d-ac32-baaf22970450' alt='Signature Maker'>
4
+ </a>
5
+ </p>
6
+
7
+ # Signature Maker (JS)
8
+
9
+ Signature Maker is a web component that lets users draw or type their signature.
10
+
11
+ #### Other implementations
12
+
13
+ - [React](https://github.com/docusealco/signature-maker-react)
14
+ - [Vue](https://github.com/docusealco/signature-maker-vue)
15
+
16
+ ## Demo
17
+
18
+ Try the live demo [here](https://www.docuseal.co/online-signature)
19
+
20
+ ## Documentation
21
+
22
+ Check out the full documentation [here](https://www.docuseal.co/docs/embedded/signature#js).
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install @docuseal/signature-maker-js
28
+ ```
29
+
30
+ OR
31
+
32
+ ```bash
33
+ yarn add @docuseal/signature-maker-js
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ Basic Usage with standard styles and default signature saving behavior:
39
+
40
+ ```html
41
+ <signature-maker
42
+ id="signatureMaker"
43
+ data-download-on-save="true"
44
+ >
45
+ </signature-maker>
46
+ ```
47
+
48
+ ---
49
+
50
+ Usage with default styles but custom signature saving behavior, such as uploading the signature to a server:
51
+
52
+ ```html
53
+ <signature-maker id="signatureMaker"><signature-maker>
54
+
55
+ <script>
56
+ window.signatureMaker.addEventListener('save', (e) => {
57
+ fetch('/save-signature', {
58
+ method: 'POST',
59
+ headers: {
60
+ 'Content-Type': 'application/json',
61
+ 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content
62
+ },
63
+ body: JSON.stringify({ file: e.detail.base64 }),
64
+ });
65
+ })
66
+ </script>
67
+ ```
68
+
69
+ ---
70
+
71
+ Usage without a save signature button, embedded in another form. The signature will be stored in a form field named `signature`:
72
+
73
+ ```html
74
+ <form id="myForm" method="POST" action="/submit-form">
75
+ <input name="name" type="text">
76
+ <signature-maker
77
+ id="signatureMaker"
78
+ data-with-submit="false"
79
+ >
80
+ <input type="hidden" type="file" name="signature">
81
+ </signature-maker>
82
+ <button type="submit">Submit</button>
83
+ </form>
84
+ ```
85
+
86
+ ---
87
+
88
+ Usage without a save signature button and tracking each signature change:
89
+
90
+ ```html
91
+ <signature-maker
92
+ id="signatureMaker"
93
+ data-with-submit="false"
94
+ >
95
+ </signature-maker>
96
+ <script>
97
+ window.signatureMaker.addEventListener('change', (e) => {
98
+ if (e.detail.base64) {
99
+ fetch('/background-save-signature', {
100
+ method: 'POST',
101
+ headers: {
102
+ 'Content-Type': 'application/json',
103
+ 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content
104
+ },
105
+ body: JSON.stringify({ file: e.detail.base64 }),
106
+ });
107
+ } else {
108
+ console.log('No signature to save');
109
+ }
110
+ })
111
+ </script>
112
+ ```
113
+
114
+ ---
115
+
116
+ Usage with custom button labels and classes (DaisyUI):
117
+
118
+ ```html
119
+ <signature-maker
120
+ class="block my-8"
121
+ data-save-button-text="Télécharger"
122
+ data-undo-button-text="Annuler"
123
+ data-clear-button-text="Clair"
124
+ data-draw-type-button-text="Dessiner"
125
+ data-text-type-button-text="Type"
126
+ data-upload-type-button-text="Télécharger"
127
+ data-text-input-placeholder="Tapez votre signature ici"
128
+ data-type-buttons-container-class="flex gap-2 mb-4 justify-center"
129
+ data-draw-type-button-class="flex items-center justify-center py-3 w-40 uppercase border-neutral-focus space-x-2 border rounded-3xl cursor-pointer hover:bg-neutral hover:text-white hover:font-semibold"
130
+ data-draw-type-button-active-class="bg-neutral text-white font-semibold"
131
+ data-text-type-button-class="flex items-center justify-center py-3 w-40 uppercase border-neutral-focus space-x-2 border rounded-3xl cursor-pointer hover:bg-neutral hover:text-white hover:font-semibold"
132
+ data-text-type-button-active-class="bg-neutral text-white font-semibold"
133
+ data-upload-type-button-class="flex items-center justify-center py-3 w-40 uppercase border-neutral-focus space-x-2 border rounded-3xl cursor-pointer hover:bg-neutral hover:text-white hover:font-semibold"
134
+ data-upload-type-button-active-class="bg-neutral text-white font-semibold"
135
+ data-text-input-class="input mb-4 input-bordered bg-white text-2xl w-full h-14 rounded-2xl"
136
+ data-canvas-class="bg-white border border-base-300 rounded-2xl w-full"
137
+ data-undo-button-class="btn btn-outline btn-sm font-medium"
138
+ data-clear-button-class="btn btn-outline btn-sm font-medium"
139
+ data-save-button-class="btn btn-neutral text-white text-base w-full"
140
+ >
141
+ </signature-maker>
142
+ ```
143
+
144
+ ---
145
+
146
+ Usage with customization of certain elements using CSS classes and styles:
147
+
148
+ ```html
149
+ <signature-maker
150
+ data-save-button-class="btn btn-neutral text-white text-base w-full"
151
+ data-canvas-class="bg-white border border-base-300 rounded-2xl w-full"
152
+ data-canvas-style="border: 2px solid #000;"
153
+ >
154
+ </signature-maker>
155
+ ```
156
+
157
+ ## Customization
158
+
159
+ Signature Maker can be customized with the following attributes:
160
+
161
+ ```
162
+ data-download-on-save
163
+ data-with-typed
164
+ data-with-drawn
165
+ data-with-upload
166
+ data-with-color-select
167
+ data-with-submit
168
+ data-save-button-text
169
+ data-control-buttons-container-class
170
+ data-control-buttons-container-style
171
+ data-save-button-class
172
+ data-save-button-style
173
+ data-save-button-disabled-class
174
+ data-save-button-disabled-style
175
+ data-undo-button-text
176
+ data-undo-button-class
177
+ data-undo-button-style
178
+ data-clear-button-text
179
+ data-clear-button-class
180
+ data-clear-button-style
181
+ data-text-input-placeholder
182
+ data-text-input-class
183
+ data-text-input-style
184
+ data-canvas-class
185
+ data-canvas-style
186
+ data-type-buttons-container-class
187
+ data-type-buttons-container-style
188
+ data-draw-type-button-text
189
+ data-draw-type-button-class
190
+ data-draw-type-button-style
191
+ data-draw-type-button-active-class
192
+ data-draw-type-button-active-style
193
+ data-text-type-button-text
194
+ data-text-type-button-class
195
+ data-text-type-button-style
196
+ data-text-type-button-active-class
197
+ data-text-type-button-active-style
198
+ data-upload-type-button-text
199
+ data-upload-type-button-class
200
+ data-upload-type-button-style
201
+ data-upload-type-button-active-class
202
+ data-upload-type-button-active-style
203
+ data-font-url
204
+ ````
205
+
206
+ The full documentation with detailed configuration and event descriptions can be found [here](https://www.docuseal.co/docs/embedded/signature#js).
207
+
208
+ # License
209
+
210
+ MIT
@@ -0,0 +1,97 @@
1
+ var g=class{constructor(t,e,s,n){if(isNaN(t)||isNaN(e))throw new Error(`Point is invalid: (${t}, ${e})`);this.x=+t,this.y=+e,this.pressure=s||0,this.time=n||Date.now()}distanceTo(t){return Math.sqrt(Math.pow(this.x-t.x,2)+Math.pow(this.y-t.y,2))}equals(t){return this.x===t.x&&this.y===t.y&&this.pressure===t.pressure&&this.time===t.time}velocityFrom(t){return this.time!==t.time?this.distanceTo(t)/(this.time-t.time):0}},b=class v{static fromPoints(t,e){let s=this.calculateControlPoints(t[0],t[1],t[2]).c2,n=this.calculateControlPoints(t[1],t[2],t[3]).c1;return new v(t[1],s,n,t[2],e.start,e.end)}static calculateControlPoints(t,e,s){let n=t.x-e.x,i=t.y-e.y,a=e.x-s.x,l=e.y-s.y,r={x:(t.x+e.x)/2,y:(t.y+e.y)/2},o={x:(e.x+s.x)/2,y:(e.y+s.y)/2},h=Math.sqrt(n*n+i*i),d=Math.sqrt(a*a+l*l),c=r.x-o.x,u=r.y-o.y,p=h+d==0?0:d/(h+d),y={x:o.x+c*p,y:o.y+u*p},f=e.x-y.x,x=e.y-y.y;return{c1:new g(r.x+f,r.y+x),c2:new g(o.x+f,o.y+x)}}constructor(t,e,s,n,i,a){this.startPoint=t,this.control2=e,this.control1=s,this.endPoint=n,this.startWidth=i,this.endWidth=a}length(){let e=0,s,n;for(let i=0;i<=10;i+=1){let a=i/10,l=this.point(a,this.startPoint.x,this.control1.x,this.control2.x,this.endPoint.x),r=this.point(a,this.startPoint.y,this.control1.y,this.control2.y,this.endPoint.y);if(i>0){let o=l-s,h=r-n;e+=Math.sqrt(o*o+h*h)}s=l,n=r}return e}point(t,e,s,n,i){return e*(1-t)*(1-t)*(1-t)+3*s*(1-t)*(1-t)*t+3*n*(1-t)*t*t+i*t*t*t}},m=class{constructor(){try{this._et=new EventTarget}catch{this._et=document}}addEventListener(t,e,s){this._et.addEventListener(t,e,s)}dispatchEvent(t){return this._et.dispatchEvent(t)}removeEventListener(t,e,s){this._et.removeEventListener(t,e,s)}};function B(v,t=250){let e=0,s=null,n,i,a,l=()=>{e=Date.now(),s=null,n=v.apply(i,a),s||(i=null,a=[])};return function(...o){let h=Date.now(),d=t-(h-e);return i=this,a=o,d<=0||d>t?(s&&(clearTimeout(s),s=null),e=h,n=v.apply(i,a),s||(i=null,a=[])):s||(s=window.setTimeout(l,d)),n}}var w=class v extends m{constructor(t,e={}){var s,n,i;super(),this.canvas=t,this._drawingStroke=!1,this._isEmpty=!0,this._lastPoints=[],this._data=[],this._lastVelocity=0,this._lastWidth=0,this._handleMouseDown=a=>{!this._isLeftButtonPressed(a,!0)||this._drawingStroke||this._strokeBegin(this._pointerEventToSignatureEvent(a))},this._handleMouseMove=a=>{if(!this._isLeftButtonPressed(a,!0)||!this._drawingStroke){this._strokeEnd(this._pointerEventToSignatureEvent(a),!1);return}this._strokeMoveUpdate(this._pointerEventToSignatureEvent(a))},this._handleMouseUp=a=>{this._isLeftButtonPressed(a)||this._strokeEnd(this._pointerEventToSignatureEvent(a))},this._handleTouchStart=a=>{a.targetTouches.length!==1||this._drawingStroke||(a.cancelable&&a.preventDefault(),this._strokeBegin(this._touchEventToSignatureEvent(a)))},this._handleTouchMove=a=>{if(a.targetTouches.length===1){if(a.cancelable&&a.preventDefault(),!this._drawingStroke){this._strokeEnd(this._touchEventToSignatureEvent(a),!1);return}this._strokeMoveUpdate(this._touchEventToSignatureEvent(a))}},this._handleTouchEnd=a=>{a.targetTouches.length===0&&(a.cancelable&&a.preventDefault(),this.canvas.removeEventListener("touchmove",this._handleTouchMove),this._strokeEnd(this._touchEventToSignatureEvent(a)))},this._handlePointerDown=a=>{!this._isLeftButtonPressed(a)||this._drawingStroke||(a.preventDefault(),this._strokeBegin(this._pointerEventToSignatureEvent(a)))},this._handlePointerMove=a=>{if(!this._isLeftButtonPressed(a,!0)||!this._drawingStroke){this._strokeEnd(this._pointerEventToSignatureEvent(a),!1);return}a.preventDefault(),this._strokeMoveUpdate(this._pointerEventToSignatureEvent(a))},this._handlePointerUp=a=>{this._isLeftButtonPressed(a)||(a.preventDefault(),this._strokeEnd(this._pointerEventToSignatureEvent(a)))},this.velocityFilterWeight=e.velocityFilterWeight||.7,this.minWidth=e.minWidth||.5,this.maxWidth=e.maxWidth||2.5,this.throttle=(s=e.throttle)!==null&&s!==void 0?s:16,this.minDistance=(n=e.minDistance)!==null&&n!==void 0?n:5,this.dotSize=e.dotSize||0,this.penColor=e.penColor||"black",this.backgroundColor=e.backgroundColor||"rgba(0,0,0,0)",this.compositeOperation=e.compositeOperation||"source-over",this.canvasContextOptions=(i=e.canvasContextOptions)!==null&&i!==void 0?i:{},this._strokeMoveUpdate=this.throttle?B(v.prototype._strokeUpdate,this.throttle):v.prototype._strokeUpdate,this._ctx=t.getContext("2d",this.canvasContextOptions),this.clear(),this.on()}clear(){let{_ctx:t,canvas:e}=this;t.fillStyle=this.backgroundColor,t.clearRect(0,0,e.width,e.height),t.fillRect(0,0,e.width,e.height),this._data=[],this._reset(this._getPointGroupOptions()),this._isEmpty=!0}fromDataURL(t,e={}){return new Promise((s,n)=>{let i=new Image,a=e.ratio||window.devicePixelRatio||1,l=e.width||this.canvas.width/a,r=e.height||this.canvas.height/a,o=e.xOffset||0,h=e.yOffset||0;this._reset(this._getPointGroupOptions()),i.onload=()=>{this._ctx.drawImage(i,o,h,l,r),s()},i.onerror=d=>{n(d)},i.crossOrigin="anonymous",i.src=t,this._isEmpty=!1})}toDataURL(t="image/png",e){switch(t){case"image/svg+xml":return typeof e!="object"&&(e=void 0),`data:image/svg+xml;base64,${btoa(this.toSVG(e))}`;default:return typeof e!="number"&&(e=void 0),this.canvas.toDataURL(t,e)}}on(){this.canvas.style.touchAction="none",this.canvas.style.msTouchAction="none",this.canvas.style.userSelect="none";let t=/Macintosh/.test(navigator.userAgent)&&"ontouchstart"in document;window.PointerEvent&&!t?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())}off(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.style.userSelect="auto",this.canvas.removeEventListener("pointerdown",this._handlePointerDown),this.canvas.removeEventListener("mousedown",this._handleMouseDown),this.canvas.removeEventListener("touchstart",this._handleTouchStart),this._removeMoveUpEventListeners()}_getListenerFunctions(){var t;let e=window.document===this.canvas.ownerDocument?window:(t=this.canvas.ownerDocument.defaultView)!==null&&t!==void 0?t:this.canvas.ownerDocument;return{addEventListener:e.addEventListener.bind(e),removeEventListener:e.removeEventListener.bind(e)}}_removeMoveUpEventListeners(){let{removeEventListener:t}=this._getListenerFunctions();t("pointermove",this._handlePointerMove),t("pointerup",this._handlePointerUp),t("mousemove",this._handleMouseMove),t("mouseup",this._handleMouseUp),t("touchmove",this._handleTouchMove),t("touchend",this._handleTouchEnd)}isEmpty(){return this._isEmpty}fromData(t,{clear:e=!0}={}){e&&this.clear(),this._fromData(t,this._drawCurve.bind(this),this._drawDot.bind(this)),this._data=this._data.concat(t)}toData(){return this._data}_isLeftButtonPressed(t,e){return e?t.buttons===1:(t.buttons&1)===1}_pointerEventToSignatureEvent(t){return{event:t,type:t.type,x:t.clientX,y:t.clientY,pressure:"pressure"in t?t.pressure:0}}_touchEventToSignatureEvent(t){let e=t.changedTouches[0];return{event:t,type:t.type,x:e.clientX,y:e.clientY,pressure:e.force}}_getPointGroupOptions(t){return{penColor:t&&"penColor"in t?t.penColor:this.penColor,dotSize:t&&"dotSize"in t?t.dotSize:this.dotSize,minWidth:t&&"minWidth"in t?t.minWidth:this.minWidth,maxWidth:t&&"maxWidth"in t?t.maxWidth:this.maxWidth,velocityFilterWeight:t&&"velocityFilterWeight"in t?t.velocityFilterWeight:this.velocityFilterWeight,compositeOperation:t&&"compositeOperation"in t?t.compositeOperation:this.compositeOperation}}_strokeBegin(t){if(!this.dispatchEvent(new CustomEvent("beginStroke",{detail:t,cancelable:!0})))return;let{addEventListener:s}=this._getListenerFunctions();switch(t.event.type){case"mousedown":s("mousemove",this._handleMouseMove),s("mouseup",this._handleMouseUp);break;case"touchstart":s("touchmove",this._handleTouchMove),s("touchend",this._handleTouchEnd);break;case"pointerdown":s("pointermove",this._handlePointerMove),s("pointerup",this._handlePointerUp);break}this._drawingStroke=!0;let n=this._getPointGroupOptions(),i=Object.assign(Object.assign({},n),{points:[]});this._data.push(i),this._reset(n),this._strokeUpdate(t)}_strokeUpdate(t){if(!this._drawingStroke)return;if(this._data.length===0){this._strokeBegin(t);return}this.dispatchEvent(new CustomEvent("beforeUpdateStroke",{detail:t}));let e=this._createPoint(t.x,t.y,t.pressure),s=this._data[this._data.length-1],n=s.points,i=n.length>0&&n[n.length-1],a=i?e.distanceTo(i)<=this.minDistance:!1,l=this._getPointGroupOptions(s);if(!i||!(i&&a)){let r=this._addPoint(e,l);i?r&&this._drawCurve(r,l):this._drawDot(e,l),n.push({time:e.time,x:e.x,y:e.y,pressure:e.pressure})}this.dispatchEvent(new CustomEvent("afterUpdateStroke",{detail:t}))}_strokeEnd(t,e=!0){this._removeMoveUpEventListeners(),this._drawingStroke&&(e&&this._strokeUpdate(t),this._drawingStroke=!1,this.dispatchEvent(new CustomEvent("endStroke",{detail:t})))}_handlePointerEvents(){this._drawingStroke=!1,this.canvas.addEventListener("pointerdown",this._handlePointerDown)}_handleMouseEvents(){this._drawingStroke=!1,this.canvas.addEventListener("mousedown",this._handleMouseDown)}_handleTouchEvents(){this.canvas.addEventListener("touchstart",this._handleTouchStart)}_reset(t){this._lastPoints=[],this._lastVelocity=0,this._lastWidth=(t.minWidth+t.maxWidth)/2,this._ctx.fillStyle=t.penColor,this._ctx.globalCompositeOperation=t.compositeOperation}_createPoint(t,e,s){let n=this.canvas.getBoundingClientRect();return new g(t-n.left,e-n.top,s,new Date().getTime())}_addPoint(t,e){let{_lastPoints:s}=this;if(s.push(t),s.length>2){s.length===3&&s.unshift(s[0]);let n=this._calculateCurveWidths(s[1],s[2],e),i=b.fromPoints(s,n);return s.shift(),i}return null}_calculateCurveWidths(t,e,s){let n=s.velocityFilterWeight*e.velocityFrom(t)+(1-s.velocityFilterWeight)*this._lastVelocity,i=this._strokeWidth(n,s),a={end:i,start:this._lastWidth};return this._lastVelocity=n,this._lastWidth=i,a}_strokeWidth(t,e){return Math.max(e.maxWidth/(t+1),e.minWidth)}_drawCurveSegment(t,e,s){let n=this._ctx;n.moveTo(t,e),n.arc(t,e,s,0,2*Math.PI,!1),this._isEmpty=!1}_drawCurve(t,e){let s=this._ctx,n=t.endWidth-t.startWidth,i=Math.ceil(t.length())*2;s.beginPath(),s.fillStyle=e.penColor;for(let a=0;a<i;a+=1){let l=a/i,r=l*l,o=r*l,h=1-l,d=h*h,c=d*h,u=c*t.startPoint.x;u+=3*d*l*t.control1.x,u+=3*h*r*t.control2.x,u+=o*t.endPoint.x;let p=c*t.startPoint.y;p+=3*d*l*t.control1.y,p+=3*h*r*t.control2.y,p+=o*t.endPoint.y;let y=Math.min(t.startWidth+o*n,e.maxWidth);this._drawCurveSegment(u,p,y)}s.closePath(),s.fill()}_drawDot(t,e){let s=this._ctx,n=e.dotSize>0?e.dotSize:(e.minWidth+e.maxWidth)/2;s.beginPath(),this._drawCurveSegment(t.x,t.y,n),s.closePath(),s.fillStyle=e.penColor,s.fill()}_fromData(t,e,s){for(let n of t){let{points:i}=n,a=this._getPointGroupOptions(n);if(i.length>1)for(let l=0;l<i.length;l+=1){let r=i[l],o=new g(r.x,r.y,r.pressure,r.time);l===0&&this._reset(a);let h=this._addPoint(o,a);h&&e(h,a)}else this._reset(a),s(i[0],a)}}toSVG({includeBackgroundColor:t=!1}={}){let e=this._data,s=Math.max(window.devicePixelRatio||1,1),n=0,i=0,a=this.canvas.width/s,l=this.canvas.height/s,r=document.createElementNS("http://www.w3.org/2000/svg","svg");if(r.setAttribute("xmlns","http://www.w3.org/2000/svg"),r.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink"),r.setAttribute("viewBox",`${n} ${i} ${a} ${l}`),r.setAttribute("width",a.toString()),r.setAttribute("height",l.toString()),t&&this.backgroundColor){let o=document.createElement("rect");o.setAttribute("width","100%"),o.setAttribute("height","100%"),o.setAttribute("fill",this.backgroundColor),r.appendChild(o)}return this._fromData(e,(o,{penColor:h})=>{let d=document.createElement("path");if(!isNaN(o.control1.x)&&!isNaN(o.control1.y)&&!isNaN(o.control2.x)&&!isNaN(o.control2.y)){let c=`M ${o.startPoint.x.toFixed(3)},${o.startPoint.y.toFixed(3)} C ${o.control1.x.toFixed(3)},${o.control1.y.toFixed(3)} ${o.control2.x.toFixed(3)},${o.control2.y.toFixed(3)} ${o.endPoint.x.toFixed(3)},${o.endPoint.y.toFixed(3)}`;d.setAttribute("d",c),d.setAttribute("stroke-width",(o.endWidth*2.25).toFixed(3)),d.setAttribute("stroke",h),d.setAttribute("fill","none"),d.setAttribute("stroke-linecap","round"),r.appendChild(d)}},(o,{penColor:h,dotSize:d,minWidth:c,maxWidth:u})=>{let p=document.createElement("circle"),y=d>0?d:(c+u)/2;p.setAttribute("r",y.toString()),p.setAttribute("cx",o.x.toString()),p.setAttribute("cy",o.y.toString()),p.setAttribute("fill",h),r.appendChild(p)}),r.outerHTML}};var S=class extends HTMLElement{static DEFAULT_STYLES={controlButtonsContainer:"display: flex; align-items: center; justify-content: space-between; text-align: center; margin: 1rem 0;",saveButton:"color: #ffffff; font-family: ui-sans-serif, system-ui, sans-serif font-size: 16px; font-weight: 600; line-height: 24px; padding: 0px 16px; text-transform: uppercase; background-color: #222222; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 48px; justify-content: center; outline-color: #222222; text-align: center; text-decoration-line: none; width: 100%; border: 1px solid #222222;",saveButtonDisabled:"background-color: #D3D3D3; color: #808080; cursor: not-allowed; border: 0;",undoButton:"color: #222222; background-color: transparent; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 14px; font-weight: 500; line-height: 14px; padding: 0px 12px; text-transform: uppercase; appearance: button; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 32px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",clearButton:"color: #222222; background-color: transparent; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 14px; font-weight: 500; line-height: 14px; padding: 0px 12px; text-transform: uppercase; appearance: button; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 32px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",canvas:"display: block; vertical-align: middle; width: 100%; border-radius: 8px; background-color: #ffffff; padding: 1px; touch-action: none; user-select: none; text-align: center; line-height: 24px; border: 1px solid #D3D3D3;",textInput:"color: #222222; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 24px; font-weight: 400; line-height: 32px; margin: 0px 0px 16px; padding: 0px 16px; background-color: #ffffff; border-radius: 8px; flex-shrink: 1; height: 56px; outline: #222222 none 0px; outline-offset: 0px; width: 100%; text-align: start; border: 1px solid #D3D3D3;",typeButtonsContainer:"margin-bottom: 1rem; display: flex; justify-content: center; flex-wrap: wrap; gap: 0.5rem;",drawTypeButton:"color: #222222; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 16px; font-weight: 500; line-height: 24px; padding: 0px 40px; text-transform: uppercase; background-color: transparent; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 48px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",drawTypeButtonActive:"color: #fff; background-color: #222222; font-weight: 500;",textTypeButton:"color: #222222; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 16px; font-weight: 500; line-height: 24px; padding: 0px 40px; text-transform: uppercase; background-color: transparent; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 48px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",textTypeButtonActive:"color: #fff; background-color: #222222; font-weight: 500;",uploadTypeButton:"color: #222222; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 16px; font-weight: 500; line-height: 24px; padding: 0px 40px; text-transform: uppercase; background-color: transparent; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 48px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",uploadTypeButtonActive:"color: #fff; background-color: #222222; font-weight: 500;"};static DEFAULT_LABELS={drawTypeButton:"Draw",textTypeButton:"Type",uploadTypeButton:"Upload",undoButton:"Undo",clearButton:"Clear",saveButton:"Submit",textInputPlaceholder:"Type signature here"};constructor(){super(),this.isMounted=!1}static observedAttributes=["data-download-on-save","data-with-typed","data-with-drawn","data-with-upload","data-with-color-select","data-with-submit","data-control-buttons-container-class","data-control-buttons-container-style","data-save-button-text","data-save-button-class","data-save-button-style","data-save-button-disabled-class","data-save-button-disabled-style","data-undo-button-text","data-undo-button-class","data-undo-button-style","data-clear-button-text","data-clear-button-class","data-clear-button-style","data-text-input-placeholder","data-text-input-class","data-text-input-style","data-canvas-class","data-canvas-style","data-type-buttons-container-class","data-type-buttons-container-style","data-draw-type-button-text","data-draw-type-button-class","data-draw-type-button-style","data-draw-type-button-active-class","data-draw-type-button-active-style","data-text-type-button-text","data-text-type-button-class","data-text-type-button-style","data-text-type-button-active-class","data-text-type-button-active-style","data-upload-type-button-text","data-upload-type-button-class","data-upload-type-button-style","data-upload-type-button-active-class","data-upload-type-button-active-style"];get defaultStyles(){return this.constructor.DEFAULT_STYLES}get defaultLabels(){return this.constructor.DEFAULT_LABELS}get clearButton(){return this.querySelector('[data-target="clearButton"]')}get undoButton(){return this.querySelector('[data-target="undoButton"]')}get controlButtonsContainer(){return this.querySelector('[data-target="controlButtonsContainer"]')}get typeButtonsContainer(){return this.querySelector('[data-target="typeButtonsContainer"]')}get drawTypeButton(){return this.querySelector('[data-target="drawTypeButton"]')}get textTypeButton(){return this.querySelector('[data-target="textTypeButton"]')}get uploadTypeButton(){return this.querySelector('[data-target="uploadTypeButton"]')}get textInput(){return this.querySelector('[data-target="textInput"]')}get fileInput(){return this.querySelector('[data-target="fileInput"]')}get saveButton(){return this.querySelector('[data-target="saveButton"]')}get canvas(){return this.querySelector('[data-target="canvas"]')}get colorSelect(){return this.querySelector('[data-target="colorSelect"]')}get colorInputs(){return[...this.querySelectorAll('[data-target="colorInput"]')]}get setters(){return{"data-with-typed":this.setDisplayType,"data-with-drawn":this.setDisplayType,"data-with-upload":this.setDisplayType,"data-with-color-select":this.setDisplayColorSelect,"data-with-submit":this.setDisplaySubmit,"data-control-buttons-container-class":this.setControlButtonsContainerClassAndStyle,"data-control-buttons-container-style":this.setControlButtonsContainerClassAndStyle,"data-save-button-text":this.setSaveButtonText,"data-save-button-class":this.setSaveButtonClassAndStyle,"data-save-button-style":this.setSaveButtonClassAndStyle,"data-save-button-disabled-class":this.setSaveButtonClassAndStyle,"data-save-button-disabled-style":this.setSaveButtonClassAndStyle,"data-undo-button-text":this.setUndoButtonText,"data-undo-button-class":this.setUndoButtonClassAndStyle,"data-undo-button-style":this.setUndoButtonClassAndStyle,"data-clear-button-text":this.setCleaButtonText,"data-clear-button-class":this.setClearButtonClassAndStyle,"data-clear-button-style":this.setClearButtonClassAndStyle,"data-canvas-class":this.setCanvasClassAndStyle,"data-canvas-style":this.setCanvasClassAndStyle,"data-text-input-placeholder":this.setTextInputPlaceholder,"data-text-input-class":this.setTextInputClassAndStyle,"data-text-input-style":this.setTextInputClassAndStyle,"data-type-buttons-container-class":this.setTypeButtonsContainerClassAndStyle,"data-type-buttons-container-style":this.setTypeButtonsContainerClassAndStyle,"data-draw-type-button-text":this.setDrawTypeButtonText,"data-draw-type-button-class":this.setDrawTypeButtonClassAndStyle,"data-draw-type-button-style":this.setDrawTypeButtonClassAndStyle,"data-draw-type-button-active-class":this.setDrawTypeButtonClassAndStyle,"data-draw-type-button-active-style":this.setDrawTypeButtonClassAndStyle,"data-text-type-button-text":this.setTextTypeButtonText,"data-text-type-button-class":this.setTextTypeButtonClassAndStyle,"data-text-type-button-style":this.setTextTypeButtonClassAndStyle,"data-text-type-button-active-class":this.setTextTypeButtonClassAndStyle,"data-text-type-button-active-style":this.setTextTypeButtonClassAndStyle,"data-upload-type-button-text":this.setUploadTypeButtonText,"data-upload-type-button-class":this.setUploadTypeButtonClassAndStyle,"data-upload-type-button-style":this.setUploadTypeButtonClassAndStyle,"data-upload-type-button-active-class":this.setUploadTypeButtonClassAndStyle,"data-upload-type-button-active-style":this.setUploadTypeButtonClassAndStyle}}get isDrawTypeSelected(){return this.drawTypeButton.querySelector("input").checked}get isTextTypeSelected(){return this.textTypeButton.querySelector("input").checked}get isUploadTypeSelected(){return this.uploadTypeButton.querySelector("input").checked}get isSaveButtonDisabled(){return this.saveButton.disabled}get isDownloadOnSaveSettingEnabled(){return this.dataset.downloadOnSave==="true"}get isColorSelectSettingEnabled(){return this.dataset.withColorSelect!=="false"}get isSubmitButtonSettingEnabled(){return this.dataset.withSubmit!=="false"}setDisplayType=()=>{let t=[this.dataset.withDrawn,this.dataset.withTyped,this.dataset.withUpload].filter(e=>e==="false");this.textTypeButton.parentNode.style.display=this.dataset.withTyped==="false"?"none":"inherit",this.drawTypeButton.parentNode.style.display=this.dataset.withDrawn==="false"?"none":"inherit",this.uploadTypeButton.parentNode.style.display=this.dataset.withUpload==="false"?"none":"inherit",this.typeButtonsContainer.parentNode.style.display=t.length>1&&this.dataset.withUpload==="false"?"none":"inherit",t.length===3?console.error('At least one of the "with-typed", "with-drawn", or "with-upload" attributes must be set to "true".'):this.dataset.withDrawn!=="false"?this.enableDrawPanel():this.dataset.withTyped!=="false"?this.enableTextPanel():this.dataset.withUpload!=="false"&&this.enableUploadPanel()};setDisplayColorSelect=()=>{this.colorSelect.style.visibility=this.dataset.withColorSelect==="false"?"hidden":"visible"};setDisplaySubmit=()=>{this.saveButton.parentNode.style.display=this.dataset.withSubmit==="false"?"none":"inherit"};setControlButtonsContainerClassAndStyle=()=>{let t=this.dataset.controlButtonsContainerClass||"",e=this.dataset.controlButtonsContainerStyle||(t?"":this.defaultStyles.controlButtonsContainer);this.controlButtonsContainer.setAttribute("style",e),this.controlButtonsContainer.setAttribute("class",t)};setSaveButtonText=()=>{let t=this.saveButton.querySelector("span");t&&(t.innerText=this.dataset.saveButtonText||this.defaultLabels.saveButton)};setSaveButtonClassAndStyle=()=>{let t=this.dataset.saveButtonClass||"",e=this.dataset.saveButtonStyle||(t?"":this.defaultStyles.saveButton);this.isSaveButtonDisabled&&(t&&this.dataset.saveButtonDisabledClass&&(t=this.combineStrings(t,this.dataset.saveButtonDisabledClass)),e&&this.dataset.saveButtonDisabledStyle?e=this.combineStrings(e,this.dataset.saveButtonDisabledStyle):t||(e=this.combineStrings(e,this.defaultStyles.saveButtonDisabled))),this.saveButton.setAttribute("class",t),this.saveButton.setAttribute("style",e)};setUndoButtonText=()=>{let t=this.undoButton.querySelector("span");t&&(t.innerText=this.dataset.undoButtonText||this.defaultLabels.undoButton)};setUndoButtonClassAndStyle=()=>{let t=this.dataset.undoButtonClass||"",e=this.dataset.undoButtonStyle||(t?"":this.defaultStyles.undoButton);this.undoButton.setAttribute("class",t),this.undoButton.setAttribute("style",e)};setCleaButtonText=()=>{let t=this.clearButton.querySelector("span");t&&(t.innerText=this.dataset.clearButtonText||this.defaultLabels.clearButton)};setClearButtonClassAndStyle=()=>{let t=this.dataset.clearButtonClass||"",e=this.dataset.clearButtonStyle||(t?"":this.defaultStyles.clearButton);this.clearButton.setAttribute("class",t),this.clearButton.setAttribute("style",e)};setCanvasClassAndStyle=()=>{let t=this.dataset.canvasClass||"",e=this.dataset.canvasStyle||(t?"padding: 1px; touch-action: none; user-select: none;":this.defaultStyles.canvas);this.canvas.setAttribute("class",t),this.canvas.setAttribute("style",e)};setTypeButtonsContainerClassAndStyle=()=>{let t=this.dataset.typeButtonsContainerClass||"",e=this.dataset.typeButtonsContainerStyle||(t?"":this.defaultStyles.typeButtonsContainer);this.typeButtonsContainer.setAttribute("style",e),this.typeButtonsContainer.setAttribute("class",t)};setTextInputPlaceholder=()=>{this.textInput.setAttribute("placeholder",this.dataset.textInputPlaceholder||this.defaultLabels.textInputPlaceholder)};setTextInputClassAndStyle=()=>{let t=this.dataset.textInputClass||"",e=this.dataset.textInputStyle||(t?"":this.defaultStyles.textInput);this.textInput.setAttribute("class",t),this.textInput.setAttribute("style",e)};setDrawTypeButtonText=()=>{let t=this.drawTypeButton.querySelector("span");t&&(t.innerText=this.dataset.drawTypeButtonText||this.defaultLabels.drawTypeButton)};setDrawTypeButtonClassAndStyle=()=>{let t=this.dataset.drawTypeButtonClass||"",e=this.dataset.drawTypeButtonStyle||(t?"":this.defaultStyles.drawTypeButton);this.isDrawTypeSelected&&(t&&this.dataset.drawTypeButtonActiveClass&&(t=this.combineStrings(t,this.dataset.drawTypeButtonActiveClass)),e&&this.dataset.drawTypeButtonActiveStyle?e=this.combineStrings(e,this.dataset.drawTypeButtonActiveStyle):t||(e=this.combineStrings(e,this.defaultStyles.drawTypeButtonActive))),this.drawTypeButton.setAttribute("class",t),this.drawTypeButton.setAttribute("style",e)};setTextTypeButtonText=()=>{let t=this.textTypeButton.querySelector("span");t&&(t.innerText=this.dataset.textTypeButtonText||this.defaultLabels.textTypeButton)};setTextTypeButtonClassAndStyle=()=>{let t=this.dataset.textTypeButtonClass||"",e=this.dataset.textTypeButtonStyle||t?"":this.defaultStyles.textTypeButton;this.isTextTypeSelected&&(t&&this.dataset.textTypeButtonActiveClass&&(t=this.combineStrings(t,this.dataset.textTypeButtonActiveClass)),e&&this.dataset.textTypeButtonActiveStyle?e=this.combineStrings(e,this.dataset.textTypeButtonActiveStyle):t||(e=this.combineStrings(e,this.defaultStyles.textTypeButtonActive))),this.textTypeButton.setAttribute("class",t),this.textTypeButton.setAttribute("style",e)};setUploadTypeButtonText=()=>{let t=this.uploadTypeButton.querySelector("span");t&&(t.innerText=this.dataset.uploadTypeButtonText||this.defaultLabels.uploadTypeButton)};setUploadTypeButtonClassAndStyle=()=>{let t=this.dataset.uploadTypeButtonClass||"",e=this.dataset.uploadTypeButtonStyle||t?"":this.defaultStyles.uploadTypeButton;this.isUploadTypeSelected&&(t&&this.dataset.uploadTypeButtonActiveClass&&(t=this.combineStrings(t,this.dataset.uploadTypeButtonActiveClass)),e&&this.dataset.uploadTypeButtonActiveStyle?e=this.combineStrings(e,this.dataset.uploadTypeButtonActiveStyle):t||(e=this.combineStrings(e,this.defaultStyles.uploadTypeButtonActive))),this.uploadTypeButton.setAttribute("class",t),this.uploadTypeButton.setAttribute("style",e)};combineStrings(t,e){return[t,e].filter(Boolean).join(" ")}attributeChangedCallback(t,e,s){this.isMounted&&this.setters[t]&&e!==s&&this.setters[t]()}connectedCallback(){document.readyState!=="complete"?document.addEventListener("DOMContentLoaded",()=>this.init()):this.init()}init(){this.style.display="block",this.childrenNode=document.createElement("div"),this.appendChild(this.childrenNode),Array.from(this.childNodes).map(t=>{this.childrenNode!==t&&this.childrenNode.appendChild(t)}),this.childrenNode.style.display="none",this.fieldNode=document.createElement("div"),this.fieldNode.innerHTML=this.tempalte,this.appendChild(this.fieldNode),this.pad=new w(this.canvas),this.isMounted=!0;for(let t in this.setters)this.setters.hasOwnProperty(t)&&this.setters[t]();this.scale=2,this.isFontLoaded=!1,this.canvas.width=this.canvas.parentNode.parentNode.clientWidth,this.canvas.height=this.canvas.parentNode.parentNode.clientWidth/this.scale,this.dataset.withDrawn!=="false"?this.enableDrawPanel():this.dataset.withTyped!=="false"?this.enableTextPanel():this.dataset.withUpload!=="false"?this.enableUploadPanel():this.enableDrawPanel(),this.pad.addEventListener("endStroke",()=>{this.handleDownloadState()}),this.clearButton.addEventListener("click",t=>{t.preventDefault(),this.cleaSignaturePad(),this.clearTextInput()}),this.undoButton.addEventListener("click",t=>{t.preventDefault();let e=this.pad.toData();e&&(e.pop(),this.pad.fromData(e),this.handleDownloadState())}),this.drawTypeButton.addEventListener("click",t=>{t.preventDefault(),this.enableDrawPanel()}),this.textTypeButton.addEventListener("click",t=>{t.preventDefault(),this.enableTextPanel()}),this.uploadTypeButton.addEventListener("click",()=>{this.uploadTypeButton.querySelector('input[type="radio"]').checked=!0,this.enableUploadPanel()}),this.fileInput.addEventListener("change",t=>{this.drawOnCanvas(t.target.files[0]).then(()=>{this.handleDownloadState()}).catch(e=>{alert(e.message)})}),this.colorInputs.forEach(t=>{t.addEventListener("change",e=>{this.textInput.value!==""&&(this.canvas.getContext("2d").fillStyle=e.target.value,this.drawText()),this.pad.penColor=e.target.value})}),this.textInput.addEventListener("input",()=>{this.drawText(),this.handleDownloadState()}),this.saveButton.addEventListener("click",t=>{t.preventDefault(),this.disableSaveButton(),this.cropCanvas(this.canvas).then(e=>{this.isDownloadOnSaveSettingEnabled&&this.downloadBlob(e,`signature-${Date.now()}.png`),this.convertBlobToBase64(e).then(s=>{this.dispatchEvent(new CustomEvent("save",{detail:{base64:s,blob:e}}))}).catch(s=>{console.error("Failed to convert blob to base64:",s)})}).then(()=>{this.enableSaveButton()}).catch(e=>{console.error("Download failed:",e),this.disableSaveButton()})}),this.intersectionObserver=new IntersectionObserver((t,e)=>{t.forEach(s=>{var n;s.isIntersecting&&(this.canvas.width=this.canvas.parentNode.clientWidth*this.scale,this.canvas.height=this.canvas.parentNode.clientWidth*this.scale/3,this.canvas.getContext("2d").scale(this.scale,this.scale),(n=this.intersectionObserver)==null||n.disconnect())})}),this.resizeObserver=new ResizeObserver(t=>{for(let e of t){let n=e.contentRect.width<576;this.drawTypeButton.getElementsByTagName("span")[0].style.display=n?"none":"inline-block",this.textTypeButton.getElementsByTagName("span")[0].style.display=n?"none":"inline-block",this.uploadTypeButton.getElementsByTagName("span")[0].style.display=n?"none":"inline-block"}}),this.resizeObserver.observe(this),this.intersectionObserver.observe(this.canvas)}enableDrawPanel(){this.drawTypeButton.querySelector("input").checked=!0,this.textTypeButton.querySelector("input").checked=!1,this.uploadTypeButton.querySelector("input").checked=!1,this.textInput.parentNode.style.display="none",this.undoButton.parentNode.style.display="inline-block",this.pad.on(),this.isColorSelectSettingEnabled&&(this.colorSelect.style.visibility="visible"),this.setTextTypeButtonClassAndStyle(),this.setDrawTypeButtonClassAndStyle(),this.setUploadTypeButtonClassAndStyle(),this.cleaSignaturePad(),this.clearTextInput(),this.clearFileInput()}enableTextPanel(){this.drawTypeButton.querySelector("input").checked=!1,this.uploadTypeButton.querySelector("input").checked=!1,this.textTypeButton.querySelector("input").checked=!0,this.textInput.parentNode.style.display="inherit",this.undoButton.parentNode.style.display="none",this.pad.off(),this.isColorSelectSettingEnabled&&(this.colorSelect.style.visibility="visible"),this.setTextTypeButtonClassAndStyle(),this.setDrawTypeButtonClassAndStyle(),this.setUploadTypeButtonClassAndStyle(),this.cleaSignaturePad(),this.loadFont(),this.clearTextInput(),this.clearFileInput()}enableUploadPanel(){this.uploadTypeButton.querySelector("input").checked=!0,this.drawTypeButton.querySelector("input").checked=!1,this.textTypeButton.querySelector("input").checked=!1,this.textInput.parentNode.style.display="none",this.undoButton.parentNode.style.display="none",this.pad.off(),this.isColorSelectSettingEnabled&&(this.colorSelect.style.visibility="hidden"),this.setTextTypeButtonClassAndStyle(),this.setDrawTypeButtonClassAndStyle(),this.setUploadTypeButtonClassAndStyle(),this.cleaSignaturePad(),this.clearTextInput(),this.clearFileInput()}enableSaveButton(){this.isSubmitButtonSettingEnabled&&(this.saveButton.disabled=!1,this.setSaveButtonClassAndStyle())}disableSaveButton(){this.isSubmitButtonSettingEnabled&&(this.saveButton.disabled=!0,this.setSaveButtonClassAndStyle())}drawText(){let t=this.canvas,e=t.getContext("2d"),s="SignatureFont",n="58px",i="italic",a="";e.font=i+" "+a+" "+n+" "+s,e.textAlign="center",e.clearRect(0,0,t.width/this.scale,t.height/this.scale),e.fillText(this.textInput.value,t.width/2/this.scale,t.height/2/this.scale+11)}drawOnCanvas(t){return new Promise((e,s)=>{if(t&&t.type.match("image.*")){let n=new FileReader,i=this.canvas;n.onload=a=>{let l=new Image;l.src=a.target.result,l.onload=()=>{let r=i.getContext("2d"),o=l.width/l.height,h=i.width/this.scale,d=i.height/this.scale,c=h,u=d;if(h/d>o?c=d*o:u=h/o,u>c){let f=u/c;c=c*f,u=u*f}let p=(h-c)/2,y=(d-u)/2;setTimeout(()=>{r.clearRect(0,0,h,d),r.drawImage(l,p,y,c,u),this.pad.fromDataURL(""),e()},50)},l.onerror=()=>s(new Error("Failed to load image"))},n.onerror=()=>s(new Error("Failed to read file")),n.readAsDataURL(t)}else s(new Error("Invalid file type"))})}clearTextInput(){this.textInput&&(this.textInput.value="",this.handleDownloadState())}cleaSignaturePad(){this.pad.clear(),this.handleDownloadState()}clearFileInput(){this.fileInput&&(this.fileInput.value="",this.handleDownloadState())}handleDownloadState(){this.pad.isEmpty()&&this.textInput.value===""?(this.distributeSignatureData(null),this.disableSaveButton()):(this.cropCanvas(this.canvas).then(t=>{this.distributeSignatureData(t)}).catch(t=>{console.error("Failed to create a PNG blob:",t)}),this.enableSaveButton())}distributeSignatureData(t){let e=this.childrenNode.querySelector('input[type="file"]');if(t){if(this.convertBlobToBase64(t).then(s=>{this.dispatchEvent(new CustomEvent("change",{detail:{base64:s,blob:t}}))}).catch(s=>{this.dispatchEvent(new CustomEvent("change",{detail:{base64:null,blob:null}})),console.error("Failed to convert blob to base64:",s)}),e){let s=new File([t],`signature-${Date.now()}.png`,{type:t.type,lastModified:new Date}),n=new DataTransfer;n.items.add(s),e.files=n.files}}else this.dispatchEvent(new CustomEvent("change",{detail:{base64:null,blob:null}})),e&&(e.value="")}convertBlobToBase64(t){return new Promise((e,s)=>{let n=new FileReader;n.onloadend=()=>{let i=n.result.split(",")[1];e(i)},n.onerror=i=>{s(i)},n.readAsDataURL(t)})}loadFont(){if(!this.isFontLoaded){let t=this.dataset.fontUrl||"https://cdn.jsdelivr.net/npm/@fontsource/dancing-script/files/dancing-script-latin-400-normal.woff";new FontFace("SignatureFont",`url(${t})`).load().then(s=>{document.fonts.add(s),this.isFontLoaded=!0}).catch(s=>{console.error("Font loading failed:",s)})}}downloadBlob(t,e){let s=window.URL.createObjectURL(t),n=document.createElement("a");return n.style="display: none",n.href=s,n.download=e,document.body.appendChild(n),n.click(),window.URL.revokeObjectURL(s),new Promise(i=>{i()})}cropCanvas(t){let e=t.getContext("2d"),s=t.width,n=t.height,i=n,a=0,l=s,r=0,h=e.getImageData(0,0,s,n).data;for(let y=0;y<n;y++)for(let f=0;f<s;f++){let x=(y*s+f)*4;h[x+3]!==0&&(i=Math.min(i,y),a=Math.max(a,y),l=Math.min(l,f),r=Math.max(r,f))}let d=r-l+1,c=a-i+1,u=document.createElement("canvas");return u.width=d,u.height=c,u.getContext("2d").drawImage(t,l,i,d,c,0,0,d,c),new Promise((y,f)=>{u.toBlob(x=>{x?y(x):f(new Error("Failed to create a PNG blob."))},"image/png")})}disconnectedCallback(){this.fieldNode.remove(),this.resizeObserver&&this.resizeObserver.unobserve(this),this.intersectionObserver&&this.intersectionObserver.unobserve(this.canvas)}get tempalte(){return`
2
+ <div>
3
+ <div>
4
+ <div data-target="typeButtonsContainer">
5
+ <div>
6
+ <label data-target="drawTypeButton">
7
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1.5rem; height: 1.5rem;" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
8
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
9
+ <path d="M3 19c3.333 -2 5 -4 5 -6c0 -3 -1 -3 -2 -3s-2.032 1.085 -2 3c.034 2.048 1.658 2.877 2.5 4c1.5 2 2.5 2.5 3.5 1c.667 -1 1.167 -1.833 1.5 -2.5c1 2.333 2.333 3.5 4 3.5h2.5"></path>
10
+ <path d="M20 17v-12c0 -1.121 -.879 -2 -2 -2s-2 .879 -2 2v12l2 2l2 -2z"></path>
11
+ <path d="M16 7h4"></path>
12
+ </svg>
13
+ <span>${this.defaultLabels.drawTypeButton}</span>
14
+ <input type="radio" name="type_option" id="draw_radio" value="draw" style="display: none;">
15
+ </label>
16
+ </div>
17
+ <div>
18
+ <label data-target="textTypeButton">
19
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1.5rem; height: 1.5rem;" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
20
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
21
+ <path d="M3 7v-2h13v2"></path>
22
+ <path d="M10 5v14"></path>
23
+ <path d="M12 19h-4"></path>
24
+ <path d="M15 13v-1h6v1"></path>
25
+ <path d="M18 12v7"></path>
26
+ <path d="M17 19h2"></path>
27
+ </svg>
28
+ <span>${this.defaultLabels.textTypeButton}</span>
29
+ <input type="radio" name="type_option" id="text_radio" value="draw" style="display: none;">
30
+ </label>
31
+ </div>
32
+ <div>
33
+ <label data-target="uploadTypeButton" for="signature_file_upload">
34
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1.5rem; height: 1.5rem;" width="16" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
35
+ <path d="M5 7h1a2 2 0 0 0 2 -2a1 1 0 0 1 1 -1h6a1 1 0 0 1 1 1a2 2 0 0 0 2 2h1a2 2 0 0 1 2 2v9a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-9a2 2 0 0 1 2 -2"></path>
36
+ <path d="M9 13a3 3 0 1 0 6 0a3 3 0 0 0 -6 0"></path>
37
+ </svg>
38
+ <span>${this.defaultLabels.uploadTypeButton}</span>
39
+ <input data-target="fileInput" id="signature_file_upload" type="file" accept="image/*" style="display: none;">
40
+ <input type="radio" name="type_option" id="upload_radio" value="upload" style="display: none;">
41
+ </label>
42
+ </div>
43
+ </div>
44
+ </div
45
+ <div>
46
+ <div>
47
+ <input placeholder="${this.defaultLabels.textInputPlaceholder}" data-target="textInput">
48
+ </div>
49
+ <div>
50
+ <canvas data-target="canvas"></canvas>
51
+ </div>
52
+ <div data-target="controlButtonsContainer">
53
+ <div data-target="colorSelect" style="display: flex; gap: 1rem;">
54
+ <input aria-label="Black" type="radio" data-target="colorInput" name="color" value="#000000" style="accent-color: #000000; transform: scale(1.5);" checked>
55
+ <input aria-label="Blue" type="radio" data-target="colorInput" name="color" value="#3B82F6" style="accent-color: #3B82F6; transform: scale(1.5);">
56
+ <input aria-label="Green" type="radio" data-target="colorInput" name="color" value="#008000" style="accent-color: #008000; transform: scale(1.5);">
57
+ <input aria-label="Red" type="radio" data-target="colorInput" name="color" value="#EF4444" style="accent-color: #EF4444; transform: scale(1.5);">
58
+ </div>
59
+ <div>
60
+ <span>
61
+ <button aria-label="Undo" data-target="undoButton">
62
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1rem; height: 1rem;" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
63
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
64
+ <path d="M9 14l-4 -4l4 -4"></path>
65
+ <path d="M5 10h11a4 4 0 1 1 0 8h-1"></path>
66
+ </svg>
67
+ <span>${this.defaultLabels.undoButton}</span>
68
+ </button>
69
+ </span>
70
+ <span>
71
+ <button aria-label="Clear" data-target="clearButton">
72
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1rem; height: 1rem;" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
73
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
74
+ <path d="M19.933 13.041a8 8 0 1 1 -9.925 -8.788c3.899 -1 7.935 1.007 9.425 4.747"></path>
75
+ <path d="M20 4v5h-5"></path>
76
+ </svg>
77
+ <span>${this.defaultLabels.clearButton}</span>
78
+ </button>
79
+ </span>
80
+ </div>
81
+ </div>
82
+ <div>
83
+ <button data-target="saveButton">
84
+ <span>${this.defaultLabels.saveButton}</span>
85
+ </button>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ `}};if(typeof window<"u"&&window.customElements&&!window.customElements.get("signature-maker"))window.customElements.define("signature-maker",S);else throw new Error("signature-maker-js can only be used in a browser environment.");
90
+ /*! Bundled license information:
91
+
92
+ signature_pad/dist/signature_pad.js:
93
+ (*!
94
+ * Signature Pad v5.0.3 | https://github.com/szimek/signature_pad
95
+ * (c) 2024 Szymon Nowak | Released under the MIT license
96
+ *)
97
+ */
@@ -0,0 +1,97 @@
1
+ var g=class{constructor(t,e,s,n){if(isNaN(t)||isNaN(e))throw new Error(`Point is invalid: (${t}, ${e})`);this.x=+t,this.y=+e,this.pressure=s||0,this.time=n||Date.now()}distanceTo(t){return Math.sqrt(Math.pow(this.x-t.x,2)+Math.pow(this.y-t.y,2))}equals(t){return this.x===t.x&&this.y===t.y&&this.pressure===t.pressure&&this.time===t.time}velocityFrom(t){return this.time!==t.time?this.distanceTo(t)/(this.time-t.time):0}},b=class v{static fromPoints(t,e){let s=this.calculateControlPoints(t[0],t[1],t[2]).c2,n=this.calculateControlPoints(t[1],t[2],t[3]).c1;return new v(t[1],s,n,t[2],e.start,e.end)}static calculateControlPoints(t,e,s){let n=t.x-e.x,i=t.y-e.y,a=e.x-s.x,l=e.y-s.y,r={x:(t.x+e.x)/2,y:(t.y+e.y)/2},o={x:(e.x+s.x)/2,y:(e.y+s.y)/2},h=Math.sqrt(n*n+i*i),d=Math.sqrt(a*a+l*l),c=r.x-o.x,u=r.y-o.y,p=h+d==0?0:d/(h+d),y={x:o.x+c*p,y:o.y+u*p},f=e.x-y.x,x=e.y-y.y;return{c1:new g(r.x+f,r.y+x),c2:new g(o.x+f,o.y+x)}}constructor(t,e,s,n,i,a){this.startPoint=t,this.control2=e,this.control1=s,this.endPoint=n,this.startWidth=i,this.endWidth=a}length(){let e=0,s,n;for(let i=0;i<=10;i+=1){let a=i/10,l=this.point(a,this.startPoint.x,this.control1.x,this.control2.x,this.endPoint.x),r=this.point(a,this.startPoint.y,this.control1.y,this.control2.y,this.endPoint.y);if(i>0){let o=l-s,h=r-n;e+=Math.sqrt(o*o+h*h)}s=l,n=r}return e}point(t,e,s,n,i){return e*(1-t)*(1-t)*(1-t)+3*s*(1-t)*(1-t)*t+3*n*(1-t)*t*t+i*t*t*t}},m=class{constructor(){try{this._et=new EventTarget}catch{this._et=document}}addEventListener(t,e,s){this._et.addEventListener(t,e,s)}dispatchEvent(t){return this._et.dispatchEvent(t)}removeEventListener(t,e,s){this._et.removeEventListener(t,e,s)}};function B(v,t=250){let e=0,s=null,n,i,a,l=()=>{e=Date.now(),s=null,n=v.apply(i,a),s||(i=null,a=[])};return function(...o){let h=Date.now(),d=t-(h-e);return i=this,a=o,d<=0||d>t?(s&&(clearTimeout(s),s=null),e=h,n=v.apply(i,a),s||(i=null,a=[])):s||(s=window.setTimeout(l,d)),n}}var w=class v extends m{constructor(t,e={}){var s,n,i;super(),this.canvas=t,this._drawingStroke=!1,this._isEmpty=!0,this._lastPoints=[],this._data=[],this._lastVelocity=0,this._lastWidth=0,this._handleMouseDown=a=>{!this._isLeftButtonPressed(a,!0)||this._drawingStroke||this._strokeBegin(this._pointerEventToSignatureEvent(a))},this._handleMouseMove=a=>{if(!this._isLeftButtonPressed(a,!0)||!this._drawingStroke){this._strokeEnd(this._pointerEventToSignatureEvent(a),!1);return}this._strokeMoveUpdate(this._pointerEventToSignatureEvent(a))},this._handleMouseUp=a=>{this._isLeftButtonPressed(a)||this._strokeEnd(this._pointerEventToSignatureEvent(a))},this._handleTouchStart=a=>{a.targetTouches.length!==1||this._drawingStroke||(a.cancelable&&a.preventDefault(),this._strokeBegin(this._touchEventToSignatureEvent(a)))},this._handleTouchMove=a=>{if(a.targetTouches.length===1){if(a.cancelable&&a.preventDefault(),!this._drawingStroke){this._strokeEnd(this._touchEventToSignatureEvent(a),!1);return}this._strokeMoveUpdate(this._touchEventToSignatureEvent(a))}},this._handleTouchEnd=a=>{a.targetTouches.length===0&&(a.cancelable&&a.preventDefault(),this.canvas.removeEventListener("touchmove",this._handleTouchMove),this._strokeEnd(this._touchEventToSignatureEvent(a)))},this._handlePointerDown=a=>{!this._isLeftButtonPressed(a)||this._drawingStroke||(a.preventDefault(),this._strokeBegin(this._pointerEventToSignatureEvent(a)))},this._handlePointerMove=a=>{if(!this._isLeftButtonPressed(a,!0)||!this._drawingStroke){this._strokeEnd(this._pointerEventToSignatureEvent(a),!1);return}a.preventDefault(),this._strokeMoveUpdate(this._pointerEventToSignatureEvent(a))},this._handlePointerUp=a=>{this._isLeftButtonPressed(a)||(a.preventDefault(),this._strokeEnd(this._pointerEventToSignatureEvent(a)))},this.velocityFilterWeight=e.velocityFilterWeight||.7,this.minWidth=e.minWidth||.5,this.maxWidth=e.maxWidth||2.5,this.throttle=(s=e.throttle)!==null&&s!==void 0?s:16,this.minDistance=(n=e.minDistance)!==null&&n!==void 0?n:5,this.dotSize=e.dotSize||0,this.penColor=e.penColor||"black",this.backgroundColor=e.backgroundColor||"rgba(0,0,0,0)",this.compositeOperation=e.compositeOperation||"source-over",this.canvasContextOptions=(i=e.canvasContextOptions)!==null&&i!==void 0?i:{},this._strokeMoveUpdate=this.throttle?B(v.prototype._strokeUpdate,this.throttle):v.prototype._strokeUpdate,this._ctx=t.getContext("2d",this.canvasContextOptions),this.clear(),this.on()}clear(){let{_ctx:t,canvas:e}=this;t.fillStyle=this.backgroundColor,t.clearRect(0,0,e.width,e.height),t.fillRect(0,0,e.width,e.height),this._data=[],this._reset(this._getPointGroupOptions()),this._isEmpty=!0}fromDataURL(t,e={}){return new Promise((s,n)=>{let i=new Image,a=e.ratio||window.devicePixelRatio||1,l=e.width||this.canvas.width/a,r=e.height||this.canvas.height/a,o=e.xOffset||0,h=e.yOffset||0;this._reset(this._getPointGroupOptions()),i.onload=()=>{this._ctx.drawImage(i,o,h,l,r),s()},i.onerror=d=>{n(d)},i.crossOrigin="anonymous",i.src=t,this._isEmpty=!1})}toDataURL(t="image/png",e){switch(t){case"image/svg+xml":return typeof e!="object"&&(e=void 0),`data:image/svg+xml;base64,${btoa(this.toSVG(e))}`;default:return typeof e!="number"&&(e=void 0),this.canvas.toDataURL(t,e)}}on(){this.canvas.style.touchAction="none",this.canvas.style.msTouchAction="none",this.canvas.style.userSelect="none";let t=/Macintosh/.test(navigator.userAgent)&&"ontouchstart"in document;window.PointerEvent&&!t?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())}off(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.style.userSelect="auto",this.canvas.removeEventListener("pointerdown",this._handlePointerDown),this.canvas.removeEventListener("mousedown",this._handleMouseDown),this.canvas.removeEventListener("touchstart",this._handleTouchStart),this._removeMoveUpEventListeners()}_getListenerFunctions(){var t;let e=window.document===this.canvas.ownerDocument?window:(t=this.canvas.ownerDocument.defaultView)!==null&&t!==void 0?t:this.canvas.ownerDocument;return{addEventListener:e.addEventListener.bind(e),removeEventListener:e.removeEventListener.bind(e)}}_removeMoveUpEventListeners(){let{removeEventListener:t}=this._getListenerFunctions();t("pointermove",this._handlePointerMove),t("pointerup",this._handlePointerUp),t("mousemove",this._handleMouseMove),t("mouseup",this._handleMouseUp),t("touchmove",this._handleTouchMove),t("touchend",this._handleTouchEnd)}isEmpty(){return this._isEmpty}fromData(t,{clear:e=!0}={}){e&&this.clear(),this._fromData(t,this._drawCurve.bind(this),this._drawDot.bind(this)),this._data=this._data.concat(t)}toData(){return this._data}_isLeftButtonPressed(t,e){return e?t.buttons===1:(t.buttons&1)===1}_pointerEventToSignatureEvent(t){return{event:t,type:t.type,x:t.clientX,y:t.clientY,pressure:"pressure"in t?t.pressure:0}}_touchEventToSignatureEvent(t){let e=t.changedTouches[0];return{event:t,type:t.type,x:e.clientX,y:e.clientY,pressure:e.force}}_getPointGroupOptions(t){return{penColor:t&&"penColor"in t?t.penColor:this.penColor,dotSize:t&&"dotSize"in t?t.dotSize:this.dotSize,minWidth:t&&"minWidth"in t?t.minWidth:this.minWidth,maxWidth:t&&"maxWidth"in t?t.maxWidth:this.maxWidth,velocityFilterWeight:t&&"velocityFilterWeight"in t?t.velocityFilterWeight:this.velocityFilterWeight,compositeOperation:t&&"compositeOperation"in t?t.compositeOperation:this.compositeOperation}}_strokeBegin(t){if(!this.dispatchEvent(new CustomEvent("beginStroke",{detail:t,cancelable:!0})))return;let{addEventListener:s}=this._getListenerFunctions();switch(t.event.type){case"mousedown":s("mousemove",this._handleMouseMove),s("mouseup",this._handleMouseUp);break;case"touchstart":s("touchmove",this._handleTouchMove),s("touchend",this._handleTouchEnd);break;case"pointerdown":s("pointermove",this._handlePointerMove),s("pointerup",this._handlePointerUp);break}this._drawingStroke=!0;let n=this._getPointGroupOptions(),i=Object.assign(Object.assign({},n),{points:[]});this._data.push(i),this._reset(n),this._strokeUpdate(t)}_strokeUpdate(t){if(!this._drawingStroke)return;if(this._data.length===0){this._strokeBegin(t);return}this.dispatchEvent(new CustomEvent("beforeUpdateStroke",{detail:t}));let e=this._createPoint(t.x,t.y,t.pressure),s=this._data[this._data.length-1],n=s.points,i=n.length>0&&n[n.length-1],a=i?e.distanceTo(i)<=this.minDistance:!1,l=this._getPointGroupOptions(s);if(!i||!(i&&a)){let r=this._addPoint(e,l);i?r&&this._drawCurve(r,l):this._drawDot(e,l),n.push({time:e.time,x:e.x,y:e.y,pressure:e.pressure})}this.dispatchEvent(new CustomEvent("afterUpdateStroke",{detail:t}))}_strokeEnd(t,e=!0){this._removeMoveUpEventListeners(),this._drawingStroke&&(e&&this._strokeUpdate(t),this._drawingStroke=!1,this.dispatchEvent(new CustomEvent("endStroke",{detail:t})))}_handlePointerEvents(){this._drawingStroke=!1,this.canvas.addEventListener("pointerdown",this._handlePointerDown)}_handleMouseEvents(){this._drawingStroke=!1,this.canvas.addEventListener("mousedown",this._handleMouseDown)}_handleTouchEvents(){this.canvas.addEventListener("touchstart",this._handleTouchStart)}_reset(t){this._lastPoints=[],this._lastVelocity=0,this._lastWidth=(t.minWidth+t.maxWidth)/2,this._ctx.fillStyle=t.penColor,this._ctx.globalCompositeOperation=t.compositeOperation}_createPoint(t,e,s){let n=this.canvas.getBoundingClientRect();return new g(t-n.left,e-n.top,s,new Date().getTime())}_addPoint(t,e){let{_lastPoints:s}=this;if(s.push(t),s.length>2){s.length===3&&s.unshift(s[0]);let n=this._calculateCurveWidths(s[1],s[2],e),i=b.fromPoints(s,n);return s.shift(),i}return null}_calculateCurveWidths(t,e,s){let n=s.velocityFilterWeight*e.velocityFrom(t)+(1-s.velocityFilterWeight)*this._lastVelocity,i=this._strokeWidth(n,s),a={end:i,start:this._lastWidth};return this._lastVelocity=n,this._lastWidth=i,a}_strokeWidth(t,e){return Math.max(e.maxWidth/(t+1),e.minWidth)}_drawCurveSegment(t,e,s){let n=this._ctx;n.moveTo(t,e),n.arc(t,e,s,0,2*Math.PI,!1),this._isEmpty=!1}_drawCurve(t,e){let s=this._ctx,n=t.endWidth-t.startWidth,i=Math.ceil(t.length())*2;s.beginPath(),s.fillStyle=e.penColor;for(let a=0;a<i;a+=1){let l=a/i,r=l*l,o=r*l,h=1-l,d=h*h,c=d*h,u=c*t.startPoint.x;u+=3*d*l*t.control1.x,u+=3*h*r*t.control2.x,u+=o*t.endPoint.x;let p=c*t.startPoint.y;p+=3*d*l*t.control1.y,p+=3*h*r*t.control2.y,p+=o*t.endPoint.y;let y=Math.min(t.startWidth+o*n,e.maxWidth);this._drawCurveSegment(u,p,y)}s.closePath(),s.fill()}_drawDot(t,e){let s=this._ctx,n=e.dotSize>0?e.dotSize:(e.minWidth+e.maxWidth)/2;s.beginPath(),this._drawCurveSegment(t.x,t.y,n),s.closePath(),s.fillStyle=e.penColor,s.fill()}_fromData(t,e,s){for(let n of t){let{points:i}=n,a=this._getPointGroupOptions(n);if(i.length>1)for(let l=0;l<i.length;l+=1){let r=i[l],o=new g(r.x,r.y,r.pressure,r.time);l===0&&this._reset(a);let h=this._addPoint(o,a);h&&e(h,a)}else this._reset(a),s(i[0],a)}}toSVG({includeBackgroundColor:t=!1}={}){let e=this._data,s=Math.max(window.devicePixelRatio||1,1),n=0,i=0,a=this.canvas.width/s,l=this.canvas.height/s,r=document.createElementNS("http://www.w3.org/2000/svg","svg");if(r.setAttribute("xmlns","http://www.w3.org/2000/svg"),r.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink"),r.setAttribute("viewBox",`${n} ${i} ${a} ${l}`),r.setAttribute("width",a.toString()),r.setAttribute("height",l.toString()),t&&this.backgroundColor){let o=document.createElement("rect");o.setAttribute("width","100%"),o.setAttribute("height","100%"),o.setAttribute("fill",this.backgroundColor),r.appendChild(o)}return this._fromData(e,(o,{penColor:h})=>{let d=document.createElement("path");if(!isNaN(o.control1.x)&&!isNaN(o.control1.y)&&!isNaN(o.control2.x)&&!isNaN(o.control2.y)){let c=`M ${o.startPoint.x.toFixed(3)},${o.startPoint.y.toFixed(3)} C ${o.control1.x.toFixed(3)},${o.control1.y.toFixed(3)} ${o.control2.x.toFixed(3)},${o.control2.y.toFixed(3)} ${o.endPoint.x.toFixed(3)},${o.endPoint.y.toFixed(3)}`;d.setAttribute("d",c),d.setAttribute("stroke-width",(o.endWidth*2.25).toFixed(3)),d.setAttribute("stroke",h),d.setAttribute("fill","none"),d.setAttribute("stroke-linecap","round"),r.appendChild(d)}},(o,{penColor:h,dotSize:d,minWidth:c,maxWidth:u})=>{let p=document.createElement("circle"),y=d>0?d:(c+u)/2;p.setAttribute("r",y.toString()),p.setAttribute("cx",o.x.toString()),p.setAttribute("cy",o.y.toString()),p.setAttribute("fill",h),r.appendChild(p)}),r.outerHTML}};var S=class extends HTMLElement{static DEFAULT_STYLES={controlButtonsContainer:"display: flex; align-items: center; justify-content: space-between; text-align: center; margin: 1rem 0;",saveButton:"color: #ffffff; font-family: ui-sans-serif, system-ui, sans-serif font-size: 16px; font-weight: 600; line-height: 24px; padding: 0px 16px; text-transform: uppercase; background-color: #222222; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 48px; justify-content: center; outline-color: #222222; text-align: center; text-decoration-line: none; width: 100%; border: 1px solid #222222;",saveButtonDisabled:"background-color: #D3D3D3; color: #808080; cursor: not-allowed; border: 0;",undoButton:"color: #222222; background-color: transparent; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 14px; font-weight: 500; line-height: 14px; padding: 0px 12px; text-transform: uppercase; appearance: button; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 32px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",clearButton:"color: #222222; background-color: transparent; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 14px; font-weight: 500; line-height: 14px; padding: 0px 12px; text-transform: uppercase; appearance: button; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 32px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",canvas:"display: block; vertical-align: middle; width: 100%; border-radius: 8px; background-color: #ffffff; padding: 1px; touch-action: none; user-select: none; text-align: center; line-height: 24px; border: 1px solid #D3D3D3;",textInput:"color: #222222; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 24px; font-weight: 400; line-height: 32px; margin: 0px 0px 16px; padding: 0px 16px; background-color: #ffffff; border-radius: 8px; flex-shrink: 1; height: 56px; outline: #222222 none 0px; outline-offset: 0px; width: 100%; text-align: start; border: 1px solid #D3D3D3;",typeButtonsContainer:"margin-bottom: 1rem; display: flex; justify-content: center; flex-wrap: wrap; gap: 0.5rem;",drawTypeButton:"color: #222222; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 16px; font-weight: 500; line-height: 24px; padding: 0px 40px; text-transform: uppercase; background-color: transparent; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 48px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",drawTypeButtonActive:"color: #fff; background-color: #222222; font-weight: 500;",textTypeButton:"color: #222222; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 16px; font-weight: 500; line-height: 24px; padding: 0px 40px; text-transform: uppercase; background-color: transparent; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 48px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",textTypeButtonActive:"color: #fff; background-color: #222222; font-weight: 500;",uploadTypeButton:"color: #222222; font-family: ui-sans-serif, system-ui, sans-serif; font-size: 16px; font-weight: 500; line-height: 24px; padding: 0px 40px; text-transform: uppercase; background-color: transparent; cursor: pointer; align-items: center; border-radius: 8px; gap: 8px; display: inline-flex; flex-shrink: 0; flex-wrap: wrap; height: 48px; justify-content: center; outline-color: #222222; text-align: center; border: 1px solid #222222;",uploadTypeButtonActive:"color: #fff; background-color: #222222; font-weight: 500;"};static DEFAULT_LABELS={drawTypeButton:"Draw",textTypeButton:"Type",uploadTypeButton:"Upload",undoButton:"Undo",clearButton:"Clear",saveButton:"Submit",textInputPlaceholder:"Type signature here"};constructor(){super(),this.isMounted=!1}static observedAttributes=["data-download-on-save","data-with-typed","data-with-drawn","data-with-upload","data-with-color-select","data-with-submit","data-control-buttons-container-class","data-control-buttons-container-style","data-save-button-text","data-save-button-class","data-save-button-style","data-save-button-disabled-class","data-save-button-disabled-style","data-undo-button-text","data-undo-button-class","data-undo-button-style","data-clear-button-text","data-clear-button-class","data-clear-button-style","data-text-input-placeholder","data-text-input-class","data-text-input-style","data-canvas-class","data-canvas-style","data-type-buttons-container-class","data-type-buttons-container-style","data-draw-type-button-text","data-draw-type-button-class","data-draw-type-button-style","data-draw-type-button-active-class","data-draw-type-button-active-style","data-text-type-button-text","data-text-type-button-class","data-text-type-button-style","data-text-type-button-active-class","data-text-type-button-active-style","data-upload-type-button-text","data-upload-type-button-class","data-upload-type-button-style","data-upload-type-button-active-class","data-upload-type-button-active-style"];get defaultStyles(){return this.constructor.DEFAULT_STYLES}get defaultLabels(){return this.constructor.DEFAULT_LABELS}get clearButton(){return this.querySelector('[data-target="clearButton"]')}get undoButton(){return this.querySelector('[data-target="undoButton"]')}get controlButtonsContainer(){return this.querySelector('[data-target="controlButtonsContainer"]')}get typeButtonsContainer(){return this.querySelector('[data-target="typeButtonsContainer"]')}get drawTypeButton(){return this.querySelector('[data-target="drawTypeButton"]')}get textTypeButton(){return this.querySelector('[data-target="textTypeButton"]')}get uploadTypeButton(){return this.querySelector('[data-target="uploadTypeButton"]')}get textInput(){return this.querySelector('[data-target="textInput"]')}get fileInput(){return this.querySelector('[data-target="fileInput"]')}get saveButton(){return this.querySelector('[data-target="saveButton"]')}get canvas(){return this.querySelector('[data-target="canvas"]')}get colorSelect(){return this.querySelector('[data-target="colorSelect"]')}get colorInputs(){return[...this.querySelectorAll('[data-target="colorInput"]')]}get setters(){return{"data-with-typed":this.setDisplayType,"data-with-drawn":this.setDisplayType,"data-with-upload":this.setDisplayType,"data-with-color-select":this.setDisplayColorSelect,"data-with-submit":this.setDisplaySubmit,"data-control-buttons-container-class":this.setControlButtonsContainerClassAndStyle,"data-control-buttons-container-style":this.setControlButtonsContainerClassAndStyle,"data-save-button-text":this.setSaveButtonText,"data-save-button-class":this.setSaveButtonClassAndStyle,"data-save-button-style":this.setSaveButtonClassAndStyle,"data-save-button-disabled-class":this.setSaveButtonClassAndStyle,"data-save-button-disabled-style":this.setSaveButtonClassAndStyle,"data-undo-button-text":this.setUndoButtonText,"data-undo-button-class":this.setUndoButtonClassAndStyle,"data-undo-button-style":this.setUndoButtonClassAndStyle,"data-clear-button-text":this.setCleaButtonText,"data-clear-button-class":this.setClearButtonClassAndStyle,"data-clear-button-style":this.setClearButtonClassAndStyle,"data-canvas-class":this.setCanvasClassAndStyle,"data-canvas-style":this.setCanvasClassAndStyle,"data-text-input-placeholder":this.setTextInputPlaceholder,"data-text-input-class":this.setTextInputClassAndStyle,"data-text-input-style":this.setTextInputClassAndStyle,"data-type-buttons-container-class":this.setTypeButtonsContainerClassAndStyle,"data-type-buttons-container-style":this.setTypeButtonsContainerClassAndStyle,"data-draw-type-button-text":this.setDrawTypeButtonText,"data-draw-type-button-class":this.setDrawTypeButtonClassAndStyle,"data-draw-type-button-style":this.setDrawTypeButtonClassAndStyle,"data-draw-type-button-active-class":this.setDrawTypeButtonClassAndStyle,"data-draw-type-button-active-style":this.setDrawTypeButtonClassAndStyle,"data-text-type-button-text":this.setTextTypeButtonText,"data-text-type-button-class":this.setTextTypeButtonClassAndStyle,"data-text-type-button-style":this.setTextTypeButtonClassAndStyle,"data-text-type-button-active-class":this.setTextTypeButtonClassAndStyle,"data-text-type-button-active-style":this.setTextTypeButtonClassAndStyle,"data-upload-type-button-text":this.setUploadTypeButtonText,"data-upload-type-button-class":this.setUploadTypeButtonClassAndStyle,"data-upload-type-button-style":this.setUploadTypeButtonClassAndStyle,"data-upload-type-button-active-class":this.setUploadTypeButtonClassAndStyle,"data-upload-type-button-active-style":this.setUploadTypeButtonClassAndStyle}}get isDrawTypeSelected(){return this.drawTypeButton.querySelector("input").checked}get isTextTypeSelected(){return this.textTypeButton.querySelector("input").checked}get isUploadTypeSelected(){return this.uploadTypeButton.querySelector("input").checked}get isSaveButtonDisabled(){return this.saveButton.disabled}get isDownloadOnSaveSettingEnabled(){return this.dataset.downloadOnSave==="true"}get isColorSelectSettingEnabled(){return this.dataset.withColorSelect!=="false"}get isSubmitButtonSettingEnabled(){return this.dataset.withSubmit!=="false"}setDisplayType=()=>{let t=[this.dataset.withDrawn,this.dataset.withTyped,this.dataset.withUpload].filter(e=>e==="false");this.textTypeButton.parentNode.style.display=this.dataset.withTyped==="false"?"none":"inherit",this.drawTypeButton.parentNode.style.display=this.dataset.withDrawn==="false"?"none":"inherit",this.uploadTypeButton.parentNode.style.display=this.dataset.withUpload==="false"?"none":"inherit",this.typeButtonsContainer.parentNode.style.display=t.length>1&&this.dataset.withUpload==="false"?"none":"inherit",t.length===3?console.error('At least one of the "with-typed", "with-drawn", or "with-upload" attributes must be set to "true".'):this.dataset.withDrawn!=="false"?this.enableDrawPanel():this.dataset.withTyped!=="false"?this.enableTextPanel():this.dataset.withUpload!=="false"&&this.enableUploadPanel()};setDisplayColorSelect=()=>{this.colorSelect.style.visibility=this.dataset.withColorSelect==="false"?"hidden":"visible"};setDisplaySubmit=()=>{this.saveButton.parentNode.style.display=this.dataset.withSubmit==="false"?"none":"inherit"};setControlButtonsContainerClassAndStyle=()=>{let t=this.dataset.controlButtonsContainerClass||"",e=this.dataset.controlButtonsContainerStyle||(t?"":this.defaultStyles.controlButtonsContainer);this.controlButtonsContainer.setAttribute("style",e),this.controlButtonsContainer.setAttribute("class",t)};setSaveButtonText=()=>{let t=this.saveButton.querySelector("span");t&&(t.innerText=this.dataset.saveButtonText||this.defaultLabels.saveButton)};setSaveButtonClassAndStyle=()=>{let t=this.dataset.saveButtonClass||"",e=this.dataset.saveButtonStyle||(t?"":this.defaultStyles.saveButton);this.isSaveButtonDisabled&&(t&&this.dataset.saveButtonDisabledClass&&(t=this.combineStrings(t,this.dataset.saveButtonDisabledClass)),e&&this.dataset.saveButtonDisabledStyle?e=this.combineStrings(e,this.dataset.saveButtonDisabledStyle):t||(e=this.combineStrings(e,this.defaultStyles.saveButtonDisabled))),this.saveButton.setAttribute("class",t),this.saveButton.setAttribute("style",e)};setUndoButtonText=()=>{let t=this.undoButton.querySelector("span");t&&(t.innerText=this.dataset.undoButtonText||this.defaultLabels.undoButton)};setUndoButtonClassAndStyle=()=>{let t=this.dataset.undoButtonClass||"",e=this.dataset.undoButtonStyle||(t?"":this.defaultStyles.undoButton);this.undoButton.setAttribute("class",t),this.undoButton.setAttribute("style",e)};setCleaButtonText=()=>{let t=this.clearButton.querySelector("span");t&&(t.innerText=this.dataset.clearButtonText||this.defaultLabels.clearButton)};setClearButtonClassAndStyle=()=>{let t=this.dataset.clearButtonClass||"",e=this.dataset.clearButtonStyle||(t?"":this.defaultStyles.clearButton);this.clearButton.setAttribute("class",t),this.clearButton.setAttribute("style",e)};setCanvasClassAndStyle=()=>{let t=this.dataset.canvasClass||"",e=this.dataset.canvasStyle||(t?"padding: 1px; touch-action: none; user-select: none;":this.defaultStyles.canvas);this.canvas.setAttribute("class",t),this.canvas.setAttribute("style",e)};setTypeButtonsContainerClassAndStyle=()=>{let t=this.dataset.typeButtonsContainerClass||"",e=this.dataset.typeButtonsContainerStyle||(t?"":this.defaultStyles.typeButtonsContainer);this.typeButtonsContainer.setAttribute("style",e),this.typeButtonsContainer.setAttribute("class",t)};setTextInputPlaceholder=()=>{this.textInput.setAttribute("placeholder",this.dataset.textInputPlaceholder||this.defaultLabels.textInputPlaceholder)};setTextInputClassAndStyle=()=>{let t=this.dataset.textInputClass||"",e=this.dataset.textInputStyle||(t?"":this.defaultStyles.textInput);this.textInput.setAttribute("class",t),this.textInput.setAttribute("style",e)};setDrawTypeButtonText=()=>{let t=this.drawTypeButton.querySelector("span");t&&(t.innerText=this.dataset.drawTypeButtonText||this.defaultLabels.drawTypeButton)};setDrawTypeButtonClassAndStyle=()=>{let t=this.dataset.drawTypeButtonClass||"",e=this.dataset.drawTypeButtonStyle||(t?"":this.defaultStyles.drawTypeButton);this.isDrawTypeSelected&&(t&&this.dataset.drawTypeButtonActiveClass&&(t=this.combineStrings(t,this.dataset.drawTypeButtonActiveClass)),e&&this.dataset.drawTypeButtonActiveStyle?e=this.combineStrings(e,this.dataset.drawTypeButtonActiveStyle):t||(e=this.combineStrings(e,this.defaultStyles.drawTypeButtonActive))),this.drawTypeButton.setAttribute("class",t),this.drawTypeButton.setAttribute("style",e)};setTextTypeButtonText=()=>{let t=this.textTypeButton.querySelector("span");t&&(t.innerText=this.dataset.textTypeButtonText||this.defaultLabels.textTypeButton)};setTextTypeButtonClassAndStyle=()=>{let t=this.dataset.textTypeButtonClass||"",e=this.dataset.textTypeButtonStyle||t?"":this.defaultStyles.textTypeButton;this.isTextTypeSelected&&(t&&this.dataset.textTypeButtonActiveClass&&(t=this.combineStrings(t,this.dataset.textTypeButtonActiveClass)),e&&this.dataset.textTypeButtonActiveStyle?e=this.combineStrings(e,this.dataset.textTypeButtonActiveStyle):t||(e=this.combineStrings(e,this.defaultStyles.textTypeButtonActive))),this.textTypeButton.setAttribute("class",t),this.textTypeButton.setAttribute("style",e)};setUploadTypeButtonText=()=>{let t=this.uploadTypeButton.querySelector("span");t&&(t.innerText=this.dataset.uploadTypeButtonText||this.defaultLabels.uploadTypeButton)};setUploadTypeButtonClassAndStyle=()=>{let t=this.dataset.uploadTypeButtonClass||"",e=this.dataset.uploadTypeButtonStyle||t?"":this.defaultStyles.uploadTypeButton;this.isUploadTypeSelected&&(t&&this.dataset.uploadTypeButtonActiveClass&&(t=this.combineStrings(t,this.dataset.uploadTypeButtonActiveClass)),e&&this.dataset.uploadTypeButtonActiveStyle?e=this.combineStrings(e,this.dataset.uploadTypeButtonActiveStyle):t||(e=this.combineStrings(e,this.defaultStyles.uploadTypeButtonActive))),this.uploadTypeButton.setAttribute("class",t),this.uploadTypeButton.setAttribute("style",e)};combineStrings(t,e){return[t,e].filter(Boolean).join(" ")}attributeChangedCallback(t,e,s){this.isMounted&&this.setters[t]&&e!==s&&this.setters[t]()}connectedCallback(){document.readyState!=="complete"?document.addEventListener("DOMContentLoaded",()=>this.init()):this.init()}init(){this.style.display="block",this.childrenNode=document.createElement("div"),this.appendChild(this.childrenNode),Array.from(this.childNodes).map(t=>{this.childrenNode!==t&&this.childrenNode.appendChild(t)}),this.childrenNode.style.display="none",this.fieldNode=document.createElement("div"),this.fieldNode.innerHTML=this.tempalte,this.appendChild(this.fieldNode),this.pad=new w(this.canvas),this.isMounted=!0;for(let t in this.setters)this.setters.hasOwnProperty(t)&&this.setters[t]();this.scale=2,this.isFontLoaded=!1,this.canvas.width=this.canvas.parentNode.parentNode.clientWidth,this.canvas.height=this.canvas.parentNode.parentNode.clientWidth/this.scale,this.dataset.withDrawn!=="false"?this.enableDrawPanel():this.dataset.withTyped!=="false"?this.enableTextPanel():this.dataset.withUpload!=="false"?this.enableUploadPanel():this.enableDrawPanel(),this.pad.addEventListener("endStroke",()=>{this.handleDownloadState()}),this.clearButton.addEventListener("click",t=>{t.preventDefault(),this.cleaSignaturePad(),this.clearTextInput()}),this.undoButton.addEventListener("click",t=>{t.preventDefault();let e=this.pad.toData();e&&(e.pop(),this.pad.fromData(e),this.handleDownloadState())}),this.drawTypeButton.addEventListener("click",t=>{t.preventDefault(),this.enableDrawPanel()}),this.textTypeButton.addEventListener("click",t=>{t.preventDefault(),this.enableTextPanel()}),this.uploadTypeButton.addEventListener("click",()=>{this.uploadTypeButton.querySelector('input[type="radio"]').checked=!0,this.enableUploadPanel()}),this.fileInput.addEventListener("change",t=>{this.drawOnCanvas(t.target.files[0]).then(()=>{this.handleDownloadState()}).catch(e=>{alert(e.message)})}),this.colorInputs.forEach(t=>{t.addEventListener("change",e=>{this.textInput.value!==""&&(this.canvas.getContext("2d").fillStyle=e.target.value,this.drawText()),this.pad.penColor=e.target.value})}),this.textInput.addEventListener("input",()=>{this.drawText(),this.handleDownloadState()}),this.saveButton.addEventListener("click",t=>{t.preventDefault(),this.disableSaveButton(),this.cropCanvas(this.canvas).then(e=>{this.isDownloadOnSaveSettingEnabled&&this.downloadBlob(e,`signature-${Date.now()}.png`),this.convertBlobToBase64(e).then(s=>{this.dispatchEvent(new CustomEvent("save",{detail:{base64:s,blob:e}}))}).catch(s=>{console.error("Failed to convert blob to base64:",s)})}).then(()=>{this.enableSaveButton()}).catch(e=>{console.error("Download failed:",e),this.disableSaveButton()})}),this.intersectionObserver=new IntersectionObserver((t,e)=>{t.forEach(s=>{var n;s.isIntersecting&&(this.canvas.width=this.canvas.parentNode.clientWidth*this.scale,this.canvas.height=this.canvas.parentNode.clientWidth*this.scale/3,this.canvas.getContext("2d").scale(this.scale,this.scale),(n=this.intersectionObserver)==null||n.disconnect())})}),this.resizeObserver=new ResizeObserver(t=>{for(let e of t){let n=e.contentRect.width<576;this.drawTypeButton.getElementsByTagName("span")[0].style.display=n?"none":"inline-block",this.textTypeButton.getElementsByTagName("span")[0].style.display=n?"none":"inline-block",this.uploadTypeButton.getElementsByTagName("span")[0].style.display=n?"none":"inline-block"}}),this.resizeObserver.observe(this),this.intersectionObserver.observe(this.canvas)}enableDrawPanel(){this.drawTypeButton.querySelector("input").checked=!0,this.textTypeButton.querySelector("input").checked=!1,this.uploadTypeButton.querySelector("input").checked=!1,this.textInput.parentNode.style.display="none",this.undoButton.parentNode.style.display="inline-block",this.pad.on(),this.isColorSelectSettingEnabled&&(this.colorSelect.style.visibility="visible"),this.setTextTypeButtonClassAndStyle(),this.setDrawTypeButtonClassAndStyle(),this.setUploadTypeButtonClassAndStyle(),this.cleaSignaturePad(),this.clearTextInput(),this.clearFileInput()}enableTextPanel(){this.drawTypeButton.querySelector("input").checked=!1,this.uploadTypeButton.querySelector("input").checked=!1,this.textTypeButton.querySelector("input").checked=!0,this.textInput.parentNode.style.display="inherit",this.undoButton.parentNode.style.display="none",this.pad.off(),this.isColorSelectSettingEnabled&&(this.colorSelect.style.visibility="visible"),this.setTextTypeButtonClassAndStyle(),this.setDrawTypeButtonClassAndStyle(),this.setUploadTypeButtonClassAndStyle(),this.cleaSignaturePad(),this.loadFont(),this.clearTextInput(),this.clearFileInput()}enableUploadPanel(){this.uploadTypeButton.querySelector("input").checked=!0,this.drawTypeButton.querySelector("input").checked=!1,this.textTypeButton.querySelector("input").checked=!1,this.textInput.parentNode.style.display="none",this.undoButton.parentNode.style.display="none",this.pad.off(),this.isColorSelectSettingEnabled&&(this.colorSelect.style.visibility="hidden"),this.setTextTypeButtonClassAndStyle(),this.setDrawTypeButtonClassAndStyle(),this.setUploadTypeButtonClassAndStyle(),this.cleaSignaturePad(),this.clearTextInput(),this.clearFileInput()}enableSaveButton(){this.isSubmitButtonSettingEnabled&&(this.saveButton.disabled=!1,this.setSaveButtonClassAndStyle())}disableSaveButton(){this.isSubmitButtonSettingEnabled&&(this.saveButton.disabled=!0,this.setSaveButtonClassAndStyle())}drawText(){let t=this.canvas,e=t.getContext("2d"),s="SignatureFont",n="58px",i="italic",a="";e.font=i+" "+a+" "+n+" "+s,e.textAlign="center",e.clearRect(0,0,t.width/this.scale,t.height/this.scale),e.fillText(this.textInput.value,t.width/2/this.scale,t.height/2/this.scale+11)}drawOnCanvas(t){return new Promise((e,s)=>{if(t&&t.type.match("image.*")){let n=new FileReader,i=this.canvas;n.onload=a=>{let l=new Image;l.src=a.target.result,l.onload=()=>{let r=i.getContext("2d"),o=l.width/l.height,h=i.width/this.scale,d=i.height/this.scale,c=h,u=d;if(h/d>o?c=d*o:u=h/o,u>c){let f=u/c;c=c*f,u=u*f}let p=(h-c)/2,y=(d-u)/2;setTimeout(()=>{r.clearRect(0,0,h,d),r.drawImage(l,p,y,c,u),this.pad.fromDataURL(""),e()},50)},l.onerror=()=>s(new Error("Failed to load image"))},n.onerror=()=>s(new Error("Failed to read file")),n.readAsDataURL(t)}else s(new Error("Invalid file type"))})}clearTextInput(){this.textInput&&(this.textInput.value="",this.handleDownloadState())}cleaSignaturePad(){this.pad.clear(),this.handleDownloadState()}clearFileInput(){this.fileInput&&(this.fileInput.value="",this.handleDownloadState())}handleDownloadState(){this.pad.isEmpty()&&this.textInput.value===""?(this.distributeSignatureData(null),this.disableSaveButton()):(this.cropCanvas(this.canvas).then(t=>{this.distributeSignatureData(t)}).catch(t=>{console.error("Failed to create a PNG blob:",t)}),this.enableSaveButton())}distributeSignatureData(t){let e=this.childrenNode.querySelector('input[type="file"]');if(t){if(this.convertBlobToBase64(t).then(s=>{this.dispatchEvent(new CustomEvent("change",{detail:{base64:s,blob:t}}))}).catch(s=>{this.dispatchEvent(new CustomEvent("change",{detail:{base64:null,blob:null}})),console.error("Failed to convert blob to base64:",s)}),e){let s=new File([t],`signature-${Date.now()}.png`,{type:t.type,lastModified:new Date}),n=new DataTransfer;n.items.add(s),e.files=n.files}}else this.dispatchEvent(new CustomEvent("change",{detail:{base64:null,blob:null}})),e&&(e.value="")}convertBlobToBase64(t){return new Promise((e,s)=>{let n=new FileReader;n.onloadend=()=>{let i=n.result.split(",")[1];e(i)},n.onerror=i=>{s(i)},n.readAsDataURL(t)})}loadFont(){if(!this.isFontLoaded){let t=this.dataset.fontUrl||"https://cdn.jsdelivr.net/npm/@fontsource/dancing-script/files/dancing-script-latin-400-normal.woff";new FontFace("SignatureFont",`url(${t})`).load().then(s=>{document.fonts.add(s),this.isFontLoaded=!0}).catch(s=>{console.error("Font loading failed:",s)})}}downloadBlob(t,e){let s=window.URL.createObjectURL(t),n=document.createElement("a");return n.style="display: none",n.href=s,n.download=e,document.body.appendChild(n),n.click(),window.URL.revokeObjectURL(s),new Promise(i=>{i()})}cropCanvas(t){let e=t.getContext("2d"),s=t.width,n=t.height,i=n,a=0,l=s,r=0,h=e.getImageData(0,0,s,n).data;for(let y=0;y<n;y++)for(let f=0;f<s;f++){let x=(y*s+f)*4;h[x+3]!==0&&(i=Math.min(i,y),a=Math.max(a,y),l=Math.min(l,f),r=Math.max(r,f))}let d=r-l+1,c=a-i+1,u=document.createElement("canvas");return u.width=d,u.height=c,u.getContext("2d").drawImage(t,l,i,d,c,0,0,d,c),new Promise((y,f)=>{u.toBlob(x=>{x?y(x):f(new Error("Failed to create a PNG blob."))},"image/png")})}disconnectedCallback(){this.fieldNode.remove(),this.resizeObserver&&this.resizeObserver.unobserve(this),this.intersectionObserver&&this.intersectionObserver.unobserve(this.canvas)}get tempalte(){return`
2
+ <div>
3
+ <div>
4
+ <div data-target="typeButtonsContainer">
5
+ <div>
6
+ <label data-target="drawTypeButton">
7
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1.5rem; height: 1.5rem;" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
8
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
9
+ <path d="M3 19c3.333 -2 5 -4 5 -6c0 -3 -1 -3 -2 -3s-2.032 1.085 -2 3c.034 2.048 1.658 2.877 2.5 4c1.5 2 2.5 2.5 3.5 1c.667 -1 1.167 -1.833 1.5 -2.5c1 2.333 2.333 3.5 4 3.5h2.5"></path>
10
+ <path d="M20 17v-12c0 -1.121 -.879 -2 -2 -2s-2 .879 -2 2v12l2 2l2 -2z"></path>
11
+ <path d="M16 7h4"></path>
12
+ </svg>
13
+ <span>${this.defaultLabels.drawTypeButton}</span>
14
+ <input type="radio" name="type_option" id="draw_radio" value="draw" style="display: none;">
15
+ </label>
16
+ </div>
17
+ <div>
18
+ <label data-target="textTypeButton">
19
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1.5rem; height: 1.5rem;" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
20
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
21
+ <path d="M3 7v-2h13v2"></path>
22
+ <path d="M10 5v14"></path>
23
+ <path d="M12 19h-4"></path>
24
+ <path d="M15 13v-1h6v1"></path>
25
+ <path d="M18 12v7"></path>
26
+ <path d="M17 19h2"></path>
27
+ </svg>
28
+ <span>${this.defaultLabels.textTypeButton}</span>
29
+ <input type="radio" name="type_option" id="text_radio" value="draw" style="display: none;">
30
+ </label>
31
+ </div>
32
+ <div>
33
+ <label data-target="uploadTypeButton" for="signature_file_upload">
34
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1.5rem; height: 1.5rem;" width="16" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
35
+ <path d="M5 7h1a2 2 0 0 0 2 -2a1 1 0 0 1 1 -1h6a1 1 0 0 1 1 1a2 2 0 0 0 2 2h1a2 2 0 0 1 2 2v9a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-9a2 2 0 0 1 2 -2"></path>
36
+ <path d="M9 13a3 3 0 1 0 6 0a3 3 0 0 0 -6 0"></path>
37
+ </svg>
38
+ <span>${this.defaultLabels.uploadTypeButton}</span>
39
+ <input data-target="fileInput" id="signature_file_upload" type="file" accept="image/*" style="display: none;">
40
+ <input type="radio" name="type_option" id="upload_radio" value="upload" style="display: none;">
41
+ </label>
42
+ </div>
43
+ </div>
44
+ </div
45
+ <div>
46
+ <div>
47
+ <input placeholder="${this.defaultLabels.textInputPlaceholder}" data-target="textInput">
48
+ </div>
49
+ <div>
50
+ <canvas data-target="canvas"></canvas>
51
+ </div>
52
+ <div data-target="controlButtonsContainer">
53
+ <div data-target="colorSelect" style="display: flex; gap: 1rem;">
54
+ <input aria-label="Black" type="radio" data-target="colorInput" name="color" value="#000000" style="accent-color: #000000; transform: scale(1.5);" checked>
55
+ <input aria-label="Blue" type="radio" data-target="colorInput" name="color" value="#3B82F6" style="accent-color: #3B82F6; transform: scale(1.5);">
56
+ <input aria-label="Green" type="radio" data-target="colorInput" name="color" value="#008000" style="accent-color: #008000; transform: scale(1.5);">
57
+ <input aria-label="Red" type="radio" data-target="colorInput" name="color" value="#EF4444" style="accent-color: #EF4444; transform: scale(1.5);">
58
+ </div>
59
+ <div>
60
+ <span>
61
+ <button aria-label="Undo" data-target="undoButton">
62
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1rem; height: 1rem;" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
63
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
64
+ <path d="M9 14l-4 -4l4 -4"></path>
65
+ <path d="M5 10h11a4 4 0 1 1 0 8h-1"></path>
66
+ </svg>
67
+ <span>${this.defaultLabels.undoButton}</span>
68
+ </button>
69
+ </span>
70
+ <span>
71
+ <button aria-label="Clear" data-target="clearButton">
72
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 1rem; height: 1rem;" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
73
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
74
+ <path d="M19.933 13.041a8 8 0 1 1 -9.925 -8.788c3.899 -1 7.935 1.007 9.425 4.747"></path>
75
+ <path d="M20 4v5h-5"></path>
76
+ </svg>
77
+ <span>${this.defaultLabels.clearButton}</span>
78
+ </button>
79
+ </span>
80
+ </div>
81
+ </div>
82
+ <div>
83
+ <button data-target="saveButton">
84
+ <span>${this.defaultLabels.saveButton}</span>
85
+ </button>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ `}};if(typeof window<"u"&&window.customElements&&!window.customElements.get("signature-maker"))window.customElements.define("signature-maker",S);else throw new Error("signature-maker-js can only be used in a browser environment.");
90
+ /*! Bundled license information:
91
+
92
+ signature_pad/dist/signature_pad.js:
93
+ (*!
94
+ * Signature Pad v5.0.3 | https://github.com/szimek/signature_pad
95
+ * (c) 2024 Szymon Nowak | Released under the MIT license
96
+ *)
97
+ */
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@docuseal/signature-maker-js",
3
+ "version": "1.0.0",
4
+ "description": "JS library for drawing signatures",
5
+ "main": "dist/index.cjs.js",
6
+ "module": "dist/index.esm.js",
7
+ "repository": "https://github.com/docusealco/signature-maker-js",
8
+ "keywords": [
9
+ "js-signature",
10
+ "signature",
11
+ "signature-drawing"
12
+ ],
13
+ "author": "Alex Turchyn <alex@docuseal.co>",
14
+ "license": "MIT",
15
+ "bugs": {
16
+ "url": "https://github.com/docusealco/signature-maker-js/issues"
17
+ },
18
+ "homepage": "https://github.com/docusealco/signature-maker-js#readme",
19
+ "dependencies": {
20
+ "signature_pad": "^5.0.3"
21
+ },
22
+ "devDependencies": {
23
+ "esbuild": "^0.23.1"
24
+ },
25
+ "files": ["dist"],
26
+ "scripts": {
27
+ "build": "node esbuild.config.js"
28
+ }
29
+ }