@kne/react-pdf-sign 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -20,13 +20,13 @@ npm i --save @kne/react-pdf-sign
20
20
 
21
21
  ## 核心特性
22
22
 
23
- **直观的签名体验** - 提供手写签名画板,用户可以通过鼠标或触摸设备自然地绘制签名,签名支持实时预览和调整。
23
+ **直观的签名体验** - 提供手写签名画板,用户可以通过鼠标或触摸设备自然地绘制签名,签名支持实时预览和调整。支持在签名画板上叠加自定义内容,如日期、文字等。
24
24
 
25
25
  **灵活的定位控制** - 签名区域可以在 PDF 页面上自由拖拽、缩放和精确定位,支持保持比例缩放,确保签名的视觉效果。
26
26
 
27
27
  **完整的 PDF 操作** - 基于 pdf-lib 和 react-pdf,支持多页 PDF 文档的浏览、签名定位和最终签名文件的生成。
28
28
 
29
- **组件化设计** - 提供多个独立组件(PDFSign、PDFViewer、LocationLayer、useSignature),开发者可以根据需求灵活组合使用。
29
+ **组件化设计** - 提供多个独立组件(PDFSign、PDFViewer、LocationLayer、useSignature),开发者可以根据需求灵活组合使用。支持默认签名位置设置和位置变化回调,便于集成到现有业务流程。
30
30
 
31
31
  **国际化支持** - 内置中英文语言包,支持多语言切换,适合国际化应用。
32
32
 
@@ -40,7 +40,7 @@ npm i --save @kne/react-pdf-sign
40
40
  - 证书颁发系统
41
41
  - 法律文件签署
42
42
 
43
- 该组件库简化了 PDF 签名的复杂实现,开发者只需要几行代码就能集成完整的签名功能,大大提升了开发效率。
43
+ 该组件库简化了 PDF 签名的复杂实现,开发者只需要几行代码就能集成完整的签名功能,大大提升了开发效率。新增的签名叠加功能让签名更加丰富和个性化,满足各种业务场景需求。
44
44
 
45
45
  ### 示例
46
46
 
