@arbidocs/blocks 0.4.101 → 0.4.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/dist/chunk-6MG62I5B.cjs +272 -0
  2. package/dist/chunk-6MG62I5B.cjs.map +1 -0
  3. package/dist/chunk-EQB3WELX.js +269 -0
  4. package/dist/chunk-EQB3WELX.js.map +1 -0
  5. package/dist/document-tools/AdoptSignatureDialog.d.ts +25 -0
  6. package/dist/document-tools/DocumentToolButtons.d.ts +2 -0
  7. package/dist/document-tools/SignatureRequestBanner.d.ts +18 -0
  8. package/dist/document-tools/index.cjs +175 -0
  9. package/dist/document-tools/index.cjs.map +1 -1
  10. package/dist/document-tools/index.d.ts +3 -1
  11. package/dist/document-tools/index.js +168 -3
  12. package/dist/document-tools/index.js.map +1 -1
  13. package/dist/document-tools/viewer/GuidedSigningViewer.d.ts +26 -0
  14. package/dist/document-tools/viewer/SignatureFieldsOverlay.d.ts +41 -0
  15. package/dist/document-tools/viewer/SignatureRequestEditor.d.ts +26 -0
  16. package/dist/document-tools/viewer/index.cjs +983 -0
  17. package/dist/document-tools/viewer/index.cjs.map +1 -1
  18. package/dist/document-tools/viewer/index.d.ts +3 -0
  19. package/dist/document-tools/viewer/index.js +983 -5
  20. package/dist/document-tools/viewer/index.js.map +1 -1
  21. package/node_modules/@arbidocs/coedit/LICENSE +21 -0
  22. package/node_modules/@arbidocs/coedit/dist/encoding.cjs +751 -0
  23. package/node_modules/@arbidocs/coedit/dist/encoding.cjs.map +1 -0
  24. package/node_modules/@arbidocs/coedit/dist/encoding.d.cts +192 -0
  25. package/node_modules/@arbidocs/coedit/dist/encoding.d.ts +192 -0
  26. package/node_modules/@arbidocs/coedit/dist/encoding.js +716 -0
  27. package/node_modules/@arbidocs/coedit/dist/encoding.js.map +1 -0
  28. package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs +1759 -0
  29. package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs.map +1 -0
  30. package/node_modules/@arbidocs/coedit/dist/hocuspocus.d.cts +39 -0
  31. package/node_modules/@arbidocs/coedit/dist/hocuspocus.d.ts +39 -0
  32. package/node_modules/@arbidocs/coedit/dist/hocuspocus.js +1736 -0
  33. package/node_modules/@arbidocs/coedit/dist/hocuspocus.js.map +1 -0
  34. package/node_modules/@arbidocs/coedit/dist/index.cjs +1692 -0
  35. package/node_modules/@arbidocs/coedit/dist/index.cjs.map +1 -0
  36. package/node_modules/@arbidocs/coedit/dist/index.d.cts +16 -0
  37. package/node_modules/@arbidocs/coedit/dist/index.d.ts +16 -0
  38. package/node_modules/@arbidocs/coedit/dist/index.js +1664 -0
  39. package/node_modules/@arbidocs/coedit/dist/index.js.map +1 -0
  40. package/node_modules/@arbidocs/coedit/dist/server.cjs +1852 -0
  41. package/node_modules/@arbidocs/coedit/dist/server.cjs.map +1 -0
  42. package/node_modules/@arbidocs/coedit/dist/server.d.cts +43 -0
  43. package/node_modules/@arbidocs/coedit/dist/server.d.ts +43 -0
  44. package/node_modules/@arbidocs/coedit/dist/server.js +1822 -0
  45. package/node_modules/@arbidocs/coedit/dist/server.js.map +1 -0
  46. package/node_modules/@arbidocs/coedit/dist/session-Cf9iu1Vt.d.cts +82 -0
  47. package/node_modules/@arbidocs/coedit/dist/session-Cf9iu1Vt.d.ts +82 -0
  48. package/node_modules/@arbidocs/coedit/dist/template.cjs +1627 -0
  49. package/node_modules/@arbidocs/coedit/dist/template.cjs.map +1 -0
  50. package/node_modules/@arbidocs/coedit/dist/template.d.cts +125 -0
  51. package/node_modules/@arbidocs/coedit/dist/template.d.ts +125 -0
  52. package/node_modules/@arbidocs/coedit/dist/template.js +1612 -0
  53. package/node_modules/@arbidocs/coedit/dist/template.js.map +1 -0
  54. package/node_modules/@arbidocs/coedit/dist/versions-DXiFQMA6.d.cts +8 -0
  55. package/node_modules/@arbidocs/coedit/dist/versions-DXiFQMA6.d.ts +8 -0
  56. package/node_modules/@arbidocs/coedit/package.json +68 -0
  57. package/node_modules/@docx-editor.dev/core/LICENSE +201 -0
  58. package/node_modules/@docx-editor.dev/core/README.md +125 -0
  59. package/node_modules/@docx-editor.dev/core/THIRD_PARTY_NOTICES.md +56 -0
  60. package/node_modules/@docx-editor.dev/core/dist/automation.cjs +1 -0
  61. package/node_modules/@docx-editor.dev/core/dist/automation.d.ts +162 -0
  62. package/node_modules/@docx-editor.dev/core/dist/automation.js +1 -0
  63. package/node_modules/@docx-editor.dev/core/dist/binding.cjs +1 -0
  64. package/node_modules/@docx-editor.dev/core/dist/binding.d.ts +164 -0
  65. package/node_modules/@docx-editor.dev/core/dist/binding.js +1 -0
  66. package/node_modules/@docx-editor.dev/core/dist/chunk-2GO5T2JU.cjs +1 -0
  67. package/node_modules/@docx-editor.dev/core/dist/chunk-2RC2EPND.js +3 -0
  68. package/node_modules/@docx-editor.dev/core/dist/chunk-4GBTELJV.cjs +28 -0
  69. package/node_modules/@docx-editor.dev/core/dist/chunk-4R3TEXMN.js +18 -0
  70. package/node_modules/@docx-editor.dev/core/dist/chunk-5CSUYANV.js +1 -0
  71. package/node_modules/@docx-editor.dev/core/dist/chunk-6APGXLBB.cjs +3 -0
  72. package/node_modules/@docx-editor.dev/core/dist/chunk-6AWEKBLB.cjs +1 -0
  73. package/node_modules/@docx-editor.dev/core/dist/chunk-6EYYL7FL.js +1 -0
  74. package/node_modules/@docx-editor.dev/core/dist/chunk-6JIJOZDW.js +1 -0
  75. package/node_modules/@docx-editor.dev/core/dist/chunk-BTQKU64Q.cjs +1 -0
  76. package/node_modules/@docx-editor.dev/core/dist/chunk-E7BQA6UP.js +2 -0
  77. package/node_modules/@docx-editor.dev/core/dist/chunk-EO4C5QJW.cjs +2 -0
  78. package/node_modules/@docx-editor.dev/core/dist/chunk-ETTO6GK3.js +1 -0
  79. package/node_modules/@docx-editor.dev/core/dist/chunk-FIJZIQXA.cjs +18 -0
  80. package/node_modules/@docx-editor.dev/core/dist/chunk-FRXAOVTB.js +28 -0
  81. package/node_modules/@docx-editor.dev/core/dist/chunk-J6BVWIDB.js +2 -0
  82. package/node_modules/@docx-editor.dev/core/dist/chunk-JGNVNT2A.cjs +2 -0
  83. package/node_modules/@docx-editor.dev/core/dist/chunk-K5U2PLDP.cjs +2 -0
  84. package/node_modules/@docx-editor.dev/core/dist/chunk-KKIJG3C6.js +2 -0
  85. package/node_modules/@docx-editor.dev/core/dist/chunk-LWDSDCMO.js +27 -0
  86. package/node_modules/@docx-editor.dev/core/dist/chunk-NBCVVZOM.cjs +1 -0
  87. package/node_modules/@docx-editor.dev/core/dist/chunk-O2AL2HSJ.cjs +1 -0
  88. package/node_modules/@docx-editor.dev/core/dist/chunk-O5INAWZQ.js +1 -0
  89. package/node_modules/@docx-editor.dev/core/dist/chunk-QMLCVPCD.cjs +1 -0
  90. package/node_modules/@docx-editor.dev/core/dist/chunk-RCHS4ZEH.cjs +27 -0
  91. package/node_modules/@docx-editor.dev/core/dist/chunk-RIYSCEFQ.js +2 -0
  92. package/node_modules/@docx-editor.dev/core/dist/chunk-S6J4O5XP.js +1 -0
  93. package/node_modules/@docx-editor.dev/core/dist/chunk-SRPILEWV.cjs +5 -0
  94. package/node_modules/@docx-editor.dev/core/dist/chunk-TSLBZ26X.js +1 -0
  95. package/node_modules/@docx-editor.dev/core/dist/chunk-UKVVUHZL.cjs +1 -0
  96. package/node_modules/@docx-editor.dev/core/dist/chunk-VDNNLG6X.js +2 -0
  97. package/node_modules/@docx-editor.dev/core/dist/chunk-VHAVHCQY.js +7 -0
  98. package/node_modules/@docx-editor.dev/core/dist/chunk-VX43VBAX.cjs +7 -0
  99. package/node_modules/@docx-editor.dev/core/dist/chunk-Z6WBFXJU.js +5 -0
  100. package/node_modules/@docx-editor.dev/core/dist/chunk-ZUHOMK52.cjs +2 -0
  101. package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.cjs +1 -0
  102. package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.d.ts +270 -0
  103. package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.js +1 -0
  104. package/node_modules/@docx-editor.dev/core/dist/collaboration.cjs +1 -0
  105. package/node_modules/@docx-editor.dev/core/dist/collaboration.d.ts +269 -0
  106. package/node_modules/@docx-editor.dev/core/dist/collaboration.js +1 -0
  107. package/node_modules/@docx-editor.dev/core/dist/contracts/document.cjs +1 -0
  108. package/node_modules/@docx-editor.dev/core/dist/contracts/document.d.ts +290 -0
  109. package/node_modules/@docx-editor.dev/core/dist/contracts/document.js +0 -0
  110. package/node_modules/@docx-editor.dev/core/dist/contracts/editor.cjs +1 -0
  111. package/node_modules/@docx-editor.dev/core/dist/contracts/editor.d.ts +22 -0
  112. package/node_modules/@docx-editor.dev/core/dist/contracts/editor.js +1 -0
  113. package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.cjs +1 -0
  114. package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.d.ts +103 -0
  115. package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.js +0 -0
  116. package/node_modules/@docx-editor.dev/core/dist/contracts/modules.cjs +1 -0
  117. package/node_modules/@docx-editor.dev/core/dist/contracts/modules.d.ts +143 -0
  118. package/node_modules/@docx-editor.dev/core/dist/contracts/modules.js +1 -0
  119. package/node_modules/@docx-editor.dev/core/dist/contracts/types.cjs +1 -0
  120. package/node_modules/@docx-editor.dev/core/dist/contracts/types.d.ts +11 -0
  121. package/node_modules/@docx-editor.dev/core/dist/contracts/types.js +0 -0
  122. package/node_modules/@docx-editor.dev/core/dist/custom-node-writes-cvL5rhcD.d.ts +323 -0
  123. package/node_modules/@docx-editor.dev/core/dist/dist-PKZR6RSH.js +2 -0
  124. package/node_modules/@docx-editor.dev/core/dist/document-protection-BAGVGqaP.d.ts +20 -0
  125. package/node_modules/@docx-editor.dev/core/dist/editor-Ci7IZGmG.d.ts +2448 -0
  126. package/node_modules/@docx-editor.dev/core/dist/editor-scope-OHPwVQ5l.d.ts +84 -0
  127. package/node_modules/@docx-editor.dev/core/dist/editor.cjs +1 -0
  128. package/node_modules/@docx-editor.dev/core/dist/editor.css +15 -0
  129. package/node_modules/@docx-editor.dev/core/dist/editor.d.ts +1394 -0
  130. package/node_modules/@docx-editor.dev/core/dist/editor.js +1 -0
  131. package/node_modules/@docx-editor.dev/core/dist/export.cjs +2 -0
  132. package/node_modules/@docx-editor.dev/core/dist/export.d.ts +391 -0
  133. package/node_modules/@docx-editor.dev/core/dist/export.js +2 -0
  134. package/node_modules/@docx-editor.dev/core/dist/failure-NS2lsya4.d.ts +115 -0
  135. package/node_modules/@docx-editor.dev/core/dist/font-resolver-BVQB14qT.d.ts +256 -0
  136. package/node_modules/@docx-editor.dev/core/dist/harfbuzz.wasm +0 -0
  137. package/node_modules/@docx-editor.dev/core/dist/headless-document-view-qH331moE.d.ts +143 -0
  138. package/node_modules/@docx-editor.dev/core/dist/image-resources-BN-hUgCn.d.ts +211 -0
  139. package/node_modules/@docx-editor.dev/core/dist/index-Bsg7oIKP.d.ts +3869 -0
  140. package/node_modules/@docx-editor.dev/core/dist/index.cjs +1 -0
  141. package/node_modules/@docx-editor.dev/core/dist/index.d.ts +53 -0
  142. package/node_modules/@docx-editor.dev/core/dist/index.js +1 -0
  143. package/node_modules/@docx-editor.dev/core/dist/layout-shaping-BEyuiQOk.d.ts +246 -0
  144. package/node_modules/@docx-editor.dev/core/dist/layout.cjs +1 -0
  145. package/node_modules/@docx-editor.dev/core/dist/layout.d.ts +3151 -0
  146. package/node_modules/@docx-editor.dev/core/dist/layout.js +1 -0
  147. package/node_modules/@docx-editor.dev/core/dist/node-module-shim-TTKTT66I.js +1 -0
  148. package/node_modules/@docx-editor.dev/core/dist/note-properties-4Y9o6Gyk.d.ts +68 -0
  149. package/node_modules/@docx-editor.dev/core/dist/omml-equation-CuzBL5DD.d.ts +85 -0
  150. package/node_modules/@docx-editor.dev/core/dist/output.cjs +1 -0
  151. package/node_modules/@docx-editor.dev/core/dist/output.d.ts +97 -0
  152. package/node_modules/@docx-editor.dev/core/dist/output.js +1 -0
  153. package/node_modules/@docx-editor.dev/core/dist/protocol-Bqk4Izjc.d.ts +1651 -0
  154. package/node_modules/@docx-editor.dev/core/dist/review-pane-D9jm8DcY.d.ts +128 -0
  155. package/node_modules/@docx-editor.dev/core/dist/review-paragraph-order-DT-n6ouC.d.ts +85 -0
  156. package/node_modules/@docx-editor.dev/core/dist/revision-projection-DZ4kKVev.d.ts +242 -0
  157. package/node_modules/@docx-editor.dev/core/dist/semantic-cell-selection-D9D1KSXq.d.ts +464 -0
  158. package/node_modules/@docx-editor.dev/core/dist/semantic-interaction-CIC-PooQ.d.ts +135 -0
  159. package/node_modules/@docx-editor.dev/core/dist/semantic-paint-BME37OMv.d.ts +326 -0
  160. package/node_modules/@docx-editor.dev/core/dist/semantic-record-queries-CBlZqZNa.d.ts +177 -0
  161. package/node_modules/@docx-editor.dev/core/dist/semantic-records-4B3WwFAi.d.ts +3532 -0
  162. package/node_modules/@docx-editor.dev/core/dist/store.cjs +1 -0
  163. package/node_modules/@docx-editor.dev/core/dist/store.d.ts +2706 -0
  164. package/node_modules/@docx-editor.dev/core/dist/store.js +1 -0
  165. package/node_modules/@docx-editor.dev/core/dist/tree-package-fragment-BeeKxDw8.d.ts +1201 -0
  166. package/node_modules/@docx-editor.dev/core/dist/tree-session-contract-CVbmlMlq.d.ts +664 -0
  167. package/node_modules/@docx-editor.dev/core/dist/types-barrel-D3xCgQX6.d.ts +4269 -0
  168. package/node_modules/@docx-editor.dev/core/licenses/HarfBuzz-COPYING.txt +42 -0
  169. package/node_modules/@docx-editor.dev/core/package.json +140 -0
  170. package/node_modules/@docx-editor.dev/react/LICENSE +201 -0
  171. package/node_modules/@docx-editor.dev/react/README.md +141 -0
  172. package/node_modules/@docx-editor.dev/react/THIRD_PARTY_NOTICES.md +18 -0
  173. package/node_modules/@docx-editor.dev/react/dist/index.d.mts +4928 -0
  174. package/node_modules/@docx-editor.dev/react/dist/index.d.ts +4928 -0
  175. package/node_modules/@docx-editor.dev/react/dist/index.js +4 -0
  176. package/node_modules/@docx-editor.dev/react/dist/index.mjs +4 -0
  177. package/node_modules/@docx-editor.dev/react/package.json +74 -0
  178. package/node_modules/@docx-editor.dev/react/src/styles/editor.css +6 -0
  179. package/node_modules/@docx-editor.dev/react/src/styles/zIndex.ts +28 -0
  180. package/package.json +26 -15
