@alfadocs/ui-kit 1.31.0 → 1.33.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.
Files changed (192) hide show
  1. package/dist/_chunks/{agenda-card-pdN49pMu.js → agenda-card-DVz3jwTf.js} +2 -2
  2. package/dist/_chunks/{agenda-tray-BweO8pDo.js → agenda-tray-1oDWCJdB.js} +2 -2
  3. package/dist/_chunks/{ai-prompt-input-CrHr-5H8.js → ai-prompt-input-Dt7tpCBh.js} +2 -2
  4. package/dist/_chunks/{alia-sidebar-BWcWZivN.js → alia-sidebar-D18kp3p9.js} +3 -3
  5. package/dist/_chunks/{anamnesis-summary-rows-DMO3MWSt.js → anamnesis-summary-rows-BYgyp_i2.js} +6 -6
  6. package/dist/_chunks/{appointment-card-CvUFFEdS.js → appointment-card-D-oj_ugh.js} +2 -2
  7. package/dist/_chunks/{appointment-timeline-DsMZY7U9.js → appointment-timeline-CymGHyIP.js} +2 -2
  8. package/dist/_chunks/{appointment-tray-Z2GaOIYQ.js → appointment-tray-DCk8gHod.js} +2 -2
  9. package/dist/_chunks/{audio-recorder-DXG6LTtO.js → audio-recorder-11wClczr.js} +2 -2
  10. package/dist/_chunks/{avatar-BNQNhoyL.js → avatar-CkDeQOSI.js} +37 -37
  11. package/dist/_chunks/{balance-badge-cell-CX6b0ML4.js → balance-badge-cell-DhBtFRoW.js} +4 -4
  12. package/dist/_chunks/{bishop-score-CJUVBfAu.js → bishop-score-CAl7C5hm.js} +2 -2
  13. package/dist/_chunks/{bmi-calculator-CcH6upht.js → bmi-calculator-Dwkih9a4.js} +3 -3
  14. package/dist/_chunks/{booking-jGzRUETo.js → booking-BqkEtsKx.js} +777 -747
  15. package/dist/_chunks/{calculator-dialog-12d3Sxaz.js → calculator-dialog-C0ixc3SU.js} +2 -2
  16. package/dist/_chunks/{calendar-BNQKpxhE.js → calendar-Dgvl5L4T.js} +2 -2
  17. package/dist/_chunks/{calendar-workspace-Dy1jHBvG.js → calendar-workspace-BX-zDyVR.js} +14 -14
  18. package/dist/_chunks/{care-plan-card-CQVboTn1.js → care-plan-card-CZW476Kg.js} +2 -2
  19. package/dist/_chunks/{care-plan-entry-card-jxHkzez5.js → care-plan-entry-card-BMUYagEw.js} +2 -2
  20. package/dist/_chunks/{chat-message-DBQu10rs.js → chat-message-C-8UU2av.js} +2 -2
  21. package/dist/_chunks/{clinical-note-card-yCTR9DB6.js → clinical-note-card-D2WTV2CO.js} +2 -2
  22. package/dist/_chunks/{data-table-DB5BiVQ0.js → data-table-DC96JJIq.js} +2 -2
  23. package/dist/_chunks/{dependent-selector-cJlJFAKD.js → dependent-selector-yTKKsuc9.js} +2 -2
  24. package/dist/_chunks/{dialog-UbKJCi1X.js → dialog-BJiLqhx6.js} +54 -46
  25. package/dist/_chunks/{document-preview-CDb-n_W7.js → document-preview-BrhMHNh8.js} +2 -2
  26. package/dist/_chunks/{due-date-calculator-BtgWeFqp.js → due-date-calculator-CxgK8vzt.js} +3 -3
  27. package/dist/_chunks/{entity-summary-B_vO5Ur4.js → entity-summary-5o768XLU.js} +2 -2
  28. package/dist/_chunks/{file-manager-Cd8V9IcZ.js → file-manager-CI2Qn8qW.js} +3 -3
  29. package/dist/_chunks/{gestational-age-calculator-KdMg9z9H.js → gestational-age-calculator-CZHVrERT.js} +4 -4
  30. package/dist/_chunks/{link-cell-renderer-tWEOv3Sc.js → link-cell-renderer-BEpMNtAa.js} +3 -3
  31. package/dist/_chunks/{marketplace-app-shell-C4AjQmvz.js → marketplace-app-shell-CK_ND8Tr.js} +2 -2
  32. package/dist/_chunks/{message-card-D8GB4FdF.js → message-card-BUMv16un.js} +2 -2
  33. package/dist/_chunks/{message-tray-CGIRQjx5.js → message-tray-0zsv27xX.js} +2 -2
  34. package/dist/_chunks/{muscle-scheme-BSJsI4-I.js → muscle-scheme-UVz_x4iE.js} +2 -2
  35. package/dist/_chunks/{notes-panel-am6e-Lwh.js → notes-panel-C4G-mhZ9.js} +3 -3
  36. package/dist/_chunks/{operator-hero-BnFv-Uef.js → operator-hero-D7-iiFQ9.js} +2 -2
  37. package/dist/_chunks/{optical-prescription-BvwuqTpl.js → optical-prescription-DUJOhKz_.js} +2 -2
  38. package/dist/_chunks/{patient-details-CdfursHt.js → patient-details-BGiawUHd.js} +3 -3
  39. package/dist/_chunks/{patient-summary-card-C9WBwct-.js → patient-summary-card--CT_gbaQ.js} +2 -2
  40. package/dist/_chunks/{periodontal-diagnosis-HrFsVi-C.js → periodontal-diagnosis-lEwA8wqX.js} +3 -3
  41. package/dist/_chunks/{practice-profile-hero-YQ7h2K4o.js → practice-profile-hero-DQyDvpJL.js} +2 -2
  42. package/dist/_chunks/{practice-results-CxIsU2YO.js → practice-results-DjEzPgAK.js} +2 -2
  43. package/dist/_chunks/{pregnancy-dating-m-c05DOI.js → pregnancy-dating-n5j5dAKy.js} +4 -4
  44. package/dist/_chunks/{pregnancy-weight-gain-CJwbs9W-.js → pregnancy-weight-gain-D5A8vPjj.js} +3 -3
  45. package/dist/_chunks/qr-code-DOJs4suh.js +750 -0
  46. package/dist/_chunks/radio-DNRe6H_8.js +193 -0
  47. package/dist/_chunks/radio-group-DyVBgnA3.js +297 -0
  48. package/dist/_chunks/{radiograph-panel.agent-ByM9M3qm.js → radiograph-panel.agent-o4jwEJPC.js} +2 -2
  49. package/dist/_chunks/{rich-text-editor-VJATL1Tk.js → rich-text-editor-CQ7yZdG3.js} +2 -2
  50. package/dist/_chunks/select-CLSUnKjF.js +520 -0
  51. package/dist/_chunks/signature-request-vihDT8On.js +2232 -0
  52. package/dist/_chunks/{tabs-DqKtTIjZ.js → tabs-BnRaLT0y.js} +2 -2
  53. package/dist/_chunks/{tasks-panel-DPCNaRko.js → tasks-panel-DQuaVvl5.js} +2 -2
  54. package/dist/_chunks/{timeline-u-2t9t_M.js → timeline-Bs9Erxlo.js} +2 -2
  55. package/dist/_chunks/{tooth-scheme-C9jssOmy.js → tooth-scheme-Qe7LO5Di.js} +2 -2
  56. package/dist/_chunks/{unit-converter-C6jMjqL9.js → unit-converter-BTgU50gk.js} +2 -2
  57. package/dist/_chunks/{widget-picker-em4xGgv0.js → widget-picker-DvUkBemi.js} +2 -2
  58. package/dist/agent-catalog.json +316 -20
  59. package/dist/agent-i18n/en.json +18 -8
  60. package/dist/components/agenda-card/index.js +1 -1
  61. package/dist/components/agenda-tray/index.js +1 -1
  62. package/dist/components/ai-prompt-input/index.js +1 -1
  63. package/dist/components/appointment-card/index.js +2 -2
  64. package/dist/components/appointment-timeline/index.js +1 -1
  65. package/dist/components/audio-recorder/index.js +1 -1
  66. package/dist/components/avatar/avatar.d.ts +2 -0
  67. package/dist/components/avatar/index.js +1 -1
  68. package/dist/components/bishop-score/index.js +1 -1
  69. package/dist/components/bmi-calculator/index.js +1 -1
  70. package/dist/components/booking/index.js +1 -1
  71. package/dist/components/calculator-dialog/index.js +1 -1
  72. package/dist/components/calendar/index.js +1 -1
  73. package/dist/components/care-plan-card/index.js +1 -1
  74. package/dist/components/care-plan-entry-card/index.js +1 -1
  75. package/dist/components/chat-message/index.js +1 -1
  76. package/dist/components/clinical-note-card/index.js +1 -1
  77. package/dist/components/data-table/index.js +2 -2
  78. package/dist/components/dependent-selector/index.js +1 -1
  79. package/dist/components/dialog/dialog.d.ts +9 -0
  80. package/dist/components/dialog/index.js +1 -1
  81. package/dist/components/document-preview/index.js +1 -1
  82. package/dist/components/due-date-calculator/index.js +1 -1
  83. package/dist/components/entity-summary/index.js +1 -1
  84. package/dist/components/file-manager/index.js +1 -1
  85. package/dist/components/gestational-age-calculator/index.js +1 -1
  86. package/dist/components/message-card/index.js +1 -1
  87. package/dist/components/message-tray/index.js +1 -1
  88. package/dist/components/muscle-scheme/index.js +1 -1
  89. package/dist/components/notes-panel/index.js +1 -1
  90. package/dist/components/operator-hero/index.js +1 -1
  91. package/dist/components/optical-prescription/index.js +1 -1
  92. package/dist/components/patient-details/index.js +1 -1
  93. package/dist/components/patient-summary-card/index.js +1 -1
  94. package/dist/components/patient-table/index.js +1 -1
  95. package/dist/components/periodontal-diagnosis/index.js +1 -1
  96. package/dist/components/practice-profile-hero/index.js +1 -1
  97. package/dist/components/practice-results/index.js +1 -1
  98. package/dist/components/pregnancy-dating/index.js +1 -1
  99. package/dist/components/pregnancy-weight-gain/index.js +1 -1
  100. package/dist/components/qr-code/index.js +1 -1
  101. package/dist/components/qr-code/qr-encode.d.ts +14 -16
  102. package/dist/components/radio/index.js +1 -1
  103. package/dist/components/radio-group/index.js +2 -2
  104. package/dist/components/radio-group/radio-group-context.d.ts +4 -1
  105. package/dist/components/radio-group/radio-group.d.ts +13 -1
  106. package/dist/components/radio-group/radio.d.ts +24 -1
  107. package/dist/components/radiograph-panel/index.js +1 -1
  108. package/dist/components/rich-text-editor/index.js +1 -1
  109. package/dist/components/select/index.js +1 -1
  110. package/dist/components/select/select.d.ts +33 -0
  111. package/dist/components/skeleton-scheme/index.js +1 -1
  112. package/dist/components/tabs/index.js +1 -1
  113. package/dist/components/tasks-panel/index.js +1 -1
  114. package/dist/components/timeline/index.js +1 -1
  115. package/dist/components/tooth-scheme/index.js +1 -1
  116. package/dist/components/unit-converter/index.js +1 -1
  117. package/dist/components/widget-picker/index.js +1 -1
  118. package/dist/i18n/locales/ar.d.ts +68 -0
  119. package/dist/i18n/locales/ar.js +69 -1
  120. package/dist/i18n/locales/de.d.ts +68 -0
  121. package/dist/i18n/locales/de.js +71 -1
  122. package/dist/i18n/locales/el.d.ts +68 -0
  123. package/dist/i18n/locales/el.js +69 -1
  124. package/dist/i18n/locales/en.d.ts +68 -0
  125. package/dist/i18n/locales/en.js +69 -1
  126. package/dist/i18n/locales/es.d.ts +68 -0
  127. package/dist/i18n/locales/es.js +69 -1
  128. package/dist/i18n/locales/fr.d.ts +68 -0
  129. package/dist/i18n/locales/fr.js +69 -1
  130. package/dist/i18n/locales/hi.d.ts +68 -0
  131. package/dist/i18n/locales/hi.js +69 -1
  132. package/dist/i18n/locales/it.d.ts +68 -0
  133. package/dist/i18n/locales/it.js +69 -1
  134. package/dist/i18n/locales/ja.d.ts +68 -0
  135. package/dist/i18n/locales/ja.js +69 -1
  136. package/dist/i18n/locales/nl.d.ts +68 -0
  137. package/dist/i18n/locales/nl.js +69 -1
  138. package/dist/i18n/locales/pl.d.ts +68 -0
  139. package/dist/i18n/locales/pl.js +69 -1
  140. package/dist/i18n/locales/pt.d.ts +68 -0
  141. package/dist/i18n/locales/pt.js +69 -1
  142. package/dist/i18n/locales/ro.d.ts +68 -0
  143. package/dist/i18n/locales/ro.js +69 -1
  144. package/dist/i18n/locales/ru.d.ts +68 -0
  145. package/dist/i18n/locales/ru.js +69 -1
  146. package/dist/i18n/locales/sq.d.ts +68 -0
  147. package/dist/i18n/locales/sq.js +69 -1
  148. package/dist/i18n/locales/sv.d.ts +68 -0
  149. package/dist/i18n/locales/sv.js +69 -1
  150. package/dist/i18n/locales/tr.d.ts +68 -0
  151. package/dist/i18n/locales/tr.js +69 -1
  152. package/dist/i18n/locales/zh.d.ts +68 -0
  153. package/dist/i18n/locales/zh.js +69 -1
  154. package/dist/index.js +57 -57
  155. package/dist/locales/ar.json +69 -1
  156. package/dist/locales/de.json +69 -1
  157. package/dist/locales/el.json +69 -1
  158. package/dist/locales/en.json +69 -1
  159. package/dist/locales/es.json +69 -1
  160. package/dist/locales/fr.json +69 -1
  161. package/dist/locales/hi.json +69 -1
  162. package/dist/locales/it.json +69 -1
  163. package/dist/locales/ja.json +69 -1
  164. package/dist/locales/nl.json +69 -1
  165. package/dist/locales/pl.json +69 -1
  166. package/dist/locales/pt.json +69 -1
  167. package/dist/locales/ro.json +69 -1
  168. package/dist/locales/ru.json +69 -1
  169. package/dist/locales/sq.json +69 -1
  170. package/dist/locales/sv.json +69 -1
  171. package/dist/locales/tr.json +69 -1
  172. package/dist/locales/zh.json +69 -1
  173. package/dist/patterns/alia-assistant/index.js +1 -1
  174. package/dist/patterns/anamnesis/index.js +1 -1
  175. package/dist/patterns/calendar/index.js +1 -1
  176. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  177. package/dist/patterns/signature-request/channel-meta.d.ts +27 -0
  178. package/dist/patterns/signature-request/index.d.ts +1 -1
  179. package/dist/patterns/signature-request/index.js +1 -1
  180. package/dist/patterns/signature-request/load-status.d.ts +13 -0
  181. package/dist/patterns/signature-request/person-grid.d.ts +32 -0
  182. package/dist/patterns/signature-request/required-documents.d.ts +127 -0
  183. package/dist/patterns/signature-request/signature-history.d.ts +57 -0
  184. package/dist/patterns/signature-request/signature-outcome.d.ts +29 -0
  185. package/dist/patterns/signature-request/signature-request.d.ts +390 -26
  186. package/dist/tokens.css +1 -1
  187. package/package.json +3 -1
  188. package/dist/_chunks/qr-code-CPkEs5mG.js +0 -574
  189. package/dist/_chunks/radio-TWf9Q-mp.js +0 -108
  190. package/dist/_chunks/radio-group-rXDJADzW.js +0 -175
  191. package/dist/_chunks/select-Bi8zril7.js +0 -471
  192. package/dist/_chunks/signature-request-C-IsbkPf.js +0 -417