@@ -75,7 +75,15 @@ const BaseExample = () => {
75
75
  </Button>
76
76
  <Button
77
77
  onClick={() => {
78
+ const { size } = ref.current.getLocation();
78
79
  signatureModal({
80
+ mask: (
81
+ <Flex justify="flex-end" align="flex-end" style={{ height: '100%', width: '100%', padding: '10px', boxSizing: 'border-box' }}>
82
+ 签字日期: {new Date().toLocaleDateString()}
83
+ </Flex>
84
+ ),
85
+ width: size.width,
86
+ height: size.height,
79
87
  onSuccess: file => {
80
88
  setSign(URL.createObjectURL(file));
81
89
  }
@@ -236,23 +244,46 @@ render(<BaseExample />);
236
244
 
237
245
  ```jsx
238
246
  const { useSignature } = _ReactPdfSign;
239
- const { Button } = antd;
247
+ const { Button, Flex } = antd;
248
+
249
+ const { useState } = React;
240
250
 
241
251
  const BaseExample = () => {
252
+ const [result, setResult] = useState(null);
242
253
  const modal = useSignature();
243
254
  return (
244
- <div>
245
- <Button
246
- onClick={() => {
247
- modal({
248
- onSuccess: file => {
249
- console.log(file);
250
- }
251
- });
252
- }}>
253
- 签名
254
- </Button>
255
- </div>
255
+ <Flex vertical gap={12}>
256
+ {result && <img src={result} alt="result" style={{ width: '300px' }} />}
257
+ <Flex gap={8}>
258
+ <Button
259
+ onClick={() => {
260
+ modal({
261
+ onSuccess: file => {
262
+ console.log(file);
263
+ setResult(URL.createObjectURL(file));
264
+ }
265
+ });
266
+ }}>
267
+ 签名
268
+ </Button>
269
+ <Button
270
+ onClick={() => {
271
+ modal({
272
+ mask: (
273
+ <Flex justify="flex-end" align="flex-end" style={{ height: '100%', width: '100%', padding: '10px', boxSizing: 'border-box' }}>
274
+ 签字日期: {new Date().toLocaleDateString()}
275
+ </Flex>
276
+ ),
277
+ onSuccess: file => {
278
+ console.log(file);
279
+ setResult(URL.createObjectURL(file));
280
+ }
281
+ });
282
+ }}>
283
+ 带有日期模版的签名
284
+ </Button>
285
+ </Flex>
286
+ </Flex>
256
287
  );
257
288
  };
258
289
 
@@ -267,14 +298,17 @@ render(<BaseExample />);
267
298
 
268
299
  主要的 PDF 签名组件,集成了 PDF 查看器和签名定位功能。
269
300
 
270
- | 属性 | 类型 | 默认值 | 说明 |
271
- |-------------|--------|-----------|----------------|
272
- | url | string | - | PDF 文件的 URL 地址 |
273
- | signature | string | - | 签名图片的 URL 地址 |
274
- | width | number | 200 | 签名区域的宽度 |
275
- | height | number | 50 | 签名区域的高度 |
276
- | padding | number | 8 | 签名区域变换器的内边距 |
277
- | placeholder | string | '拖拽到签名位置' | 签名区域的占位文本 |
301
+ | 属性 | 类型 | 默认值 | 说明 |
302
+ |----------------|----------|-------------------|-------------------|
303
+ | url | string | - | PDF 文件的 URL 地址 |
304
+ | signature | string | - | 签名图片的 URL 地址 |
305
+ | width | number | 200 | 签名区域的宽度 |
306
+ | height | number | 50 | 签名区域的高度 |
307
+ | padding | number | 8 | 签名区域变换器的内边距 |
308
+ | placeholder | string | '拖拽到签名位置' | 签名区域的占位文本 |
309
+ | filename | string | 'signed-document.pdf' | 生成签名PDF的文件名 |
310
+ | defaultLocation | object | - | 默认签名位置信息 |
311
+ | onChange | function | - | 签名位置变化回调函数 |
278
312
 
279
313
  #### 实例方法
280
314
 
@@ -334,7 +368,8 @@ PDF 文档查看器组件,提供 PDF 页面浏览功能。
334
368
  |------------|----------|-----------------|------------|
335
369
  | filename | string | 'signature.png' | 签名文件名 |
336
370
  | width | number | 200 | 签名画板宽度 |
337
- | height | number | 50 | 签名画板高度 |
371
+ | height | number | 80 | 签名画板高度 |
372
+ | mask | ReactNode | - | 签名画板叠加内容 |
338
373
  | onSuccess | function | - | 签名完成回调 |
339
374
  | modalProps | object | - | Modal 组件属性 |
340
375
 
@@ -343,4 +378,4 @@ PDF 文档查看器组件,提供 PDF 页面浏览功能。
343
378
  | 参数 | 类型 | 默认值 | 说明 |
344
379
  |--------|--------|-----|----------|
345
380
  | width | number | 200 | 默认签名画板宽度 |
346
- | height | number | 50 | 默认签名画板高度 |
381
+ | height | number | 80 | 默认签名画板高度 |
package/dist/index.css CHANGED
@@ -51,6 +51,7 @@
51
51
  ._6TDb- {
52
52
  border: 1px solid #cccccc;
53
53
  border-radius: 4px;
54
+ position: relative;
54
55
  }
55
56
 
56
57
  ._2CGF4 {
@@ -61,4 +62,13 @@
61
62
  ._kWe3k .ant-modal-confirm-paragraph {
62
63
  max-width: unset;
63
64
  }
65
+
66
+ ._FSvLv {
67
+ position: absolute;
68
+ top: 0;
69
+ left: 0;
70
+ width: 100%;
71
+ height: 100%;
72
+ pointer-events: none;
73
+ }
64
74
  /*# sourceMappingURL=index.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["style.module.scss"],"names":[],"mappings":"AAAA;EACE,cAAc;EACd,kBAAkB;EAClB,iBAAiB;EACjB,WAAW;AACb;AACA;;EAEE,cAAc;AAChB;;AAEA;EACE,wEAAwE;AAC1E;;AAEA;EACE,kBAAkB;EAClB,MAAM;EACN,OAAO;EACP,WAAW;EACX,YAAY;EACZ,WAAW;AACb;;AAEA;;EAEE,kBAAkB;EAClB,eAAe;EACf,qBAAqB;EACrB,WAAW;EACX,YAAY;EACZ,eAAe;EACf,YAAY;AACd;;AAEA;EACE,kBAAkB;EAClB,YAAY;EACZ,SAAS;EACT,2BAA2B;EAC3B,cAAc;EACd,0CAA0C;EAC1C,yCAAyC;EACzC,kBAAkB;AACpB;;AAEA;EACE,QAAQ;AACV;;AAEA;EACE,yBAAyB;EACzB,kBAAkB;AACpB;;AAEA;EACE,WAAW;EACX,YAAY;AACd;;AAEA;EACE,gBAAgB;AAClB","file":"index.css","sourcesContent":[".pdf-view-container {\n margin: 0 auto;\n position: relative;\n max-width: 1200px;\n width: 100%;\n}\n.pdf-view-container :global(.react-pdf__Page__canvas),\n.pdf-view-container :global(.textLayer) {\n margin: 0 auto;\n}\n\n.pdf-view {\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n}\n\n.pdf-view-children {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 10;\n}\n\n.pdf-view-page-control-left,\n.pdf-view-page-control-right {\n position: absolute;\n font-size: 30px;\n top: calc(50% - 19px);\n z-index: 10;\n padding: 8px;\n cursor: pointer;\n opacity: 0.3;\n}\n\n.pdf-view-page-control-current {\n position: absolute;\n bottom: 10px;\n left: 50%;\n transform: translateX(-50%);\n color: #666666;\n background-color: rgba(255, 255, 255, 0.5);\n text-shadow: 0 0 8px white, 0 0 8px white;\n border-radius: 4px;\n}\n\n.pdf-view-page-control-right {\n right: 0;\n}\n\n.signature-container {\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\n\n.signature-canvas {\n width: 100%;\n height: 100%;\n}\n\n.signature-modal :global .ant-modal-confirm-paragraph {\n max-width: unset;\n}"]}
1
+ {"version":3,"sources":["style.module.scss"],"names":[],"mappings":"AAAA;EACE,cAAc;EACd,kBAAkB;EAClB,iBAAiB;EACjB,WAAW;AACb;AACA;;EAEE,cAAc;AAChB;;AAEA;EACE,wEAAwE;AAC1E;;AAEA;EACE,kBAAkB;EAClB,MAAM;EACN,OAAO;EACP,WAAW;EACX,YAAY;EACZ,WAAW;AACb;;AAEA;;EAEE,kBAAkB;EAClB,eAAe;EACf,qBAAqB;EACrB,WAAW;EACX,YAAY;EACZ,eAAe;EACf,YAAY;AACd;;AAEA;EACE,kBAAkB;EAClB,YAAY;EACZ,SAAS;EACT,2BAA2B;EAC3B,cAAc;EACd,0CAA0C;EAC1C,yCAAyC;EACzC,kBAAkB;AACpB;;AAEA;EACE,QAAQ;AACV;;AAEA;EACE,yBAAyB;EACzB,kBAAkB;EAClB,kBAAkB;AACpB;;AAEA;EACE,WAAW;EACX,YAAY;AACd;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,kBAAkB;EAClB,MAAM;EACN,OAAO;EACP,WAAW;EACX,YAAY;EACZ,oBAAoB;AACtB","file":"index.css","sourcesContent":[".pdf-view-container {\n margin: 0 auto;\n position: relative;\n max-width: 1200px;\n width: 100%;\n}\n.pdf-view-container :global(.react-pdf__Page__canvas),\n.pdf-view-container :global(.textLayer) {\n margin: 0 auto;\n}\n\n.pdf-view {\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n}\n\n.pdf-view-children {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 10;\n}\n\n.pdf-view-page-control-left,\n.pdf-view-page-control-right {\n position: absolute;\n font-size: 30px;\n top: calc(50% - 19px);\n z-index: 10;\n padding: 8px;\n cursor: pointer;\n opacity: 0.3;\n}\n\n.pdf-view-page-control-current {\n position: absolute;\n bottom: 10px;\n left: 50%;\n transform: translateX(-50%);\n color: #666666;\n background-color: rgba(255, 255, 255, 0.5);\n text-shadow: 0 0 8px white, 0 0 8px white;\n border-radius: 4px;\n}\n\n.pdf-view-page-control-right {\n right: 0;\n}\n\n.signature-container {\n border: 1px solid #cccccc;\n border-radius: 4px;\n position: relative;\n}\n\n.signature-canvas {\n width: 100%;\n height: 100%;\n}\n\n.signature-modal :global .ant-modal-confirm-paragraph {\n max-width: unset;\n}\n\n.signature-mask {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n}"]}
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ var useImage = require('use-image');
15
15
  var reactIntl = require('@kne/react-intl');
16
16
  var pdfLib = require('pdf-lib');
17
17
  var SignatureCanvas = require('react-signature-canvas');
18
+ var snapdom = require('@zumer/snapdom');
18
19
 
19
20
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
20
21
 
@@ -44,7 +45,7 @@ function _objectWithoutPropertiesLoose(r, e) {
44
45
  return t;
45
46
  }
46
47
 
47
- var style = {"pdf-view-container":"_RgZXN","pdf-view":"_PAju1","pdf-view-children":"_N11Pj","pdf-view-page-control-left":"_IbVpf","pdf-view-page-control-right":"_IIgqj","pdf-view-page-control-current":"_JW3CT","signature-container":"_6TDb-","signature-canvas":"_2CGF4","signature-modal":"_kWe3k"};
48
+ var style = {"pdf-view-container":"_RgZXN","pdf-view":"_PAju1","pdf-view-children":"_N11Pj","pdf-view-page-control-left":"_IbVpf","pdf-view-page-control-right":"_IIgqj","pdf-view-page-control-current":"_JW3CT","signature-container":"_6TDb-","signature-canvas":"_2CGF4","signature-modal":"_kWe3k","signature-mask":"_FSvLv"};
48
49
 
49
50
  const _excluded$3 = ["numPages"];
50
51
  const PDFViewer = _ref => {
@@ -183,7 +184,7 @@ const LocationLayer = withLocale(p => {
183
184
  } = reactIntl.useIntl();
184
185
  const {
185
186
  width = 200,
186
- height = 50,
187
+ height = 80,
187
188
  padding = 8,
188
189
  stageWidth,
189
190
  stageHeight,
@@ -198,6 +199,7 @@ const LocationLayer = withLocale(p => {
198
199
  const [signatureImage] = useImage__default["default"](signature);
199
200
  const groupRef = react.useRef();
200
201
  const signRef = react.useRef();
202
+ const targetRef = react.useRef();
201
203
  const transformerRef = react.useRef();
202
204
  const computedSignLocation = () => {
203
205
  const absolutePosition = signRef.current.absolutePosition();
@@ -229,8 +231,8 @@ const LocationLayer = withLocale(p => {
229
231
  y: Math.round((stageHeight - height) / 2)
230
232
  }
231
233
  });
232
- setIsInit(true);
233
234
  }
235
+ setIsInit(true);
234
236
  });
235
237
  const themeColor = react.useMemo(() => {
236
238
  const el = document.createElement('div');
@@ -245,7 +247,7 @@ const LocationLayer = withLocale(p => {
245
247
  }, []);
246
248
  react.useEffect(() => {
247
249
  if (isInit) {
248
- transformerRef.current.nodes([groupRef.current]);
250
+ transformerRef.current.nodes([targetRef.current]);
249
251
  }
250
252
  }, [isInit]);
251
253
  if (!(isInit && value)) {
@@ -261,19 +263,22 @@ const LocationLayer = withLocale(p => {
261
263
  draggable: true,
262
264
  ref: groupRef,
263
265
  onDragEnd: computedSignLocation,
264
- onTransformEnd: computedSignLocation,
265
- children: [signatureImage ? /*#__PURE__*/jsxRuntime.jsx(reactKonva.Image, {
266
- width: width,
267
- height: height,
268
- image: signatureImage,
269
- cornerRadius: 8,
270
- ref: signRef
271
- }) : /*#__PURE__*/jsxRuntime.jsx(reactKonva.Rect, {
272
- width: width,
273
- height: height,
274
- fill: "#f0f0f0",
275
- cornerRadius: 8,
276
- ref: signRef
266
+ children: [/*#__PURE__*/jsxRuntime.jsx(reactKonva.Group, {
267
+ ref: targetRef,
268
+ onTransformEnd: computedSignLocation,
269
+ children: signatureImage ? /*#__PURE__*/jsxRuntime.jsx(reactKonva.Image, {
270
+ width: width,
271
+ height: height,
272
+ image: signatureImage,
273
+ cornerRadius: 8,
274
+ ref: signRef
275
+ }) : /*#__PURE__*/jsxRuntime.jsx(reactKonva.Rect, {
276
+ width: width,
277
+ height: height,
278
+ fill: "#f0f0f0",
279
+ cornerRadius: 8,
280
+ ref: signRef
281
+ })
277
282
  }), /*#__PURE__*/jsxRuntime.jsx(reactKonva.Text, {
278
283
  text: signatureImage ? '' : placeholder,
279
284
  fontSize: 16,
@@ -295,8 +300,7 @@ const LocationLayer = withLocale(p => {
295
300
  borderStroke: themeColor,
296
301
  rotateAnchorStroke: themeColor,
297
302
  anchorStroke: themeColor,
298
- padding: padding,
299
- enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right']
303
+ padding: padding
300
304
  })]
301
305
  })
302
306
  });
@@ -2507,7 +2511,46 @@ function isEqual(value, other) {
2507
2511
 
2508
2512
  var isEqual_1 = isEqual;
2509
2513
 
2510
- const _excluded$1 = ["placeholder", "signature", "url", "width", "height", "padding", "filename"];
2514
+ const signPdfFile = function (pdfSignature) {
2515
+ try {
2516
+ const {
2517
+ x,
2518
+ y,
2519
+ page,
2520
+ width,
2521
+ height,
2522
+ signature,
2523
+ url,
2524
+ filename
2525
+ } = pdfSignature;
2526
+ return Promise.resolve(window.fetch(url)).then(function (response) {
2527
+ return Promise.resolve(response.arrayBuffer()).then(function (pdfBytes) {
2528
+ return Promise.resolve(pdfLib.PDFDocument.load(pdfBytes)).then(function (pdfDoc) {
2529
+ const pdfPage = pdfDoc.getPage(page - 1);
2530
+ return Promise.resolve(window.fetch(signature).then(res => res.arrayBuffer())).then(function (signatureBytes) {
2531
+ return Promise.resolve(pdfDoc.embedPng(signatureBytes)).then(function (signatureImageEmbed) {
2532
+ pdfPage.drawImage(signatureImageEmbed, {
2533
+ x,
2534
+ y,
2535
+ width,
2536
+ height
2537
+ });
2538
+ return Promise.resolve(pdfDoc.save()).then(function (modifiedPdfBytes) {
2539
+ return new window.File([modifiedPdfBytes], filename, {
2540
+ type: 'application/pdf'
2541
+ });
2542
+ });
2543
+ });
2544
+ });
2545
+ });
2546
+ });
2547
+ });
2548
+ } catch (e) {
2549
+ return Promise.reject(e);
2550
+ }
2551
+ };
2552
+
2553
+ const _excluded$1 = ["placeholder", "signature", "url", "width", "height", "padding", "filename", "defaultLocation", "onChange"];
2511
2554
  const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
2512
2555
  let {
2513
2556
  placeholder,
@@ -2516,10 +2559,12 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
2516
2559
  width,
2517
2560
  height,
2518
2561
  padding,
2519
- filename = 'signed-document.pdf'
2562
+ filename = 'signed-document.pdf',
2563
+ defaultLocation,
2564
+ onChange
2520
2565
  } = _ref,
2521
2566
  props = _objectWithoutPropertiesLoose(_ref, _excluded$1);
2522
- const [location, setLocation] = react.useState({});
2567
+ const [location, setLocation] = react.useState(Object.assign({}, defaultLocation));
2523
2568
  const [pdfProps, setPdfProps] = react.useState(null);
2524
2569
  const {
2525
2570
  formatMessage
@@ -2536,18 +2581,21 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
2536
2581
  const scaleY = size.height / size.originalHeight;
2537
2582
  const pdfX = Math.round(location.size.x / scaleX);
2538
2583
  const pdfY = Math.round(size.originalHeight - location.size.y / scaleY);
2584
+ const signWidth = Math.round(location.size.width / scaleX);
2585
+ const signHeight = Math.round(location.size.height / scaleY);
2539
2586
  return {
2540
2587
  x: pdfX,
2541
- y: pdfY - location.size.height,
2588
+ y: pdfY - signHeight,
2542
2589
  page: currentPage,
2543
- pageWidth: size.originalWidth,
2544
- pageHeight: size.originalHeight,
2545
- width: location.size.width,
2546
- height: location.size.height,
2590
+ pageWidth: Math.round(size.originalWidth),
2591
+ pageHeight: Math.round(size.originalHeight),
2592
+ width: signWidth,
2593
+ height: signHeight,
2547
2594
  signature,
2548
- url
2595
+ url,
2596
+ filename
2549
2597
  };
2550
- }, [pdfProps, location, signature, url]);
2598
+ }, [pdfProps, location, signature, url, filename]);
2551
2599
  const signPdf = react.useCallback(function () {
2552
2600
  try {
2553
2601
  if (!pdfProps) {
@@ -2555,37 +2603,7 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
2555
2603
  id: 'loadingError'
2556
2604
  }));
2557
2605
  }
2558
- const {
2559
- x,
2560
- y,
2561
- page,
2562
- width,
2563
- height,
2564
- signature,
2565
- url
2566
- } = pdfSignature;
2567
- return Promise.resolve(window.fetch(url)).then(function (response) {
2568
- return Promise.resolve(response.arrayBuffer()).then(function (pdfBytes) {
2569
- return Promise.resolve(pdfLib.PDFDocument.load(pdfBytes)).then(function (pdfDoc) {
2570
- const pdfPage = pdfDoc.getPage(page - 1);
2571
- return Promise.resolve(window.fetch(signature).then(res => res.arrayBuffer())).then(function (signatureBytes) {
2572
- return Promise.resolve(pdfDoc.embedPng(signatureBytes)).then(function (signatureImageEmbed) {
2573
- pdfPage.drawImage(signatureImageEmbed, {
2574
- x,
2575
- y,
2576
- width,
2577
- height
2578
- });
2579
- return Promise.resolve(pdfDoc.save()).then(function (modifiedPdfBytes) {
2580
- return new window.File([modifiedPdfBytes], filename, {
2581
- type: 'application/pdf'
2582
- });
2583
- });
2584
- });
2585
- });
2586
- });
2587
- });
2588
- });
2606
+ return Promise.resolve(signPdfFile(pdfSignature));
2589
2607
  } catch (e) {
2590
2608
  return Promise.reject(e);
2591
2609
  }
@@ -2596,6 +2614,13 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
2596
2614
  getPdfSignature: () => pdfSignature,
2597
2615
  sign: () => signPdf()
2598
2616
  }));
2617
+ const handlerChange = useRefCallback__default["default"](onChange);
2618
+ react.useEffect(() => {
2619
+ handlerChange == null || handlerChange({
2620
+ pdfSignature,
2621
+ location
2622
+ });
2623
+ }, [pdfSignature, location, handlerChange]);
2599
2624
  return /*#__PURE__*/jsxRuntime.jsx(PDFViewer, _extends({}, props, {
2600
2625
  url: url,
2601
2626
  children: _ref2 => {
@@ -2629,7 +2654,7 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
2629
2654
  }));
2630
2655
  }));
2631
2656
 
2632
- const _excluded = ["filename", "onSuccess"];
2657
+ const _excluded = ["filename", "onSuccess", "width", "height", "mask"];
2633
2658
  const dataURLtoBlob = dataURL => {
2634
2659
  let arr = dataURL.split(',');
2635
2660
  // 注意base64的最后面中括号和引号是不转译的
@@ -2651,7 +2676,8 @@ const Signature = withLocale(_ref => {
2651
2676
  onSuccess,
2652
2677
  filename,
2653
2678
  width,
2654
- height
2679
+ height,
2680
+ mask = null
2655
2681
  } = _ref;
2656
2682
  const {
2657
2683
  formatMessage
@@ -2660,22 +2686,27 @@ const Signature = withLocale(_ref => {
2660
2686
  message
2661
2687
  } = antd.App.useApp();
2662
2688
  const signatureCanvasRef = react.useRef(null);
2689
+ const maskRef = react.useRef(null);
2663
2690
  return /*#__PURE__*/jsxRuntime.jsxs(antd.Flex, {
2664
2691
  vertical: true,
2665
2692
  gap: 12,
2666
2693
  className: classnames__default["default"](style['signature-modal-content'], 'signature-modal-content'),
2667
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2694
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2668
2695
  className: classnames__default["default"](style['signature-container'], 'signature-container'),
2669
2696
  style: {
2670
2697
  width: '368px',
2671
2698
  height: Math.round(height * 368 / width) + "px"
2672
2699
  },
2673
- children: /*#__PURE__*/jsxRuntime.jsx(SignatureCanvas__default["default"], {
2700
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2701
+ className: classnames__default["default"](style['signature-mask'], 'signature-mask'),
2702
+ ref: maskRef,
2703
+ children: mask
2704
+ }), /*#__PURE__*/jsxRuntime.jsx(SignatureCanvas__default["default"], {
2674
2705
  ref: signatureCanvasRef,
2675
2706
  canvasProps: {
2676
2707
  className: classnames__default["default"](style['signature-canvas'], 'signature-canvas')
2677
2708
  }
2678
- })
2709
+ })]
2679
2710
  }), /*#__PURE__*/jsxRuntime.jsxs(antd.Flex, {
2680
2711
  justify: "flex-end",
2681
2712
  align: "center",
@@ -2689,18 +2720,47 @@ const Signature = withLocale(_ref => {
2689
2720
  })
2690
2721
  }), /*#__PURE__*/jsxRuntime.jsx(antd.Button, {
2691
2722
  type: "primary",
2692
- onClick: () => {
2693
- if (signatureCanvasRef.current.isEmpty()) {
2694
- message.error(formatMessage({
2695
- id: 'signatureEmptyError'
2696
- }));
2697
- return;
2723
+ onClick: function () {
2724
+ try {
2725
+ function _temp2() {
2726
+ const file = new window.File([dataURLtoBlob(result)], filename, {
2727
+ type: 'image/png'
2728
+ });
2729
+ onClose();
2730
+ onSuccess(file);
2731
+ }
2732
+ if (signatureCanvasRef.current.isEmpty()) {
2733
+ message.error(formatMessage({
2734
+ id: 'signatureEmptyError'
2735
+ }));
2736
+ return Promise.resolve();
2737
+ }
2738
+ let result = signatureCanvasRef.current.toDataURL('image/png');
2739
+ const _temp = function () {
2740
+ if (mask) {
2741
+ return Promise.resolve(snapdom.snapdom.toPng(maskRef.current, {
2742
+ scale: 2
2743
+ })).then(function (maskPng) {
2744
+ const canvas = document.createElement('canvas');
2745
+ canvas.width = width * 2;
2746
+ canvas.height = height * 2;
2747
+ const ctx = canvas.getContext('2d');
2748
+ ctx.drawImage(maskPng, 0, 0, canvas.width, canvas.height);
2749
+ const resultImage = new Image();
2750
+ resultImage.src = result;
2751
+ return Promise.resolve(new Promise(resolve => {
2752
+ resultImage.onload = resolve;
2753
+ })).then(function () {
2754
+ ctx.drawImage(resultImage, 0, 0, canvas.width, canvas.height);
2755
+ result = canvas.toDataURL('image/png');
2756
+ });
2757
+ });
2758
+ }
2759
+ }();
2760
+ return Promise.resolve(_temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp));
2761
+ } catch (e) {
2762
+ return Promise.reject(e);
2698
2763
  }
2699
- const file = new window.File([dataURLtoBlob(signatureCanvasRef.current.toDataURL('image/png'))], filename, {
2700
- type: 'image/png'
2701
- });
2702
- onClose();
2703
- onSuccess(file);
2704
2764
  },
2705
2765
  children: formatMessage({
2706
2766
  id: 'signatureConfirmText'
@@ -2719,24 +2779,18 @@ const Title = withLocale(() => {
2719
2779
  })
2720
2780
  });
2721
2781
  });
2722
- const useSignature = props => {
2782
+ const useSignature = () => {
2723
2783
  const {
2724
- width,
2725
- height
2726
- } = Object.assign({}, {
2727
- width: 200,
2728
- height: 50
2729
- }, props);
2730
- const {
2731
- modal,
2732
- message
2784
+ modal
2733
2785
  } = antd.App.useApp();
2734
- react.useRef(null);
2735
2786
  return props => {
2736
2787
  const _Object$assign = Object.assign({}, props),
2737
2788
  {
2738
2789
  filename = 'signature.png',
2739
- onSuccess
2790
+ onSuccess,
2791
+ width = 200,
2792
+ height = 80,
2793
+ mask
2740
2794
  } = _Object$assign,
2741
2795
  modalProps = _objectWithoutPropertiesLoose(_Object$assign, _excluded);
2742
2796
  const modalApi = modal.info(Object.assign({}, {
@@ -2751,6 +2805,7 @@ const useSignature = props => {
2751
2805
  content: /*#__PURE__*/jsxRuntime.jsx(Signature, {
2752
2806
  width: width,
2753
2807
  height: height,
2808
+ mask: mask,
2754
2809
  filename: filename,
2755
2810
  onSuccess: onSuccess,
2756
2811
  onClose: () => {