@@ -1,13 +1,15 @@
1
1
  "use client";
2
+ import { TYPED_SIGNATURE_STYLE, AdoptSignatureDialog } from '../../chunk-EQB3WELX.js';
3
+ import { ModalScaffold } from '../../chunk-TX2ZICS7.js';
2
4
  import '../../chunk-VUNV25KB.js';
3
5
  import { useRef, useMemo, useEffect, useState, useCallback } from 'react';
4
6
  import { useAnnotationLayer, redactionLogCsv, AnnotationPageOverlay, AnnotationToolbar, FreezeDialog, createMemoryStore } from '@arbidocs/react/annotations';
5
7
  import { freezePdfInBrowser } from '@arbidocs/react/annotations/freeze';
6
- import { useDocumentTools, useIsOnline, createMarkupStore, fetchMarkupPdf, uploadFrozenCopy, redactionLogName, SIGNED_LOCKED_REASON, isLegibleSignatureBox, toAppearance } from '@arbidocs/react/document-tools';
8
+ import { useDocumentTools, useIsOnline, createMarkupStore, fetchMarkupPdf, uploadFrozenCopy, redactionLogName, SIGNED_LOCKED_REASON, isLegibleSignatureBox, toAppearance, FIELD_TYPE_LABELS, useSignSignatureRequest, useDeclineSignatureRequest, fieldsInSigningOrder, MARK_FIELD_TYPES, intentText, useSignerCandidates, useSaveSignatureRequest, sendBlocker, newFieldId, SIGNATURE_FIELD_TYPES, SigningError, DEFAULT_FIELD_SIZE, suggestSignatureFields, fieldsFromSuggestions } from '@arbidocs/react/document-tools';
7
9
  import { PdfViewer } from '@arbidocs/react/viewers';