@@ -2,7 +2,7 @@
2
2
  * SignatureRequestModal — the practice-side "Documenti firmati" modal that
3
3
  * dispatches a document-signature request: assign the operator who must
4
4
  * counter-sign (or leave the request unassigned) and how their request is
5
- * delivered (their system-defined default channel arrives pre-checked),
5
+ * delivered (their system-defined default channel arrives preselected),
6
6
  * build the patient-side signer roster (up to `maxSigners`, each with their
7
7
  * own delivery channel and, for on-device signing, an OTP waiver), and send.
8
8
  *
@@ -13,55 +13,248 @@
13
13
  * option lists, and what happens on submit. Multiple on-device signers sign
14
14
  * sequentially in roster order — the execution side is the Signing pattern's
15
15
  * multi-signer flow; this modal only encodes the intents.
16
+ *
17
+ * Via QR is a second step of the same dialog: after a submit with a `'qr'`
18
+ * signer the dialog stays open and waits, then shows one server-issued code
19
+ * per QR signer once the host passes `qrCodes`. The kit never builds a link.
20
+ *
21
+ * Signed versions: when the host passes `signatures` (or
22
+ * `signaturesLoading`) the form shows the document's past signature requests
23
+ * in a table above the operator and signers, on one screen as platform's
24
+ * "Documenti firmati" modal does. A host that passes neither sees the plain
25
+ * form.
26
+ *
27
+ * Required documents mode: when the host passes `requiredItems` (or
28
+ * `requiredItemsLoading`) the form asks the patient to sign every
29
+ * outstanding document and anamnesis interview in one batch. Each item that
30
+ * needs an operator gets its own picker in place of the single operator row
31
+ * (and, with `showOperatorChannels`, that operator's channel); the roster
32
+ * applies to the whole batch. A second signee follows platform's rules:
33
+ * every item can carry it, the main signer signs on this device, and the
34
+ * main signer is a registered signee, not the patient.
35
+ *
36
+ * Channel mode (`channelMode`), in every mode: `'perSigner'` (the default)
37
+ * gives each signer row its own channel; `'batch'` puts one channel on the
38
+ * whole roster (platform's sign mode) with one OTP waiver, and submits
39
+ * `signMode`.
40
+ *
41
+ * Outcome states (`outcome`) replace every other view with a final screen
42
+ * and a Close action; credits used up can also go back to the form.
43
+ *
44
+ * Channel rules: by default the operator may sign on this device only while
45
+ * a patient signer does. A host with its own rules passes `resolveChannels`,
46
+ * which replaces that rule.
16
47
  */
17
48
  import { type ComponentPropsWithoutRef } from 'react';
18
- /** Delivery channel for one signer's signature request. */
19
- export type SignatureChannel = 'sms' | 'email' | 'whatsapp' | 'on-device';
49
+ import { type OperatorChannel, type SignatureChannel } from './channel-meta';
50
+ import { type SignatureDownloadVersion, type SignatureRecord, type SignatureShareTarget } from './signature-history';
51
+ import { type RequiredSignatureItem } from './required-documents';
52
+ import { type SignatureRequestOutcome } from './signature-outcome';
53
+ export type { OperatorChannel, SignatureChannel } from './channel-meta';
54
+ export type { SignatureDownloadVersion, SignatureLegalLevel, SignatureRecord, SignatureShareTarget, } from './signature-history';
55
+ export type { RequiredSignatureItem, RequiredSignatureItemKind, } from './required-documents';
56
+ export type { SignatureRequestOutcome } from './signature-outcome';
20
57
  /**
21
- * Delivery channel for the operator's counter-sign request. The default is
22
- * system defined — the assigned operator's own `defaultChannel` (e-mail or
23
- * SMS) arrives pre-checked; `'on-device'` is offerable only while a roster
24
- * signer also signs on this device.
58
+ * How patient signers get their channel. `'perSigner'`: each signer row has
59
+ * its own channel dropdown beside the name. `'batch'`: one channel for the
60
+ * whole roster, under the signers heading, submitted as `signMode`.
25
61
  */
26
- export type OperatorChannel = 'sms' | 'email' | 'on-device';
62
+ export type SignatureChannelMode = 'perSigner' | 'batch';
63
+ /** The channel choices on the form, handed to `resolveChannels`. */
64
+ export interface SignatureChannelDraft {
65
+ /** The assigned operator; `null` with no operator row or on Assign later. */
66
+ operatorId: string | null;
67
+ /** The operator's channel; `null` whenever `operatorId` is. */
68
+ operatorChannel: OperatorChannel | null;
69
+ /** The patient-side roster, in order. Empty when the patient does not sign. */
70
+ signers: SignerRequest[];
71
+ /**
72
+ * What the user just changed: `'operator'` (the operator or their
73
+ * channel) or `'signers'` (a signer's channel or person, or a row added or
74
+ * removed). `null` when the dialog opens, and when the modal reads the
75
+ * available channels while rendering.
76
+ */
77
+ changed: 'operator' | 'signers' | null;
78
+ /**
79
+ * Channels each draft signer has greyed out (`unavailableChannels` on
80
+ * their `SignerOption`), by `signerId`. Absent when no signer has any.
81
+ * The modal never applies one, whatever the rule returns.
82
+ */
83
+ signerUnavailableChannels?: Record<string, SignatureChannel[]>;
84
+ }
85
+ /** What `resolveChannels` returns: the channels to use and to offer. */
86
+ export interface SignatureChannelResolution {
87
+ /** The operator's channel to use. Ignored while the draft's is `null`. */
88
+ operatorChannel: OperatorChannel | null;
89
+ /**
90
+ * The roster with the channels to use. Only `channel` is read, matched by
91
+ * `signerId`; the roster itself never changes here.
92
+ */
93
+ signers: SignerRequest[];
94
+ /** Channels the operator's dropdown offers. Omit to offer all three. */
95
+ operatorAvailableChannels?: OperatorChannel[];
96
+ /**
97
+ * Channels each signer's dropdown offers, by `signerId`. Narrows that
98
+ * person's own `availableChannels`; a list that leaves nothing selectable
99
+ * is ignored. It cannot re-enable a channel in the person's
100
+ * `unavailableChannels`: that one stays greyed out.
101
+ */
102
+ signerAvailableChannels?: Record<string, SignatureChannel[]>;
103
+ }
27
104
  /** One selectable person/role for the operator or signer selects. */
28
105
  export interface SignerOption {
29
106
  value: string;
30
107
  label: string;
31
108
  /**
32
109
  * Delivery channels this person can actually receive. Omit (or pass an
33
- * empty list) to offer every channel. Hosts gate this from per-patient
34
- * capability flags — e.g. a patient with no mobile number drops `'sms'`
35
- * and `'whatsapp'`. Only meaningful for signer options, not operators.
110
+ * empty list) to offer every channel, Via QR included. Hosts gate this
111
+ * from per-patient capability flags — e.g. a patient with no mobile number
112
+ * drops `'sms'` and `'whatsapp'`. Only meaningful for signer options, not
113
+ * operators.
36
114
  */
37
115
  availableChannels?: SignatureChannel[];
116
+ /**
117
+ * Channels to show greyed out, each with the host-translated reason shown
118
+ * under it (e.g. SMS and WhatsApp with "No mobile number"), instead of
119
+ * hiding them. Wins over `availableChannels`; a channel that list leaves
120
+ * out stays hidden. Never selected, seeded or submitted: the row falls
121
+ * back to the first channel still available, and a signer with none
122
+ * shows the reasons under the row and blocks the request. Only meaningful
123
+ * for signer options, not operators.
124
+ */
125
+ unavailableChannels?: ReadonlyArray<{
126
+ channel: SignatureChannel;
127
+ reason: string;
128
+ }>;
38
129
  /**
39
130
  * The delivery channel this operator's own settings resolve to — the
40
- * system-defined default, pre-checked when the operator is assigned.
41
- * Falls back to `'email'` when omitted. Only meaningful for operator
42
- * options, not signers.
131
+ * system-defined default, preselected when the operator is assigned and
132
+ * again whenever a different operator is picked (a channel the user
133
+ * changed by hand is kept until then). Falls back to `'email'` when
134
+ * omitted. `'on-device'` applies only where it is offered: in the request
135
+ * form, while a patient signer signs on this device (else e-mail), unless
136
+ * `resolveChannels` decides. Also seeds each item's operator channel with
137
+ * `showOperatorChannels`. Only meaningful for operator options, not
138
+ * signers.
43
139
  */
44
- defaultChannel?: 'sms' | 'email';
140
+ defaultChannel?: OperatorChannel;
141
+ /**
142
+ * The host has worked out that this person is under 18. A roster row with
143
+ * this person selected shows a warning to check whether a second signee is
144
+ * needed. It never blocks the request; the kit does not compute age. Only
145
+ * meaningful for signer options, not operators.
146
+ */
147
+ isMinor?: boolean;
148
+ /**
149
+ * This option is the patient's own record, not one of their registered
150
+ * signees (a legal guardian, a parent). Read in required documents mode
151
+ * and in `channelMode: 'batch'`, as on platform. Required documents mode:
152
+ * a second signee needs a registered signee as the main signer, and the
153
+ * patient is never offered as a second signee. The OTP waiver (the
154
+ * batch's, or the main signer's row per signer) starts on when the patient
155
+ * cannot receive SMS, and is forced on when the patient is the main signer.
156
+ * Batch mode: the channel defaults to SMS when the patient signs and can
157
+ * receive it, and offers a channel the patient OR the main signer can
158
+ * receive (so pass each person's own channels, not a combined list). Omit
159
+ * it and the person counts as a registered signee. Only meaningful for
160
+ * signer options, not operators.
161
+ */
162
+ isPatient?: boolean;
163
+ }
164
+ /**
165
+ * One operator offered in the operator pickers: the single-document form's
166
+ * operator select and, in required documents mode, every item's picker.
167
+ * Operators keep host order. "Assign later" comes after them in the request
168
+ * form, and first in required documents mode, as on platform
169
+ * (OperatorSignee.js).
170
+ */
171
+ export interface OperatorOption extends SignerOption {
172
+ /**
173
+ * Shows the operator greyed out, with `reason` under the name. It cannot
174
+ * be picked, and is never seeded as the first operator. A host-seeded
175
+ * value stays as it is.
176
+ */
177
+ disabled?: boolean;
178
+ /**
179
+ * Why the operator is greyed out, host-translated (e.g. "non ha un numero
180
+ * di telefono"). Shown under the name and read on the picker trigger.
181
+ * Ignored unless `disabled`.
182
+ */
183
+ reason?: string;
184
+ /**
185
+ * The operator was deleted. Hidden, unless they are a picker's current
186
+ * value (e.g. an item still assigned to them); once changed they are gone
187
+ * from that picker. Never picked or seeded as the first operator.
188
+ */
189
+ deleted?: boolean;
45
190
  }
46
191
  /** One patient-side signer row in the submission. */
47
192
  export interface SignerRequest {
48
193
  signerId: string;
194
+ /** In `channelMode: 'batch'` every row carries the batch channel. */
49
195
  channel: SignatureChannel;
50
- /** Only meaningful when `channel` is `'on-device'`. */
196
+ /**
197
+ * Only meaningful when `channel` is `'on-device'`. In batch mode it is set
198
+ * on the main signer (the first row) only: the batch's "Do not require OTP
199
+ * from the patient" (platform `doesNotRequireOtp`). In required documents
200
+ * mode the main signer always carries it on this device.
201
+ */
51
202
  skipOtp?: boolean;
52
203
  }
53
204
  /** Payload handed to `onRequestSignature`. */
54
205
  export interface SignatureRequestSubmission {
55
- /** `null` when the counter-signing operator is left unassigned. */
206
+ /**
207
+ * `null` when the counter-signing operator is left unassigned. In required
208
+ * documents mode: the first assigned operator in list order (or `null`),
209
+ * for hosts that still need one operator; `operatorAssignments` is the
210
+ * full picture.
211
+ */
56
212
  operatorId: string | null;
57
213
  /**
58
214
  * How the operator's counter-sign request is delivered. `null` while the
59
215
  * operator is unassigned. Defaults to the operator's own system-defined
60
- * channel unless explicitly changed in the modal.
216
+ * channel unless explicitly changed in the modal. Always `null` in
217
+ * required documents mode: see `operatorChannels`.
61
218
  */
62
219
  operatorChannel: OperatorChannel | null;
63
220
  /** 1..N signers; on-device signers sign sequentially in this order. */
64
221
  signers: SignerRequest[];
222
+ /**
223
+ * `channelMode: 'batch'` only: the one channel the whole roster goes out
224
+ * on (platform `signMode`), the same value as every `signers[].channel`.
225
+ * Absent per signer, and when the patient does not sign.
226
+ */
227
+ signMode?: SignatureChannel;
228
+ /**
229
+ * Required documents mode with `showOperatorChannels` only: the operator's
230
+ * channel per item id, for every item with an assigned operator (items on
231
+ * Assign later have none).
232
+ */
233
+ operatorChannels?: Record<string, OperatorChannel>;
234
+ /**
235
+ * Required documents mode only: the operator per listed item id, for every
236
+ * item that `requiresOperator`; `null` means "Assign later". Absent in the
237
+ * single-document form.
238
+ */
239
+ operatorAssignments?: Record<string, string | null>;
240
+ /**
241
+ * Required documents mode only: the ids of the items in this batch (the
242
+ * ones still to sign), in list order. Absent in the single-document form.
243
+ */
244
+ requiredItemIds?: string[];
245
+ }
246
+ /** One server-issued signing link for a signer on the Via QR channel. */
247
+ export interface SignatureQrCode {
248
+ /** The roster signer this link belongs to (`SignerRequest.signerId`). */
249
+ signerId: string;
250
+ /** The signing link, encoded byte-for-byte. The kit never builds it. */
251
+ url: string;
252
+ /**
253
+ * When the link stops working: a `Date` or an ISO 8601 string, formatted
254
+ * in the active locale and the browser's time zone. Today shows the time
255
+ * alone; any other day adds the date. An unparseable value hides the line.
256
+ */
257
+ expiresAt: Date | string;
65
258
  }
66
259
  export interface SignatureRequestModalProps {
67
260
  /** Controlled open state. Reopening re-seeds the form from `initial*`. */
@@ -72,29 +265,66 @@ export interface SignatureRequestModalProps {
72
265
  * persist a "dismissed this session" flag there.
73
266
  */
74
267
  onOpenChange: (open: boolean) => void;
75
- /** Operators offered as the counter-signing signer. */
76
- operators: SignerOption[];
268
+ /**
269
+ * Operators offered as the counter-signing signer, in host order ("Assign
270
+ * later" follows them, or leads in required documents mode). `disabled`
271
+ * shows one greyed out with its `reason`; `deleted` hides one unless it
272
+ * is a picker's current value.
273
+ */
274
+ operators: OperatorOption[];
77
275
  /** Patient-side people/roles offered in each signer row. */
78
276
  signerOptions: SignerOption[];
79
- /** Enables the "Assign to me" shortcut targeting this operator. */
277
+ /**
278
+ * Enables the "Assign to me" shortcut targeting this operator ("Assign all
279
+ * to me" in required documents mode, which sets every item's picker).
280
+ */
80
281
  currentOperatorId?: string;
81
282
  /** Offer an "Assign later" option in the operator select. Default `true`. */
82
283
  allowAssignLater?: boolean;
83
284
  /**
84
285
  * Preselected operator; `null` preselects "Assign later" (honoured only
85
- * while `allowAssignLater` — otherwise the first operator is seeded).
286
+ * while `allowAssignLater` — otherwise the first operator is seeded). In
287
+ * required documents mode it seeds every item picker whose item has no
288
+ * `initialOperatorId` of its own.
86
289
  */
87
290
  initialOperatorId?: string | null;
88
291
  /**
89
292
  * Preselected operator delivery channel. Defaults to the seeded operator's
90
293
  * system-defined `defaultChannel`. `'on-device'` is honoured only while a
91
- * seeded roster signer also signs on this device.
294
+ * seeded roster signer also signs on this device, unless `resolveChannels`
295
+ * is passed: then the host decides.
92
296
  */
93
297
  initialOperatorChannel?: OperatorChannel;
94
- /** Seed the signer roster. Defaults to the first option, on-device. */
298
+ /**
299
+ * Seed the signer roster. Defaults to the first option, on-device. Each
300
+ * row's `channel` is read per signer; in batch mode only the first row's
301
+ * `skipOtp` is read.
302
+ */
95
303
  initialSigners?: SignerRequest[];
96
- /** Cap on roster size. Default `2`. */
304
+ /**
305
+ * Cap on roster size. Default `2`. In required documents mode the roster
306
+ * is the main signer plus at most one second signee, offered only when
307
+ * the second signee rules allow it.
308
+ */
97
309
  maxSigners?: number;
310
+ /**
311
+ * How signers get their channel, in the request form and in required
312
+ * documents mode. `'perSigner'` (default): a channel dropdown beside each
313
+ * signer's name. `'batch'`: one "Signature channel" select under the
314
+ * signers heading for the whole roster, with one OTP waiver; every
315
+ * `SignerRequest.channel` carries it and the submission gains `signMode`.
316
+ */
317
+ channelMode?: SignatureChannelMode;
318
+ /**
319
+ * `channelMode: 'batch'` only: the channel to start on. Omit it for
320
+ * platform's default: e-mail, or SMS when the main signer `isPatient` and
321
+ * can receive SMS. A channel neither the main signer nor the patient can
322
+ * receive falls back to the first one on offer. Read when the dialog
323
+ * opens only: in required documents mode, changing the main signer
324
+ * returns the batch to platform's default. The channels in
325
+ * `initialSigners` are not read in batch mode. Ignored per signer.
326
+ */
327
+ initialBatchChannel?: SignatureChannel;
98
328
  /**
99
329
  * Whether an operator must counter-sign. `false` drops the operator
100
330
  * section entirely and submits `operatorId: null` — a host whose document
@@ -117,8 +347,142 @@ export interface SignatureRequestModalProps {
117
347
  title?: string;
118
348
  /** Override the dialog description. Defaults to the `ui.*` string. */
119
349
  description?: string;
120
- /** Receives the completed submission. The host closes via `onOpenChange`. */
350
+ /**
351
+ * Receives the completed submission. The host closes via `onOpenChange`,
352
+ * except when a signer chose `'qr'`: then the dialog moves to its QR step
353
+ * and waits, so keep it open and pass `qrCodes` once the server replies
354
+ * (or `error` to send the user back to the form).
355
+ */
121
356
  onRequestSignature: (submission: SignatureRequestSubmission) => void;
357
+ /**
358
+ * Server-issued signing links, one per `'qr'` signer. While non-empty the
359
+ * dialog shows the QR step instead of the form, one code at a time. A QR
360
+ * signer with no entry gets an error slot. Clear it when the dialog closes,
361
+ * and drop a server response that arrives after the close.
362
+ */
363
+ qrCodes?: readonly SignatureQrCode[];
364
+ /**
365
+ * Shows the QR step's waiting state without a submit, e.g. when the host
366
+ * remounts the dialog mid-request. The dialog enters this state by itself
367
+ * after a submit with a `'qr'` signer; `qrCodes` arriving ends it. A set
368
+ * `error` always wins and shows the form, even while this stays `true`.
369
+ */
370
+ qrPending?: boolean;
371
+ /**
372
+ * Fires when the user presses Done on the QR step, before
373
+ * `onOpenChange(false)`. Close, Esc and any other dismissal do not fire it.
374
+ */
375
+ onQrDone?: () => void;
376
+ /**
377
+ * The document's past signature requests. Passing it (even empty) adds a
378
+ * signed versions table (Date, Signature type, Actions) at the top of the
379
+ * form, on the same screen, as on platform. Rows show newest first by
380
+ * `createdAt`; records with the same or an unparseable date keep the host
381
+ * order. An empty array shows one line saying there are no signed
382
+ * versions. Omit it (and `signaturesLoading`) for the plain form.
383
+ */
384
+ signatures?: readonly SignatureRecord[];
385
+ /**
386
+ * Shows the signed versions table's loading state (skeleton rows). Also
387
+ * adds the table while `signatures` is still undefined.
388
+ */
389
+ signaturesLoading?: boolean;
390
+ /**
391
+ * Show each row's legal level (simple or advanced). Default `true`. Pass
392
+ * `false` where the level does not apply, e.g. for German practices.
393
+ */
394
+ showLegalLevel?: boolean;
395
+ /** Row action "View". The button shows only when this is passed. */
396
+ onViewSignature?: (id: string) => void;
397
+ /**
398
+ * Row action "Download". The button shows only when this is passed. It is
399
+ * a menu (full or anonymised) when the record `hasAnonymisedVersion`,
400
+ * otherwise a button that asks for `'full'`.
401
+ */
402
+ onDownloadSignature?: (id: string, version: SignatureDownloadVersion) => void;
403
+ /**
404
+ * Row action "Share", a menu of link, e-mail and WhatsApp. The button
405
+ * shows only when this is passed. The host does the sharing.
406
+ */
407
+ onShareSignature?: (id: string, via: SignatureShareTarget) => void;
408
+ /**
409
+ * The share targets for rows whose record has no `shareTargets` of its
410
+ * own. Default: link, e-mail and WhatsApp. An empty list hides Share.
411
+ */
412
+ signatureShareTargets?: readonly SignatureShareTarget[];
413
+ /**
414
+ * Row action "Delete". The button shows only when this is passed. It asks
415
+ * for confirmation first; this fires only on confirm. The host deletes and
416
+ * drops the record from `signatures`.
417
+ */
418
+ onDeleteSignature?: (id: string) => void;
419
+ /**
420
+ * The host's channel rules, in place of the built-in one (the operator may
421
+ * sign on this device only while a patient signer does). Called with the
422
+ * choices after every channel change, and when the dialog opens; the
423
+ * modal uses the channels it returns, clamped to what is offered. Also
424
+ * called while rendering, with `changed: null`, to read the available
425
+ * channels, so it must be pure. Omit it to keep the built-in rule.
426
+ */
427
+ resolveChannels?: (draft: SignatureChannelDraft) => SignatureChannelResolution;
428
+ /**
429
+ * Required documents mode: every outstanding document and anamnesis
430
+ * interview for one patient, signed in one batch. Passing it (even empty)
431
+ * replaces the single operator row with one picker per item that
432
+ * `requiresOperator`, seeded from the item's `initialOperatorId`, else the
433
+ * modal's `initialOperatorId`. Fully signed items are left out; when none
434
+ * is left the dialog shows the `'allSigned'` outcome. The roster applies
435
+ * to the whole batch, each signer on their own channel, or on one channel
436
+ * with `channelMode: 'batch'`. A second roster row (the second signee) is
437
+ * offered only when every listed item is a document with
438
+ * `canCarrySecondary`, the main signer's channel (the batch's, or their
439
+ * row's) is on this device and the main signer is not `isPatient`.
440
+ * `signatures`, `requireOperator` and `requirePatient` do not apply. The
441
+ * submission gains `operatorAssignments` and `requiredItemIds`.
442
+ */
443
+ requiredItems?: readonly RequiredSignatureItem[];
444
+ /**
445
+ * Shows required documents mode loading (skeleton rows). Also enters the
446
+ * mode while `requiredItems` is still undefined.
447
+ */
448
+ requiredItemsLoading?: boolean;
449
+ /**
450
+ * Required documents mode: shows each item's operator channel (SMS,
451
+ * e-mail, on this device) beside its operator picker, starting on the
452
+ * chosen operator's `defaultChannel` and following a new operator, and
453
+ * hides the note that each operator's settings decide. The submission
454
+ * gains `operatorChannels`. Default `false`.
455
+ */
456
+ showOperatorChannels?: boolean;
457
+ /**
458
+ * A final screen in place of any other view, with a Close action:
459
+ * `'linkSent'` after a request sent by link, `'allSigned'` when nothing is
460
+ * left to sign, `'creditsExhausted'` when the practice has no electronic
461
+ * signature documents left. The host sets and clears it; reopening does
462
+ * not clear it.
463
+ */
464
+ outcome?: SignatureRequestOutcome;
465
+ /**
466
+ * "Buy more" on the `'creditsExhausted'` outcome. The button shows only
467
+ * when this is passed; the host navigates to the purchase page.
468
+ */
469
+ onBuyMoreSignatures?: () => void;
470
+ /**
471
+ * "Cancel" on the `'creditsExhausted'` outcome (platform's Annulla). The
472
+ * button shows only when this is passed. It returns the dialog to the view
473
+ * under the outcome (the form) by itself, then calls this so the host
474
+ * clears `outcome`. Clear it here: the modal shows the outcome again only
475
+ * when the prop changes, or on reopen.
476
+ */
477
+ onOutcomeCancel?: () => void;
478
+ /**
479
+ * Required documents mode: a link-style "Add signatory" under the Patient
480
+ * signers heading while the patient has no registered signee (no
481
+ * `signerOptions` entry without `isPatient`), as on platform. The host
482
+ * opens its own create-signee flow and passes the new person in
483
+ * `signerOptions`. Hidden when omitted, and in the single-document form.
484
+ */
485
+ onAddSignee?: () => void;
122
486
  /**
123
487
  * Extra attributes for the portaled dialog surface (e.g. `dir`/`lang`
124
488
  * when the host pins a locale below `<html>`, or a test id).