UNPKG

6.35 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _preact = require("preact");
9
10var _ = require("./");
11
12const height = 300;
13
14class SignatureInput extends _preact.Component {
15 constructor(props) {
16 super(props);
17 this.mouseMove = this.mouseMove.bind(this);
18 this.mouseEnd = this.mouseEnd.bind(this);
19 this.mouseDown = this.mouseDown.bind(this);
20 this.mouseUp = this.mouseUp.bind(this);
21 this.mouseLeave = this.mouseLeave.bind(this);
22 this.touchStart = this.touchStart.bind(this);
23 this.touchMove = this.touchMove.bind(this);
24 this.touchEnd = this.touchEnd.bind(this);
25 this.calculateCanvasInfo = this.calculateCanvasInfo.bind(this);
26 this.renderCanvas = this.renderCanvas.bind(this);
27 }
28
29 reset() {
30 this.path = '';
31 this.break = true;
32 }
33
34 componentDidMount() {
35 this.reset();
36 this.canvas = this.base.querySelector('canvas');
37 this.ctx = this.canvas.getContext('2d');
38 window.addEventListener('resize', this.calculateCanvasInfo, {
39 passive: true
40 });
41 window.addEventListener('scroll', this.calculateCanvasInfo, {
42 passive: true
43 });
44 document.addEventListener('mouseup', this.mouseUp);
45 document.addEventListener('touchmove', this.touchMove);
46 document.addEventListener('touchend', this.touchEnd);
47 document.addEventListener('touchcancel', this.touchEnd);
48 this.canvas.addEventListener('touchstart', this.touchStart);
49 this.calculateCanvasInfo();
50 this.renderCanvas();
51 }
52
53 calculateCanvasInfo() {
54 const {
55 top,
56 left,
57 width,
58 height
59 } = this.canvas.getBoundingClientRect();
60 this.canvasInfo = {
61 left,
62 top,
63 height,
64 width
65 };
66 }
67
68 componentWillUnmount() {
69 window.removeEventListener('resize', this.calculateCanvasInfo, {
70 passive: true
71 });
72 window.removeEventListener('scroll', this.calculateCanvasInfo, {
73 passive: true
74 });
75 document.removeEventListener('mouseup', this.mouseUp);
76 document.removeEventListener('touchmove', this.touchMove);
77 document.removeEventListener('touchend', this.touchEnd);
78 document.removeEventListener('touchcancel', this.touchEnd);
79 this.canvas && this.canvas.removeEventListener('touchstart', this.touchStart);
80 }
81
82 adjustCoord(clientX, clientY) {
83 const {
84 left,
85 top,
86 height,
87 width
88 } = this.canvasInfo;
89 const x = clientX - left;
90 const y = clientY - top;
91
92 if (x < 0 || x > width) {
93 return null;
94 }
95
96 if (y < 0 || y > height) {
97 return null;
98 }
99
100 return {
101 x,
102 y
103 };
104 }
105
106 appendCoord(x, y) {
107 this.path += " ".concat(x, ",").concat(y);
108 requestAnimationFrame(this.renderCanvas);
109 }
110
111 mouseDown(e) {
112 e.preventDefault();
113 e.stopImmediatePropagation();
114 }
115
116 mouseLeave(e) {
117 if (e.buttons === 1) {
118 this.appendCoord(e.layerX, e.layerY);
119 this.break = true;
120 }
121 }
122
123 mouseUp() {
124 this.break = true;
125 }
126
127 mouseEnd(e) {
128 e.preventDefault();
129 e.stopImmediatePropagation();
130 this.break = true;
131 }
132
133 mouseMove(e) {
134 e.preventDefault();
135 e.stopImmediatePropagation();
136
137 if (e.buttons === 1) {
138 if (this.break) {
139 this.break = false;
140 this.path += ' M';
141 }
142
143 const adjusted = this.adjustCoord(e.clientX, e.clientY);
144
145 if (adjusted) {
146 this.appendCoord(adjusted.x, adjusted.y);
147 } else {
148 this.break = true;
149 }
150 }
151 }
152
153 touchStart(e) {
154 this.drawing = true;
155 this.path += ' M'; // this prevents to "M"s next to each other if
156 // there's a touch start without a touch move
157
158 this.touchMove(e);
159 e.preventDefault();
160 }
161
162 touchMove(e) {
163 if (this.drawing) {
164 const touch = e.touches[0];
165 const isStylus = touch.touchType === 'stylus';
166 const adjusted = this.adjustCoord(touch.clientX + (isStylus ? 0 : -20), touch.clientY + (isStylus ? 0 : -10));
167
168 if (adjusted) {
169 this.appendCoord(adjusted.x, adjusted.y);
170 } else {
171 this.break = true;
172 }
173 }
174 }
175
176 touchEnd() {
177 this.break = true;
178 }
179
180 renderCanvas() {
181 const {
182 ctx
183 } = this;
184 const {
185 width,
186 height
187 } = this.canvas;
188 ctx.clearRect(0, 0, width, height);
189 const marginFromEdge = width * 0.1;
190 const marginFromBottom = 80; // signature line
191
192 ctx.beginPath();
193 ctx.moveTo(marginFromEdge, height - marginFromBottom);
194 ctx.lineTo(width - marginFromEdge, height - marginFromBottom);
195 ctx.strokeStyle = '#ddd';
196 ctx.lineWidth = 2;
197 ctx.stroke();
198 ctx.strokeStyle = '#000';
199 ctx.lineWidth = 1;
200 ctx.fillStyle = '#000';
201
202 if (this.path) {
203 ctx.stroke(new Path2D(this.path));
204 }
205
206 if (this.props.name) {
207 ctx.font = '18px sans-serif';
208 ctx.fillText(this.props.name, marginFromEdge, height - (marginFromBottom - 25));
209 }
210 }
211
212 shouldComponentUpdate() {
213 return false;
214 }
215
216 render({
217 updateValue,
218 close
219 }) {
220 return (0, _preact.h)("div", {
221 className: "top-0 left-0 fixed bg-gray w-100 h-100 z-9999 flex items-center justify-center"
222 }, (0, _preact.h)("div", {
223 "data-e2e": "signatureBox"
224 }, (0, _preact.h)("canvas", {
225 "data-e2e": "signaturePad",
226 className: "bg-white ba",
227 width: Math.min(window.innerWidth - 10, 660),
228 height: height,
229 onMouseMove: this.mouseMove,
230 onMouseDown: this.mouseDown,
231 onMouseCancel: this.mouseCancel,
232 onMouseLeave: this.mouseLeave
233 }), (0, _preact.h)("div", {
234 className: "flex items-center justify-between mt2"
235 }, (0, _preact.h)(_.Button, {
236 primary: true,
237 large: true,
238 "data-e2e": "signatureSaveButton",
239 onClick: () => {
240 updateValue(this.path.trim());
241 },
242 type: "button"
243 }, "Save"), (0, _preact.h)("div", null, (0, _preact.h)(_.Button, {
244 large: true,
245 onClick: () => {
246 this.reset();
247 this.renderCanvas();
248 },
249 className: "mr2",
250 type: "button"
251 }, "Clear"), (0, _preact.h)(_.Button, {
252 large: true,
253 onClick: () => {
254 this.reset();
255 this.renderCanvas();
256 close();
257 },
258 "data-e2e": "cancelSignatureButton",
259 type: "button"
260 }, "Cancel")))));
261 }
262
263}
264
265var _default = SignatureInput;
266exports.default = _default;
\No newline at end of file