8
- import { Download } from 'lucide-react';
9
- import { jsx, jsxs } from 'react/jsx-runtime';
10
- import { Button } from '@arbidocs/react/ui';
10
+ import { Download, X, ArrowRight, ArrowLeft, Check, UserPlus, ScanSearch, Send, PenLine } from 'lucide-react';
11
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
12
+ import { Button, cn, Progress, Label, Input, Checkbox } from '@arbidocs/react/ui';
11
13
 
12
14
  var MARKUP_AUTOSAVE_MS = 2500;
13
15
  var MARKUP_PULL_MS = 2e4;
@@ -262,7 +264,983 @@ function SignaturePlacementViewer({
262
264
  /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(PdfViewer$1, { ...viewerProps, file, renderPageOverlay }) })
263
265
  ] });
264
266
  }
267
+ var SIGNER_COLORS = ["#1c7ed6", "#e8590c", "#2f9e44", "#9c36b5", "#c2255c", "#0c8599"];
268
+ var MIN_DRAG = 0.01;
269
+ var clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
270
+ var round = (v) => Math.round(v * 1e4) / 1e4;
271
+ function fit(box) {
272
+ const width = clamp(box.width, 0.02, 1);
273
+ const height = clamp(box.height, 0.015, 1);
274
+ return {
275
+ x: round(clamp(box.x, 0, 1 - width)),
276
+ y: round(clamp(box.y, 0, 1 - height)),
277
+ width: round(width),
278
+ height: round(height)
279
+ };
280
+ }
281
+ function SignatureFieldsOverlay({
282
+ page,
283
+ fields,
284
+ colorOf,
285
+ labelOf = (f) => FIELD_TYPE_LABELS[f.type],
286
+ editable = false,
287
+ placing = null,
288
+ selectedId = null,
289
+ onSelect,
290
+ onCreate,
291
+ onChange,
292
+ onRemove,
293
+ activeId = null,
294
+ onActivate,
295
+ renderContent
296
+ }) {
297
+ const ref = useRef(null);
298
+ const [drag, setDrag] = useState(null);
299
+ const [preview, setPreview] = useState(null);
300
+ const onPage = fields.filter((f) => f.page === page);
301
+ const point = (e) => {
302
+ const r = ref.current.getBoundingClientRect();
303
+ return { x: (e.clientX - r.left) / r.width, y: (e.clientY - r.top) / r.height };
304
+ };
305
+ const startCreate = (e) => {
306
+ if (!editable || e.target !== e.currentTarget || e.button !== 0) return;
307
+ if (!placing) {
308
+ onSelect?.(null);
309
+ return;
310
+ }
311
+ const p = point(e);
312
+ e.currentTarget.setPointerCapture?.(e.pointerId);
313
+ setDrag({ kind: "create", startX: p.x, startY: p.y, box: { ...p, width: 0, height: 0 } });
314
+ };
315
+ const startField = (e, field, kind) => {
316
+ if (!editable || e.button !== 0) return;
317
+ e.stopPropagation();
318
+ onSelect?.(field.id);
319
+ const p = point(e);
320
+ ref.current?.setPointerCapture?.(e.pointerId);
321
+ setDrag({
322
+ kind,
323
+ id: field.id,
324
+ startX: p.x,
325
+ startY: p.y,
326
+ origin: { x: field.x, y: field.y, width: field.width, height: field.height }
327
+ });
328
+ };
329
+ const onMove = (e) => {
330
+ if (!drag) return;
331
+ const p = point(e);
332
+ const dx = p.x - drag.startX;
333
+ const dy = p.y - drag.startY;
334
+ if (drag.kind === "create") {
335
+ setPreview({
336
+ x: Math.min(p.x, drag.startX),
337
+ y: Math.min(p.y, drag.startY),
338
+ width: Math.abs(dx),
339
+ height: Math.abs(dy)
340
+ });
341
+ } else if (drag.kind === "move") {
342
+ setPreview(fit({ ...drag.origin, x: drag.origin.x + dx, y: drag.origin.y + dy }));
343
+ } else {
344
+ setPreview(
345
+ fit({ ...drag.origin, width: drag.origin.width + dx, height: drag.origin.height + dy })
346
+ );
347
+ }
348
+ };
349
+ const onUp = (e) => {
350
+ if (!drag) return;
351
+ const p = point(e);
352
+ if (drag.kind === "create" && placing) {
353
+ const drawn = Math.abs(p.x - drag.startX) > MIN_DRAG && Math.abs(p.y - drag.startY) > MIN_DRAG;
354
+ const size = DEFAULT_FIELD_SIZE[placing];
355
+ onCreate?.(
356
+ fit(
357
+ drawn && preview ? preview : { x: drag.startX - size.width / 2, y: drag.startY - size.height / 2, ...size }
358
+ )
359
+ );
360
+ } else if (drag.kind !== "create" && preview) {
361
+ onChange?.(drag.id, preview);
362
+ }
363
+ setDrag(null);
364
+ setPreview(null);
365
+ };
366
+ return /* @__PURE__ */ jsxs(
367
+ "div",
368
+ {
369
+ ref,
370
+ className: cn(
371
+ "absolute inset-0",
372
+ editable && placing && "cursor-crosshair",
373
+ !editable && "pointer-events-none"
374
+ ),
375
+ onPointerDown: startCreate,
376
+ onPointerMove: onMove,
377
+ onPointerUp: onUp,
378
+ onPointerCancel: () => {
379
+ setDrag(null);
380
+ setPreview(null);
381
+ },
382
+ "data-testid": `signature-fields-page-${page}`,
383
+ children: [
384
+ onPage.map((field) => {
385
+ const dragging = drag && drag.kind !== "create" && drag.id === field.id && preview;
386
+ const box = dragging ? preview : field;
387
+ const color = colorOf(field.signer);
388
+ const selected = editable && selectedId === field.id;
389
+ const active = !editable && activeId === field.id;
390
+ const content = renderContent?.(field);
391
+ return /* @__PURE__ */ jsxs(
392
+ "div",
393
+ {
394
+ role: editable ? void 0 : "button",
395
+ tabIndex: editable ? void 0 : 0,
396
+ "aria-label": editable ? void 0 : `${labelOf(field)}${content ? " (done)" : ""}`,
397
+ className: cn(
398
+ "pointer-events-auto absolute flex items-center justify-center overflow-visible rounded-sm border-2 text-[11px] font-medium select-none",
399
+ editable ? "cursor-move" : "cursor-pointer",
400
+ active && "ring-4 ring-offset-1 motion-safe:animate-pulse",
401
+ selected && "ring-2 ring-offset-1"
402
+ ),
403
+ style: {
404
+ left: `${box.x * 100}%`,
405
+ top: `${box.y * 100}%`,
406
+ width: `${box.width * 100}%`,
407
+ height: `${box.height * 100}%`,
408
+ borderColor: color,
409
+ borderStyle: content ? "solid" : "dashed",
410
+ backgroundColor: content ? "transparent" : `${color}22`,
411
+ color,
412
+ ["--tw-ring-color"]: color
413
+ },
414
+ onPointerDown: (e) => startField(e, field, "move"),
415
+ onClick: () => !editable && onActivate?.(field.id),
416
+ onKeyDown: (e) => {
417
+ if (!editable && (e.key === "Enter" || e.key === " ")) {
418
+ e.preventDefault();
419
+ onActivate?.(field.id);
420
+ }
421
+ if (editable && selected && (e.key === "Delete" || e.key === "Backspace")) {
422
+ onRemove?.(field.id);
423
+ }
424
+ },
425
+ "data-testid": `signature-field-${field.id}`,
426
+ "data-field-type": field.type,
427
+ "data-field-done": content ? "true" : void 0,
428
+ children: [
429
+ content ?? /* @__PURE__ */ jsxs("span", { className: "truncate px-1", children: [
430
+ labelOf(field),
431
+ field.required ? "" : " (optional)"
432
+ ] }),
433
+ selected && /* @__PURE__ */ jsxs(Fragment, { children: [
434
+ /* @__PURE__ */ jsx(
435
+ "button",
436
+ {
437
+ type: "button",
438
+ "aria-label": "Remove field",
439
+ className: "absolute -top-2.5 -right-2.5 flex size-5 items-center justify-center rounded-full border bg-background text-foreground shadow",
440
+ onPointerDown: (e) => e.stopPropagation(),
441
+ onClick: () => onRemove?.(field.id),
442
+ "data-testid": "signature-field-remove",
443
+ children: /* @__PURE__ */ jsx(X, { className: "size-3" })
444
+ }
445
+ ),
446
+ /* @__PURE__ */ jsx(
447
+ "span",
448
+ {
449
+ "aria-hidden": true,
450
+ className: "absolute -right-1.5 -bottom-1.5 size-3 cursor-nwse-resize rounded-sm border bg-background",
451
+ style: { borderColor: color },
452
+ onPointerDown: (e) => startField(e, field, "resize"),
453
+ "data-testid": "signature-field-resize"
454
+ }
455
+ )
456
+ ] })
457
+ ]
458
+ },
459
+ field.id
460
+ );
461
+ }),
462
+ drag?.kind === "create" && preview && /* @__PURE__ */ jsx(
463
+ "div",
464
+ {
465
+ className: "pointer-events-none absolute rounded-sm border-2 border-dashed",
466
+ style: {
467
+ left: `${preview.x * 100}%`,
468
+ top: `${preview.y * 100}%`,
469
+ width: `${preview.width * 100}%`,
470
+ height: `${preview.height * 100}%`,
471
+ borderColor: "#868e96"
472
+ }
473
+ }
474
+ )
475
+ ]
476
+ }
477
+ );
478
+ }
479
+ var INK = "#1c7ed6";
480
+ function signingDate(date = /* @__PURE__ */ new Date()) {
481
+ return `${date.getDate()} ${date.toLocaleString("en-GB", { month: "long" })} ${date.getFullYear()}`;
482
+ }
483
+ function GuidedSigningViewer({
484
+ file,
485
+ request,
486
+ signer,
487
+ onClose,
488
+ onSigned,
489
+ viewer: PdfViewer$1 = PdfViewer,
490
+ ...viewerProps
491
+ }) {
492
+ const { user, notify } = useDocumentTools();
493
+ const sign = useSignSignatureRequest();
494
+ const decline = useDeclineSignatureRequest();
495
+ const mine = useMemo(() => fieldsInSigningOrder(request.fields, signer), [request.fields, signer]);
496
+ const [mark, setMark] = useState(null);
497
+ const [applied, setApplied] = useState(/* @__PURE__ */ new Set());
498
+ const [index, setIndex] = useState(-1);
499
+ const [page, setPage] = useState(1);
500
+ const [trigger, setTrigger] = useState(0);
501
+ const [adoptFor, setAdoptFor] = useState(null);
502
+ const [finishing, setFinishing] = useState(false);
503
+ const [password, setPassword] = useState("");
504
+ const [error, setError] = useState(null);
505
+ const [declining, setDeclining] = useState(false);
506
+ const [declineReason, setDeclineReason] = useState("");
507
+ const scrollTimer = useRef(void 0);
508
+ const required = mine.filter((f) => f.required);
509
+ const done = mine.filter((f) => applied.has(f.id)).length;
510
+ const ready = required.every((f) => applied.has(f.id));
511
+ const current = index >= 0 ? mine[index] : void 0;
512
+ useEffect(() => () => window.clearTimeout(scrollTimer.current), []);
513
+ const goTo = useCallback(
514
+ (i) => {
515
+ const field = mine[i];
516
+ if (!field) return;
517
+ setIndex(i);
518
+ setPage(field.page + 1);
519
+ setTrigger((t) => t + 1);
520
+ window.clearTimeout(scrollTimer.current);
521
+ scrollTimer.current = window.setTimeout(() => {
522
+ document.querySelector(`[data-testid="signature-field-${field.id}"]`)?.scrollIntoView({ block: "center", behavior: "smooth" });
523
+ }, 300);
524
+ },
525
+ [mine]
526
+ );
527
+ const nextOpen = (from, filled) => {
528
+ for (let k = 1; k <= mine.length; k++) {
529
+ const i = (from + k) % mine.length;
530
+ if (!filled.has(mine[i].id)) return i;
531
+ }
532
+ return -1;
533
+ };
534
+ const apply = (field, base = applied) => {
535
+ const next = new Set(base);
536
+ next.add(field.id);
537
+ setApplied(next);
538
+ const i = nextOpen(mine.indexOf(field), next);
539
+ if (i >= 0) goTo(i);
540
+ else setIndex(mine.indexOf(field));
541
+ };
542
+ const activate = (id) => {
543
+ const field = mine.find((f) => f.id === id);
544
+ if (!field) return;
545
+ setIndex(mine.indexOf(field));
546
+ if (applied.has(id)) {
547
+ setApplied((a) => {
548
+ const next = new Set(a);
549
+ next.delete(id);
550
+ return next;
551
+ });
552
+ return;
553
+ }
554
+ if (!mark) {
555
+ setAdoptFor(field);
556
+ return;
557
+ }
558
+ apply(field);
559
+ };
560
+ const onAdopt = (adopted) => {
561
+ setMark(adopted);
562
+ const field = adoptFor;
563
+ setAdoptFor(null);
564
+ const filled = new Set(applied);
565
+ for (const f of mine)
566
+ if (f.required && (f.type === "date" || f.type === "name")) filled.add(f.id);
567
+ if (field) apply(field, filled);
568
+ else setApplied(filled);
569
+ };
570
+ const renderContent = useCallback(
571
+ (field) => {
572
+ if (!applied.has(field.id) || !mark) return null;
573
+ const { adopted, signatureUrl } = mark;
574
+ if (field.type === "signature" && signatureUrl) {
575
+ return /* @__PURE__ */ jsx("img", { src: signatureUrl, alt: "Your signature", className: "h-full w-full object-contain" });
576
+ }
577
+ const text = field.type === "signature" ? adopted.name : field.type === "initials" ? adopted.initials : field.type === "date" ? signingDate() : adopted.name;
578
+ const typed = MARK_FIELD_TYPES.includes(field.type);
579
+ return /* @__PURE__ */ jsx(
580
+ "span",
581
+ {
582
+ className: "flex h-full w-full items-center px-1 whitespace-nowrap [container-type:size]",
583
+ style: typed ? TYPED_SIGNATURE_STYLE : { color: "#1a1a26" },
584
+ children: /* @__PURE__ */ jsx("span", { style: { fontSize: typed ? "70cqh" : "62cqh", lineHeight: 1 }, children: text })
585
+ }
586
+ );
587
+ },
588
+ [applied, mark]
589
+ );
590
+ const renderPageOverlay = useCallback(
591
+ ({ pageNumber }) => /* @__PURE__ */ jsx(
592
+ SignatureFieldsOverlay,
593
+ {
594
+ page: pageNumber - 1,
595
+ fields: mine,
596
+ colorOf: () => INK,
597
+ labelOf: (f) => MARK_FIELD_TYPES.includes(f.type) ? `Sign: ${FIELD_TYPE_LABELS[f.type]}` : FIELD_TYPE_LABELS[f.type],
598
+ activeId: current?.id ?? null,
599
+ onActivate: activate,
600
+ renderContent
601
+ }
602
+ ),
603
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- activate reads the latest state
604
+ [mine, current?.id, renderContent, mark, applied]
605
+ );
606
+ const submit = async (e) => {
607
+ e.preventDefault();
608
+ if (!mark || !user?.email) return;
609
+ setError(null);
610
+ try {
611
+ const result = await sign.mutateAsync({
612
+ request,
613
+ pdfBlob: file,
614
+ email: user.email,
615
+ password,
616
+ adopted: mark.adopted,
617
+ fields: mine.filter((f) => applied.has(f.id)).map((f) => f.id)
618
+ });
619
+ setPassword("");
620
+ setFinishing(false);
621
+ notify(
622
+ result.completed ? `Signed. Everyone has signed: the signed copy is version ${result.signed_version}.` : "Signed. The others are still to sign; you will see the signed copy when they have.",
623
+ "success"
624
+ );
625
+ onSigned?.(result);
626
+ } catch (err) {
627
+ setError(err instanceof Error ? err.message : "Signing failed");
628
+ if (err instanceof SigningError && err.reason === "stale") setFinishing(false);
629
+ }
630
+ };
631
+ const onDecline = async (e) => {
632
+ e.preventDefault();
633
+ try {
634
+ await decline.mutateAsync({ requestId: request.external_id, reason: declineReason.trim() });
635
+ setDeclining(false);
636
+ notify("You declined to sign. The sender has been told.", "info");
637
+ onClose();
638
+ } catch (err) {
639
+ notify(err instanceof Error ? err.message : "Could not decline", "error");
640
+ }
641
+ };
642
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 flex-col", "data-testid": "guided-signing-viewer", children: [
643
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 border-b border-border px-3 py-2 text-sm", children: [
644
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
645
+ index < 0 ? /* @__PURE__ */ jsxs("span", { className: "mr-auto", "data-testid": "guided-signing-intro", children: [
646
+ "You are asked to complete ",
647
+ mine.length,
648
+ " field",
649
+ mine.length === 1 ? "" : "s",
650
+ ".",
651
+ request.message ? /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
652
+ " \u201C",
653
+ request.message,
654
+ "\u201D"
655
+ ] }) : null
656
+ ] }) : /* @__PURE__ */ jsxs("span", { className: "mr-auto font-medium", "data-testid": "guided-signing-position", children: [
657
+ "Field ",
658
+ index + 1,
659
+ " of ",
660
+ mine.length,
661
+ ": ",
662
+ current ? FIELD_TYPE_LABELS[current.type] : "",
663
+ current && !current.required ? " (optional)" : "",
664
+ /* @__PURE__ */ jsxs("span", { className: "ml-2 font-normal text-muted-foreground", children: [
665
+ "Page ",
666
+ current ? current.page + 1 : ""
667
+ ] })
668
+ ] }),
669
+ /* @__PURE__ */ jsx(
670
+ Button,
671
+ {
672
+ type: "button",
673
+ variant: "ghost",
674
+ size: "sm",
675
+ onClick: () => setDeclining(true),
676
+ "data-testid": "guided-signing-decline",
677
+ children: "Decline"
678
+ }
679
+ ),
680
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onClose, children: "Close" }),
681
+ index < 0 ? /* @__PURE__ */ jsxs(
682
+ Button,
683
+ {
684
+ type: "button",
685
+ size: "sm",
686
+ onClick: () => goTo(0),
687
+ "data-testid": "guided-signing-start",
688
+ children: [
689
+ "Start",
690
+ /* @__PURE__ */ jsx(ArrowRight, { className: "ml-1 size-4", "aria-hidden": true })
691
+ ]
692
+ }
693
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
694
+ /* @__PURE__ */ jsx(
695
+ Button,
696
+ {
697
+ type: "button",
698
+ variant: "outline",
699
+ size: "sm",
700
+ onClick: () => goTo(Math.max(0, index - 1)),
701
+ disabled: index === 0,
702
+ "aria-label": "Previous field",
703
+ children: /* @__PURE__ */ jsx(ArrowLeft, { className: "size-4", "aria-hidden": true })
704
+ }
705
+ ),
706
+ /* @__PURE__ */ jsx(
707
+ Button,
708
+ {
709
+ type: "button",
710
+ variant: "outline",
711
+ size: "sm",
712
+ onClick: () => goTo(Math.min(mine.length - 1, index + 1)),
713
+ disabled: index >= mine.length - 1,
714
+ "aria-label": "Next field",
715
+ "data-testid": "guided-signing-next",
716
+ children: /* @__PURE__ */ jsx(ArrowRight, { className: "size-4", "aria-hidden": true })
717
+ }
718
+ ),
719
+ current && !applied.has(current.id) && /* @__PURE__ */ jsx(
720
+ Button,
721
+ {
722
+ type: "button",
723
+ size: "sm",
724
+ onClick: () => activate(current.id),
725
+ "data-testid": "guided-signing-apply",
726
+ children: MARK_FIELD_TYPES.includes(current.type) ? "Sign here" : "Fill in"
727
+ }
728
+ )
729
+ ] }),
730
+ /* @__PURE__ */ jsxs(
731
+ Button,
732
+ {
733
+ type: "button",
734
+ size: "sm",
735
+ variant: ready ? "default" : "outline",
736
+ disabled: !ready || !mark,
737
+ onClick: () => setFinishing(true),
738
+ "data-testid": "guided-signing-finish",
739
+ children: [
740
+ /* @__PURE__ */ jsx(Check, { className: "mr-1 size-4", "aria-hidden": true }),
741
+ "Finish"
742
+ ]
743
+ }
744
+ )
745
+ ] }),
746
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
747
+ /* @__PURE__ */ jsx(
748
+ Progress,
749
+ {
750
+ value: mine.length ? done / mine.length * 100 : 0,
751
+ className: "h-1.5 max-w-xs"
752
+ }
753
+ ),
754
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", "data-testid": "guided-signing-progress", children: [
755
+ done,
756
+ " of ",
757
+ mine.length,
758
+ " done"
759
+ ] })
760
+ ] })
761
+ ] }),
762
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(
763
+ PdfViewer$1,
764
+ {
765
+ ...viewerProps,
766
+ file,
767
+ currentPage: page,
768
+ scrollTrigger: trigger,
769
+ renderPageOverlay
770
+ }
771
+ ) }),
772
+ /* @__PURE__ */ jsx(
773
+ AdoptSignatureDialog,
774
+ {
775
+ open: !!adoptFor,
776
+ onOpenChange: (open) => !open && setAdoptFor(null),
777
+ defaultName: user?.name ?? "",
778
+ onAdopt
779
+ }
780
+ ),
781
+ /* @__PURE__ */ jsx(
782
+ ModalScaffold,
783
+ {
784
+ open: declining,
785
+ onOpenChange: (open) => !decline.isPending && setDeclining(open),
786
+ title: "Decline to sign",
787
+ description: "The request ends for everyone and the sender is told. The document is unchanged.",
788
+ showDescription: true,
789
+ testId: "guided-signing-decline-dialog",
790
+ children: /* @__PURE__ */ jsxs("form", { onSubmit: onDecline, children: [
791
+ /* @__PURE__ */ jsx(ModalScaffold.Body, { children: /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
792
+ /* @__PURE__ */ jsx(Label, { htmlFor: "guided-decline-reason", children: "Reason (optional)" }),
793
+ /* @__PURE__ */ jsx(
794
+ Input,
795
+ {
796
+ id: "guided-decline-reason",
797
+ value: declineReason,
798
+ maxLength: 1e3,
799
+ onChange: (e) => setDeclineReason(e.target.value)
800
+ }
801
+ )
802
+ ] }) }),
803
+ /* @__PURE__ */ jsxs(ModalScaffold.Footer, { children: [
804
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: () => setDeclining(false), children: "Cancel" }),
805
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: "destructive", disabled: decline.isPending, children: "Decline" })
806
+ ] })
807
+ ] })
808
+ }
809
+ ),
810
+ /* @__PURE__ */ jsx(
811
+ ModalScaffold,
812
+ {
813
+ open: finishing,
814
+ onOpenChange: (open) => !sign.isPending && setFinishing(open),
815
+ title: "Sign the document",
816
+ description: "Confirm with your password. Your signature is applied to every field you completed.",
817
+ showDescription: true,
818
+ testId: "guided-signing-confirm",
819
+ children: /* @__PURE__ */ jsxs("form", { onSubmit: submit, children: [
820
+ /* @__PURE__ */ jsxs(ModalScaffold.Body, { children: [
821
+ mark && /* @__PURE__ */ jsx("blockquote", { className: "border-l-2 border-border pl-3 text-sm text-muted-foreground", children: intentText({ name: mark.adopted.name }) }),
822
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
823
+ /* @__PURE__ */ jsx(Label, { htmlFor: "guided-sign-password", children: "Password" }),
824
+ /* @__PURE__ */ jsx(
825
+ Input,
826
+ {
827
+ id: "guided-sign-password",
828
+ type: "password",
829
+ autoComplete: "current-password",
830
+ value: password,
831
+ onChange: (e) => setPassword(e.target.value),
832
+ "data-testid": "guided-signing-password",
833
+ required: true
834
+ }
835
+ )
836
+ ] }),
837
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-red-text", role: "alert", "data-testid": "guided-signing-error", children: error })
838
+ ] }),
839
+ /* @__PURE__ */ jsxs(ModalScaffold.Footer, { children: [
840
+ /* @__PURE__ */ jsx(
841
+ Button,
842
+ {
843
+ type: "button",
844
+ variant: "outline",
845
+ onClick: () => setFinishing(false),
846
+ disabled: sign.isPending,
847
+ children: "Cancel"
848
+ }
849
+ ),
850
+ /* @__PURE__ */ jsx(
851
+ Button,
852
+ {
853
+ type: "submit",
854
+ disabled: sign.isPending || !password,
855
+ "data-testid": "guided-signing-submit",
856
+ children: sign.isPending ? "Signing\u2026" : "Sign"
857
+ }
858
+ )
859
+ ] })
860
+ ] })
861
+ }
862
+ )
863
+ ] });
864
+ }
865
+ var selectClass = "h-8 rounded-md border border-input bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
866
+ function SignatureRequestEditor({
867
+ file,
868
+ documentId,
869
+ version,
870
+ draft,
871
+ onCancel,
872
+ onSaved,
873
+ viewer: PdfViewer$1 = PdfViewer,
874
+ ...viewerProps
875
+ }) {
876
+ const { client, notify } = useDocumentTools();
877
+ const candidates = useSignerCandidates();
878
+ const save = useSaveSignatureRequest();
879
+ const [fields, setFields] = useState(() => draft?.fields ?? []);
880
+ const [signers, setSigners] = useState(() => [
881
+ ...new Set((draft?.fields ?? []).map((f) => f.signer))
882
+ ]);
883
+ const [current, setCurrent] = useState(signers[0] ?? null);
884
+ const [placing, setPlacing] = useState(null);
885
+ const [selectedId, setSelectedId] = useState(null);
886
+ const [message, setMessage] = useState(draft?.message ?? "");
887
+ const [suggestions, setSuggestions] = useState(null);
888
+ const [assign, setAssign] = useState({});
889
+ const [finding, setFinding] = useState(false);
890
+ const [error, setError] = useState(null);
891
+ const people = useMemo(() => candidates.data ?? [], [candidates.data]);
892
+ const nameOf = useCallback(
893
+ (ext) => people.find((p) => p.externalId === ext)?.name ?? ext,
894
+ [people]
895
+ );
896
+ const colorOf = useCallback(
897
+ (ext) => {
898
+ const i = signers.indexOf(ext);
899
+ return SIGNER_COLORS[(i < 0 ? 0 : i) % SIGNER_COLORS.length];
900
+ },
901
+ [signers]
902
+ );
903
+ const selected = fields.find((f) => f.id === selectedId) ?? null;
904
+ const blocker = signers.length === 0 ? "Add a signer." : sendBlocker(fields);
905
+ const addSigner = (ext) => {
906
+ if (!ext || signers.includes(ext)) return;
907
+ setSigners((s) => [...s, ext]);
908
+ setCurrent(ext);
909
+ setPlacing((p) => p ?? "signature");
910
+ };
911
+ const removeSigner = (ext) => {
912
+ setSigners((s) => s.filter((x) => x !== ext));
913
+ setFields((fs) => fs.filter((f) => f.signer !== ext));
914
+ if (current === ext) setCurrent(signers.find((x) => x !== ext) ?? null);
915
+ };
916
+ const updateField = (id, patch) => setFields((fs) => fs.map((f) => f.id === id ? { ...f, ...patch } : f));
917
+ const findBlocks = async () => {
918
+ setFinding(true);
919
+ setError(null);
920
+ try {
921
+ const found = await suggestSignatureFields(client, documentId, version);
922
+ setSuggestions(found);
923
+ const groups2 = [...new Set(found.map((s) => s.group))];
924
+ setAssign(Object.fromEntries(groups2.map((g, i) => [g, signers[i]])));
925
+ if (found.length === 0) notify("No signature blocks were found in this document.", "info");
926
+ } catch (err) {
927
+ setError(err instanceof Error ? err.message : "Signature blocks could not be read");
928
+ } finally {
929
+ setFinding(false);
930
+ }
931
+ };
932
+ const applySuggestions = () => {
933
+ if (!suggestions) return;
934
+ const added = fieldsFromSuggestions(suggestions, assign);
935
+ setFields((fs) => [...fs, ...added]);
936
+ const assigned = [...new Set(added.map((f) => f.signer))];
937
+ setSigners((s) => [...s, ...assigned.filter((ext) => !s.includes(ext))]);
938
+ if (!current && assigned[0]) setCurrent(assigned[0]);
939
+ setSuggestions(null);
940
+ notify(`${added.length} field${added.length === 1 ? "" : "s"} added.`, "success");
941
+ };
942
+ const submit = async (send) => {
943
+ setError(null);
944
+ try {
945
+ const request = await save.mutateAsync({
946
+ documentId,
947
+ version,
948
+ fields,
949
+ message: message.trim() || void 0,
950
+ requestId: draft?.status === "draft" ? draft.external_id : void 0,
951
+ send
952
+ });
953
+ notify(
954
+ send ? `Sent for signature to ${request.signers.length} signer${request.signers.length === 1 ? "" : "s"}.` : "Draft saved.",
955
+ "success"
956
+ );
957
+ onSaved(request);
958
+ } catch (err) {
959
+ setError(err instanceof Error ? err.message : "The request could not be saved");
960
+ }
961
+ };
962
+ const renderPageOverlay = useCallback(
963
+ ({ pageNumber }) => /* @__PURE__ */ jsx(
964
+ SignatureFieldsOverlay,
965
+ {
966
+ page: pageNumber - 1,
967
+ fields,
968
+ colorOf,
969
+ labelOf: (f) => `${FIELD_TYPE_LABELS[f.type]} \xB7 ${nameOf(f.signer).split(" ")[0]}`,
970
+ editable: true,
971
+ placing: current ? placing : null,
972
+ selectedId,
973
+ onSelect: setSelectedId,
974
+ onCreate: (box) => {
975
+ if (!current || !placing) return;
976
+ const field = {
977
+ id: newFieldId(),
978
+ type: placing,
979
+ page: pageNumber - 1,
980
+ signer: current,
981
+ required: true,
982
+ ...box
983
+ };
984
+ setFields((fs) => [...fs, field]);
985
+ setSelectedId(field.id);
986
+ },
987
+ onChange: (id, box) => updateField(id, box),
988
+ onRemove: (id) => {
989
+ setFields((fs) => fs.filter((f) => f.id !== id));
990
+ setSelectedId(null);
991
+ }
992
+ }
993
+ ),
994
+ [fields, colorOf, nameOf, current, placing, selectedId]
995
+ );
996
+ const groups = suggestions ? [...new Set(suggestions.map((s) => s.group))] : [];
997
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 flex-col", "data-testid": "signature-request-editor", children: [
998
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 border-b border-border px-3 py-2 text-sm", children: [
999
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
1000
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Signers" }),
1001
+ signers.map((ext) => /* @__PURE__ */ jsxs(
1002
+ "span",
1003
+ {
1004
+ className: cn(
1005
+ "inline-flex items-center gap-1.5 rounded-full border py-0.5 pr-1 pl-2",
1006
+ current === ext && "bg-muted"
1007
+ ),
1008
+ style: { borderColor: colorOf(ext) },
1009
+ children: [
1010
+ /* @__PURE__ */ jsxs(
1011
+ "button",
1012
+ {
1013
+ type: "button",
1014
+ className: "inline-flex items-center gap-1.5",
1015
+ onClick: () => setCurrent(ext),
1016
+ "aria-pressed": current === ext,
1017
+ "data-testid": `signer-chip-${ext}`,
1018
+ children: [
1019
+ /* @__PURE__ */ jsx("span", { className: "size-2.5 rounded-full", style: { background: colorOf(ext) } }),
1020
+ nameOf(ext)
1021
+ ]
1022
+ }
1023
+ ),
1024
+ /* @__PURE__ */ jsx(
1025
+ "button",
1026
+ {
1027
+ type: "button",
1028
+ "aria-label": `Remove ${nameOf(ext)}`,
1029
+ className: "rounded-full p-0.5 hover:bg-accent",
1030
+ onClick: () => removeSigner(ext),
1031
+ children: /* @__PURE__ */ jsx(X, { className: "size-3" })
1032
+ }
1033
+ )
1034
+ ]
1035
+ },
1036
+ ext
1037
+ )),
1038
+ /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-1 text-muted-foreground", children: [
1039
+ /* @__PURE__ */ jsx(UserPlus, { className: "size-4", "aria-hidden": true }),
1040
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add a signer" }),
1041
+ /* @__PURE__ */ jsxs(
1042
+ "select",
1043
+ {
1044
+ className: selectClass,
1045
+ value: "",
1046
+ onChange: (e) => addSigner(e.target.value),
1047
+ disabled: candidates.isLoading,
1048
+ "data-testid": "signature-add-signer",
1049
+ children: [
1050
+ /* @__PURE__ */ jsx("option", { value: "", children: candidates.isLoading ? "Loading members\u2026" : "Add a signer\u2026" }),
1051
+ people.filter((p) => !signers.includes(p.externalId)).map((p) => /* @__PURE__ */ jsxs("option", { value: p.externalId, children: [
1052
+ p.name,
1053
+ " (",
1054
+ p.email,
1055
+ ")"
1056
+ ] }, p.externalId))
1057
+ ]
1058
+ }
1059
+ )
1060
+ ] })
1061
+ ] }),
1062
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
1063
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: current ? `Place for ${nameOf(current)}:` : "Add a signer, then place their fields." }),
1064
+ SIGNATURE_FIELD_TYPES.map((type) => /* @__PURE__ */ jsx(
1065
+ Button,
1066
+ {
1067
+ type: "button",
1068
+ size: "sm",
1069
+ variant: placing === type && current ? "default" : "outline",
1070
+ disabled: !current,
1071
+ onClick: () => setPlacing(placing === type ? null : type),
1072
+ "data-testid": `signature-place-${type}`,
1073
+ children: FIELD_TYPE_LABELS[type]
1074
+ },
1075
+ type
1076
+ )),
1077
+ /* @__PURE__ */ jsxs(
1078
+ Button,
1079
+ {
1080
+ type: "button",
1081
+ size: "sm",
1082
+ variant: "ghost",
1083
+ onClick: findBlocks,
1084
+ disabled: finding,
1085
+ "data-testid": "signature-find-blocks",
1086
+ children: [
1087
+ /* @__PURE__ */ jsx(ScanSearch, { className: "mr-1 size-4", "aria-hidden": true }),
1088
+ finding ? "Looking\u2026" : "Find signature blocks"
1089
+ ]
1090
+ }
1091
+ ),
1092
+ /* @__PURE__ */ jsxs("span", { className: "ml-auto flex items-center gap-2", children: [
1093
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onCancel, children: "Cancel" }),
1094
+ /* @__PURE__ */ jsx(
1095
+ Button,
1096
+ {
1097
+ type: "button",
1098
+ variant: "outline",
1099
+ size: "sm",
1100
+ onClick: () => submit(false),
1101
+ disabled: save.isPending || fields.length === 0,
1102
+ "data-testid": "signature-save-draft",
1103
+ children: "Save draft"
1104
+ }
1105
+ ),
1106
+ /* @__PURE__ */ jsxs(
1107
+ Button,
1108
+ {
1109
+ type: "button",
1110
+ size: "sm",
1111
+ onClick: () => submit(true),
1112
+ disabled: save.isPending || !!blocker,
1113
+ title: blocker ?? void 0,
1114
+ "data-testid": "signature-send",
1115
+ children: [
1116
+ /* @__PURE__ */ jsx(Send, { className: "mr-1 size-4", "aria-hidden": true }),
1117
+ save.isPending ? "Sending\u2026" : "Send for signature"
1118
+ ]
1119
+ }
1120
+ )
1121
+ ] })
1122
+ ] }),
1123
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
1124
+ /* @__PURE__ */ jsx(
1125
+ Input,
1126
+ {
1127
+ value: message,
1128
+ onChange: (e) => setMessage(e.target.value),
1129
+ maxLength: 2e3,
1130
+ placeholder: "Message to the signers (optional)",
1131
+ className: "h-8 max-w-md",
1132
+ "data-testid": "signature-message"
1133
+ }
1134
+ ),
1135
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", "data-testid": "signature-editor-summary", children: [
1136
+ fields.length,
1137
+ " field",
1138
+ fields.length === 1 ? "" : "s",
1139
+ blocker ? ` \xB7 ${blocker}` : " \xB7 ready to send"
1140
+ ] })
1141
+ ] }),
1142
+ selected && /* @__PURE__ */ jsxs(
1143
+ "div",
1144
+ {
1145
+ className: "flex flex-wrap items-center gap-3 rounded-md bg-muted px-2 py-1.5",
1146
+ "data-testid": "signature-field-details",
1147
+ children: [
1148
+ /* @__PURE__ */ jsx(PenLine, { className: "size-4", "aria-hidden": true }),
1149
+ /* @__PURE__ */ jsx(
1150
+ "select",
1151
+ {
1152
+ className: selectClass,
1153
+ value: selected.type,
1154
+ "aria-label": "Field type",
1155
+ onChange: (e) => updateField(selected.id, { type: e.target.value }),
1156
+ children: SIGNATURE_FIELD_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: FIELD_TYPE_LABELS[t] }, t))
1157
+ }
1158
+ ),
1159
+ /* @__PURE__ */ jsx(
1160
+ "select",
1161
+ {
1162
+ className: selectClass,
1163
+ value: selected.signer,
1164
+ "aria-label": "Signer",
1165
+ onChange: (e) => updateField(selected.id, { signer: e.target.value }),
1166
+ "data-testid": "signature-field-signer",
1167
+ children: signers.map((ext) => /* @__PURE__ */ jsx("option", { value: ext, children: nameOf(ext) }, ext))
1168
+ }
1169
+ ),
1170
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
1171
+ /* @__PURE__ */ jsx(
1172
+ Checkbox,
1173
+ {
1174
+ id: "signature-field-required",
1175
+ checked: selected.required,
1176
+ onCheckedChange: (c) => updateField(selected.id, { required: c === true })
1177
+ }
1178
+ ),
1179
+ /* @__PURE__ */ jsx(Label, { htmlFor: "signature-field-required", className: "font-normal", children: "Required" })
1180
+ ] })
1181
+ ]
1182
+ }
1183
+ ),
1184
+ suggestions && suggestions.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 rounded-md border p-2", "data-testid": "signature-suggestions", children: [
1185
+ /* @__PURE__ */ jsxs("div", { className: "font-medium", children: [
1186
+ "Found ",
1187
+ groups.length,
1188
+ " signature block",
1189
+ groups.length === 1 ? "" : "s",
1190
+ ". Choose who signs each."
1191
+ ] }),
1192
+ groups.map((g) => {
1193
+ const inBlock = suggestions.filter((s) => s.group === g);
1194
+ const role = inBlock.find((s) => s.role)?.role;
1195
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
1196
+ /* @__PURE__ */ jsxs("span", { className: "min-w-40", children: [
1197
+ role ?? `Block ${g + 1}`,
1198
+ " ",
1199
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
1200
+ "(p. ",
1201
+ inBlock[0].page + 1,
1202
+ ":",
1203
+ " ",
1204
+ inBlock.map((s) => FIELD_TYPE_LABELS[s.type]).join(", "),
1205
+ ")"
1206
+ ] })
1207
+ ] }),
1208
+ /* @__PURE__ */ jsxs(
1209
+ "select",
1210
+ {
1211
+ className: selectClass,
1212
+ value: assign[g] ?? "",
1213
+ onChange: (e) => setAssign((a) => ({ ...a, [g]: e.target.value || void 0 })),
1214
+ "data-testid": `signature-suggestion-signer-${g}`,
1215
+ children: [
1216
+ /* @__PURE__ */ jsx("option", { value: "", children: "Skip" }),
1217
+ people.map((p) => /* @__PURE__ */ jsx("option", { value: p.externalId, children: p.name }, p.externalId))
1218
+ ]
1219
+ }
1220
+ )
1221
+ ] }, g);
1222
+ }),
1223
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1224
+ /* @__PURE__ */ jsx(
1225
+ Button,
1226
+ {
1227
+ type: "button",
1228
+ size: "sm",
1229
+ onClick: applySuggestions,
1230
+ disabled: !Object.values(assign).some(Boolean),
1231
+ "data-testid": "signature-suggestions-apply",
1232
+ children: "Add fields"
1233
+ }
1234
+ ),
1235
+ /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => setSuggestions(null), children: "Dismiss" })
1236
+ ] })
1237
+ ] }),
1238
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-red-text", role: "alert", "data-testid": "signature-editor-error", children: error })
1239
+ ] }),
1240
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(PdfViewer$1, { ...viewerProps, file, renderPageOverlay }) })
1241
+ ] });
1242
+ }
265
1243
 
266
- export { AnnotatedPdfViewer, MARKUP_AUTOSAVE_MS, MARKUP_PULL_MS, SignaturePlacementViewer };
1244
+ export { AnnotatedPdfViewer, GuidedSigningViewer, MARKUP_AUTOSAVE_MS, MARKUP_PULL_MS, SIGNER_COLORS, SignatureFieldsOverlay, SignaturePlacementViewer, SignatureRequestEditor, signingDate };
267
1245
  //# sourceMappingURL=index.js.map
268
1246
  //# sourceMappingURL=index.js.map