@alfadocs/ui-kit-debug 1.48.0 → 1.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{agenda-card-C4h0xMGi.js → agenda-card-CjjxlA9K.js} +2 -2
- package/dist/_chunks/{agenda-card-C4h0xMGi.js.map → agenda-card-CjjxlA9K.js.map} +1 -1
- package/dist/_chunks/{agenda-tray-DNZYW2xt.js → agenda-tray-BhZASyJm.js} +2 -2
- package/dist/_chunks/{agenda-tray-DNZYW2xt.js.map → agenda-tray-BhZASyJm.js.map} +1 -1
- package/dist/_chunks/{alia-sidebar-Crn8OGPF.js → alia-sidebar-Dx-oeOV2.js} +3 -3
- package/dist/_chunks/{alia-sidebar-Crn8OGPF.js.map → alia-sidebar-Dx-oeOV2.js.map} +1 -1
- package/dist/_chunks/{appointment-card-CvGU0QP6.js → appointment-card-BgLpE6T5.js} +2 -2
- package/dist/_chunks/{appointment-card-CvGU0QP6.js.map → appointment-card-BgLpE6T5.js.map} +1 -1
- package/dist/_chunks/{appointment-peek--dmWznLZ.js → appointment-peek-BDiCIBb-.js} +2 -2
- package/dist/_chunks/{appointment-peek--dmWznLZ.js.map → appointment-peek-BDiCIBb-.js.map} +1 -1
- package/dist/_chunks/{appointment-timeline-y9uYZMUd.js → appointment-timeline-wQ-PdkFV.js} +2 -2
- package/dist/_chunks/{appointment-timeline-y9uYZMUd.js.map → appointment-timeline-wQ-PdkFV.js.map} +1 -1
- package/dist/_chunks/{appointment-tray-BTecNeSb.js → appointment-tray-D7Gt6m8x.js} +2 -2
- package/dist/_chunks/{appointment-tray-BTecNeSb.js.map → appointment-tray-D7Gt6m8x.js.map} +1 -1
- package/dist/_chunks/{avatar-CkDeQOSI.js → avatar-BVvjKNTp.js} +2 -2
- package/dist/_chunks/avatar-BVvjKNTp.js.map +1 -0
- package/dist/_chunks/{balance-badge-cell-CA0YNJMR.js → balance-badge-cell-klaxFNL_.js} +3 -3
- package/dist/_chunks/{balance-badge-cell-CA0YNJMR.js.map → balance-badge-cell-klaxFNL_.js.map} +1 -1
- package/dist/_chunks/{booking-BQYFDcrz.js → booking-BF9pVa2n.js} +377 -381
- package/dist/_chunks/booking-BF9pVa2n.js.map +1 -0
- package/dist/_chunks/{calendar-DjoJ9ovF.js → calendar-Bt44KMNO.js} +3 -2
- package/dist/_chunks/{calendar-DjoJ9ovF.js.map → calendar-Bt44KMNO.js.map} +1 -1
- package/dist/_chunks/calendar-workspace-C_eXL1by.js +10464 -0
- package/dist/_chunks/{calendar-workspace-D8zX9JWm.js.map → calendar-workspace-C_eXL1by.js.map} +1 -1
- package/dist/_chunks/{chat-message-Co_NRGM4.js → chat-message-B4ihjNy3.js} +2 -2
- package/dist/_chunks/{chat-message-Co_NRGM4.js.map → chat-message-B4ihjNy3.js.map} +1 -1
- package/dist/_chunks/{clinical-note-card-DYDQ3q2x.js → clinical-note-card-B7s5BtEl.js} +2 -2
- package/dist/_chunks/{clinical-note-card-DYDQ3q2x.js.map → clinical-note-card-B7s5BtEl.js.map} +1 -1
- package/dist/_chunks/{data-table-DWOSxlsy.js → data-table-CrI3_bjH.js} +411 -410
- package/dist/_chunks/data-table-CrI3_bjH.js.map +1 -0
- package/dist/_chunks/{dependent-selector-BR_8D2Qu.js → dependent-selector-58hTg5rB.js} +2 -2
- package/dist/_chunks/{dependent-selector-BR_8D2Qu.js.map → dependent-selector-58hTg5rB.js.map} +1 -1
- package/dist/_chunks/{entity-summary-Ckz_U00H.js → entity-summary-CFJfBdVP.js} +2 -2
- package/dist/_chunks/{entity-summary-Ckz_U00H.js.map → entity-summary-CFJfBdVP.js.map} +1 -1
- package/dist/_chunks/{file-manager-CqgxLqoA.js → file-manager-C6QQPQV5.js} +2 -2
- package/dist/_chunks/{file-manager-CqgxLqoA.js.map → file-manager-C6QQPQV5.js.map} +1 -1
- package/dist/_chunks/link-cell-renderer-CkNbUsBM.js +867 -0
- package/dist/_chunks/link-cell-renderer-CkNbUsBM.js.map +1 -0
- package/dist/_chunks/{marketplace-app-shell-Dehuxbi-.js → marketplace-app-shell-1uKqs4gD.js} +2 -2
- package/dist/_chunks/{marketplace-app-shell-Dehuxbi-.js.map → marketplace-app-shell-1uKqs4gD.js.map} +1 -1
- package/dist/_chunks/{message-card-DKOtnBHy.js → message-card-C2zsvyj0.js} +2 -2
- package/dist/_chunks/{message-card-DKOtnBHy.js.map → message-card-C2zsvyj0.js.map} +1 -1
- package/dist/_chunks/{message-tray-COMEtmyr.js → message-tray-CMlmxdH2.js} +2 -2
- package/dist/_chunks/{message-tray-COMEtmyr.js.map → message-tray-CMlmxdH2.js.map} +1 -1
- package/dist/_chunks/{notes-panel-BiOxZL_0.js → notes-panel-xxpFt-I1.js} +2 -2
- package/dist/_chunks/{notes-panel-BiOxZL_0.js.map → notes-panel-xxpFt-I1.js.map} +1 -1
- package/dist/_chunks/{operator-hero-5061fkY5.js → operator-hero-DyrNLoRO.js} +2 -2
- package/dist/_chunks/{operator-hero-5061fkY5.js.map → operator-hero-DyrNLoRO.js.map} +1 -1
- package/dist/_chunks/{patient-details-C23Hdm8v.js → patient-details-tTlvrJSU.js} +2 -2
- package/dist/_chunks/{patient-details-C23Hdm8v.js.map → patient-details-tTlvrJSU.js.map} +1 -1
- package/dist/_chunks/{patient-summary-card-C36L3h7h.js → patient-summary-card-DQ__6DR-.js} +2 -2
- package/dist/_chunks/{patient-summary-card-C36L3h7h.js.map → patient-summary-card-DQ__6DR-.js.map} +1 -1
- package/dist/_chunks/{practice-profile-hero-CPy5h2yI.js → practice-profile-hero-B-WcJYNH.js} +2 -2
- package/dist/_chunks/{practice-profile-hero-CPy5h2yI.js.map → practice-profile-hero-B-WcJYNH.js.map} +1 -1
- package/dist/_chunks/{practice-results-t2BHht91.js → practice-results-EKRiqWtQ.js} +2 -2
- package/dist/_chunks/{practice-results-t2BHht91.js.map → practice-results-EKRiqWtQ.js.map} +1 -1
- package/dist/_chunks/{signature-request-15D363w5.js → signature-request-BUGeG8oD.js} +2 -2
- package/dist/_chunks/{signature-request-15D363w5.js.map → signature-request-BUGeG8oD.js.map} +1 -1
- package/dist/_chunks/{task-card-CTTQfPS6.js → task-card-jaOhnj_q.js} +31 -30
- package/dist/_chunks/task-card-jaOhnj_q.js.map +1 -0
- package/dist/_chunks/{task-tray-JA-qp_pB.js → task-tray-HHyxi9ga.js} +2 -2
- package/dist/_chunks/{task-tray-JA-qp_pB.js.map → task-tray-HHyxi9ga.js.map} +1 -1
- package/dist/_chunks/{tasks-panel-C_dVDQKJ.js → tasks-panel-DbSjq_mz.js} +2 -2
- package/dist/_chunks/{tasks-panel-C_dVDQKJ.js.map → tasks-panel-DbSjq_mz.js.map} +1 -1
- package/dist/_chunks/{timeline-61AihzYz.js → timeline-ChY7iZrs.js} +2 -2
- package/dist/_chunks/{timeline-61AihzYz.js.map → timeline-ChY7iZrs.js.map} +1 -1
- package/dist/_chunks/{use-appointment-details-read-D2FH-cHF.js → use-appointment-details-read-5-hV-2xA.js} +4 -4
- package/dist/_chunks/{use-appointment-details-read-D2FH-cHF.js.map → use-appointment-details-read-5-hV-2xA.js.map} +1 -1
- package/dist/agent-catalog.json +1 -1
- package/dist/components/agenda-card/index.js +1 -1
- package/dist/components/agenda-tray/index.js +1 -1
- package/dist/components/appointment-card/index.js +2 -2
- package/dist/components/appointment-details-panel/index.js +1 -1
- package/dist/components/appointment-peek/index.js +1 -1
- package/dist/components/appointment-timeline/index.js +1 -1
- package/dist/components/avatar/avatar.d.ts.map +1 -1
- package/dist/components/avatar/index.js +1 -1
- package/dist/components/booking/booking.d.ts.map +1 -1
- package/dist/components/booking/cascade.d.ts +5 -0
- package/dist/components/booking/cascade.d.ts.map +1 -1
- package/dist/components/booking/index.js +1 -1
- package/dist/components/calendar/calendar.d.ts.map +1 -1
- package/dist/components/calendar/index.js +1 -1
- package/dist/components/chat-message/index.js +1 -1
- package/dist/components/clinical-note-card/index.js +1 -1
- package/dist/components/data-table/filters/number-filter.d.ts +26 -12
- package/dist/components/data-table/filters/number-filter.d.ts.map +1 -1
- package/dist/components/data-table/index.js +2 -2
- package/dist/components/data-table/toolbar.d.ts.map +1 -1
- package/dist/components/dependent-selector/index.js +1 -1
- package/dist/components/entity-summary/index.js +1 -1
- package/dist/components/file-manager/index.js +1 -1
- package/dist/components/message-card/index.js +1 -1
- package/dist/components/message-tray/index.js +1 -1
- package/dist/components/notes-panel/index.js +1 -1
- package/dist/components/operator-hero/index.js +1 -1
- package/dist/components/patient-details/index.js +1 -1
- package/dist/components/patient-summary-card/index.js +1 -1
- package/dist/components/patient-table/index.js +1 -1
- package/dist/components/practice-profile-hero/index.js +1 -1
- package/dist/components/practice-results/index.js +1 -1
- package/dist/components/task-card/index.js +1 -1
- package/dist/components/task-card/task-card.d.ts +3 -2
- package/dist/components/task-card/task-card.d.ts.map +1 -1
- package/dist/components/task-tray/index.js +1 -1
- package/dist/components/tasks-panel/index.js +1 -1
- package/dist/components/timeline/index.js +1 -1
- package/dist/i18n/locales/ar.d.ts +19 -14
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +19 -14
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +19 -14
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +19 -14
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +19 -14
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +19 -14
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +5 -0
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +6 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +19 -14
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +19 -14
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +19 -14
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +19 -14
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +19 -14
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +19 -14
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +5 -0
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +6 -0
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +19 -14
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +19 -14
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +19 -14
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +19 -14
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +19 -14
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +19 -14
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +19 -14
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +19 -14
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +19 -14
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +19 -14
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +19 -14
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +19 -14
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +19 -14
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +19 -14
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +19 -14
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +19 -14
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +19 -14
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +19 -14
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +19 -14
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +19 -14
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +34 -34
- package/dist/locales/ar.json +19 -14
- package/dist/locales/de.json +19 -14
- package/dist/locales/el.json +19 -14
- package/dist/locales/en.json +5 -0
- package/dist/locales/es.json +19 -14
- package/dist/locales/fr.json +19 -14
- package/dist/locales/hi.json +19 -14
- package/dist/locales/it.json +5 -0
- package/dist/locales/ja.json +19 -14
- package/dist/locales/nl.json +19 -14
- package/dist/locales/pl.json +19 -14
- package/dist/locales/pt.json +19 -14
- package/dist/locales/ro.json +19 -14
- package/dist/locales/ru.json +19 -14
- package/dist/locales/sq.json +19 -14
- package/dist/locales/sv.json +19 -14
- package/dist/locales/tr.json +19 -14
- package/dist/locales/zh.json +19 -14
- package/dist/patterns/alia-assistant/index.js +1 -1
- package/dist/patterns/calendar/calendar-workspace.d.ts +10 -0
- package/dist/patterns/calendar/calendar-workspace.d.ts.map +1 -1
- package/dist/patterns/calendar/calendar.surface.d.ts +4 -1
- package/dist/patterns/calendar/calendar.surface.d.ts.map +1 -1
- package/dist/patterns/calendar/index.js +1 -1
- package/dist/patterns/marketplace-app-shell/index.js +1 -1
- package/dist/patterns/signature-request/index.js +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +12 -12
- package/dist/_chunks/avatar-CkDeQOSI.js.map +0 -1
- package/dist/_chunks/booking-BQYFDcrz.js.map +0 -1
- package/dist/_chunks/calendar-workspace-D8zX9JWm.js +0 -10423
- package/dist/_chunks/data-table-DWOSxlsy.js.map +0 -1
- package/dist/_chunks/link-cell-renderer-Tswqf6BT.js +0 -778
- package/dist/_chunks/link-cell-renderer-Tswqf6BT.js.map +0 -1
- package/dist/_chunks/task-card-CTTQfPS6.js.map +0 -1
package/dist/_chunks/{signature-request-15D363w5.js.map → signature-request-BUGeG8oD.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signature-request-15D363w5.js","sources":["../../node_modules/lucide-react/dist/esm/icons/link-2.mjs","../../node_modules/lucide-react/dist/esm/icons/qr-code.mjs","../../node_modules/lucide-react/dist/esm/icons/shopping-cart.mjs","../../node_modules/lucide-react/dist/esm/icons/tablet.mjs","../../src/patterns/signature-request/channel-meta.tsx","../../src/patterns/signature-request/load-status.tsx","../../src/patterns/signature-request/person-grid.tsx","../../src/patterns/signature-request/signature-history.tsx","../../src/patterns/signature-request/required-documents.tsx","../../src/patterns/signature-request/signature-outcome.tsx","../../src/patterns/signature-request/signature-request.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M9 17H7A5 5 0 0 1 7 7h2\", key: \"8i5ue5\" }],\n [\"path\", { d: \"M15 7h2a5 5 0 1 1 0 10h-2\", key: \"1b9ql8\" }],\n [\"line\", { x1: \"8\", x2: \"16\", y1: \"12\", y2: \"12\", key: \"1jonct\" }]\n];\nconst Link2 = createLucideIcon(\"link-2\", __iconNode);\n\nexport { __iconNode, Link2 as default };\n//# sourceMappingURL=link-2.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"3\", rx: \"1\", key: \"1tu5fj\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"16\", y: \"3\", rx: \"1\", key: \"1v8r4q\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"1x03jg\" }],\n [\"path\", { d: \"M21 16h-3a2 2 0 0 0-2 2v3\", key: \"177gqh\" }],\n [\"path\", { d: \"M21 21v.01\", key: \"ents32\" }],\n [\"path\", { d: \"M12 7v3a2 2 0 0 1-2 2H7\", key: \"8crl2c\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M12 3h.01\", key: \"n36tog\" }],\n [\"path\", { d: \"M12 16v.01\", key: \"133mhm\" }],\n [\"path\", { d: \"M16 12h1\", key: \"1slzba\" }],\n [\"path\", { d: \"M21 12v.01\", key: \"1lwtk9\" }],\n [\"path\", { d: \"M12 21v-1\", key: \"1880an\" }]\n];\nconst QrCode = createLucideIcon(\"qr-code\", __iconNode);\n\nexport { __iconNode, QrCode as default };\n//# sourceMappingURL=qr-code.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"circle\", { cx: \"8\", cy: \"21\", r: \"1\", key: \"jimo8o\" }],\n [\"circle\", { cx: \"19\", cy: \"21\", r: \"1\", key: \"13723u\" }],\n [\n \"path\",\n {\n d: \"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\",\n key: \"9zh506\"\n }\n ]\n];\nconst ShoppingCart = createLucideIcon(\"shopping-cart\", __iconNode);\n\nexport { __iconNode, ShoppingCart as default };\n//# sourceMappingURL=shopping-cart.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"rect\", { width: \"16\", height: \"20\", x: \"4\", y: \"2\", rx: \"2\", ry: \"2\", key: \"76otgf\" }],\n [\"line\", { x1: \"12\", x2: \"12.01\", y1: \"18\", y2: \"18\", key: \"1dp563\" }]\n];\nconst Tablet = createLucideIcon(\"tablet\", __iconNode);\n\nexport { __iconNode, Tablet as default };\n//# sourceMappingURL=tablet.mjs.map\n","/**\n * Channel labels and icons shared by the request form and the signatures\n * list, so a channel reads the same in both views.\n */\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Mail,\n MessageSquare,\n QrCode as QrCodeIcon,\n Tablet,\n} from 'lucide-react';\nimport { WhatsAppGlyph } from '../../components/whatsapp-button';\n\n/**\n * Delivery channel for one signer's signature request. `'qr'` means the\n * signer scans a QR code that the dialog shows in its QR step after the\n * request (see `qrCodes`). Every patient-side signer is offered `'qr'`\n * unless their `availableChannels` leaves it out; the operator never is.\n */\nexport type SignatureChannel =\n | 'sms'\n | 'email'\n | 'whatsapp'\n | 'on-device'\n | 'qr';\n\n/**\n * Delivery channel for an operator's counter-sign request. The default is\n * system defined: the operator's own `defaultChannel` arrives preselected.\n */\nexport type OperatorChannel = 'sms' | 'email' | 'on-device';\n\n/** Operator channel display order. */\nexport const OPERATOR_CHANNELS: readonly OperatorChannel[] = [\n 'sms',\n 'email',\n 'on-device',\n];\n\nexport type ChannelMeta = Record<\n SignatureChannel,\n {\n /** The label: the list's text and the channel dropdown's option. */\n label: string;\n icon: ReactNode;\n }\n>;\n\n/** Translated labels and decorative icon for every channel. */\nexport function useChannelMeta(): ChannelMeta {\n const { t } = useTranslation();\n return {\n sms: {\n label: t('signatureRequest.viaSms'),\n icon: <MessageSquare className=\"ds:size-4\" aria-hidden />,\n },\n email: {\n label: t('signatureRequest.viaEmail'),\n icon: <Mail className=\"ds:size-4\" aria-hidden />,\n },\n whatsapp: {\n label: t('signatureRequest.viaWhatsapp'),\n icon: <WhatsAppGlyph className=\"ds:size-4\" aria-hidden />,\n },\n 'on-device': {\n label: t('signatureRequest.onThisDevice'),\n icon: <Tablet className=\"ds:size-4\" aria-hidden />,\n },\n qr: {\n label: t('signatureRequest.viaQr'),\n icon: <QrCodeIcon className=\"ds:size-4\" aria-hidden />,\n },\n };\n}\n","/**\n * A polite, visually hidden status for a view that loads its rows. It stays\n * mounted in both states and starts empty, so screen readers hear the\n * loading text as a change, and then hear that the rows arrived.\n *\n * Keep it outside any `aria-busy` container: screen readers hold back\n * updates inside a busy subtree.\n */\nimport { useEffect, useRef, useState } from 'react';\n\nexport interface LoadStatusProps {\n loading: boolean;\n loadingText: string;\n /** Said once when loading ends. Nothing is said if it never loaded. */\n loadedText: string;\n /**\n * Another message for the same region, e.g. that a row was deleted. It\n * wins while set and not loading; `''` empties the region.\n */\n message?: string;\n}\n\nexport function LoadStatus({\n loading,\n loadingText,\n loadedText,\n message: override,\n}: LoadStatusProps) {\n const [message, setMessage] = useState('');\n const wasLoading = useRef(false);\n // Set after mount, never on the first render, so the text is an update.\n useEffect(() => {\n if (loading) setMessage(loadingText);\n else if (wasLoading.current) setMessage(loadedText);\n wasLoading.current = loading;\n }, [loading, loadingText, loadedText]);\n return (\n <span role=\"status\" className=\"ds:sr-only\">\n {override !== undefined && !loading ? override : message}\n </span>\n );\n}\n","/**\n * One grid for every person row in SignatureRequestModal: the operator, each\n * patient signer and each required item's operator picker.\n *\n * wide: [avatar] [name, 1fr] [channel, sized to the longest label] [action]\n * narrow: [avatar] [name, 1fr] [action]\n * [channel ]\n *\n * The avatar column fits Avatar `sm`. The action column is the remove\n * control's target size (`--min-target-size`: IconButton `sm` widens its hit\n * area to it on small screens) and stays reserved when a row has no action,\n * so every select ends on the same edges. Everything under a person (OTP switch,\n * notes, errors) spans the name and channel columns, so it starts at the\n * name select's left edge. The wide layout needs a `PERSON_SECTION`\n * ancestor at least 512px wide (px, not rem: see host-compat).\n */\nimport { ChevronDown } from 'lucide-react';\nimport { selectTriggerVariants } from '../../components/select/select';\nimport type { ChannelMeta } from './channel-meta';\n\nexport const PERSON_GRID =\n 'ds:grid ds:grid-cols-[var(--spacing-xl)_minmax(0,1fr)_var(--min-target-size)] ds:@[512px]/person:grid-cols-[var(--spacing-xl)_minmax(0,1fr)_max-content_var(--min-target-size)] ds:items-center ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-sm)]';\n\nexport const PERSON_AVATAR =\n 'ds:col-start-1 ds:row-start-1 ds:flex ds:items-center ds:justify-center';\n\n/** The name select, in a row that also has a channel select. */\nexport const PERSON_NAME = 'ds:col-start-2 ds:row-start-1 ds:min-w-0';\n\n/** The name select, in a row with no channel: it takes the channel's width. */\nexport const PERSON_NAME_FULL = 'ds:col-[2/-2] ds:row-start-1 ds:min-w-0';\n\n/**\n * The channel select: beside the name when wide, under it when narrow.\n * `-3/-2` is the name column in the 3-column grid and the channel column in\n * the 4-column one.\n */\nexport const PERSON_CHANNEL =\n 'ds:col-[-3/-2] ds:row-start-2 ds:min-w-0 ds:@[512px]/person:row-start-1';\n\nexport const PERSON_ACTION =\n 'ds:col-[-2/-1] ds:row-start-1 ds:flex ds:items-center ds:justify-center';\n\n/** Rows under a person (OTP switch, notes, errors): name to channel edge. */\nexport const PERSON_UNDER = 'ds:col-[2/-2] ds:min-w-0 ds:text-start';\n\n/** A section header row: eyebrow at the avatar edge, action at the selects' end edge. */\nexport const PERSON_HEADER =\n 'ds:col-[1/-2] ds:row-start-1 ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]';\n\n/** Space between two person blocks: larger than the gap inside one. */\nexport const PERSON_LIST = 'ds:flex ds:flex-col ds:gap-[var(--spacing-md)]';\n\n/** Put on each section that holds person grids: the container above. */\nexport const PERSON_SECTION = 'ds:@container/person';\n\n/**\n * Sizes the channel column to the longest channel label, in every row and\n * whatever is selected, so all channel selects share one width. A hidden,\n * zero-height copy of the select trigger per label; the column's\n * `max-content` width comes from the widest.\n */\nexport function ChannelColumnSizer({ meta }: { meta: ChannelMeta }) {\n return (\n <span\n aria-hidden=\"true\"\n data-channel-sizer=\"\"\n className=\"ds:invisible ds:block ds:h-0 ds:overflow-hidden\"\n >\n {Object.entries(meta).map(([channel, { label, icon }]) => (\n <span key={channel} className=\"ds:flex ds:w-max\">\n <span className={selectTriggerVariants({ size: 'md' })}>\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span className=\"ds:inline-flex ds:shrink-0\">{icon}</span>\n <span className=\"ds:whitespace-nowrap\">{label}</span>\n </span>\n <ChevronDown className=\"ds:size-4 ds:shrink-0\" />\n </span>\n </span>\n ))}\n </span>\n );\n}\n","/**\n * The signed versions section of SignatureRequestModal, shown at the top of\n * the request form when the host passes `signatures` (or\n * `signaturesLoading`), as on platform's \"Documenti firmati\" modal. A table\n * of past signature requests with the columns Date, Signature type and\n * Actions: when it was made, its legal level, how it was sent and who has\n * signed (SignatureStatusChip, names in its tooltip), then View, Download,\n * Share (to the targets the host allows) and Delete (after a confirmation).\n *\n * The table is ARIA (`role=\"table\"`), not an HTML table, so rows can stack\n * on narrow widths. It sits on the person grid, so its edges match the form's\n * sections below it.\n */\nimport { useEffect, useId, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Download, Eye, Link2, Mail, Share2, Trash2 } from 'lucide-react';\nimport { Button } from '../../components/button';\nimport { Dialog } from '../../components/dialog';\nimport { Skeleton } from '../../components/skeleton';\nimport { IconButton } from '../../components/icon-button';\nimport { DropdownMenu } from '../../components/dropdown-menu';\nimport { Tooltip, TooltipProvider } from '../../components/tooltip';\nimport { WhatsAppGlyph } from '../../components/whatsapp-button';\nimport {\n SignatureStatusChip,\n type SignatureParty,\n type SignatureSignerNames,\n} from '../../components/signature-status-chip';\nimport { useChannelMeta, type SignatureChannel } from './channel-meta';\nimport { LoadStatus } from './load-status';\nimport { PERSON_GRID, PERSON_HEADER, PERSON_SECTION } from './person-grid';\n\n/** Legal weight of a signature. Advanced needs an OTP-verified signer. */\nexport type SignatureLegalLevel = 'simple' | 'advanced';\n\n/** Which file a download asks for. */\nexport type SignatureDownloadVersion = 'full' | 'anonymised';\n\n/** How a signed document is shared. */\nexport type SignatureShareTarget = 'link' | 'email' | 'whatsapp';\n\n/** Every share target, in menu order. */\nconst SHARE_TARGETS: readonly SignatureShareTarget[] = [\n 'link',\n 'email',\n 'whatsapp',\n];\n\n/** One past signature request on the document. */\nexport interface SignatureRecord {\n /** Host id, handed back to every row callback. */\n id: string;\n /**\n * When the request was made: a `Date` or an ISO 8601 string, shown as\n * weekday, date and time in the active locale and the browser's time zone\n * (Italian: \"Mar. il 25/08/2026 ore 12:45\"). An unparseable string is\n * shown as it is.\n */\n createdAt: Date | string;\n /** How the request reached the signer. */\n channel: SignatureChannel;\n /** Omit to show no legal level on this row. */\n legalLevel?: SignatureLegalLevel;\n /** The operator's standing, as on SignatureStatusChip. */\n operator: SignatureParty;\n /** The patient's standing, as on SignatureStatusChip. */\n patient: SignatureParty;\n /** The second signee's standing. Defaults to `notRequired`. */\n secondary?: SignatureParty;\n /**\n * Signer names for the chip's tooltip, including who signed on a\n * party's behalf (a parent for a minor). Same shape as the chip's `names`.\n */\n names?: SignatureSignerNames;\n /** Offer the anonymised file beside the full one on download. */\n hasAnonymisedVersion?: boolean;\n /**\n * Where this document can be shared, e.g. no `'whatsapp'` for a patient\n * with no mobile number. Wins over the list's `shareTargets`. The menu\n * keeps its own order (link, e-mail, WhatsApp); an empty list hides Share\n * on this row.\n */\n shareTargets?: readonly SignatureShareTarget[];\n}\n\nexport interface SignatureHistoryProps {\n signatures?: readonly SignatureRecord[];\n loading?: boolean;\n showLegalLevel?: boolean;\n onView?: (id: string) => void;\n onDownload?: (id: string, version: SignatureDownloadVersion) => void;\n onShare?: (id: string, via: SignatureShareTarget) => void;\n /** Share targets for rows without their own. Default: all three. */\n shareTargets?: readonly SignatureShareTarget[];\n onDelete?: (id: string) => void;\n}\n\nconst LOADING_ROWS = [0, 1];\n\n/*\n * Narrow: date and actions on one line, the signature type under them, no\n * visible column headers. Wide (the person container at 512px, as the form's\n * rows): three columns shared by every row through subgrid, headers shown.\n */\nconst TABLE =\n 'ds:flex ds:flex-col ds:@[512px]/person:grid ds:@[512px]/person:grid-cols-[max-content_minmax(0,1fr)_max-content] ds:@[512px]/person:gap-x-[var(--spacing-md)]';\nconst ROWGROUP =\n 'ds:flex ds:flex-col ds:@[512px]/person:col-span-full ds:@[512px]/person:grid ds:@[512px]/person:grid-cols-subgrid';\nconst ROW =\n 'ds:grid ds:grid-cols-[minmax(0,1fr)_max-content] ds:items-center ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-xs)] ds:py-[var(--spacing-xs)] ds:@[512px]/person:col-span-full ds:@[512px]/person:grid-cols-subgrid ds:@[512px]/person:gap-x-[var(--spacing-md)]';\nconst CELL_DATE =\n 'ds:col-start-1 ds:row-start-1 ds:min-w-0 ds:text-start ds:@[512px]/person:col-start-1 ds:@[512px]/person:whitespace-nowrap';\nconst CELL_TYPE =\n 'ds:col-span-full ds:row-start-2 ds:min-w-0 ds:text-start ds:@[512px]/person:col-span-1 ds:@[512px]/person:col-start-2 ds:@[512px]/person:row-start-1';\nconst CELL_ACTIONS =\n 'ds:col-start-2 ds:row-start-1 ds:flex ds:justify-end ds:@[512px]/person:col-start-3';\n\nfunction timeOf(value: Date | string): number | null {\n const ms = (value instanceof Date ? value : new Date(value)).getTime();\n return Number.isNaN(ms) ? null : ms;\n}\n\n/** Newest first. Equal or unparseable dates keep the host order, last. */\nfunction newestFirst(\n records: readonly SignatureRecord[],\n): readonly SignatureRecord[] {\n return records\n .map((record, index) => ({ record, index, ms: timeOf(record.createdAt) }))\n .sort((a, b) => {\n if (a.ms === b.ms) return a.index - b.index;\n if (a.ms === null) return 1;\n if (b.ms === null) return -1;\n return b.ms - a.ms;\n })\n .map(({ record }) => record);\n}\n\nexport function SignatureHistory({\n signatures,\n loading = false,\n showLegalLevel = true,\n onView,\n onDownload,\n onShare,\n shareTargets = SHARE_TARGETS,\n onDelete,\n}: SignatureHistoryProps) {\n const { t, i18n } = useTranslation();\n const channelMeta = useChannelMeta();\n const headingId = useId();\n const shareMeta: Record<\n SignatureShareTarget,\n { label: string; icon: React.ReactNode }\n > = {\n link: { label: t('signatureRequest.shareLink'), icon: <Link2 /> },\n email: { label: t('signatureRequest.viaEmail'), icon: <Mail /> },\n whatsapp: {\n label: t('signatureRequest.viaWhatsapp'),\n icon: <WhatsAppGlyph />,\n },\n };\n // Platform's date: short weekday, numeric date, time. House English is\n // British, so `en` asks for en-GB (25/08/2026, 24-hour).\n const language = i18n.language || 'en';\n const intlLocale = language === 'en' ? 'en-GB' : language;\n const weekdayFormat = new Intl.DateTimeFormat(intlLocale, {\n weekday: 'short',\n });\n const dayFormat = new Intl.DateTimeFormat(intlLocale, {\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n });\n const timeFormat = new Intl.DateTimeFormat(intlLocale, {\n hour: '2-digit',\n minute: '2-digit',\n });\n const formatWhen = (ms: number) => {\n const weekday = weekdayFormat.format(ms);\n return t('signatureRequest.signedAt', {\n weekday:\n weekday.charAt(0).toLocaleUpperCase(intlLocale) + weekday.slice(1),\n date: dayFormat.format(ms),\n time: timeFormat.format(ms),\n interpolation: { escapeValue: false },\n });\n };\n\n const tableRef = useRef<HTMLDivElement>(null);\n const emptyRef = useRef<HTMLParagraphElement>(null);\n // A confirmed delete, with the row order at that moment, until the host\n // drops the record.\n const pendingDelete = useRef<{ id: string; order: string[] } | null>(null);\n const [deleteStatus, setDeleteStatus] = useState<string>();\n\n // The deleted row takes its Delete button (and Radix's focus target) with\n // it, so focus moves on purpose: next row, else previous, else the empty\n // line.\n useEffect(() => {\n const pending = pendingDelete.current;\n if (!pending || loading) return;\n const remaining = new Set((signatures ?? []).map((record) => record.id));\n if (remaining.has(pending.id)) return;\n pendingDelete.current = null;\n setDeleteStatus(t('signatureRequest.signatureDeleted'));\n const at = pending.order.indexOf(pending.id);\n const targetId =\n pending.order.slice(at + 1).find((id) => remaining.has(id)) ??\n pending.order\n .slice(0, at)\n .reverse()\n .find((id) => remaining.has(id));\n // After Radix's own unmount focus, which runs on a zero timeout.\n window.setTimeout(() => {\n const active = document.activeElement;\n const lost =\n !active ||\n active === document.body ||\n !active.isConnected ||\n active.matches('[role=\"dialog\"], [role=\"alertdialog\"]');\n if (!lost) return;\n if (targetId === undefined) {\n emptyRef.current?.focus();\n return;\n }\n const row = Array.from(\n tableRef.current?.querySelectorAll<HTMLElement>(\n '[data-signature-id]',\n ) ?? [],\n ).find((element) => element.dataset.signatureId === targetId);\n row?.querySelector<HTMLElement>('[role=\"group\"] button')?.focus();\n }, 0);\n }, [signatures, loading, t]);\n\n const sorted = signatures ? newestFirst(signatures) : [];\n\n let content: React.ReactNode;\n if (loading) {\n content = (\n <div\n aria-busy=\"true\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n {LOADING_ROWS.map((row) => (\n <div\n key={row}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\"\n >\n <div className=\"ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <Skeleton size=\"md\" width=\"40%\" />\n <Skeleton size=\"sm\" width=\"70%\" />\n </div>\n <Skeleton variant=\"circular\" size=\"sm\" />\n <Skeleton variant=\"circular\" size=\"sm\" />\n <Skeleton variant=\"circular\" size=\"sm\" />\n </div>\n ))}\n </div>\n );\n } else if (sorted.length === 0) {\n content = (\n <p\n ref={emptyRef}\n // Focus lands here when the last row is deleted.\n tabIndex={-1}\n data-note=\"no-signed-versions\"\n className=\"type-body-sm ds:text-[color:var(--muted-foreground)] ds:outline-none\"\n >\n {t('signatureRequest.noSignedVersions')}\n </p>\n );\n } else {\n const headerCell =\n 'type-label ds:text-[color:var(--muted-foreground)] ds:pb-[var(--spacing-xs)]';\n content = (\n // The chip's tooltip and the icon-button tooltips need a provider; the\n // section brings its own so a host without one does not crash.\n <TooltipProvider>\n <div\n ref={tableRef}\n role=\"table\"\n aria-labelledby={headingId}\n className={TABLE}\n >\n {/* Column headers: visible on wide screens, for assistive tech\n only when the rows stack. */}\n <div\n role=\"rowgroup\"\n className={`${ROWGROUP} ds:sr-only ds:@[512px]/person:not-sr-only`}\n >\n <div\n role=\"row\"\n className={`${ROW} ds:border-b ds:border-[color:var(--border)]`}\n >\n <span\n role=\"columnheader\"\n className={`${CELL_DATE} ${headerCell}`}\n >\n {t('signatureRequest.columnDate')}\n </span>\n <span\n role=\"columnheader\"\n className={`${CELL_TYPE} ${headerCell}`}\n >\n {t('signatureRequest.columnSignatureType')}\n </span>\n <span\n role=\"columnheader\"\n className={`${CELL_ACTIONS} ${headerCell}`}\n >\n {t('signatureRequest.columnActions')}\n </span>\n </div>\n </div>\n <div role=\"rowgroup\" className={ROWGROUP}>\n {sorted.map((record, index) => {\n const ms = timeOf(record.createdAt);\n const when =\n ms === null ? String(record.createdAt) : formatWhen(ms);\n const dateTime =\n ms === null ? undefined : new Date(ms).toISOString();\n const channel = channelMeta[record.channel];\n const allowedTargets = record.shareTargets ?? shareTargets;\n const rowShareTargets = onShare\n ? SHARE_TARGETS.filter((target) =>\n allowedTargets.includes(target),\n )\n : [];\n const hasActions =\n onView !== undefined ||\n onDownload !== undefined ||\n rowShareTargets.length > 0 ||\n onDelete !== undefined;\n return (\n <div\n key={record.id}\n role=\"row\"\n data-signature-id={record.id}\n className={\n index === 0\n ? ROW\n : `${ROW} ds:border-t ds:border-[color:var(--border)]`\n }\n >\n <div role=\"cell\" className={`${CELL_DATE} type-body`}>\n <time dateTime={dateTime}>{when}</time>\n </div>\n <div role=\"cell\" className={CELL_TYPE}>\n <span className=\"type-body-sm ds:flex ds:flex-wrap ds:items-center ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\">\n {showLegalLevel && record.legalLevel ? (\n <span>\n {record.legalLevel === 'advanced'\n ? t('signatureRequest.legalLevelAdvanced')\n : t('signatureRequest.legalLevelSimple')}\n </span>\n ) : null}\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[var(--accent)]\"\n >\n {channel.icon}\n </span>\n {channel.label}\n </span>\n <SignatureStatusChip\n size=\"sm\"\n operator={record.operator}\n patient={record.patient}\n secondary={record.secondary}\n names={record.names}\n tooltip\n />\n </span>\n </div>\n <div role=\"cell\" className={CELL_ACTIONS}>\n {hasActions ? (\n <span\n role=\"group\"\n aria-label={t('signatureRequest.signatureActions', {\n date: when,\n interpolation: { escapeValue: false },\n })}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {onView ? (\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={<Eye />}\n aria-label={t('signatureRequest.viewSignature')}\n tooltip={t('signatureRequest.viewSignature')}\n onClick={() => onView(record.id)}\n />\n ) : null}\n {onDownload && record.hasAnonymisedVersion ? (\n <RowMenu\n id={`signature-download-${record.id}`}\n label={t('signatureRequest.downloadSignature')}\n icon={<Download />}\n >\n <DropdownMenu.Item\n onSelect={() => onDownload(record.id, 'full')}\n >\n {t('signatureRequest.downloadFull')}\n </DropdownMenu.Item>\n <DropdownMenu.Item\n onSelect={() =>\n onDownload(record.id, 'anonymised')\n }\n >\n {t('signatureRequest.downloadAnonymised')}\n </DropdownMenu.Item>\n </RowMenu>\n ) : onDownload ? (\n // One file only: a menu with a single entry would\n // be an extra click for nothing.\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={<Download />}\n aria-label={t('signatureRequest.downloadSignature')}\n tooltip={t('signatureRequest.downloadSignature')}\n onClick={() => onDownload(record.id, 'full')}\n />\n ) : null}\n {onShare && rowShareTargets.length > 0 ? (\n <RowMenu\n id={`signature-share-${record.id}`}\n label={t('signatureRequest.shareSignature')}\n icon={<Share2 />}\n >\n {rowShareTargets.map((target) => (\n <DropdownMenu.Item\n key={target}\n startIcon={shareMeta[target].icon}\n onSelect={() => onShare(record.id, target)}\n >\n {shareMeta[target].label}\n </DropdownMenu.Item>\n ))}\n </RowMenu>\n ) : null}\n {onDelete ? (\n <DeleteConfirm\n id={`signature-delete-${record.id}`}\n when={when}\n dateTime={dateTime}\n onConfirm={() => {\n pendingDelete.current = {\n id: record.id,\n order: sorted.map((item) => item.id),\n };\n setDeleteStatus('');\n onDelete(record.id);\n }}\n />\n ) : null}\n </span>\n ) : null}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n </TooltipProvider>\n );\n }\n\n return (\n <section\n aria-labelledby={headingId}\n data-section=\"signed-versions\"\n className={`${PERSON_SECTION} ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:text-start`}\n >\n <div className={PERSON_GRID}>\n <div className={PERSON_HEADER}>\n <h3\n id={headingId}\n className=\"type-eyebrow ds:m-0 ds:text-[color:var(--muted-foreground)]\"\n >\n {t('signatureRequest.signedVersions')}\n </h3>\n </div>\n </div>\n <div className={PERSON_GRID}>\n {/* From the avatar edge to the selects' end edge, as the form. */}\n <div className=\"ds:col-[1/-2] ds:min-w-0\">\n {/* One status region for loading, loaded and deleted, outside the\n busy container. */}\n <LoadStatus\n loading={loading}\n loadingText={t('signatureRequest.signaturesLoading')}\n loadedText={t('signatureRequest.signaturesLoaded')}\n message={deleteStatus}\n />\n {content}\n </div>\n </div>\n </section>\n );\n}\n\n/**\n * Keeps an icon button's tooltip shut while focus comes back to the button\n * from the menu or dialog it opened. A focused trigger opens its tooltip, so\n * without this the tip pops up unasked. It opens again once the user moves\n * the pointer onto the button or focus leaves it.\n */\nfunction useQuietReturnTooltip() {\n const [tipOpen, setTipOpen] = useState(false);\n const restoringFocus = useRef(false);\n return {\n tooltipProps: {\n open: tipOpen,\n onOpenChange: (next: boolean) => {\n if (next && restoringFocus.current) return;\n setTipOpen(next);\n },\n },\n triggerProps: {\n onPointerMove: () => {\n restoringFocus.current = false;\n },\n onBlur: () => {\n restoringFocus.current = false;\n },\n },\n hideTip: () => setTipOpen(false),\n /** Call just before focus returns to the trigger. */\n markReturning: () => {\n restoringFocus.current = true;\n },\n };\n}\n\ninterface RowMenuProps {\n /** Stable, non-PHI instance id for the dropdown-menu adapter. */\n id: string;\n label: string;\n icon: React.ReactNode;\n children: React.ReactNode;\n}\n\n/** An icon button with a tooltip that opens a menu. */\nfunction RowMenu({ id, label, icon, children }: RowMenuProps) {\n const tip = useQuietReturnTooltip();\n return (\n <DropdownMenu.Root\n id={id}\n onOpenChange={(menuOpen) => {\n if (menuOpen) tip.hideTip();\n }}\n >\n <Tooltip label={label} {...tip.tooltipProps}>\n <DropdownMenu.Trigger asChild>\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={icon}\n aria-label={label}\n {...tip.triggerProps}\n />\n </DropdownMenu.Trigger>\n </Tooltip>\n <DropdownMenu.Content\n align=\"end\"\n // Runs before Radix moves focus back to the trigger.\n onCloseAutoFocus={tip.markReturning}\n >\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\ninterface DeleteConfirmProps {\n /** Stable, non-PHI instance id for the dialog adapter. */\n id: string;\n /** The row's date as shown, repeated in the confirmation. */\n when: string;\n dateTime?: string;\n onConfirm: () => void;\n}\n\n/**\n * The row's Delete button and its confirmation, a forced-choice alert\n * dialog. Cancel, Esc and Delete all put focus back on the button; once the\n * host drops the record, SignatureHistory moves it on.\n */\nfunction DeleteConfirm({ id, when, dateTime, onConfirm }: DeleteConfirmProps) {\n const { t } = useTranslation();\n const tip = useQuietReturnTooltip();\n const [open, setOpen] = useState(false);\n const label = t('signatureRequest.deleteSignature');\n return (\n <Dialog\n id={id}\n open={open}\n onOpenChange={(next) => {\n if (next) tip.hideTip();\n setOpen(next);\n }}\n >\n <Tooltip label={label} {...tip.tooltipProps}>\n <Dialog.Trigger asChild>\n <IconButton\n intent=\"destructiveOutline\"\n size=\"sm\"\n icon={<Trash2 />}\n aria-label={label}\n {...tip.triggerProps}\n />\n </Dialog.Trigger>\n </Tooltip>\n <Dialog.Content\n variant=\"alert\"\n size=\"sm\"\n // Runs before Radix moves focus back to the trigger.\n onCloseAutoFocus={tip.markReturning}\n >\n <Dialog.Header>\n <Dialog.Title>\n {t('signatureRequest.deleteSignatureConfirm')}\n </Dialog.Title>\n {/* Which request this is: the date the row shows. */}\n <Dialog.Description>\n <time dateTime={dateTime}>{when}</time>\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button intent=\"outline\">{t('common.cancel')}</Button>\n </Dialog.Close>\n <Button\n intent=\"destructive\"\n startIcon={<Trash2 />}\n onClick={() => {\n onConfirm();\n setOpen(false);\n }}\n >\n {label}\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog>\n );\n}\n","/**\n * The required documents view: the body of SignatureRequestModal when the\n * host passes `requiredItems` (or `requiredItemsLoading`). It lists every\n * outstanding document and anamnesis interview for one patient, in two\n * groups with counts, each row with the item name and, where an operator must\n * sign, that item's own operator picker. Rows show no signing status: as on\n * platform, the documents API says only whether an item is signed.\n *\n * Renders body content only; the modal owns the header, the signer roster\n * and the footer, and holds the per-item operator assignments.\n */\nimport { useId } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { UserPlus } from 'lucide-react';\nimport { Alert } from '../../components/alert';\nimport { Button } from '../../components/button';\nimport { List } from '../../components/list';\nimport { Select, type SelectOption } from '../../components/select';\nimport { Skeleton } from '../../components/skeleton';\nimport {\n OPERATOR_CHANNELS,\n useChannelMeta,\n type OperatorChannel,\n type SignatureChannel,\n} from './channel-meta';\nimport { LoadStatus } from './load-status';\nimport {\n ChannelColumnSizer,\n PERSON_GRID,\n PERSON_HEADER,\n PERSON_SECTION,\n PERSON_UNDER,\n} from './person-grid';\n\n/** Select value for \"Assign later\" in every operator picker. */\nexport const ASSIGN_LATER = '__assign-later__';\n\n/** What a required item is. Anamnesis interviews never carry a second signee. */\nexport type RequiredSignatureItemKind = 'document' | 'anamnesis';\n\n/** One outstanding document or anamnesis interview in the batch. */\nexport interface RequiredSignatureItem {\n /** Host id, the key of `operatorAssignments` in the submission. */\n id: string;\n kind: RequiredSignatureItemKind;\n /** Display name, e.g. the document template name. */\n name: string;\n /** Whether an operator must sign this item. Shows its operator picker. */\n requiresOperator: boolean;\n /**\n * Whether this document has a field for the second signee. The second\n * signee is offered only when every listed item can carry it. Ignored for\n * `kind: 'anamnesis'`, which never can. Default `false`.\n */\n canCarrySecondary?: boolean;\n /**\n * Preselected operator for this item; `null` preselects \"Assign later\".\n * Omit to use the modal's `initialOperatorId`.\n */\n initialOperatorId?: string | null;\n /**\n * Whether the item is already signed (platform `signed` on a document,\n * `isSigned` on an interview). Signed items are left out. Default `false`.\n * There is no per-party standing: platform's documents API has none.\n */\n signed?: boolean;\n}\n\n/** The items that still need a signature: those not signed. */\nexport function itemsStillToSign(\n items: readonly RequiredSignatureItem[],\n): RequiredSignatureItem[] {\n return items.filter((item) => item.signed !== true);\n}\n\n/**\n * The second signee signs the whole batch in one round, so it is offered\n * only when every item can carry that signature. `[].every()` is true, so an\n * empty batch cannot.\n */\nexport function batchCanCarrySecondary(\n items: readonly RequiredSignatureItem[],\n): boolean {\n return (\n items.length > 0 &&\n items.every(\n (item) => item.kind === 'document' && item.canCarrySecondary === true,\n )\n );\n}\n\n/** Whether an item gets an operator picker: an operator must sign it. */\nexport function needsOperatorPick(item: RequiredSignatureItem): boolean {\n return item.requiresOperator;\n}\n\n/**\n * One option in an operator picker. \"Assign later\" comes first, as on\n * platform (OperatorSignee.js). A `disabled` operator shows greyed out with\n * its `description` (the host's reason); a `deleted` one is hidden unless it\n * is the picker's current value.\n */\nexport interface OperatorPickerOption {\n value: string;\n label: string;\n disabled?: boolean;\n description?: string;\n deleted?: boolean;\n}\n\n/** The options one picker lists, given its current value. */\nexport function operatorPickerOptions(\n options: readonly OperatorPickerOption[],\n selected: string | undefined,\n): SelectOption[] {\n return options\n .filter((option) => option.deleted !== true || option.value === selected)\n .map(({ deleted: _deleted, ...option }) => option);\n}\n\n/** Whether a user could pick this value: listed, not greyed out or deleted. */\nexport function isPickableOperator(\n options: readonly OperatorPickerOption[],\n value: string,\n): boolean {\n return options.some(\n (option) =>\n option.value === value &&\n option.disabled !== true &&\n option.deleted !== true,\n );\n}\n\n/**\n * The greyed-out operators and their reasons, for the picker trigger: a\n * disabled option cannot take focus, so its own description is never heard.\n * `undefined` when none is greyed out.\n */\nexport function operatorReasonsHint(\n options: readonly OperatorPickerOption[],\n locale: string,\n): string | undefined {\n const entries = options\n .filter((option) => option.disabled === true && option.deleted !== true)\n .map((option) =>\n option.description\n ? `${option.label} (${option.description})`\n : option.label,\n );\n if (entries.length === 0) return undefined;\n return new Intl.ListFormat(locale || 'en', { type: 'unit' }).format(entries);\n}\n\n/**\n * Why the second signee is withheld from a batch, first reason first; `null`\n * when it is offered. Mirrors platform (secondarySigneeAvailability.ts and\n * SecondarySignee.tsx): every item can carry it, the batch is signed on this\n * device, and the main signer is a registered signee, not the patient.\n */\nexport type SecondSigneeBlock =\n | 'anamnesis'\n | 'documents'\n | 'patient'\n | 'channel';\n\nexport function secondSigneeBlock({\n items,\n channel,\n primaryIsPatient,\n}: {\n items: readonly RequiredSignatureItem[];\n channel: SignatureChannel;\n primaryIsPatient: boolean;\n}): SecondSigneeBlock | null {\n if (!batchCanCarrySecondary(items)) {\n return items.some((item) => item.kind === 'anamnesis')\n ? 'anamnesis'\n : 'documents';\n }\n if (primaryIsPatient) return 'patient';\n if (channel !== 'on-device') return 'channel';\n return null;\n}\n\n/** What is wrong with the chosen second signee (platform secondarySigneeValidation.ts). */\nexport type SecondSigneeIssue =\n | 'sameAsPrimary'\n | 'unknownSignee'\n | 'missingPhone'\n | 'missingEmail';\n\n/** The parts of a `SignerOption` the second signee checks read. */\nexport interface SecondSigneeCandidate {\n value: string;\n isPatient?: boolean;\n availableChannels?: readonly SignatureChannel[];\n unavailableChannels?: ReadonlyArray<{ channel: SignatureChannel }>;\n}\n\n/**\n * The first issue with a second signee, or `null`. Phone and e-mail are read\n * from channel availability, so no contact data reaches the kit: a person who\n * cannot receive SMS or WhatsApp has no phone, one who cannot receive e-mail\n * has no e-mail. The patient is never a signee, so picking them is unknown.\n */\nexport function secondSigneeIssue({\n primaryId,\n secondId,\n channel,\n options,\n}: {\n primaryId: string | undefined;\n secondId: string;\n channel: SignatureChannel;\n options: readonly SecondSigneeCandidate[];\n}): SecondSigneeIssue | null {\n if (secondId === primaryId) return 'sameAsPrimary';\n const second = options.find((option) => option.value === secondId);\n if (!second || second.isPatient === true) return 'unknownSignee';\n const receives = (wanted: SignatureChannel) =>\n (!second.availableChannels ||\n second.availableChannels.length === 0 ||\n second.availableChannels.includes(wanted)) &&\n !second.unavailableChannels?.some((entry) => entry.channel === wanted);\n if ((channel === 'sms' || channel === 'whatsapp') && !receives(channel)) {\n return 'missingPhone';\n }\n if (channel === 'email' && !receives('email')) return 'missingEmail';\n return null;\n}\n\nexport interface RequiredDocumentsProps {\n /** The items to list, already narrowed to those still to sign. */\n items: readonly RequiredSignatureItem[];\n loading?: boolean;\n /**\n * Operator options, \"Assign later\" first when allowed. Deleted operators\n * show only in a picker whose value they are.\n */\n operatorOptions: readonly OperatorPickerOption[];\n /** The picker value per item id, for items that require an operator. */\n assignments: Readonly<Record<string, string>>;\n onAssign: (itemId: string, operatorValue: string) => void;\n /** Shows \"Assign all to me\" when passed. */\n onAssignAllToMe?: () => void;\n busy?: boolean;\n /**\n * Adds each picked operator's channel beside their picker, in place of\n * the note that their settings decide. Default `false`.\n */\n showOperatorChannels?: boolean;\n /** The channel per item id, for items with an assigned operator. */\n operatorChannels?: Readonly<Record<string, OperatorChannel>>;\n onOperatorChannel?: (itemId: string, channel: OperatorChannel) => void;\n}\n\nconst LOADING_ROWS = [0, 1, 2];\n\n/**\n * One item row: the name, then the operator picker on the same\n * line. Two equal columns, so every picker in the list shares both edges;\n * the picker drops under the name when the section is narrow. With operator\n * channels a third column holds the channel select, as wide as the roster's\n * channel column (the same sizer), so its edges match the rows below.\n */\nconst ITEM_ROW =\n 'ds:grid ds:grid-cols-1 ds:@[512px]/person:grid-cols-2 ds:items-center ds:gap-[var(--spacing-sm)] ds:font-normal';\nconst ITEM_ROW_WITH_CHANNEL =\n 'ds:grid ds:grid-cols-1 ds:@[512px]/person:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_max-content] ds:items-center ds:gap-[var(--spacing-sm)] ds:font-normal';\nconst ITEM_NAME = 'ds:min-w-0 ds:font-medium';\nconst ITEM_NAME_FULL = 'ds:col-span-full ds:min-w-0 ds:font-medium';\nconst ITEM_PICKER = 'ds:block ds:min-w-0';\n\n/** A section note: the info Alert with the row's small padding and gap. */\nconst COMPACT_NOTE = 'ds:!gap-[var(--spacing-sm)] ds:!p-[var(--spacing-sm)]';\n\nexport function RequiredDocuments({\n items,\n loading = false,\n operatorOptions,\n assignments,\n onAssign,\n onAssignAllToMe,\n busy = false,\n showOperatorChannels = false,\n operatorChannels = {},\n onOperatorChannel,\n}: RequiredDocumentsProps) {\n const { t, i18n } = useTranslation();\n const channelMeta = useChannelMeta();\n // SMS, e-mail and on this device, as the request form's operator offers.\n const channelOptions: SelectOption<OperatorChannel>[] = OPERATOR_CHANNELS.map(\n (channel) => ({\n value: channel,\n label: channelMeta[channel].label,\n startAdornment: channelMeta[channel].icon,\n }),\n );\n const documentsHeadingId = useId();\n const interviewsHeadingId = useId();\n const operatorHintId = useId();\n\n // One status region for loading and loaded, outside the busy container.\n const status = (\n <LoadStatus\n loading={loading}\n loadingText={t('signatureRequest.requiredLoading')}\n loadedText={t('signatureRequest.requiredLoaded')}\n />\n );\n\n if (loading) {\n return (\n <>\n {status}\n <div\n aria-busy=\"true\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n {LOADING_ROWS.map((row) => (\n <div\n key={row}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <Skeleton size=\"md\" width=\"50%\" />\n <Skeleton size=\"sm\" width=\"30%\" />\n </div>\n ))}\n </div>\n </>\n );\n }\n\n const documents = items.filter((item) => item.kind === 'document');\n const interviews = items.filter((item) => item.kind === 'anamnesis');\n const anyUnassigned = items.some(\n (item) => needsOperatorPick(item) && assignments[item.id] === ASSIGN_LATER,\n );\n\n // \"Assign all to me\" and the two notes explain every picker, so they sit\n // once, at the top of the first group that has one.\n const operatorGroup = [documents, interviews].find((groupItems) =>\n groupItems.some(needsOperatorPick),\n );\n // One hidden line serves every picker: the greyed-out operators and why.\n const operatorHint = operatorReasonsHint(operatorOptions, i18n.language);\n\n const group = (\n groupItems: RequiredSignatureItem[],\n headingId: string,\n heading: string,\n ) => {\n if (groupItems.length === 0) return null;\n const withOperatorControls = groupItems === operatorGroup;\n return (\n <section\n className={`${PERSON_SECTION} ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]`}\n >\n <div className={PERSON_GRID}>\n <div className={PERSON_HEADER}>\n <p\n id={headingId}\n className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\"\n >\n {heading}\n </p>\n {withOperatorControls && onAssignAllToMe ? (\n <Button\n intent=\"outline\"\n size=\"sm\"\n startIcon={<UserPlus />}\n disabled={busy}\n onClick={onAssignAllToMe}\n >\n {t('signatureRequest.assignAllToMe')}\n </Button>\n ) : null}\n </div>\n {withOperatorControls && anyUnassigned ? (\n <Alert\n variant=\"info\"\n data-note=\"assign-later\"\n className={`${PERSON_UNDER} ${COMPACT_NOTE}`}\n >\n <Alert.Description>\n {t('signatureRequest.assignLaterNote')}\n </Alert.Description>\n </Alert>\n ) : null}\n {/* With the channels on screen the note has nothing to add. */}\n {withOperatorControls && !showOperatorChannels ? (\n <Alert\n variant=\"info\"\n data-note=\"operator-channel\"\n className={`${PERSON_UNDER} ${COMPACT_NOTE}`}\n >\n <Alert.Description>\n {t('signatureRequest.operatorChannelNote')}\n </Alert.Description>\n </Alert>\n ) : null}\n </div>\n {/* The list takes the name to channel columns, so rows start at the\n roster's name edge and end where its selects end. */}\n <div className={PERSON_GRID}>\n <List\n density=\"relaxed\"\n aria-labelledby={headingId}\n className={PERSON_UNDER}\n >\n {groupItems.map((item) => {\n const withPicker = needsOperatorPick(item);\n const withChannel = withPicker && showOperatorChannels;\n const assigned =\n withPicker &&\n assignments[item.id] !== undefined &&\n assignments[item.id] !== ASSIGN_LATER &&\n assignments[item.id] !== '';\n return (\n <List.Item\n key={item.id}\n value={item.id}\n data-required-item-id={item.id}\n className=\"ds:!p-[var(--spacing-none)]\"\n title={\n <span\n className={withChannel ? ITEM_ROW_WITH_CHANNEL : ITEM_ROW}\n >\n <span className={withPicker ? ITEM_NAME : ITEM_NAME_FULL}>\n {item.name}\n </span>\n {withPicker ? (\n <span className={ITEM_PICKER}>\n <Select\n id={`signature-request-item-operator-${item.id}`}\n options={operatorPickerOptions(\n operatorOptions,\n assignments[item.id],\n )}\n value={assignments[item.id]}\n onValueChange={(value) => {\n // The agent's set_value skips the list, so a\n // greyed-out or deleted operator is refused here.\n if (\n value &&\n isPickableOperator(operatorOptions, value)\n ) {\n onAssign(item.id, value);\n }\n }}\n showDescriptions\n aria-describedby={\n operatorHint ? operatorHintId : undefined\n }\n required\n disabled={busy}\n placeholder={t(\n 'signatureRequest.operatorPlaceholder',\n )}\n aria-label={t(\n 'signatureRequest.itemOperatorLabel',\n { name: item.name },\n )}\n />\n </span>\n ) : null}\n {withChannel ? (\n // The chosen operator's channel, from their settings\n // unless changed here. Nobody to deliver to while\n // unassigned, but the column keeps its width.\n <span\n className={\n assigned\n ? ITEM_PICKER\n : `${ITEM_PICKER} ds:hidden ds:@[512px]/person:block`\n }\n >\n {assigned ? (\n <Select<OperatorChannel>\n id={`signature-request-item-operator-channel-${item.id}`}\n options={channelOptions}\n value={operatorChannels[item.id]}\n adornmentInTrigger\n disabled={busy}\n aria-label={t(\n 'signatureRequest.itemOperatorChannelLabel',\n { name: item.name },\n )}\n onValueChange={(value) => {\n // The agent's set_value skips the list.\n if (\n OPERATOR_CHANNELS.includes(\n value as OperatorChannel,\n )\n ) {\n onOperatorChannel?.(\n item.id,\n value as OperatorChannel,\n );\n }\n }}\n />\n ) : null}\n <ChannelColumnSizer meta={channelMeta} />\n </span>\n ) : null}\n </span>\n }\n />\n );\n })}\n </List>\n </div>\n </section>\n );\n };\n\n // The status keeps its place from the loading branch, so it stays mounted\n // and can say the items loaded.\n return (\n <>\n {status}\n {operatorHint ? (\n <span id={operatorHintId} className=\"ds:sr-only\">\n {operatorHint}\n </span>\n ) : null}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)] ds:text-start\">\n {group(\n documents,\n documentsHeadingId,\n t('signatureRequest.requiredDocumentsHeading', {\n count: documents.length,\n }),\n )}\n {group(\n interviews,\n interviewsHeadingId,\n t('signatureRequest.requiredAnamnesisHeading', {\n count: interviews.length,\n }),\n )}\n </div>\n </>\n );\n}\n","/**\n * Outcome states of SignatureRequestModal: a final screen in the same dialog\n * once there is nothing left to fill in. The modal puts the title and the\n * description in its header and its own actions in the footer; this file\n * holds the copy and the decorative body.\n */\nimport type { TFunction } from 'i18next';\nimport { CircleCheck, TriangleAlert } from 'lucide-react';\n\n/**\n * - `linkSent`: the request went out by link (SMS, e-mail, WhatsApp).\n * - `allSigned`: nothing is left to sign.\n * - `creditsExhausted`: the practice has no electronic signature documents\n * left, so the request cannot be sent.\n */\nexport type SignatureRequestOutcome =\n | 'linkSent'\n | 'allSigned'\n | 'creditsExhausted';\n\n/**\n * Title and description for an outcome, in the active locale. `required`\n * (required documents mode) uses platform's batch copy for `linkSent`.\n */\nexport function outcomeCopy(\n outcome: SignatureRequestOutcome,\n t: TFunction,\n { required = false }: { required?: boolean } = {},\n): { title: string; description: string } {\n switch (outcome) {\n case 'linkSent':\n if (required) {\n return {\n title: t('signatureRequest.requiredLinkSentTitle'),\n description: t('signatureRequest.requiredLinkSentDescription'),\n };\n }\n return {\n title: t('signatureRequest.outcomeLinkSentTitle'),\n description: t('signatureRequest.outcomeLinkSentDescription'),\n };\n case 'allSigned':\n return {\n title: t('signatureRequest.outcomeAllSignedTitle'),\n description: t('signatureRequest.outcomeAllSignedDescription'),\n };\n case 'creditsExhausted':\n return {\n title: t('signatureRequest.outcomeCreditsTitle'),\n description: t('signatureRequest.outcomeCreditsDescription'),\n };\n }\n}\n\n/** The outcome's body: a decorative status icon. The header carries the words. */\nexport function SignatureOutcome({\n outcome,\n}: {\n outcome: SignatureRequestOutcome;\n}) {\n const warning = outcome === 'creditsExhausted';\n return (\n <div\n data-outcome={outcome}\n className=\"ds:flex ds:justify-center ds:py-[var(--spacing-md)]\"\n >\n <span\n aria-hidden=\"true\"\n className={\n warning\n ? 'ds:text-[color:var(--warning)]'\n : 'ds:text-[color:var(--success)]'\n }\n >\n {warning ? (\n <TriangleAlert className=\"ds:size-[var(--icon-size-lg)]\" />\n ) : (\n <CircleCheck className=\"ds:size-[var(--icon-size-lg)]\" />\n )}\n </span>\n </div>\n );\n}\n","/**\n * SignatureRequestModal — the practice-side \"Documenti firmati\" modal that\n * dispatches a document-signature request: assign the operator who must\n * counter-sign (or leave the request unassigned) and how their request is\n * delivered (their system-defined default channel arrives preselected),\n * build the patient-side signer roster (up to `maxSigners`, each with their\n * own delivery channel and, for on-device signing, an OTP waiver), and send.\n *\n * Runtime pattern: real consuming apps mount this in production (surfaced via\n * `src/patterns/index.ts` and the `./patterns/signature-request` subpath).\n * The component owns the form state — re-seeded from the `initial*` props\n * every time `open` flips back to `true` — while the host owns `open`, the\n * option lists, and what happens on submit. Multiple on-device signers sign\n * sequentially in roster order — the execution side is the Signing pattern's\n * multi-signer flow; this modal only encodes the intents.\n *\n * Via QR is a second step of the same dialog: after a submit with a `'qr'`\n * signer the dialog stays open and waits, then shows one server-issued code\n * per QR signer once the host passes `qrCodes`. The kit never builds a link.\n *\n * Signed versions: when the host passes `signatures` (or\n * `signaturesLoading`) the form shows the document's past signature requests\n * in a table above the operator and signers, on one screen as platform's\n * \"Documenti firmati\" modal does. A host that passes neither sees the plain\n * form.\n *\n * Required documents mode: when the host passes `requiredItems` (or\n * `requiredItemsLoading`) the form asks the patient to sign every\n * outstanding document and anamnesis interview in one batch. Each item that\n * needs an operator gets its own picker in place of the single operator row\n * (and, with `showOperatorChannels`, that operator's channel); the roster\n * applies to the whole batch. A second signee follows platform's rules:\n * every item can carry it, the main signer signs on this device, and the\n * main signer is a registered signee, not the patient.\n *\n * Channel mode (`channelMode`), in every mode: `'perSigner'` (the default)\n * gives each signer row its own channel; `'batch'` puts one channel on the\n * whole roster (platform's sign mode) with one OTP waiver, and submits\n * `signMode`.\n *\n * Outcome states (`outcome`) replace every other view with a final screen\n * and a Close action; credits used up can also go back to the form.\n *\n * Channel rules: by default the operator may sign on this device only while\n * a patient signer does. A host with its own rules passes `resolveChannels`,\n * which replaces that rule.\n */\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { TFunction } from 'i18next';\nimport { PenLine, Plus, ShoppingCart, UserPlus, X } from 'lucide-react';\nimport { Dialog } from '../../components/dialog';\nimport { QrCode } from '../../components/qr-code';\nimport { Spinner } from '../../components/spinner';\nimport { Button } from '../../components/button';\nimport { IconButton } from '../../components/icon-button';\nimport { Select, type SelectOption } from '../../components/select';\nimport { Switch } from '../../components/switch';\nimport { Alert } from '../../components/alert';\nimport { Separator } from '../../components/separator';\nimport { Avatar } from '../../components/avatar';\nimport { TooltipProvider } from '../../components/tooltip';\nimport {\n OPERATOR_CHANNELS,\n useChannelMeta,\n type OperatorChannel,\n type SignatureChannel,\n} from './channel-meta';\nimport {\n SignatureHistory,\n type SignatureDownloadVersion,\n type SignatureRecord,\n type SignatureShareTarget,\n} from './signature-history';\nimport {\n ASSIGN_LATER,\n RequiredDocuments,\n isPickableOperator,\n itemsStillToSign,\n needsOperatorPick,\n operatorPickerOptions,\n operatorReasonsHint,\n secondSigneeBlock,\n secondSigneeIssue,\n type OperatorPickerOption,\n type RequiredSignatureItem,\n type SecondSigneeBlock,\n type SecondSigneeIssue,\n} from './required-documents';\nimport {\n SignatureOutcome,\n outcomeCopy,\n type SignatureRequestOutcome,\n} from './signature-outcome';\nimport {\n ChannelColumnSizer,\n PERSON_ACTION,\n PERSON_AVATAR,\n PERSON_CHANNEL,\n PERSON_GRID,\n PERSON_HEADER,\n PERSON_LIST,\n PERSON_NAME,\n PERSON_NAME_FULL,\n PERSON_SECTION,\n PERSON_UNDER,\n} from './person-grid';\n\nexport type { OperatorChannel, SignatureChannel } from './channel-meta';\nexport type {\n SignatureDownloadVersion,\n SignatureLegalLevel,\n SignatureRecord,\n SignatureShareTarget,\n} from './signature-history';\nexport type {\n RequiredSignatureItem,\n RequiredSignatureItemKind,\n} from './required-documents';\nexport type { SignatureRequestOutcome } from './signature-outcome';\n\n/**\n * How patient signers get their channel. `'perSigner'`: each signer row has\n * its own channel dropdown beside the name. `'batch'`: one channel for the\n * whole roster, under the signers heading, submitted as `signMode`.\n */\nexport type SignatureChannelMode = 'perSigner' | 'batch';\n\n/** The channel choices on the form, handed to `resolveChannels`. */\nexport interface SignatureChannelDraft {\n /** The assigned operator; `null` with no operator row or on Assign later. */\n operatorId: string | null;\n /** The operator's channel; `null` whenever `operatorId` is. */\n operatorChannel: OperatorChannel | null;\n /** The patient-side roster, in order. Empty when the patient does not sign. */\n signers: SignerRequest[];\n /**\n * What the user just changed: `'operator'` (the operator or their\n * channel) or `'signers'` (a signer's channel or person, or a row added or\n * removed). `null` when the dialog opens, and when the modal reads the\n * available channels while rendering.\n */\n changed: 'operator' | 'signers' | null;\n /**\n * Channels each draft signer has greyed out (`unavailableChannels` on\n * their `SignerOption`), by `signerId`. Absent when no signer has any.\n * The modal never applies one, whatever the rule returns.\n */\n signerUnavailableChannels?: Record<string, SignatureChannel[]>;\n}\n\n/** What `resolveChannels` returns: the channels to use and to offer. */\nexport interface SignatureChannelResolution {\n /** The operator's channel to use. Ignored while the draft's is `null`. */\n operatorChannel: OperatorChannel | null;\n /**\n * The roster with the channels to use. Only `channel` is read, matched by\n * `signerId`; the roster itself never changes here.\n */\n signers: SignerRequest[];\n /** Channels the operator's dropdown offers. Omit to offer all three. */\n operatorAvailableChannels?: OperatorChannel[];\n /**\n * Channels each signer's dropdown offers, by `signerId`. Narrows that\n * person's own `availableChannels`; a list that leaves nothing selectable\n * is ignored. It cannot re-enable a channel in the person's\n * `unavailableChannels`: that one stays greyed out.\n */\n signerAvailableChannels?: Record<string, SignatureChannel[]>;\n}\n\n/** One selectable person/role for the operator or signer selects. */\nexport interface SignerOption {\n value: string;\n label: string;\n /**\n * Delivery channels this person can actually receive. Omit (or pass an\n * empty list) to offer every channel, Via QR included. Hosts gate this\n * from per-patient capability flags — e.g. a patient with no mobile number\n * drops `'sms'` and `'whatsapp'`. Only meaningful for signer options, not\n * operators.\n */\n availableChannels?: SignatureChannel[];\n /**\n * Channels to show greyed out, each with the host-translated reason shown\n * under it (e.g. SMS and WhatsApp with \"No mobile number\"), instead of\n * hiding them. Wins over `availableChannels`; a channel that list leaves\n * out stays hidden. Never selected, seeded or submitted: the row falls\n * back to the first channel still available, and a signer with none\n * shows the reasons under the row and blocks the request. Only meaningful\n * for signer options, not operators.\n */\n unavailableChannels?: ReadonlyArray<{\n channel: SignatureChannel;\n reason: string;\n }>;\n /**\n * The delivery channel this operator's own settings resolve to — the\n * system-defined default, preselected when the operator is assigned and\n * again whenever a different operator is picked (a channel the user\n * changed by hand is kept until then). Falls back to `'email'` when\n * omitted. `'on-device'` applies only where it is offered: in the request\n * form, while a patient signer signs on this device (else e-mail), unless\n * `resolveChannels` decides. Also seeds each item's operator channel with\n * `showOperatorChannels`. Only meaningful for operator options, not\n * signers.\n */\n defaultChannel?: OperatorChannel;\n /**\n * The host has worked out that this person is under 18. A roster row with\n * this person selected shows a warning to check whether a second signee is\n * needed. It never blocks the request; the kit does not compute age. Only\n * meaningful for signer options, not operators.\n */\n isMinor?: boolean;\n /**\n * This option is the patient's own record, not one of their registered\n * signees (a legal guardian, a parent). Read in required documents mode\n * and in `channelMode: 'batch'`, as on platform. Required documents mode:\n * a second signee needs a registered signee as the main signer, and the\n * patient is never offered as a second signee. The OTP waiver (the\n * batch's, or the main signer's row per signer) starts on when the patient\n * cannot receive SMS, and is forced on when the patient is the main signer.\n * Batch mode: the channel defaults to SMS when the patient signs and can\n * receive it, and offers a channel the patient OR the main signer can\n * receive (so pass each person's own channels, not a combined list). Omit\n * it and the person counts as a registered signee. Only meaningful for\n * signer options, not operators.\n */\n isPatient?: boolean;\n}\n\n/**\n * One operator offered in the operator pickers: the single-document form's\n * operator select and, in required documents mode, every item's picker.\n * Operators keep host order. \"Assign later\" comes after them in the request\n * form, and first in required documents mode, as on platform\n * (OperatorSignee.js).\n */\nexport interface OperatorOption extends SignerOption {\n /**\n * Shows the operator greyed out, with `reason` under the name. It cannot\n * be picked, and is never seeded as the first operator. A host-seeded\n * value stays as it is.\n */\n disabled?: boolean;\n /**\n * Why the operator is greyed out, host-translated (e.g. \"non ha un numero\n * di telefono\"). Shown under the name and read on the picker trigger.\n * Ignored unless `disabled`.\n */\n reason?: string;\n /**\n * The operator was deleted. Hidden, unless they are a picker's current\n * value (e.g. an item still assigned to them); once changed they are gone\n * from that picker. Never picked or seeded as the first operator.\n */\n deleted?: boolean;\n}\n\n/** One patient-side signer row in the submission. */\nexport interface SignerRequest {\n signerId: string;\n /** In `channelMode: 'batch'` every row carries the batch channel. */\n channel: SignatureChannel;\n /**\n * Only meaningful when `channel` is `'on-device'`. In batch mode it is set\n * on the main signer (the first row) only: the batch's \"Do not require OTP\n * from the patient\" (platform `doesNotRequireOtp`). In required documents\n * mode the main signer always carries it on this device.\n */\n skipOtp?: boolean;\n}\n\n/** Payload handed to `onRequestSignature`. */\nexport interface SignatureRequestSubmission {\n /**\n * `null` when the counter-signing operator is left unassigned. In required\n * documents mode: the first assigned operator in list order (or `null`),\n * for hosts that still need one operator; `operatorAssignments` is the\n * full picture.\n */\n operatorId: string | null;\n /**\n * How the operator's counter-sign request is delivered. `null` while the\n * operator is unassigned. Defaults to the operator's own system-defined\n * channel unless explicitly changed in the modal. Always `null` in\n * required documents mode: see `operatorChannels`.\n */\n operatorChannel: OperatorChannel | null;\n /** 1..N signers; on-device signers sign sequentially in this order. */\n signers: SignerRequest[];\n /**\n * `channelMode: 'batch'` only: the one channel the whole roster goes out\n * on (platform `signMode`), the same value as every `signers[].channel`.\n * Absent per signer, and when the patient does not sign.\n */\n signMode?: SignatureChannel;\n /**\n * Required documents mode with `showOperatorChannels` only: the operator's\n * channel per item id, for every item with an assigned operator (items on\n * Assign later have none).\n */\n operatorChannels?: Record<string, OperatorChannel>;\n /**\n * Required documents mode only: the operator per listed item id, for every\n * item that `requiresOperator`; `null` means \"Assign later\". Absent in the\n * single-document form.\n */\n operatorAssignments?: Record<string, string | null>;\n /**\n * Required documents mode only: the ids of the items in this batch (the\n * ones still to sign), in list order. Absent in the single-document form.\n */\n requiredItemIds?: string[];\n}\n\n/** One server-issued signing link for a signer on the Via QR channel. */\nexport interface SignatureQrCode {\n /** The roster signer this link belongs to (`SignerRequest.signerId`). */\n signerId: string;\n /** The signing link, encoded byte-for-byte. The kit never builds it. */\n url: string;\n /**\n * When the link stops working: a `Date` or an ISO 8601 string, formatted\n * in the active locale and the browser's time zone. Today shows the time\n * alone; any other day adds the date. An unparseable value hides the line.\n */\n expiresAt: Date | string;\n}\n\nexport interface SignatureRequestModalProps {\n /** Controlled open state. Reopening re-seeds the form from `initial*`. */\n open: boolean;\n /**\n * Fires when the dialog requests a state change (<kbd>Esc</kbd> or the\n * footer Close button). `false` is the dismiss signal — hosts typically\n * persist a \"dismissed this session\" flag there.\n */\n onOpenChange: (open: boolean) => void;\n /**\n * Operators offered as the counter-signing signer, in host order (\"Assign\n * later\" follows them, or leads in required documents mode). `disabled`\n * shows one greyed out with its `reason`; `deleted` hides one unless it\n * is a picker's current value.\n */\n operators: OperatorOption[];\n /** Patient-side people/roles offered in each signer row. */\n signerOptions: SignerOption[];\n /**\n * Enables the \"Assign to me\" shortcut targeting this operator (\"Assign all\n * to me\" in required documents mode, which sets every item's picker).\n */\n currentOperatorId?: string;\n /** Offer an \"Assign later\" option in the operator select. Default `true`. */\n allowAssignLater?: boolean;\n /**\n * Preselected operator; `null` preselects \"Assign later\" (honoured only\n * while `allowAssignLater` — otherwise the first operator is seeded). In\n * required documents mode it seeds every item picker whose item has no\n * `initialOperatorId` of its own.\n */\n initialOperatorId?: string | null;\n /**\n * Preselected operator delivery channel. Defaults to the seeded operator's\n * system-defined `defaultChannel`. `'on-device'` is honoured only while a\n * seeded roster signer also signs on this device, unless `resolveChannels`\n * is passed: then the host decides.\n */\n initialOperatorChannel?: OperatorChannel;\n /**\n * Seed the signer roster. Defaults to the first option, on-device. Each\n * row's `channel` is read per signer; in batch mode only the first row's\n * `skipOtp` is read.\n */\n initialSigners?: SignerRequest[];\n /**\n * Cap on roster size. Default `2`. In required documents mode the roster\n * is the main signer plus at most one second signee, offered only when\n * the second signee rules allow it.\n */\n maxSigners?: number;\n /**\n * How signers get their channel, in the request form and in required\n * documents mode. `'perSigner'` (default): a channel dropdown beside each\n * signer's name. `'batch'`: one \"Signature channel\" select under the\n * signers heading for the whole roster, with one OTP waiver; every\n * `SignerRequest.channel` carries it and the submission gains `signMode`.\n */\n channelMode?: SignatureChannelMode;\n /**\n * `channelMode: 'batch'` only: the channel to start on. Omit it for\n * platform's default: e-mail, or SMS when the main signer `isPatient` and\n * can receive SMS. A channel neither the main signer nor the patient can\n * receive falls back to the first one on offer. Read when the dialog\n * opens only: in required documents mode, changing the main signer\n * returns the batch to platform's default. The channels in\n * `initialSigners` are not read in batch mode. Ignored per signer.\n */\n initialBatchChannel?: SignatureChannel;\n /**\n * Whether an operator must counter-sign. `false` drops the operator\n * section entirely and submits `operatorId: null` — a host whose document\n * does not require a counter-signature must not be asked for one. Default\n * `true`.\n */\n requireOperator?: boolean;\n /**\n * Whether the patient side signs at all. `false` drops the signer roster\n * and submits an empty `signers` array — for documents only an operator\n * signs. Default `true`. Setting BOTH this and `requireOperator` to false\n * leaves nothing to request, so the primary action stays disabled.\n */\n requirePatient?: boolean;\n /** Disables all inputs and shows the primary action as loading. */\n busy?: boolean;\n /** Consumer-translated error shown above the footer (e.g. server failure). */\n error?: string;\n /** Override the dialog title. Defaults to the `ui.*` string. */\n title?: string;\n /** Override the dialog description. Defaults to the `ui.*` string. */\n description?: string;\n /**\n * Receives the completed submission. The host closes via `onOpenChange`,\n * except when a signer chose `'qr'`: then the dialog moves to its QR step\n * and waits, so keep it open and pass `qrCodes` once the server replies\n * (or `error` to send the user back to the form).\n */\n onRequestSignature: (submission: SignatureRequestSubmission) => void;\n /**\n * Server-issued signing links, one per `'qr'` signer. While non-empty the\n * dialog shows the QR step instead of the form, one code at a time. A QR\n * signer with no entry gets an error slot. Clear it when the dialog closes,\n * and drop a server response that arrives after the close.\n */\n qrCodes?: readonly SignatureQrCode[];\n /**\n * Shows the QR step's waiting state without a submit, e.g. when the host\n * remounts the dialog mid-request. The dialog enters this state by itself\n * after a submit with a `'qr'` signer; `qrCodes` arriving ends it. A set\n * `error` always wins and shows the form, even while this stays `true`.\n */\n qrPending?: boolean;\n /**\n * Fires when the user presses Done on the QR step, before\n * `onOpenChange(false)`. Close, Esc and any other dismissal do not fire it.\n */\n onQrDone?: () => void;\n /**\n * The document's past signature requests. Passing it (even empty) adds a\n * signed versions table (Date, Signature type, Actions) at the top of the\n * form, on the same screen, as on platform. Rows show newest first by\n * `createdAt`; records with the same or an unparseable date keep the host\n * order. An empty array shows one line saying there are no signed\n * versions. Omit it (and `signaturesLoading`) for the plain form.\n */\n signatures?: readonly SignatureRecord[];\n /**\n * Shows the signed versions table's loading state (skeleton rows). Also\n * adds the table while `signatures` is still undefined.\n */\n signaturesLoading?: boolean;\n /**\n * Show each row's legal level (simple or advanced). Default `true`. Pass\n * `false` where the level does not apply, e.g. for German practices.\n */\n showLegalLevel?: boolean;\n /** Row action \"View\". The button shows only when this is passed. */\n onViewSignature?: (id: string) => void;\n /**\n * Row action \"Download\". The button shows only when this is passed. It is\n * a menu (full or anonymised) when the record `hasAnonymisedVersion`,\n * otherwise a button that asks for `'full'`.\n */\n onDownloadSignature?: (id: string, version: SignatureDownloadVersion) => void;\n /**\n * Row action \"Share\", a menu of link, e-mail and WhatsApp. The button\n * shows only when this is passed. The host does the sharing.\n */\n onShareSignature?: (id: string, via: SignatureShareTarget) => void;\n /**\n * The share targets for rows whose record has no `shareTargets` of its\n * own. Default: link, e-mail and WhatsApp. An empty list hides Share.\n */\n signatureShareTargets?: readonly SignatureShareTarget[];\n /**\n * Row action \"Delete\". The button shows only when this is passed. It asks\n * for confirmation first; this fires only on confirm. The host deletes and\n * drops the record from `signatures`.\n */\n onDeleteSignature?: (id: string) => void;\n /**\n * The host's channel rules, in place of the built-in one (the operator may\n * sign on this device only while a patient signer does). Called with the\n * choices after every channel change, and when the dialog opens; the\n * modal uses the channels it returns, clamped to what is offered. Also\n * called while rendering, with `changed: null`, to read the available\n * channels, so it must be pure. Omit it to keep the built-in rule.\n */\n resolveChannels?: (\n draft: SignatureChannelDraft,\n ) => SignatureChannelResolution;\n /**\n * Required documents mode: every outstanding document and anamnesis\n * interview for one patient, signed in one batch. Passing it (even empty)\n * replaces the single operator row with one picker per item that\n * `requiresOperator`, seeded from the item's `initialOperatorId`, else the\n * modal's `initialOperatorId`. Fully signed items are left out; when none\n * is left the dialog shows the `'allSigned'` outcome. The roster applies\n * to the whole batch, each signer on their own channel, or on one channel\n * with `channelMode: 'batch'`. A second roster row (the second signee) is\n * offered only when every listed item is a document with\n * `canCarrySecondary`, the main signer's channel (the batch's, or their\n * row's) is on this device and the main signer is not `isPatient`.\n * `signatures`, `requireOperator` and `requirePatient` do not apply. The\n * submission gains `operatorAssignments` and `requiredItemIds`.\n */\n requiredItems?: readonly RequiredSignatureItem[];\n /**\n * Shows required documents mode loading (skeleton rows). Also enters the\n * mode while `requiredItems` is still undefined.\n */\n requiredItemsLoading?: boolean;\n /**\n * Required documents mode: shows each item's operator channel (SMS,\n * e-mail, on this device) beside its operator picker, starting on the\n * chosen operator's `defaultChannel` and following a new operator, and\n * hides the note that each operator's settings decide. The submission\n * gains `operatorChannels`. Default `false`.\n */\n showOperatorChannels?: boolean;\n /**\n * A final screen in place of any other view, with a Close action:\n * `'linkSent'` after a request sent by link, `'allSigned'` when nothing is\n * left to sign, `'creditsExhausted'` when the practice has no electronic\n * signature documents left. The host sets and clears it; reopening does\n * not clear it.\n */\n outcome?: SignatureRequestOutcome;\n /**\n * \"Buy more\" on the `'creditsExhausted'` outcome. The button shows only\n * when this is passed; the host navigates to the purchase page.\n */\n onBuyMoreSignatures?: () => void;\n /**\n * \"Cancel\" on the `'creditsExhausted'` outcome (platform's Annulla). The\n * button shows only when this is passed. It returns the dialog to the view\n * under the outcome (the form) by itself, then calls this so the host\n * clears `outcome`. Clear it here: the modal shows the outcome again only\n * when the prop changes, or on reopen.\n */\n onOutcomeCancel?: () => void;\n /**\n * Required documents mode: a link-style \"Add signatory\" under the Patient\n * signers heading while the patient has no registered signee (no\n * `signerOptions` entry without `isPatient`), as on platform. The host\n * opens its own create-signee flow and passes the new person in\n * `signerOptions`. Hidden when omitted, and in the single-document form.\n */\n onAddSignee?: () => void;\n /**\n * Extra attributes for the portaled dialog surface (e.g. `dir`/`lang`\n * when the host pins a locale below `<html>`, or a test id).\n */\n contentProps?: ComponentPropsWithoutRef<'div'>;\n}\n\n/** Canonical channel display order; per-signer availability filters this. */\nconst CHANNEL_ORDER: SignatureChannel[] = [\n 'sms',\n 'email',\n 'whatsapp',\n 'on-device',\n 'qr',\n];\n\n/** Stable id of the batch channel select in required documents mode. */\nconst BATCH_CHANNEL_ID = 'signature-request-batch-channel';\n\n/** Why the second signee is withheld, as the visible line under the heading. */\nconst SECOND_SIGNEE_HINTS: Record<SecondSigneeBlock, string> = {\n anamnesis: 'signatureRequest.secondSigneeUnavailableAnamnesis',\n documents: 'signatureRequest.secondSigneeUnavailableDocuments',\n patient: 'signatureRequest.secondSigneeUnavailablePatient',\n channel: 'signatureRequest.secondSigneeUnavailableChannel',\n};\n\n/** A second signee's validation message, under their row. */\nconst SECOND_SIGNEE_ISSUES: Record<SecondSigneeIssue, string> = {\n sameAsPrimary: 'signatureRequest.secondSigneeSameAsPrimary',\n unknownSignee: 'signatureRequest.secondSigneeUnknown',\n missingPhone: 'signatureRequest.secondSigneeMissingPhone',\n missingEmail: 'signatureRequest.secondSigneeMissingEmail',\n};\n\n/** Expiry line for a QR code: time alone reads as \"today\", so any other day\n * also shows the date. `null` for an unparseable value. */\nfunction formatQrExpiry(\n expiresAt: Date | string,\n locale: string,\n t: TFunction,\n): string | null {\n const date = expiresAt instanceof Date ? expiresAt : new Date(expiresAt);\n if (Number.isNaN(date.getTime())) return null;\n const time = { hour: '2-digit', minute: '2-digit' } as const;\n if (date.toDateString() === new Date().toDateString()) {\n return t('signatureRequest.qrExpiresAt', {\n time: new Intl.DateTimeFormat(locale, time).format(date),\n });\n }\n return t('signatureRequest.qrExpiresOn', {\n dateTime: new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'short',\n year: 'numeric',\n ...time,\n }).format(date),\n });\n}\n\n/** Internal roster row — `rowId` keys the DOM so editing a row's person\n * never remounts the row (which would drop keyboard focus). */\ninterface RosterRow extends SignerRequest {\n rowId: number;\n}\n\nfunction labelFor(options: SignerOption[], value: string): string {\n return options.find((option) => option.value === value)?.label ?? '';\n}\n\nexport const SignatureRequestModal = forwardRef<\n HTMLDivElement,\n SignatureRequestModalProps\n>(\n (\n {\n open,\n onOpenChange,\n operators,\n signerOptions,\n currentOperatorId,\n allowAssignLater = true,\n requireOperator = true,\n requirePatient = true,\n initialOperatorId,\n initialOperatorChannel,\n initialSigners,\n maxSigners = 2,\n channelMode = 'perSigner',\n initialBatchChannel,\n busy = false,\n error,\n title,\n description,\n onRequestSignature,\n qrCodes,\n qrPending = false,\n onQrDone,\n signatures,\n signaturesLoading = false,\n showLegalLevel = true,\n onViewSignature,\n onDownloadSignature,\n onShareSignature,\n signatureShareTargets,\n onDeleteSignature,\n resolveChannels,\n requiredItems,\n requiredItemsLoading = false,\n showOperatorChannels = false,\n outcome,\n onBuyMoreSignatures,\n onOutcomeCancel,\n onAddSignee,\n contentProps,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n\n const nextRowId = useRef(0);\n const addButtonRef = useRef<HTMLButtonElement>(null);\n const titleRef = useRef<HTMLHeadingElement>(null);\n const qrDescriptionId = useId();\n const qrCountId = useId();\n const outcomeDescriptionId = useId();\n const secondSigneeHintId = useId();\n const operatorHintId = useId();\n const signerChannelHintId = useId();\n const batchChannelHintId = useId();\n const secondSigneeLabelId = useId();\n const secondSigneeIssueId = useId();\n const otpWarningId = useId();\n\n // Required documents mode: the batch replaces the single operator row,\n // the patient always signs, and the signatures list does not apply.\n const requiredMode = requiredItems !== undefined || requiredItemsLoading;\n const listedItems = requiredItems ? itemsStillToSign(requiredItems) : [];\n const withOperator = requireOperator && !requiredMode;\n const withPatient = requirePatient || requiredMode;\n // One channel for the whole roster instead of one per signer.\n const batchMode = channelMode === 'batch';\n\n const isPatientId = (signerId: string | undefined): boolean =>\n signerOptions.find((option) => option.value === signerId)?.isPatient ===\n true;\n // The roster cap for these rows. Required documents mode seats a second\n // signee only when the rules allow one, reading the main signer's\n // channel (the batch's, or the main row's own), and platform has one\n // second signee at most.\n const capFor = (\n rows: readonly SignerRequest[],\n batch: SignatureChannel,\n ): number => {\n if (!requiredMode) return maxSigners;\n const block = secondSigneeBlock({\n items: listedItems,\n channel: batchMode ? batch : (rows[0]?.channel ?? batch),\n primaryIsPatient: isPatientId(rows[0]?.signerId),\n });\n return block === null ? Math.min(maxSigners, 2) : 1;\n };\n\n // Cancel on an outcome hides the host's outcome until the prop changes\n // or the dialog reopens. Adjusted during render, so no frame shows it.\n const [outcomeCancelled, setOutcomeCancelled] = useState(false);\n const [prevOutcome, setPrevOutcome] = useState(outcome);\n if (outcome !== prevOutcome) {\n setPrevOutcome(outcome);\n setOutcomeCancelled(false);\n }\n\n // Nothing left to sign is an outcome of its own; a host outcome wins.\n const shownOutcome: SignatureRequestOutcome | undefined =\n (outcomeCancelled ? undefined : outcome) ??\n (requiredItems !== undefined &&\n !requiredItemsLoading &&\n listedItems.length === 0\n ? 'allSigned'\n : undefined);\n const outcomeText = shownOutcome\n ? outcomeCopy(shownOutcome, t, { required: requiredMode })\n : null;\n\n // A signer's greyed-out channels, each with its host-translated reason.\n const unavailableFor = (signerId: string): Map<SignatureChannel, string> =>\n new Map(\n (\n signerOptions.find((option) => option.value === signerId)\n ?.unavailableChannels ?? []\n ).map(({ channel, reason }) => [channel, reason]),\n );\n\n // Channels a signer's dropdown lists — the person's `availableChannels`\n // filtered into canonical order; omitted/empty means every channel. A\n // host rule's list narrows it, unless nothing selectable would be left.\n // Unavailable channels stay listed (greyed out) and are never selectable.\n const listedChannelsFor = (\n signerId: string,\n hostAllowed?: SignatureChannel[],\n ): SignatureChannel[] => {\n const allowed = signerOptions.find(\n (option) => option.value === signerId,\n )?.availableChannels;\n const own =\n allowed && allowed.length > 0\n ? CHANNEL_ORDER.filter((channel) => allowed.includes(channel))\n : CHANNEL_ORDER;\n if (!hostAllowed) return own;\n const unavailable = unavailableFor(signerId);\n const narrowed = own.filter((channel) => hostAllowed.includes(channel));\n return narrowed.some((channel) => !unavailable.has(channel))\n ? narrowed\n : own;\n };\n\n // Channels a given signer can actually be given: listed and not greyed\n // out. Empty when every listed channel is unavailable.\n const channelsFor = (\n signerId: string,\n hostAllowed?: SignatureChannel[],\n ): SignatureChannel[] => {\n const unavailable = unavailableFor(signerId);\n return listedChannelsFor(signerId, hostAllowed).filter(\n (channel) => !unavailable.has(channel),\n );\n };\n\n // Operator channels a host rule offers; all three without one.\n const operatorChannelsFrom = (\n resolution: SignatureChannelResolution | undefined,\n ): readonly OperatorChannel[] => {\n const allowed = resolution?.operatorAvailableChannels;\n return allowed && allowed.length > 0\n ? OPERATOR_CHANNELS.filter((channel) => allowed.includes(channel))\n : OPERATOR_CHANNELS;\n };\n\n // First available channel for a signer, preferring `preferred` when offered.\n // A signer with none keeps `preferred`: that row blocks the request.\n const resolveChannel = (\n signerId: string,\n preferred: SignatureChannel,\n ): SignatureChannel => {\n const available = channelsFor(signerId);\n return available.includes(preferred)\n ? preferred\n : (available[0] ?? preferred);\n };\n\n // Required documents mode: one channel for the whole batch. As on\n // platform, a channel is on offer when the main signer OR the patient\n // can receive it; on this device always is. Greyed out, with a reason,\n // only when neither can.\n const patientOption = signerOptions.find(\n (option) => option.isPatient === true,\n );\n const batchPeopleFor = (primaryId: string | undefined): string[] => {\n if (primaryId === undefined) return [];\n return patientOption && patientOption.value !== primaryId\n ? [primaryId, patientOption.value]\n : [primaryId];\n };\n const batchUnavailableFor = (\n primaryId: string | undefined,\n ): Map<SignatureChannel, string> => {\n const people = batchPeopleFor(primaryId);\n const unavailable = new Map<SignatureChannel, string>();\n for (const channel of CHANNEL_ORDER) {\n if (channel === 'on-device') continue;\n if (people.some((id) => channelsFor(id).includes(channel))) continue;\n const reason = people\n .map((id) => unavailableFor(id).get(channel))\n .find((text) => text !== undefined);\n if (reason !== undefined) unavailable.set(channel, reason);\n }\n return unavailable;\n };\n const batchListedFor = (\n primaryId: string | undefined,\n hostAllowed?: SignatureChannel[],\n ): SignatureChannel[] => {\n if (primaryId === undefined) return CHANNEL_ORDER;\n const people = batchPeopleFor(primaryId);\n const own = CHANNEL_ORDER.filter((channel) =>\n people.some((id) => listedChannelsFor(id).includes(channel)),\n );\n // A host rule's list narrows it, unless nothing selectable is left.\n const unavailable = batchUnavailableFor(primaryId);\n const narrowed = hostAllowed\n ? own.filter((channel) => hostAllowed.includes(channel))\n : own;\n const listed = narrowed.some((channel) => !unavailable.has(channel))\n ? narrowed\n : own;\n return CHANNEL_ORDER.filter(\n (channel) => channel === 'on-device' || listed.includes(channel),\n );\n };\n const batchChannelsFor = (\n primaryId: string | undefined,\n hostAllowed?: SignatureChannel[],\n ): SignatureChannel[] => {\n const unavailable = batchUnavailableFor(primaryId);\n return batchListedFor(primaryId, hostAllowed).filter(\n (channel) => !unavailable.has(channel),\n );\n };\n // Platform's default with the unified flow on: e-mail, but SMS when the\n // patient signs and can receive it. Never empty: on this device is left.\n // `initialBatchChannel` applies when the dialog opens, not when the main\n // signer changes (platform's _onSigneeIdChanged re-reads its default).\n const seedBatchChannel = (\n primaryId: string | undefined,\n withInitial = true,\n ): SignatureChannel => {\n const available = batchChannelsFor(primaryId);\n const preferred =\n (withInitial ? initialBatchChannel : undefined) ??\n (isPatientId(primaryId) && available.includes('sms') ? 'sms' : 'email');\n return available.includes(preferred) ? preferred : available[0];\n };\n\n // The first operator a user could pick: greyed-out and deleted ones are\n // never seeded in their place.\n const firstOperator = operators.find(\n (option) => option.disabled !== true && option.deleted !== true,\n )?.value;\n const resolveOperatorSeed = (seed: string | null | undefined) => {\n if (seed === null) {\n return allowAssignLater\n ? ASSIGN_LATER\n : (firstOperator ?? ASSIGN_LATER);\n }\n return seed ?? firstOperator ?? (allowAssignLater ? ASSIGN_LATER : '');\n };\n const seedOperator = () => resolveOperatorSeed(initialOperatorId);\n const seedRows = (): RosterRow[] => {\n const seed =\n initialSigners && initialSigners.length > 0\n ? initialSigners\n : signerOptions.length > 0\n ? [\n {\n signerId: signerOptions[0].value,\n channel: resolveChannel(signerOptions[0].value, 'on-device'),\n },\n ]\n : [];\n return seed.map((signer) => {\n // Clamp a seeded channel the signer cannot receive (e.g. `'qr'` on a\n // signer whose `availableChannels` excludes it), so a row never\n // renders with no channel selected.\n const channel = resolveChannel(signer.signerId, signer.channel);\n const { skipOtp, ...rest } = signer;\n return {\n ...rest,\n channel,\n ...(channel === 'on-device' && skipOtp !== undefined\n ? { skipOtp }\n : {}),\n rowId: nextRowId.current++,\n };\n });\n };\n\n // System-defined default for one operator — the channel their own\n // settings resolve to. On this device only where it is offered (the\n // built-in rule passes whether a patient signs here), else e-mail.\n const operatorDefaultChannel = (\n operatorId: string,\n onDeviceOffered = true,\n ): OperatorChannel => {\n const setting =\n operators.find((option) => option.value === operatorId)\n ?.defaultChannel ?? 'email';\n return setting === 'on-device' && !onDeviceOffered ? 'email' : setting;\n };\n\n // Seed clamp: `'on-device'` is honoured only when the seeded roster\n // makes it available, so the option is never checked-and-disabled, not\n // even for a frame.\n const seedOperatorChannel = (\n operatorId: string,\n onDeviceSigner: boolean,\n ): OperatorChannel => {\n if (initialOperatorChannel === 'on-device') {\n return onDeviceSigner\n ? 'on-device'\n : operatorDefaultChannel(operatorId, false);\n }\n return (\n initialOperatorChannel ??\n operatorDefaultChannel(operatorId, onDeviceSigner)\n );\n };\n\n // The operator's channel from a host rule, clamped to what it offers:\n // the wanted channel, else the operator's default, else the first.\n const clampOperatorChannel = (\n resolution: SignatureChannelResolution,\n operatorId: string,\n channel: OperatorChannel,\n ): OperatorChannel => {\n const offered = operatorChannelsFrom(resolution);\n const wanted = resolution.operatorChannel ?? channel;\n const fallback = operatorDefaultChannel(operatorId);\n return offered.includes(wanted)\n ? wanted\n : offered.includes(fallback)\n ? fallback\n : offered[0];\n };\n\n /* ---- Host channel rules (`resolveChannels`) --------------------- */\n const draftOf = (\n operatorId: string,\n channel: OperatorChannel,\n rows: RosterRow[],\n changed: SignatureChannelDraft['changed'],\n // Batch mode: every signer's channel is the batch's.\n batch: SignatureChannel = 'on-device',\n ): SignatureChannelDraft => {\n const hasOperator =\n withOperator && operatorId !== ASSIGN_LATER && operatorId !== '';\n const visible = requiredMode ? rows.slice(0, capFor(rows, batch)) : rows;\n const signerUnavailableChannels: Record<string, SignatureChannel[]> = {};\n if (withPatient) {\n for (const row of visible) {\n const unavailable = [...unavailableFor(row.signerId).keys()];\n if (unavailable.length > 0) {\n signerUnavailableChannels[row.signerId] = unavailable;\n }\n }\n }\n return {\n operatorId: hasOperator ? operatorId : null,\n operatorChannel: hasOperator ? channel : null,\n signers: withPatient\n ? visible.map(({ rowId: _rowId, ...signer }) =>\n batchMode\n ? { signerId: signer.signerId, channel: batch }\n : signer,\n )\n : [],\n changed,\n ...(Object.keys(signerUnavailableChannels).length > 0\n ? { signerUnavailableChannels }\n : {}),\n };\n };\n\n // Runs the host rule over a draft and applies what it returns, clamped\n // to the channels on offer, so no dropdown is ever left without a value.\n const resolveWithHost = (\n rule: NonNullable<SignatureRequestModalProps['resolveChannels']>,\n operatorId: string,\n channel: OperatorChannel,\n rows: RosterRow[],\n changed: SignatureChannelDraft['changed'],\n ): { operatorChannel: OperatorChannel; rows: RosterRow[] } => {\n const draft = draftOf(operatorId, channel, rows, changed);\n const resolution = rule(draft);\n const nextChannel =\n draft.operatorChannel === null\n ? channel\n : clampOperatorChannel(resolution, operatorId, channel);\n const visibleCount = draft.signers.length;\n const nextRows = rows.map((row, index) => {\n if (index >= visibleCount) return row;\n const offered = channelsFor(\n row.signerId,\n resolution.signerAvailableChannels?.[row.signerId],\n );\n const wanted =\n resolution.signers.find((signer) => signer.signerId === row.signerId)\n ?.channel ?? row.channel;\n // Nothing selectable: keep the channel, the row blocks the request.\n const next = offered.includes(wanted)\n ? wanted\n : (offered[0] ?? row.channel);\n return next === row.channel\n ? row\n : { ...row, channel: next, skipOtp: undefined };\n });\n return { operatorChannel: nextChannel, rows: nextRows };\n };\n\n // Batch mode: the batch channel after the host rule, clamped to what the\n // main signer is offered, and the operator's channel the rule returns\n // (only the request form has an operator row). With no rule, just the\n // clamp.\n const resolveBatch = (\n rows: RosterRow[],\n channel: SignatureChannel,\n changed: SignatureChannelDraft['changed'],\n operatorId = '',\n opChannel: OperatorChannel = 'email',\n ): { batch: SignatureChannel; operatorChannel: OperatorChannel } => {\n const primaryId = rows[0]?.signerId;\n if (!resolveChannels) {\n const offered = batchChannelsFor(primaryId);\n return {\n batch: offered.includes(channel) ? channel : offered[0],\n operatorChannel: opChannel,\n };\n }\n const draft = draftOf(operatorId, opChannel, rows, changed, channel);\n const resolution = resolveChannels(draft);\n const offered = batchChannelsFor(\n primaryId,\n primaryId === undefined\n ? undefined\n : resolution.signerAvailableChannels?.[primaryId],\n );\n const wanted =\n resolution.signers.find((signer) => signer.signerId === primaryId)\n ?.channel ?? channel;\n return {\n batch: offered.includes(wanted)\n ? wanted\n : offered.includes(channel)\n ? channel\n : offered[0],\n operatorChannel:\n draft.operatorChannel === null\n ? opChannel\n : clampOperatorChannel(resolution, operatorId, opChannel),\n };\n };\n\n // The whole form seed: operator, roster, operator channel, and in batch\n // mode the batch channel and OTP waiver.\n const seedForm = (): {\n operator: string;\n rows: RosterRow[];\n operatorChannel: OperatorChannel;\n batchChannel: SignatureChannel;\n otpOverride: boolean | null;\n } => {\n const seededOperator = seedOperator();\n const seededRows = seedRows();\n if (batchMode) {\n const seeded = resolveBatch(\n seededRows,\n seedBatchChannel(seededRows[0]?.signerId),\n null,\n seededOperator,\n initialOperatorChannel ?? operatorDefaultChannel(seededOperator),\n );\n return {\n operator: seededOperator,\n rows: seededRows,\n // Required documents mode has no operator row: nothing reads it.\n operatorChannel: resolveChannels\n ? seeded.operatorChannel\n : seedOperatorChannel(\n seededOperator,\n seededRows.length > 0 && seeded.batch === 'on-device',\n ),\n batchChannel: seeded.batch,\n otpOverride: initialSigners?.[0]?.skipOtp ?? null,\n };\n }\n const noBatch = { batchChannel: 'on-device' as const, otpOverride: null };\n if (!resolveChannels) {\n return {\n operator: seededOperator,\n rows: seededRows,\n operatorChannel: seedOperatorChannel(\n seededOperator,\n seededRows.some((signer) => signer.channel === 'on-device'),\n ),\n ...noBatch,\n };\n }\n const resolved = resolveWithHost(\n resolveChannels,\n seededOperator,\n initialOperatorChannel ?? operatorDefaultChannel(seededOperator),\n seededRows,\n null,\n );\n return {\n operator: seededOperator,\n rows: resolved.rows,\n operatorChannel: resolved.operatorChannel,\n ...noBatch,\n };\n };\n\n const [formSeed] = useState(seedForm);\n const [operator, setOperator] = useState<string>(formSeed.operator);\n const [rosterRows, setSigners] = useState<RosterRow[]>(formSeed.rows);\n const [operatorChannel, setOperatorChannel] = useState<OperatorChannel>(\n formSeed.operatorChannel,\n );\n // Required documents mode: the batch channel, and the user's own OTP\n // waiver choice (`null` until they pick, so it follows the main signer).\n const [batchChannel, setBatchChannel] = useState<SignatureChannel>(\n formSeed.batchChannel,\n );\n const [otpOverride, setOtpOverride] = useState<boolean | null>(\n formSeed.otpOverride,\n );\n const rosterCap = capFor(rosterRows, batchChannel);\n // Rows past the cap stay in state but are neither shown nor submitted,\n // so a batch that later allows a second signee gets the row back.\n const signers = requiredMode ? rosterRows.slice(0, rosterCap) : rosterRows;\n\n // Per-item operator picks the user made. Unpicked items read their seed,\n // so items that arrive after the dialog opened are seeded too.\n const [assignmentOverrides, setAssignmentOverrides] = useState<\n Record<string, string>\n >({});\n const assignments: Record<string, string> = {};\n for (const item of listedItems) {\n if (!needsOperatorPick(item)) continue;\n assignments[item.id] =\n assignmentOverrides[item.id] ??\n resolveOperatorSeed(\n item.initialOperatorId !== undefined\n ? item.initialOperatorId\n : initialOperatorId,\n );\n }\n // `showOperatorChannels`: the channel picks the user made, per item. A\n // pick holds until that item's operator changes; otherwise the channel\n // follows the assigned operator's own settings.\n const [operatorChannelOverrides, setOperatorChannelOverrides] = useState<\n Record<string, OperatorChannel>\n >({});\n const itemOperatorChannels: Record<string, OperatorChannel> = {};\n for (const item of listedItems) {\n const value = assignments[item.id];\n if (value === undefined || value === ASSIGN_LATER || value === '') {\n continue;\n }\n itemOperatorChannels[item.id] =\n operatorChannelOverrides[item.id] ?? operatorDefaultChannel(value);\n }\n const dropChannelPicks = (itemIds: readonly string[]) => {\n if (itemIds.length === 0) return;\n setOperatorChannelOverrides((current) =>\n Object.fromEntries(\n Object.entries(current).filter(([id]) => !itemIds.includes(id)),\n ),\n );\n };\n const assignItem = (itemId: string, value: string) => {\n if (assignments[itemId] !== value) dropChannelPicks([itemId]);\n setAssignmentOverrides((current) => ({ ...current, [itemId]: value }));\n };\n const assignAllToMe = () => {\n if (currentOperatorId === undefined) return;\n dropChannelPicks(\n listedItems\n .filter(\n (item) =>\n needsOperatorPick(item) &&\n assignments[item.id] !== currentOperatorId,\n )\n .map((item) => item.id),\n );\n setAssignmentOverrides((current) => {\n const next = { ...current };\n for (const item of listedItems) {\n if (needsOperatorPick(item)) next[item.id] = currentOperatorId;\n }\n return next;\n });\n };\n // Feeds the sr-only live region announcing the automatic channel\n // fallback below; any explicit choice clears it.\n const [revertedTo, setRevertedTo] = useState<OperatorChannel | null>(null);\n // The same region's message when a host rule moves a channel the user\n // did not touch.\n const [hostAnnouncement, setHostAnnouncement] = useState<string | null>(\n null,\n );\n // Set by a submit with a `'qr'` signer: the dialog waits in its QR step\n // for the host's `qrCodes`. `qrIndex` is the code on screen.\n const [awaitingQr, setAwaitingQr] = useState(false);\n const [qrIndex, setQrIndex] = useState(0);\n // The signed versions table tops the form only when the host provides it.\n const hasHistory =\n !requiredMode && (signatures !== undefined || signaturesLoading);\n\n // Reset the step during render on reopen, not in an effect: the first\n // committed render (and Radix's open auto-focus) must see it.\n const [prevOpen, setPrevOpen] = useState(open);\n if (open !== prevOpen) {\n setPrevOpen(open);\n if (open) {\n setAwaitingQr(false);\n setQrIndex(0);\n setOutcomeCancelled(false);\n }\n }\n\n // Re-seed the form whenever the host reopens the (still-mounted) modal,\n // so a previous request's choices never leak into the next one.\n const wasOpen = useRef(open);\n useEffect(() => {\n if (open && !wasOpen.current) {\n const next = seedForm();\n setOperator(next.operator);\n setSigners(next.rows);\n setOperatorChannel(next.operatorChannel);\n setBatchChannel(next.batchChannel);\n setOtpOverride(next.otpOverride);\n setRevertedTo(null);\n setHostAnnouncement(null);\n setAssignmentOverrides({});\n setOperatorChannelOverrides({});\n }\n wasOpen.current = open;\n // The seeds intentionally read the render-time props on the rising\n // edge only — prop changes while open (or closed) don't reset input.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n // Operator on-device signing piggybacks on a patient handover: it is\n // offerable only while a roster signer signs on this device, and falls\n // back to the operator's system default the moment the last on-device\n // row leaves. The fallback is announced via the live region — the\n // trigger lives in the roster section, far from the radio it moves.\n // A host rule (`resolveChannels`) replaces all of this.\n // A signer with no available channel counts for nothing: their row\n // blocks the request.\n const hasNoChannel = (signerId: string) =>\n channelsFor(signerId).length === 0;\n // Batch mode reads the batch channel, which always has a signer to\n // carry it.\n const anySignerOnDevice = batchMode\n ? signers.length > 0 && batchChannel === 'on-device'\n : signers.some(\n (signer) =>\n signer.channel === 'on-device' && !hasNoChannel(signer.signerId),\n );\n const hostRule = resolveChannels !== undefined;\n useEffect(() => {\n // Only the request form has an operator row.\n if (hostRule || !withOperator) return;\n if (operatorChannel === 'on-device' && !anySignerOnDevice) {\n const fallback = operatorDefaultChannel(operator, false);\n setOperatorChannel(fallback);\n setRevertedTo(fallback);\n }\n // `operatorDefaultChannel` reads the render-time `operators` prop.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [operatorChannel, anySignerOnDevice, operator, hostRule, withOperator]);\n\n // Every operator picker's options: greyed-out operators with their\n // reason, and deleted ones kept for pickers that still hold them.\n // \"Assign later\" comes first in required documents mode, as on platform,\n // and last in the request form, as it always has.\n const assignLaterOptions: OperatorPickerOption[] = allowAssignLater\n ? [{ value: ASSIGN_LATER, label: t('signatureRequest.assignLater') }]\n : [];\n const operatorEntries: OperatorPickerOption[] = operators.map(\n ({ value, label, disabled, reason, deleted }) => ({\n value,\n label,\n ...(disabled === true\n ? { disabled: true, ...(reason ? { description: reason } : {}) }\n : {}),\n ...(deleted === true ? { deleted: true } : {}),\n }),\n );\n const operatorPickerList: OperatorPickerOption[] = requiredMode\n ? [...assignLaterOptions, ...operatorEntries]\n : [...operatorEntries, ...assignLaterOptions];\n const operatorHint = operatorReasonsHint(operatorPickerList, i18n.language);\n const operatorPickerHintId = useId();\n const isUnassigned = operator === ASSIGN_LATER;\n\n const channelMeta = useChannelMeta();\n\n // The host rule's offer for the current choices.\n const hostView = resolveChannels\n ? resolveChannels(\n draftOf(operator, operatorChannel, rosterRows, null, batchChannel),\n )\n : undefined;\n\n // Applies a change through the host rule, and announces any channel the\n // rule moved that the user did not touch: it may sit in another section.\n // `extra` joins the announcement (e.g. a second signee hidden or\n // cleared). Batch mode runs the batch through the rule instead.\n const commitWithHost = (\n operatorId: string,\n channel: OperatorChannel,\n rows: RosterRow[],\n changed: 'operator' | 'signers',\n extra: readonly string[] = [],\n ) => {\n if (!resolveChannels) return;\n if (batchMode) {\n commitBatch(rows, batchChannel, {\n operatorId,\n opChannel: channel,\n changed,\n });\n return;\n }\n const resolved = resolveWithHost(\n resolveChannels,\n operatorId,\n channel,\n rows,\n changed,\n );\n setOperatorChannel(resolved.operatorChannel);\n setSigners(resolved.rows);\n setRevertedTo(null);\n const messages: string[] = [];\n const hasOperator =\n withOperator && operatorId !== ASSIGN_LATER && operatorId !== '';\n // `channel` and `rows` already hold the user's own change, so any\n // difference is the rule's doing, whichever section changed.\n if (hasOperator && resolved.operatorChannel !== channel) {\n messages.push(\n t('signatureRequest.operatorChannelChanged', {\n channel: channelMeta[resolved.operatorChannel].label,\n }),\n );\n }\n resolved.rows.forEach((row, index) => {\n if (row.channel === rows[index].channel) return;\n messages.push(\n t('signatureRequest.signerChannelChanged', {\n name: labelFor(signerOptions, row.signerId),\n channel: channelMeta[row.channel].label,\n }),\n );\n });\n messages.push(...extra);\n setHostAnnouncement(messages.length > 0 ? messages.join(' ') : null);\n };\n\n // Batch mode: applies a roster, batch channel or operator change through\n // the host rule. In required documents mode, as platform's\n // _onSigneeIdChanged, a new main signer clears the second signee and\n // returns the batch to its default channel, and a batch that stops\n // allowing a second signee only hides them: they come back with it.\n // What the user did not pick is announced.\n const commitBatch = (\n rows: RosterRow[],\n channel: SignatureChannel,\n {\n primaryChanged = false,\n userChannel = false,\n operatorId = operator,\n opChannel = operatorChannel,\n changed = 'signers',\n }: {\n primaryChanged?: boolean;\n userChannel?: boolean;\n operatorId?: string;\n opChannel?: OperatorChannel;\n changed?: 'operator' | 'signers';\n } = {},\n ) => {\n const resolved = resolveBatch(\n rows,\n primaryChanged ? seedBatchChannel(rows[0]?.signerId, false) : channel,\n changed,\n operatorId,\n opChannel,\n );\n const next = resolved.batch;\n const clear = requiredMode && rows.length > 1 && primaryChanged;\n const messages: string[] = [];\n const hasOperator =\n withOperator && operatorId !== ASSIGN_LATER && operatorId !== '';\n if (hasOperator && resolved.operatorChannel !== opChannel) {\n messages.push(\n t('signatureRequest.operatorChannelChanged', {\n channel: channelMeta[resolved.operatorChannel].label,\n }),\n );\n }\n if (next !== (userChannel ? channel : batchChannel)) {\n messages.push(\n t('signatureRequest.signerChannelChanged', {\n name: labelFor(signerOptions, rows[0]?.signerId ?? ''),\n channel: channelMeta[next].label,\n }),\n );\n }\n // Only a second signee the user could see.\n if (requiredMode && signers.length > 1) {\n const block = secondSigneeBlock({\n items: listedItems,\n channel: next,\n primaryIsPatient: isPatientId(rows[0]?.signerId),\n });\n if (clear) {\n messages.push(t('signatureRequest.secondSigneeCleared'));\n } else if (block !== null && rows.length > 1) {\n messages.push(t(SECOND_SIGNEE_HINTS[block]));\n }\n }\n setSigners(clear ? rows.slice(0, 1) : rows);\n if (withOperator) setOperatorChannel(resolved.operatorChannel);\n // As platform, the waiver re-reads its default when the channel changes.\n if (next !== batchChannel) setOtpOverride(null);\n setBatchChannel(next);\n setRevertedTo(null);\n setHostAnnouncement(messages.length > 0 ? messages.join(' ') : null);\n };\n\n // A channel that stops being available while the dialog is open (the\n // host greys it out or hides it) falls back to the first one still\n // available, through the host rule when there is one. Adjusted during\n // render, like the reopen reset above, so a greyed-out channel is never\n // shown selected. A signer with nothing available keeps their channel:\n // that row blocks the request instead. Batch mode does the same for the\n // batch channel, below.\n // The same list the select offers, host rule included.\n const batchOffered = batchChannelsFor(\n rosterRows[0]?.signerId,\n rosterRows[0] === undefined\n ? undefined\n : hostView?.signerAvailableChannels?.[rosterRows[0].signerId],\n );\n if (batchMode && !batchOffered.includes(batchChannel)) {\n commitBatch(rosterRows, batchOffered[0]);\n }\n const fallbackRows = batchMode\n ? rosterRows\n : rosterRows.map((row) => {\n const available = channelsFor(row.signerId);\n return available.length === 0 || available.includes(row.channel)\n ? row\n : { ...row, channel: available[0], skipOtp: undefined };\n });\n if (fallbackRows.some((row, index) => row !== rosterRows[index])) {\n const resolved = resolveChannels\n ? resolveWithHost(\n resolveChannels,\n operator,\n operatorChannel,\n fallbackRows,\n 'signers',\n )\n : { operatorChannel, rows: fallbackRows };\n setSigners(resolved.rows);\n setOperatorChannel(resolved.operatorChannel);\n setRevertedTo(null);\n const messages = resolved.rows\n .filter((row, index) => row.channel !== rosterRows[index].channel)\n .map((row) =>\n t('signatureRequest.signerChannelChanged', {\n name: labelFor(signerOptions, row.signerId),\n channel: channelMeta[row.channel].label,\n }),\n );\n setHostAnnouncement(messages.length > 0 ? messages.join(' ') : null);\n }\n\n const channelOption = <T extends string>(\n value: T,\n channel: SignatureChannel,\n ): SelectOption<T> => ({\n value,\n label: channelMeta[channel].label,\n startAdornment: channelMeta[channel].icon,\n });\n\n // Operator delivery — the same dropdown as the signer rows, minus\n // WhatsApp and Via QR. No \"system defined\" option: the operator's own\n // default (e-mail or SMS per their settings) arrives preselected instead.\n // On-device greys out while no patient signer signs on this device, with\n // the reason under it in the list and on the trigger for screen readers\n // (a disabled option cannot take focus).\n // A host rule offers its own list instead, with nothing greyed out.\n const onDeviceHint =\n hostRule || anySignerOnDevice\n ? undefined\n : t('signatureRequest.onDeviceUnavailableHint');\n const operatorChannelOptions: SelectOption<OperatorChannel>[] = hostRule\n ? operatorChannelsFrom(hostView).map((channel) =>\n channelOption(channel, channel),\n )\n : [\n channelOption('sms', 'sms'),\n channelOption('email', 'email'),\n {\n ...channelOption('on-device', 'on-device'),\n disabled: !anySignerOnDevice,\n description: onDeviceHint,\n },\n ];\n const channelSizer = <ChannelColumnSizer meta={channelMeta} />;\n\n const chosenIds = signers.map((signer) => signer.signerId);\n // The patient is never a second signee (platform lists signees only).\n const nextFreeOption = signerOptions.find(\n (option) =>\n !chosenIds.includes(option.value) &&\n !(requiredMode && option.isPatient === true),\n );\n const canAddSigner =\n !busy && signers.length < rosterCap && nextFreeOption !== undefined;\n\n // Why the second signee is not on offer in this batch. Only worth saying\n // when there is a second person who could have signed.\n // The platform rules read the main signer: in required documents mode,\n // and in batch mode for the batch channel and waiver.\n const primaryId =\n requiredMode || batchMode ? signers[0]?.signerId : undefined;\n const primaryIsPatient = isPatientId(primaryId);\n // The main signer's channel: the batch's, or the main row's own.\n const mainChannel: SignatureChannel = batchMode\n ? batchChannel\n : (signers[0]?.channel ?? batchChannel);\n const secondBlock = requiredMode\n ? secondSigneeBlock({\n items: listedItems,\n channel: mainChannel,\n primaryIsPatient,\n })\n : null;\n const secondSigneeHint =\n requiredMode &&\n !requiredItemsLoading &&\n listedItems.length > 0 &&\n secondBlock !== null &&\n signerOptions.length > 1\n ? t(SECOND_SIGNEE_HINTS[secondBlock])\n : null;\n // What is wrong with the second signee, shown under their row; it blocks\n // the request, as platform's validation does. It reads the second\n // signee's own channel: the batch's, or their row's.\n const secondIssue =\n requiredMode && signers.length > 1\n ? secondSigneeIssue({\n primaryId,\n secondId: signers[1].signerId,\n channel: batchMode ? batchChannel : signers[1].channel,\n options: signerOptions,\n })\n : null;\n // OTP (platform SignedDocumentsSignMode), on this device only. As\n // platform's _getDoesNotRequireOtp the waiver starts on when the PATIENT\n // cannot receive SMS, whoever signs, and is forced on when the patient\n // is the main signer and cannot. With no `isPatient` option the main\n // signer stands in for the patient. Batch mode has one waiver for the\n // batch; per signer, the main signer's row in required documents mode\n // follows these rules and every other row is the user's own choice.\n const patientSmsPossible = batchChannelsFor(\n patientOption?.value ?? primaryId,\n ).includes('sms');\n const otpForced =\n (requiredMode || batchMode) && primaryIsPatient && !patientSmsPossible;\n const batchSkipOtp =\n batchMode &&\n batchChannel === 'on-device' &&\n (otpForced || (otpOverride ?? !patientSmsPossible));\n // As platform, the batch warning shows whenever the waiver is forced or\n // on, whatever the channel.\n const batchOtpWarning =\n batchMode && signers.length > 0 && (otpForced || batchSkipOtp);\n const followsOtpRules = (index: number) => requiredMode && index === 0;\n // A signer row's waiver, per signer.\n const rowSkipOtp = (signer: SignerRequest, index: number): boolean =>\n signer.channel === 'on-device' &&\n (followsOtpRules(index)\n ? otpForced || (signer.skipOtp ?? !patientSmsPossible)\n : signer.skipOtp === true);\n const rosterVisible =\n withPatient && !(requiredMode && requiredItemsLoading);\n\n const patchSigner = (rowId: number, patch: Partial<SignerRequest>) => {\n setSigners((current) =>\n current.map((signer) =>\n signer.rowId === rowId ? { ...signer, ...patch } : signer,\n ),\n );\n };\n\n const addSigner = () => {\n if (!nextFreeOption) return;\n if (batchMode) {\n commitBatch(\n [\n ...rosterRows,\n {\n signerId: nextFreeOption.value,\n channel: batchChannel,\n rowId: nextRowId.current++,\n },\n ],\n batchChannel,\n );\n return;\n }\n // A second signee joins the main signer on this device.\n const channel = resolveChannel(\n nextFreeOption.value,\n requiredMode ? 'on-device' : 'sms',\n );\n if (resolveChannels) {\n commitWithHost(\n operator,\n operatorChannel,\n [\n ...rosterRows,\n {\n signerId: nextFreeOption.value,\n channel,\n rowId: nextRowId.current++,\n },\n ],\n 'signers',\n );\n return;\n }\n setSigners((current) => [\n ...current,\n {\n signerId: nextFreeOption.value,\n channel,\n rowId: nextRowId.current++,\n },\n ]);\n };\n\n const removeSigner = (rowId: number) => {\n // Move focus BEFORE the row (and the focused remove button) unmounts —\n // otherwise Radix's focus scope dumps focus on the dialog container.\n addButtonRef.current?.focus();\n if (batchMode) {\n commitBatch(\n rosterRows.filter((signer) => signer.rowId !== rowId),\n batchChannel,\n );\n return;\n }\n if (resolveChannels) {\n commitWithHost(\n operator,\n operatorChannel,\n rosterRows.filter((signer) => signer.rowId !== rowId),\n 'signers',\n );\n return;\n }\n setSigners((current) =>\n current.filter((signer) => signer.rowId !== rowId),\n );\n };\n\n // A signer with no available channel cannot be sent anything, so the\n // request waits, as it does with no signer at all.\n // Batch mode reads the batch channel, which always has on this device to\n // offer.\n const anySignerWithoutChannel =\n withPatient &&\n !batchMode &&\n signers.some((signer) => hasNoChannel(signer.signerId));\n const anySignerOnQr =\n withPatient &&\n (batchMode\n ? signers.length > 0 && batchChannel === 'qr'\n : signers.some((signer) => signer.channel === 'qr'));\n // The shared warning per signer; batch mode has its own\n // (`batchOtpWarning`).\n const anySignerSkipsOtp =\n !batchMode &&\n signers.some(\n (signer, index) =>\n rowSkipOtp(signer, index) && !hasNoChannel(signer.signerId),\n );\n\n // Joins host reasons or channel labels the locale's way (\"a, b\").\n const formatList = (items: string[]): string =>\n new Intl.ListFormat(i18n.language || 'en', { type: 'unit' }).format(\n items,\n );\n\n // A channel dropdown's options: greyed-out channels stay listed, with\n // their reason under them, as the operator's on-device option does.\n const channelOptionsFor = (\n listed: SignatureChannel[],\n unavailable: Map<SignatureChannel, string>,\n ): SelectOption<SignatureChannel>[] =>\n listed.map((channel) => {\n const reason = unavailable.get(channel);\n return reason === undefined\n ? channelOption(channel, channel)\n : {\n ...channelOption(channel, channel),\n disabled: true,\n description: reason,\n };\n });\n\n // The reasons, for the trigger: a disabled option cannot take focus.\n // `reasonsOnly` when nothing is available and they show under the row.\n const channelReasons = (\n listed: SignatureChannel[],\n unavailable: Map<SignatureChannel, string>,\n reasonsOnly: boolean,\n ): string | undefined => {\n const byReason = new Map<string, string[]>();\n for (const channel of listed) {\n const reason = unavailable.get(channel);\n if (reason === undefined) continue;\n byReason.set(reason, [\n ...(byReason.get(reason) ?? []),\n channelMeta[channel].label,\n ]);\n }\n if (byReason.size === 0) return undefined;\n return reasonsOnly\n ? formatList([...byReason.keys()])\n : formatList(\n [...byReason].map(\n ([reason, labels]) => `${formatList(labels)} (${reason})`,\n ),\n );\n };\n\n const batchListed = batchListedFor(\n primaryId,\n primaryId === undefined\n ? undefined\n : hostView?.signerAvailableChannels?.[primaryId],\n );\n const batchUnavailable = batchUnavailableFor(primaryId);\n const batchChannelOptions = channelOptionsFor(\n batchListed,\n batchUnavailable,\n );\n const batchChannelHint = channelReasons(\n batchListed,\n batchUnavailable,\n false,\n );\n\n const handleRequest = () => {\n // The button is disabled too; this stops any other route in.\n if (anySignerWithoutChannel || secondIssue !== null) return;\n // Always set: a stale wait from an earlier failed QR submit must not\n // resurface the spinner after a submit without QR signers.\n setAwaitingQr(anySignerOnQr);\n if (anySignerOnQr) {\n // Move focus to the heading BEFORE the form footer unmounts, so it\n // never drops to the dialog container.\n titleRef.current?.focus();\n setQrIndex(0);\n }\n const roster: SignerRequest[] = signers.map(\n ({ rowId: _rowId, ...signer }, index) => {\n if (batchMode) {\n return {\n signerId: signer.signerId,\n channel: batchChannel,\n // The batch's OTP waiver rides on the main signer.\n ...(index === 0 && batchChannel === 'on-device'\n ? { skipOtp: batchSkipOtp }\n : {}),\n };\n }\n // The main signer's waiver follows the patient's SMS.\n return followsOtpRules(index) && signer.channel === 'on-device'\n ? { ...signer, skipOtp: rowSkipOtp(signer, index) }\n : signer;\n },\n );\n const signMode = batchMode ? { signMode: batchChannel } : {};\n if (requiredMode) {\n // Walk the items in list order: object key order puts numeric ids\n // ('87', '1204') first, so it cannot decide the first operator.\n const operatorAssignments: Record<string, string | null> = {};\n let firstOperatorId: string | null = null;\n for (const item of listedItems) {\n if (!needsOperatorPick(item)) continue;\n const value = assignments[item.id];\n const assigned =\n value === ASSIGN_LATER || value === '' || value === undefined\n ? null\n : value;\n operatorAssignments[item.id] = assigned;\n firstOperatorId ??= assigned;\n }\n // Each assigned item's operator channel, when shown.\n const operatorChannels: Record<string, OperatorChannel> = {};\n for (const [itemId, operatorId] of Object.entries(\n operatorAssignments,\n )) {\n if (operatorId !== null) {\n operatorChannels[itemId] = itemOperatorChannels[itemId];\n }\n }\n onRequestSignature({\n operatorId: firstOperatorId,\n operatorChannel: null,\n signers: roster,\n ...signMode,\n operatorAssignments,\n ...(showOperatorChannels ? { operatorChannels } : {}),\n requiredItemIds: listedItems.map((item) => item.id),\n });\n return;\n }\n onRequestSignature({\n operatorId: !requireOperator || isUnassigned ? null : operator,\n operatorChannel:\n !requireOperator || isUnassigned ? null : operatorChannel,\n signers: requirePatient ? roster : [],\n ...(requirePatient ? signMode : {}),\n });\n };\n\n // A host error ends the wait and returns the user to the form, where the\n // error alert shows and they can retry.\n useEffect(() => {\n if (error) setAwaitingQr(false);\n }, [error]);\n\n /* ---- QR step --------------------------------------------------- */\n const hasQrCodes = (qrCodes?.length ?? 0) > 0;\n // `error` wins over any wait (`qrPending` included, and an error string\n // the host left set from an earlier failure), since only the form\n // renders it. Codes that arrive still show.\n const qrStep = hasQrCodes || (!error && (qrPending || awaitingQr));\n // One slot per `'qr'` roster signer, in roster order, plus any code for a\n // signer the roster does not list (e.g. a host that opens on the step).\n const qrSlots = withPatient\n ? signers\n .filter(\n (signer) => (batchMode ? batchChannel : signer.channel) === 'qr',\n )\n .map((signer) => signer.signerId)\n : [];\n for (const code of qrCodes ?? []) {\n if (!qrSlots.includes(code.signerId)) qrSlots.push(code.signerId);\n }\n const qrTotal = qrSlots.length;\n const qrCurrent = Math.min(qrIndex, Math.max(qrTotal - 1, 0));\n const qrSignerId = qrSlots[qrCurrent];\n const qrName =\n qrSignerId === undefined ? '' : labelFor(signerOptions, qrSignerId);\n const qrCode = qrCodes?.find((code) => code.signerId === qrSignerId);\n const qrExpiry = qrCode\n ? formatQrExpiry(qrCode.expiresAt, i18n.language || 'en', t)\n : null;\n const isLastQr = qrCurrent >= qrTotal - 1;\n const showQrCount = hasQrCodes && qrTotal > 1;\n\n // Focus the step heading when the step opens, when the codes arrive and\n // when the code changes, so screen readers hear the new signer and expiry.\n const qrFocusKey =\n open && qrStep && !shownOutcome ? `${hasQrCodes}:${qrCurrent}` : null;\n useEffect(() => {\n if (qrFocusKey !== null) titleRef.current?.focus();\n }, [qrFocusKey]);\n // Same for an outcome: its header holds the message.\n const outcomeFocusKey = open && shownOutcome ? shownOutcome : null;\n useEffect(() => {\n if (outcomeFocusKey !== null) titleRef.current?.focus();\n }, [outcomeFocusKey]);\n\n const qrDescription = !hasQrCodes\n ? t('signatureRequest.qrPending')\n : !qrCode\n ? // The error alert in the body carries the message (and announces\n // itself); the description only names whose slot this is.\n qrName || qrSignerId\n : qrName\n ? t('signatureRequest.qrCaptionNamed', { name: qrName })\n : t('signatureRequest.qrCaption');\n\n return (\n <div ref={ref} className=\"ds:contents\" data-component=\"signature-request\">\n {/* Covers every view, e.g. the signatures list's tooltips. */}\n <TooltipProvider>\n <Dialog open={open} onOpenChange={onOpenChange}>\n {/* Every view keeps its title and actions in view: only the\n body scrolls. */}\n <Dialog.Content\n size=\"lg\"\n scroll=\"body\"\n hideCloseButton\n onOpenAutoFocus={(event) => {\n // Opening on the QR step, an outcome or the signed versions:\n // start at the heading. With signed versions the first\n // focusable is a tooltip trigger, and focusing it on open\n // would pop its tooltip unasked.\n if (!qrStep && !hasHistory && !shownOutcome) return;\n event.preventDefault();\n titleRef.current?.focus();\n }}\n {...contentProps}\n >\n <Dialog.Header>\n {/* One title element for both steps, focusable from script only,\n so focus can land here as the step or code changes. */}\n <Dialog.Title\n ref={titleRef}\n tabIndex={-1}\n aria-describedby={\n outcomeText\n ? outcomeDescriptionId\n : qrStep\n ? showQrCount\n ? `${qrDescriptionId} ${qrCountId}`\n : qrDescriptionId\n : undefined\n }\n className=\"ds:outline-none\"\n >\n {outcomeText\n ? outcomeText.title\n : qrStep\n ? t('signatureRequest.qrTitle')\n : (title ??\n t(\n requiredMode\n ? 'signatureRequest.requiredTitle'\n : 'signatureRequest.title',\n ))}\n </Dialog.Title>\n {outcomeText ? (\n <Dialog.Description asChild>\n {/* Same shape as the QR step: the inner id describes the\n heading, which takes focus when the outcome shows. */}\n <div>\n <p id={outcomeDescriptionId}>{outcomeText.description}</p>\n </div>\n </Dialog.Description>\n ) : qrStep ? (\n <Dialog.Description asChild>\n {/* Radix stamps its own id on this element for the dialog's\n aria-describedby; the inner id describes the heading. */}\n <div>\n <div\n id={qrDescriptionId}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <p>{qrDescription}</p>\n {qrExpiry ? <p>{qrExpiry}</p> : null}\n </div>\n </div>\n </Dialog.Description>\n ) : (\n <Dialog.Description>\n {description ??\n t(\n requiredMode\n ? 'signatureRequest.requiredDescription'\n : hasHistory\n ? // The table says whether there are signed\n // versions, so the header describes the form.\n 'signatureRequest.requestDescription'\n : 'signatureRequest.noSignedVersions',\n )}\n </Dialog.Description>\n )}\n </Dialog.Header>\n\n {shownOutcome ? (\n <>\n <Dialog.Body>\n <SignatureOutcome outcome={shownOutcome} />\n </Dialog.Body>\n <Dialog.Footer>\n {shownOutcome === 'creditsExhausted' &&\n onBuyMoreSignatures ? (\n <Button\n intent=\"primary\"\n startIcon={<ShoppingCart />}\n onClick={onBuyMoreSignatures}\n >\n {t('signatureRequest.buyMoreSignatures')}\n </Button>\n ) : null}\n {/* Back to the form, as platform's Annulla. Focus moves\n to the heading BEFORE this footer unmounts. */}\n {shownOutcome === 'creditsExhausted' &&\n outcome === 'creditsExhausted' &&\n onOutcomeCancel ? (\n <Button\n intent=\"ghost\"\n onClick={() => {\n titleRef.current?.focus();\n setOutcomeCancelled(true);\n onOutcomeCancel();\n }}\n >\n {t('signatureRequest.outcomeCancel')}\n </Button>\n ) : null}\n <Dialog.Close asChild>\n <Button intent=\"outline\">\n {t('signatureRequest.close')}\n </Button>\n </Dialog.Close>\n </Dialog.Footer>\n </>\n ) : qrStep ? (\n <>\n <Dialog.Body className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)] ds:text-center\">\n {!hasQrCodes ? (\n // Waiting for the server: the spinner's status role\n // announces the wait politely.\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)] ds:py-[var(--spacing-xl)]\">\n <Spinner\n size=\"lg\"\n label={t('signatureRequest.qrPending')}\n />\n </div>\n ) : (\n <>\n {showQrCount ? (\n // Also describes the heading, so screen readers hear\n // the position when Previous or Next moves focus there.\n <p\n id={qrCountId}\n className=\"type-label ds:text-[var(--muted-foreground)]\"\n >\n {t('signatureRequest.qrStepCount', {\n current: qrCurrent + 1,\n total: qrTotal,\n })}\n </p>\n ) : null}\n {qrName ? (\n <p className=\"type-title-item ds:break-words\">\n {qrName}\n </p>\n ) : null}\n {qrCode ? (\n // The QrCode's own name speaks of check-in, so the\n // pattern names the code and hides the inner figure.\n // `lg` keeps a long signing link at a module size a\n // phone camera can read off a desk monitor.\n <div\n role=\"img\"\n aria-label={t('signatureRequest.qrCodeLabel')}\n data-signer-id={qrSignerId}\n >\n <QrCode\n value={qrCode.url}\n variant=\"framed\"\n size=\"lg\"\n decorative\n />\n </div>\n ) : (\n <Alert\n variant=\"error\"\n className=\"ds:text-start\"\n data-signer-id={qrSignerId}\n >\n <Alert.Description>\n {t('signatureRequest.qrMissing', {\n name: qrName || qrSignerId,\n })}\n </Alert.Description>\n </Alert>\n )}\n </>\n )}\n </Dialog.Body>\n\n <Dialog.Footer>\n {!hasQrCodes ? (\n <Dialog.Close asChild>\n <Button intent=\"outline\">\n {t('signatureRequest.close')}\n </Button>\n </Dialog.Close>\n ) : (\n <>\n {qrTotal > 1 ? (\n <Button\n intent=\"outline\"\n disabled={qrCurrent === 0}\n onClick={() => setQrIndex(qrCurrent - 1)}\n >\n {t('signatureRequest.qrPrevious')}\n </Button>\n ) : null}\n {isLastQr ? (\n <Button\n intent=\"primary\"\n onClick={() => {\n onQrDone?.();\n onOpenChange(false);\n }}\n >\n {t('signatureRequest.qrDone')}\n </Button>\n ) : (\n <Button\n intent=\"primary\"\n onClick={() => setQrIndex(qrCurrent + 1)}\n >\n {t('signatureRequest.qrNext')}\n </Button>\n )}\n </>\n )}\n </Dialog.Footer>\n </>\n ) : (\n <>\n <Dialog.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n {/* Who signed what and when, above the request form on\n the same screen, as on platform. */}\n {hasHistory ? (\n <>\n <SignatureHistory\n signatures={signatures}\n loading={signaturesLoading}\n showLegalLevel={showLegalLevel}\n onView={onViewSignature}\n onDownload={onDownloadSignature}\n onShare={onShareSignature}\n shareTargets={signatureShareTargets}\n onDelete={onDeleteSignature}\n />\n {withOperator || rosterVisible ? (\n <Separator decorative />\n ) : null}\n </>\n ) : null}\n {requiredMode ? (\n <RequiredDocuments\n items={listedItems}\n loading={requiredItemsLoading}\n operatorOptions={operatorPickerList}\n assignments={assignments}\n onAssign={assignItem}\n showOperatorChannels={showOperatorChannels}\n operatorChannels={itemOperatorChannels}\n onOperatorChannel={(itemId, channel) =>\n setOperatorChannelOverrides((current) => ({\n ...current,\n [itemId]: channel,\n }))\n }\n onAssignAllToMe={\n currentOperatorId !== undefined\n ? assignAllToMe\n : undefined\n }\n busy={busy}\n />\n ) : null}\n {withOperator ? (\n <section\n className={`${PERSON_SECTION} ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:text-start`}\n >\n <div className={PERSON_GRID}>\n <div className={PERSON_HEADER}>\n <p className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {t('signatureRequest.operatorSection')}\n </p>\n {currentOperatorId !== undefined ? (\n <Button\n intent=\"outline\"\n size=\"sm\"\n startIcon={<UserPlus />}\n disabled={busy}\n onClick={() => {\n setOperator(currentOperatorId);\n if (resolveChannels) {\n commitWithHost(\n currentOperatorId,\n operatorDefaultChannel(currentOperatorId),\n rosterRows,\n 'operator',\n );\n return;\n }\n setOperatorChannel(\n operatorDefaultChannel(\n currentOperatorId,\n anySignerOnDevice,\n ),\n );\n setRevertedTo(null);\n }}\n >\n {t('signatureRequest.assignToMe')}\n </Button>\n ) : null}\n </div>\n </div>\n\n {/* The action column stays empty but reserved, and the\n channel column keeps its width while unassigned, so\n both selects end where the signer rows' do. */}\n <div className={PERSON_GRID} data-person-row=\"operator\">\n {/* Mirrors the select value — decorative for AT. No\n name → Avatar's built-in placeholder icon. */}\n <div className={PERSON_AVATAR}>\n <Avatar\n aria-hidden=\"true\"\n name={\n isUnassigned\n ? undefined\n : labelFor(operators, operator)\n }\n size=\"sm\"\n />\n </div>\n <div className={PERSON_NAME}>\n <Select\n options={operatorPickerOptions(\n operatorPickerList,\n operator,\n )}\n value={operator}\n showDescriptions\n aria-describedby={\n operatorHint ? operatorPickerHintId : undefined\n }\n onValueChange={(value) => {\n // A greyed-out or deleted operator (e.g. from\n // the agent's set_value) is refused.\n if (\n !value ||\n !isPickableOperator(operatorPickerList, value)\n )\n return;\n setOperator(value);\n if (resolveChannels) {\n commitWithHost(\n value,\n value === ASSIGN_LATER\n ? 'email'\n : operatorDefaultChannel(value),\n rosterRows,\n 'operator',\n );\n return;\n }\n // A different operator brings their own system\n // default along, replacing a hand-picked one.\n setOperatorChannel(\n value === ASSIGN_LATER\n ? 'email'\n : operatorDefaultChannel(\n value,\n anySignerOnDevice,\n ),\n );\n setRevertedTo(null);\n }}\n required\n disabled={busy}\n placeholder={t(\n 'signatureRequest.operatorPlaceholder',\n )}\n aria-label={t('signatureRequest.operatorSection')}\n />\n {operatorHint ? (\n <span\n id={operatorPickerHintId}\n className=\"ds:sr-only\"\n >\n {operatorHint}\n </span>\n ) : null}\n </div>\n\n {/* One channel for the operator too, in the same\n dropdown as the signer rows. Hidden while the\n request is unassigned: nobody to deliver to. The\n name is for assistive tech only. */}\n <div\n className={\n isUnassigned\n ? `${PERSON_CHANNEL} ds:hidden ds:@[512px]/person:block`\n : PERSON_CHANNEL\n }\n >\n {isUnassigned ? null : (\n <Select<OperatorChannel>\n id=\"signature-request-operator-channel\"\n options={operatorChannelOptions}\n value={operatorChannel}\n adornmentInTrigger\n showDescriptions\n disabled={busy}\n aria-label={t(\n 'signatureRequest.operatorChannelLabel',\n )}\n aria-describedby={\n onDeviceHint ? operatorHintId : undefined\n }\n onValueChange={(value) => {\n // The agent's set_value skips the list, so\n // a disabled option is refused here too.\n const offered = operatorChannelOptions.some(\n (option) =>\n option.value === value &&\n !option.disabled,\n );\n if (!offered) return;\n if (resolveChannels) {\n commitWithHost(\n operator,\n value as OperatorChannel,\n rosterRows,\n 'operator',\n );\n return;\n }\n setOperatorChannel(value as OperatorChannel);\n setRevertedTo(null);\n }}\n />\n )}\n {channelSizer}\n </div>\n {/* Why on this device is greyed out, for screen\n readers on the trigger; sighted users read it\n under the option. */}\n {onDeviceHint && !isUnassigned ? (\n <span id={operatorHintId} className=\"ds:sr-only\">\n {onDeviceHint}\n </span>\n ) : null}\n </div>\n </section>\n ) : null}\n\n {/* Announces a channel moved in a section the user did not\n touch: the built-in on-device fallback or a host rule.\n Outside both sections, so it is there in required\n documents mode too. */}\n {withOperator || rosterVisible ? (\n <span role=\"status\" className=\"ds:sr-only\">\n {revertedTo\n ? t('signatureRequest.operatorChannelReverted', {\n channel: channelMeta[revertedTo].label,\n })\n : hostAnnouncement}\n </span>\n ) : null}\n\n {/* The rule only separates two sections that are both there. */}\n {(withOperator || requiredMode) && rosterVisible ? (\n <Separator decorative />\n ) : null}\n\n {rosterVisible ? (\n <section\n className={`${PERSON_SECTION} ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:text-start`}\n >\n <div className={PERSON_GRID}>\n <div className={PERSON_HEADER}>\n <p className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {t('signatureRequest.signersSection')}\n </p>\n {/* Offered only when the roster holds more than one\n person. A patient with nobody else to sign for\n them saw a permanently greyed action — a promise\n the modal could never keep. With two or more it\n stays, greying (not hiding) once every seat is\n taken so the cap reads. */}\n {signerOptions.length > 1 ? (\n <Button\n ref={addButtonRef}\n intent=\"outline\"\n size=\"sm\"\n startIcon={<Plus />}\n disabled={!canAddSigner}\n aria-describedby={\n secondSigneeHint\n ? secondSigneeHintId\n : undefined\n }\n onClick={addSigner}\n >\n {t('signatureRequest.addSigner')}\n </Button>\n ) : null}\n </div>\n {/* Required documents mode, as platform's Signee:\n with no registered signee, a link to add one,\n at the name column's start edge. */}\n {requiredMode &&\n onAddSignee &&\n !signerOptions.some(\n (option) => option.isPatient !== true,\n ) ? (\n <div className={PERSON_UNDER}>\n <Button\n intent=\"link\"\n size=\"sm\"\n startIcon={<Plus />}\n disabled={busy}\n onClick={onAddSignee}\n >\n {t('signatureRequest.addSignatory')}\n </Button>\n </div>\n ) : null}\n {/* Batch mode: one channel for the whole roster\n (platform's sign mode), on the person grid from\n the name edge to the selects' end edge. */}\n {batchMode ? (\n <div\n className={`${PERSON_UNDER} ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]`}\n >\n <label\n htmlFor={BATCH_CHANNEL_ID}\n className=\"type-label ds:text-foreground\"\n >\n {t('signatureRequest.channelLabel')}\n </label>\n <Select<SignatureChannel>\n id={BATCH_CHANNEL_ID}\n options={batchChannelOptions}\n value={batchChannel}\n adornmentInTrigger\n showDescriptions\n disabled={busy}\n aria-label={t('signatureRequest.channelLabel')}\n aria-describedby={\n batchChannelHint\n ? batchChannelHintId\n : undefined\n }\n onValueChange={(value) => {\n // The agent's set_value skips the list, so\n // a greyed-out channel is refused here too.\n const offered = batchChannelOptions.some(\n (option) =>\n option.value === value &&\n !option.disabled,\n );\n if (!offered) return;\n commitBatch(\n rosterRows,\n value as SignatureChannel,\n { userChannel: true },\n );\n }}\n />\n {batchChannelHint ? (\n <span\n id={batchChannelHintId}\n className=\"ds:sr-only\"\n >\n {batchChannelHint}\n </span>\n ) : null}\n </div>\n ) : null}\n {/* One OTP waiver for the batch, on this device\n only. Forced on (and disabled) when the patient\n signs and cannot receive SMS; the warning right\n under it says what that costs. As on platform,\n a forced waiver warns on every channel. */}\n {batchMode && batchChannel === 'on-device' ? (\n <div className={PERSON_UNDER}>\n <Switch\n label={t('signatureRequest.noOtp')}\n checked={batchSkipOtp}\n disabled={busy || otpForced}\n aria-describedby={\n otpForced ? otpWarningId : undefined\n }\n onCheckedChange={(checked) =>\n setOtpOverride(checked)\n }\n />\n </div>\n ) : null}\n {batchOtpWarning ? (\n <Alert\n variant=\"warning\"\n id={otpWarningId}\n className={PERSON_UNDER}\n >\n <Alert.Description>\n {t('signatureRequest.noOtpWarning')}\n </Alert.Description>\n </Alert>\n ) : null}\n {/* Visible, not a tip: the reason a second signee is\n missing matters before the user looks for one. */}\n {secondSigneeHint ? (\n <p\n id={secondSigneeHintId}\n className={`${PERSON_UNDER} type-body-sm ds:text-[color:var(--muted-foreground)]`}\n >\n {secondSigneeHint}\n </p>\n ) : null}\n </div>\n\n <div className={PERSON_LIST}>\n {signers.map((signer, index) => {\n const rowOptions = signerOptions.filter(\n (option) =>\n option.value === signer.signerId ||\n !chosenIds.includes(option.value),\n );\n const rowLabel = labelFor(\n signerOptions,\n signer.signerId,\n );\n const rowIsMinor =\n signerOptions.find(\n (option) => option.value === signer.signerId,\n )?.isMinor === true;\n // Required documents mode: the main signer, then\n // the second signee, who is never the patient.\n const isSecond = requiredMode && index > 0;\n const personOptions = isSecond\n ? rowOptions.filter(\n (option) => option.isPatient !== true,\n )\n : rowOptions;\n const known = personOptions.some(\n (option) => option.value === signer.signerId,\n );\n const issue = isSecond ? secondIssue : null;\n const issueId = `${secondSigneeIssueId}-${signer.rowId}`;\n const labelId = `${secondSigneeLabelId}-${signer.rowId}`;\n // Per signer: greyed-out channels stay listed with\n // their reason under them, as the operator's\n // on-device option does. Batch mode has no\n // channel beside the name.\n const rowUnavailable = unavailableFor(\n signer.signerId,\n );\n const rowListed = listedChannelsFor(\n signer.signerId,\n hostView?.signerAvailableChannels?.[\n signer.signerId\n ],\n );\n const rowChannelOptions = channelOptionsFor(\n rowListed,\n rowUnavailable,\n );\n const rowNoChannel =\n !batchMode &&\n rowChannelOptions.every(\n (option) => option.disabled,\n );\n // With nothing available the reasons show under\n // the row instead.\n const rowChannelHint = batchMode\n ? undefined\n : channelReasons(\n rowListed,\n rowUnavailable,\n rowNoChannel,\n );\n const rowChannelHintId = `${signerChannelHintId}-${signer.rowId}`;\n const rowOtpForced =\n followsOtpRules(index) && otpForced;\n // Required documents mode keeps the main signer.\n const canRemove = requiredMode\n ? isSecond\n : signers.length > 1;\n\n const changePerson = (value: string) => {\n // Someone already on another row, or the\n // patient as second signee (e.g. from the\n // agent's set_value), is refused.\n if (\n !value ||\n !personOptions.some(\n (option) => option.value === value,\n )\n )\n return;\n if (batchMode) {\n commitBatch(\n rosterRows.map((row) =>\n row.rowId === signer.rowId\n ? { ...row, signerId: value }\n : row,\n ),\n batchChannel,\n { primaryChanged: requiredMode && !isSecond },\n );\n return;\n }\n const channel = resolveChannel(\n value,\n signer.channel,\n );\n // As platform's _onSigneeIdChanged, a new main\n // signer clears the second signee.\n const clearSecond =\n requiredMode &&\n !isSecond &&\n rosterRows.length > 1;\n const nextRows = (\n clearSecond\n ? rosterRows.slice(0, 1)\n : rosterRows\n ).map((row) =>\n row.rowId === signer.rowId\n ? {\n ...row,\n signerId: value,\n channel,\n skipOtp:\n channel === 'on-device'\n ? row.skipOtp\n : undefined,\n }\n : row,\n );\n const extra =\n clearSecond && signers.length > 1\n ? [t('signatureRequest.secondSigneeCleared')]\n : [];\n if (resolveChannels) {\n commitWithHost(\n operator,\n operatorChannel,\n nextRows,\n 'signers',\n extra,\n );\n return;\n }\n setSigners(nextRows);\n if (extra.length > 0) {\n setRevertedTo(null);\n setHostAnnouncement(extra.join(' '));\n }\n };\n\n const changeChannel = (value: string) => {\n // A channel this signer cannot receive, hidden\n // or greyed out (e.g. from the agent's\n // set_value), is refused.\n const offered = rowChannelOptions.some(\n (option) =>\n option.value === value && !option.disabled,\n );\n if (!offered) return;\n const channel = value as SignatureChannel;\n const nextRows = rosterRows.map((row) =>\n row.rowId === signer.rowId\n ? { ...row, channel, skipOtp: undefined }\n : row,\n );\n // A main signer who stops allowing a second\n // signee hides them, and the status says why.\n const block =\n requiredMode && !isSecond && signers.length > 1\n ? secondSigneeBlock({\n items: listedItems,\n channel,\n primaryIsPatient,\n })\n : null;\n const extra =\n block === null\n ? []\n : [t(SECOND_SIGNEE_HINTS[block])];\n if (resolveChannels) {\n commitWithHost(\n operator,\n operatorChannel,\n nextRows,\n 'signers',\n extra,\n );\n return;\n }\n setSigners(nextRows);\n if (extra.length > 0) {\n setRevertedTo(null);\n setHostAnnouncement(extra.join(' '));\n }\n };\n\n const personRow = (\n <div\n key={signer.rowId}\n role=\"group\"\n aria-label={isSecond ? undefined : rowLabel}\n aria-labelledby={isSecond ? labelId : undefined}\n data-signer-id={signer.signerId}\n data-signer-role={\n requiredMode\n ? isSecond\n ? 'second'\n : 'main'\n : undefined\n }\n className={PERSON_GRID}\n >\n {/* Mirrors the select value — decorative for AT. */}\n <div className={PERSON_AVATAR}>\n <Avatar\n aria-hidden=\"true\"\n name={\n requiredMode && !known\n ? undefined\n : rowLabel\n }\n size=\"sm\"\n />\n </div>\n <div\n className={\n batchMode ? PERSON_NAME_FULL : PERSON_NAME\n }\n >\n <Select\n options={personOptions}\n value={\n requiredMode && !known\n ? ''\n : signer.signerId\n }\n tone={issue ? 'error' : 'default'}\n aria-describedby={\n issue ? issueId : undefined\n }\n onValueChange={changePerson}\n required\n disabled={busy}\n placeholder={t(\n 'signatureRequest.signerPlaceholder',\n )}\n aria-label={t(\n 'signatureRequest.signerPlaceholder',\n )}\n />\n </div>\n\n {/* One channel per signer, beside the name. The\n name is for assistive tech only. */}\n {batchMode ? null : (\n <div className={PERSON_CHANNEL}>\n <Select<SignatureChannel>\n id={`signature-request-signer-channel-${signer.rowId}`}\n options={rowChannelOptions}\n value={rowNoChannel ? '' : signer.channel}\n adornmentInTrigger\n showDescriptions\n disabled={busy}\n aria-label={t(\n 'signatureRequest.channelLabel',\n )}\n aria-describedby={\n rowChannelHint\n ? rowChannelHintId\n : undefined\n }\n onValueChange={changeChannel}\n />\n {channelSizer}\n </div>\n )}\n {rowChannelHint && !rowNoChannel ? (\n <span\n id={rowChannelHintId}\n className=\"ds:sr-only\"\n >\n {rowChannelHint}\n </span>\n ) : null}\n\n {canRemove ? (\n <div className={PERSON_ACTION}>\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={<X />}\n disabled={busy}\n aria-label={t(\n 'signatureRequest.removeSigner',\n )}\n onClick={() => removeSigner(signer.rowId)}\n />\n </div>\n ) : null}\n\n {/* Under 18: a reminder to check for a second\n signee, under this person's name. It never\n blocks the request, so it is polite. */}\n {rowIsMinor ? (\n <Alert\n variant=\"warning\"\n announce=\"polite\"\n data-note=\"minor-signer\"\n className={PERSON_UNDER}\n >\n <Alert.Description>\n {t('signatureRequest.minorSignerWarning')}\n </Alert.Description>\n </Alert>\n ) : null}\n\n {/* A status: it can appear with no user action\n (the host drops the person) and disables\n Request signature. */}\n {issue ? (\n <p\n id={issueId}\n role=\"status\"\n data-note=\"second-signee-issue\"\n data-issue={issue}\n className={`${PERSON_UNDER} type-body-sm ds:text-[color:var(--destructive)]`}\n >\n {t(SECOND_SIGNEE_ISSUES[issue])}\n </p>\n ) : null}\n\n {/* Nothing to send this person on: the reasons\n under their name, and the request waits. */}\n {rowNoChannel && rowChannelHint ? (\n <p\n id={rowChannelHintId}\n data-note=\"no-channel\"\n className={`${PERSON_UNDER} type-body-sm ds:text-[color:var(--muted-foreground)]`}\n >\n {rowChannelHint}\n </p>\n ) : null}\n\n {/* The row's OTP waiver, on this device. The\n main signer's in required documents mode\n is forced on (and disabled) when the\n patient signs and cannot receive SMS; the\n warning says what that costs. */}\n {!batchMode &&\n signer.channel === 'on-device' &&\n !rowNoChannel ? (\n <div className={PERSON_UNDER}>\n <Switch\n label={t('signatureRequest.noOtp')}\n checked={rowSkipOtp(signer, index)}\n disabled={busy || rowOtpForced}\n aria-describedby={\n rowOtpForced ? otpWarningId : undefined\n }\n onCheckedChange={(checked) =>\n patchSigner(signer.rowId, {\n skipOtp: checked,\n })\n }\n />\n </div>\n ) : null}\n </div>\n );\n if (!isSecond) return personRow;\n // The second signee's row, under its own label.\n return (\n <div\n key={signer.rowId}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <div className={PERSON_GRID}>\n <p\n id={labelId}\n className={`${PERSON_UNDER} type-label ds:text-[color:var(--muted-foreground)]`}\n >\n {t('signatureRequest.secondSigneeLabel')}\n </p>\n </div>\n {personRow}\n </div>\n );\n })}\n </div>\n </section>\n ) : null}\n\n {/* Dedicated alert area — one warning regardless of how many\n signers waive OTP, stacked with any submission error,\n under the names like everything under a person. Required\n documents mode shows its warning under the batch switch. */}\n {anySignerSkipsOtp || error ? (\n <div className={PERSON_SECTION}>\n <div className={PERSON_GRID}>\n {anySignerSkipsOtp ? (\n <Alert\n variant=\"warning\"\n id={otpWarningId}\n className={PERSON_UNDER}\n >\n <Alert.Description>\n {t('signatureRequest.noOtpWarning')}\n </Alert.Description>\n </Alert>\n ) : null}\n {error ? (\n <Alert variant=\"error\" className={PERSON_UNDER}>\n <Alert.Description>{error}</Alert.Description>\n </Alert>\n ) : null}\n </div>\n </div>\n ) : null}\n </Dialog.Body>\n\n <Dialog.Footer>\n <Button\n intent=\"primary\"\n startIcon={<PenLine />}\n onClick={handleRequest}\n // Why it is disabled, while the second signee has an issue.\n aria-describedby={\n secondIssue !== null && signers[1]\n ? `${secondSigneeIssueId}-${signers[1].rowId}`\n : undefined\n }\n disabled={\n busy ||\n (withPatient && signers.length === 0) ||\n anySignerWithoutChannel ||\n secondIssue !== null ||\n (!withPatient && !withOperator) ||\n (requiredMode &&\n (requiredItemsLoading || listedItems.length === 0))\n }\n loading={busy}\n >\n {t('signatureRequest.requestSignature')}\n </Button>\n <Dialog.Close asChild>\n <Button intent=\"outline\" disabled={busy}>\n {t('signatureRequest.close')}\n </Button>\n </Dialog.Close>\n </Dialog.Footer>\n </>\n )}\n </Dialog.Content>\n </Dialog>\n </TooltipProvider>\n </div>\n );\n },\n);\nSignatureRequestModal.displayName = 'SignatureRequestModal';\n"],"names":["__iconNode","Link2","createLucideIcon","QrCode","ShoppingCart","Tablet","OPERATOR_CHANNELS","useChannelMeta","t","useTranslation","jsx","MessageSquare","Mail","WhatsAppGlyph","QrCodeIcon","LoadStatus","loading","loadingText","loadedText","override","message","setMessage","useState","wasLoading","useRef","useEffect","PERSON_GRID","PERSON_AVATAR","PERSON_NAME","PERSON_NAME_FULL","PERSON_CHANNEL","PERSON_ACTION","PERSON_UNDER","PERSON_HEADER","PERSON_LIST","PERSON_SECTION","ChannelColumnSizer","meta","channel","label","icon","jsxs","selectTriggerVariants","ChevronDown","SHARE_TARGETS","LOADING_ROWS","TABLE","ROWGROUP","ROW","CELL_DATE","CELL_TYPE","CELL_ACTIONS","timeOf","value","ms","newestFirst","records","record","index","a","b","SignatureHistory","signatures","showLegalLevel","onView","onDownload","onShare","shareTargets","onDelete","i18n","channelMeta","headingId","useId","shareMeta","language","intlLocale","weekdayFormat","dayFormat","timeFormat","formatWhen","weekday","tableRef","emptyRef","pendingDelete","deleteStatus","setDeleteStatus","pending","remaining","at","targetId","id","active","_a","row","_b","element","_c","sorted","content","Skeleton","headerCell","TooltipProvider","when","dateTime","allowedTargets","rowShareTargets","target","hasActions","SignatureStatusChip","IconButton","Eye","RowMenu","Download","DropdownMenu","Share2","DeleteConfirm","item","useQuietReturnTooltip","tipOpen","setTipOpen","restoringFocus","next","children","tip","menuOpen","Tooltip","onConfirm","open","setOpen","Dialog","Trash2","Button","ASSIGN_LATER","itemsStillToSign","items","batchCanCarrySecondary","needsOperatorPick","operatorPickerOptions","options","selected","option","_deleted","isPickableOperator","operatorReasonsHint","locale","entries","secondSigneeBlock","primaryIsPatient","secondSigneeIssue","primaryId","secondId","second","receives","wanted","entry","ITEM_ROW","ITEM_ROW_WITH_CHANNEL","ITEM_NAME","ITEM_NAME_FULL","ITEM_PICKER","COMPACT_NOTE","RequiredDocuments","operatorOptions","assignments","onAssign","onAssignAllToMe","busy","showOperatorChannels","operatorChannels","onOperatorChannel","channelOptions","documentsHeadingId","interviewsHeadingId","operatorHintId","status","Fragment","documents","interviews","anyUnassigned","operatorGroup","groupItems","operatorHint","group","heading","withOperatorControls","UserPlus","Alert","List","withPicker","withChannel","assigned","Select","outcomeCopy","outcome","required","SignatureOutcome","warning","TriangleAlert","CircleCheck","CHANNEL_ORDER","BATCH_CHANNEL_ID","SECOND_SIGNEE_HINTS","SECOND_SIGNEE_ISSUES","formatQrExpiry","expiresAt","date","time","labelFor","SignatureRequestModal","forwardRef","onOpenChange","operators","signerOptions","currentOperatorId","allowAssignLater","requireOperator","requirePatient","initialOperatorId","initialOperatorChannel","initialSigners","maxSigners","channelMode","initialBatchChannel","error","title","description","onRequestSignature","qrCodes","qrPending","onQrDone","signaturesLoading","onViewSignature","onDownloadSignature","onShareSignature","signatureShareTargets","onDeleteSignature","resolveChannels","requiredItems","requiredItemsLoading","onBuyMoreSignatures","onOutcomeCancel","onAddSignee","contentProps","ref","nextRowId","addButtonRef","titleRef","qrDescriptionId","qrCountId","outcomeDescriptionId","secondSigneeHintId","signerChannelHintId","batchChannelHintId","secondSigneeLabelId","secondSigneeIssueId","otpWarningId","requiredMode","listedItems","withOperator","withPatient","batchMode","isPatientId","signerId","capFor","rows","batch","outcomeCancelled","setOutcomeCancelled","prevOutcome","setPrevOutcome","shownOutcome","outcomeText","unavailableFor","reason","listedChannelsFor","hostAllowed","allowed","own","unavailable","narrowed","channelsFor","operatorChannelsFrom","resolution","resolveChannel","preferred","available","patientOption","batchPeopleFor","batchUnavailableFor","people","text","batchListedFor","listed","batchChannelsFor","seedBatchChannel","withInitial","firstOperator","resolveOperatorSeed","seed","seedOperator","seedRows","signer","skipOtp","rest","operatorDefaultChannel","operatorId","onDeviceOffered","setting","seedOperatorChannel","onDeviceSigner","clampOperatorChannel","offered","fallback","draftOf","changed","hasOperator","visible","signerUnavailableChannels","_rowId","resolveWithHost","rule","draft","nextChannel","visibleCount","nextRows","resolveBatch","opChannel","seedForm","seededOperator","seededRows","seeded","noBatch","resolved","formSeed","operator","setOperator","rosterRows","setSigners","operatorChannel","setOperatorChannel","batchChannel","setBatchChannel","otpOverride","setOtpOverride","rosterCap","signers","assignmentOverrides","setAssignmentOverrides","operatorChannelOverrides","setOperatorChannelOverrides","itemOperatorChannels","dropChannelPicks","itemIds","current","assignItem","itemId","assignAllToMe","revertedTo","setRevertedTo","hostAnnouncement","setHostAnnouncement","awaitingQr","setAwaitingQr","qrIndex","setQrIndex","hasHistory","prevOpen","setPrevOpen","wasOpen","hasNoChannel","anySignerOnDevice","hostRule","assignLaterOptions","operatorEntries","disabled","deleted","operatorPickerList","operatorPickerHintId","isUnassigned","hostView","commitWithHost","extra","commitBatch","messages","primaryChanged","userChannel","clear","block","batchOffered","fallbackRows","channelOption","onDeviceHint","operatorChannelOptions","channelSizer","chosenIds","nextFreeOption","canAddSigner","_d","mainChannel","_e","secondBlock","secondSigneeHint","secondIssue","patientSmsPossible","otpForced","batchSkipOtp","batchOtpWarning","followsOtpRules","rowSkipOtp","rosterVisible","patchSigner","rowId","patch","addSigner","removeSigner","anySignerWithoutChannel","anySignerOnQr","anySignerSkipsOtp","formatList","channelOptionsFor","channelReasons","reasonsOnly","byReason","labels","batchListed","_f","batchUnavailable","batchChannelOptions","batchChannelHint","handleRequest","roster","signMode","operatorAssignments","firstOperatorId","hasQrCodes","qrStep","qrSlots","code","qrTotal","qrCurrent","qrSignerId","qrName","qrCode","qrExpiry","isLastQr","showQrCount","qrFocusKey","outcomeFocusKey","qrDescription","event","Spinner","Separator","Avatar","Plus","Switch","checked","rowOptions","rowLabel","rowIsMinor","isSecond","personOptions","known","issue","issueId","labelId","rowUnavailable","rowListed","rowChannelOptions","rowNoChannel","rowChannelHint","rowChannelHintId","rowOtpForced","canRemove","changePerson","clearSecond","changeChannel","personRow","X","PenLine"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}
|
|
1
|
+
{"version":3,"file":"signature-request-BUGeG8oD.js","sources":["../../node_modules/lucide-react/dist/esm/icons/link-2.mjs","../../node_modules/lucide-react/dist/esm/icons/qr-code.mjs","../../node_modules/lucide-react/dist/esm/icons/shopping-cart.mjs","../../node_modules/lucide-react/dist/esm/icons/tablet.mjs","../../src/patterns/signature-request/channel-meta.tsx","../../src/patterns/signature-request/load-status.tsx","../../src/patterns/signature-request/person-grid.tsx","../../src/patterns/signature-request/signature-history.tsx","../../src/patterns/signature-request/required-documents.tsx","../../src/patterns/signature-request/signature-outcome.tsx","../../src/patterns/signature-request/signature-request.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M9 17H7A5 5 0 0 1 7 7h2\", key: \"8i5ue5\" }],\n [\"path\", { d: \"M15 7h2a5 5 0 1 1 0 10h-2\", key: \"1b9ql8\" }],\n [\"line\", { x1: \"8\", x2: \"16\", y1: \"12\", y2: \"12\", key: \"1jonct\" }]\n];\nconst Link2 = createLucideIcon(\"link-2\", __iconNode);\n\nexport { __iconNode, Link2 as default };\n//# sourceMappingURL=link-2.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"3\", rx: \"1\", key: \"1tu5fj\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"16\", y: \"3\", rx: \"1\", key: \"1v8r4q\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"1x03jg\" }],\n [\"path\", { d: \"M21 16h-3a2 2 0 0 0-2 2v3\", key: \"177gqh\" }],\n [\"path\", { d: \"M21 21v.01\", key: \"ents32\" }],\n [\"path\", { d: \"M12 7v3a2 2 0 0 1-2 2H7\", key: \"8crl2c\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M12 3h.01\", key: \"n36tog\" }],\n [\"path\", { d: \"M12 16v.01\", key: \"133mhm\" }],\n [\"path\", { d: \"M16 12h1\", key: \"1slzba\" }],\n [\"path\", { d: \"M21 12v.01\", key: \"1lwtk9\" }],\n [\"path\", { d: \"M12 21v-1\", key: \"1880an\" }]\n];\nconst QrCode = createLucideIcon(\"qr-code\", __iconNode);\n\nexport { __iconNode, QrCode as default };\n//# sourceMappingURL=qr-code.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"circle\", { cx: \"8\", cy: \"21\", r: \"1\", key: \"jimo8o\" }],\n [\"circle\", { cx: \"19\", cy: \"21\", r: \"1\", key: \"13723u\" }],\n [\n \"path\",\n {\n d: \"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\",\n key: \"9zh506\"\n }\n ]\n];\nconst ShoppingCart = createLucideIcon(\"shopping-cart\", __iconNode);\n\nexport { __iconNode, ShoppingCart as default };\n//# sourceMappingURL=shopping-cart.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"rect\", { width: \"16\", height: \"20\", x: \"4\", y: \"2\", rx: \"2\", ry: \"2\", key: \"76otgf\" }],\n [\"line\", { x1: \"12\", x2: \"12.01\", y1: \"18\", y2: \"18\", key: \"1dp563\" }]\n];\nconst Tablet = createLucideIcon(\"tablet\", __iconNode);\n\nexport { __iconNode, Tablet as default };\n//# sourceMappingURL=tablet.mjs.map\n","/**\n * Channel labels and icons shared by the request form and the signatures\n * list, so a channel reads the same in both views.\n */\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Mail,\n MessageSquare,\n QrCode as QrCodeIcon,\n Tablet,\n} from 'lucide-react';\nimport { WhatsAppGlyph } from '../../components/whatsapp-button';\n\n/**\n * Delivery channel for one signer's signature request. `'qr'` means the\n * signer scans a QR code that the dialog shows in its QR step after the\n * request (see `qrCodes`). Every patient-side signer is offered `'qr'`\n * unless their `availableChannels` leaves it out; the operator never is.\n */\nexport type SignatureChannel =\n | 'sms'\n | 'email'\n | 'whatsapp'\n | 'on-device'\n | 'qr';\n\n/**\n * Delivery channel for an operator's counter-sign request. The default is\n * system defined: the operator's own `defaultChannel` arrives preselected.\n */\nexport type OperatorChannel = 'sms' | 'email' | 'on-device';\n\n/** Operator channel display order. */\nexport const OPERATOR_CHANNELS: readonly OperatorChannel[] = [\n 'sms',\n 'email',\n 'on-device',\n];\n\nexport type ChannelMeta = Record<\n SignatureChannel,\n {\n /** The label: the list's text and the channel dropdown's option. */\n label: string;\n icon: ReactNode;\n }\n>;\n\n/** Translated labels and decorative icon for every channel. */\nexport function useChannelMeta(): ChannelMeta {\n const { t } = useTranslation();\n return {\n sms: {\n label: t('signatureRequest.viaSms'),\n icon: <MessageSquare className=\"ds:size-4\" aria-hidden />,\n },\n email: {\n label: t('signatureRequest.viaEmail'),\n icon: <Mail className=\"ds:size-4\" aria-hidden />,\n },\n whatsapp: {\n label: t('signatureRequest.viaWhatsapp'),\n icon: <WhatsAppGlyph className=\"ds:size-4\" aria-hidden />,\n },\n 'on-device': {\n label: t('signatureRequest.onThisDevice'),\n icon: <Tablet className=\"ds:size-4\" aria-hidden />,\n },\n qr: {\n label: t('signatureRequest.viaQr'),\n icon: <QrCodeIcon className=\"ds:size-4\" aria-hidden />,\n },\n };\n}\n","/**\n * A polite, visually hidden status for a view that loads its rows. It stays\n * mounted in both states and starts empty, so screen readers hear the\n * loading text as a change, and then hear that the rows arrived.\n *\n * Keep it outside any `aria-busy` container: screen readers hold back\n * updates inside a busy subtree.\n */\nimport { useEffect, useRef, useState } from 'react';\n\nexport interface LoadStatusProps {\n loading: boolean;\n loadingText: string;\n /** Said once when loading ends. Nothing is said if it never loaded. */\n loadedText: string;\n /**\n * Another message for the same region, e.g. that a row was deleted. It\n * wins while set and not loading; `''` empties the region.\n */\n message?: string;\n}\n\nexport function LoadStatus({\n loading,\n loadingText,\n loadedText,\n message: override,\n}: LoadStatusProps) {\n const [message, setMessage] = useState('');\n const wasLoading = useRef(false);\n // Set after mount, never on the first render, so the text is an update.\n useEffect(() => {\n if (loading) setMessage(loadingText);\n else if (wasLoading.current) setMessage(loadedText);\n wasLoading.current = loading;\n }, [loading, loadingText, loadedText]);\n return (\n <span role=\"status\" className=\"ds:sr-only\">\n {override !== undefined && !loading ? override : message}\n </span>\n );\n}\n","/**\n * One grid for every person row in SignatureRequestModal: the operator, each\n * patient signer and each required item's operator picker.\n *\n * wide: [avatar] [name, 1fr] [channel, sized to the longest label] [action]\n * narrow: [avatar] [name, 1fr] [action]\n * [channel ]\n *\n * The avatar column fits Avatar `sm`. The action column is the remove\n * control's target size (`--min-target-size`: IconButton `sm` widens its hit\n * area to it on small screens) and stays reserved when a row has no action,\n * so every select ends on the same edges. Everything under a person (OTP switch,\n * notes, errors) spans the name and channel columns, so it starts at the\n * name select's left edge. The wide layout needs a `PERSON_SECTION`\n * ancestor at least 512px wide (px, not rem: see host-compat).\n */\nimport { ChevronDown } from 'lucide-react';\nimport { selectTriggerVariants } from '../../components/select/select';\nimport type { ChannelMeta } from './channel-meta';\n\nexport const PERSON_GRID =\n 'ds:grid ds:grid-cols-[var(--spacing-xl)_minmax(0,1fr)_var(--min-target-size)] ds:@[512px]/person:grid-cols-[var(--spacing-xl)_minmax(0,1fr)_max-content_var(--min-target-size)] ds:items-center ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-sm)]';\n\nexport const PERSON_AVATAR =\n 'ds:col-start-1 ds:row-start-1 ds:flex ds:items-center ds:justify-center';\n\n/** The name select, in a row that also has a channel select. */\nexport const PERSON_NAME = 'ds:col-start-2 ds:row-start-1 ds:min-w-0';\n\n/** The name select, in a row with no channel: it takes the channel's width. */\nexport const PERSON_NAME_FULL = 'ds:col-[2/-2] ds:row-start-1 ds:min-w-0';\n\n/**\n * The channel select: beside the name when wide, under it when narrow.\n * `-3/-2` is the name column in the 3-column grid and the channel column in\n * the 4-column one.\n */\nexport const PERSON_CHANNEL =\n 'ds:col-[-3/-2] ds:row-start-2 ds:min-w-0 ds:@[512px]/person:row-start-1';\n\nexport const PERSON_ACTION =\n 'ds:col-[-2/-1] ds:row-start-1 ds:flex ds:items-center ds:justify-center';\n\n/** Rows under a person (OTP switch, notes, errors): name to channel edge. */\nexport const PERSON_UNDER = 'ds:col-[2/-2] ds:min-w-0 ds:text-start';\n\n/** A section header row: eyebrow at the avatar edge, action at the selects' end edge. */\nexport const PERSON_HEADER =\n 'ds:col-[1/-2] ds:row-start-1 ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]';\n\n/** Space between two person blocks: larger than the gap inside one. */\nexport const PERSON_LIST = 'ds:flex ds:flex-col ds:gap-[var(--spacing-md)]';\n\n/** Put on each section that holds person grids: the container above. */\nexport const PERSON_SECTION = 'ds:@container/person';\n\n/**\n * Sizes the channel column to the longest channel label, in every row and\n * whatever is selected, so all channel selects share one width. A hidden,\n * zero-height copy of the select trigger per label; the column's\n * `max-content` width comes from the widest.\n */\nexport function ChannelColumnSizer({ meta }: { meta: ChannelMeta }) {\n return (\n <span\n aria-hidden=\"true\"\n data-channel-sizer=\"\"\n className=\"ds:invisible ds:block ds:h-0 ds:overflow-hidden\"\n >\n {Object.entries(meta).map(([channel, { label, icon }]) => (\n <span key={channel} className=\"ds:flex ds:w-max\">\n <span className={selectTriggerVariants({ size: 'md' })}>\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span className=\"ds:inline-flex ds:shrink-0\">{icon}</span>\n <span className=\"ds:whitespace-nowrap\">{label}</span>\n </span>\n <ChevronDown className=\"ds:size-4 ds:shrink-0\" />\n </span>\n </span>\n ))}\n </span>\n );\n}\n","/**\n * The signed versions section of SignatureRequestModal, shown at the top of\n * the request form when the host passes `signatures` (or\n * `signaturesLoading`), as on platform's \"Documenti firmati\" modal. A table\n * of past signature requests with the columns Date, Signature type and\n * Actions: when it was made, its legal level, how it was sent and who has\n * signed (SignatureStatusChip, names in its tooltip), then View, Download,\n * Share (to the targets the host allows) and Delete (after a confirmation).\n *\n * The table is ARIA (`role=\"table\"`), not an HTML table, so rows can stack\n * on narrow widths. It sits on the person grid, so its edges match the form's\n * sections below it.\n */\nimport { useEffect, useId, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Download, Eye, Link2, Mail, Share2, Trash2 } from 'lucide-react';\nimport { Button } from '../../components/button';\nimport { Dialog } from '../../components/dialog';\nimport { Skeleton } from '../../components/skeleton';\nimport { IconButton } from '../../components/icon-button';\nimport { DropdownMenu } from '../../components/dropdown-menu';\nimport { Tooltip, TooltipProvider } from '../../components/tooltip';\nimport { WhatsAppGlyph } from '../../components/whatsapp-button';\nimport {\n SignatureStatusChip,\n type SignatureParty,\n type SignatureSignerNames,\n} from '../../components/signature-status-chip';\nimport { useChannelMeta, type SignatureChannel } from './channel-meta';\nimport { LoadStatus } from './load-status';\nimport { PERSON_GRID, PERSON_HEADER, PERSON_SECTION } from './person-grid';\n\n/** Legal weight of a signature. Advanced needs an OTP-verified signer. */\nexport type SignatureLegalLevel = 'simple' | 'advanced';\n\n/** Which file a download asks for. */\nexport type SignatureDownloadVersion = 'full' | 'anonymised';\n\n/** How a signed document is shared. */\nexport type SignatureShareTarget = 'link' | 'email' | 'whatsapp';\n\n/** Every share target, in menu order. */\nconst SHARE_TARGETS: readonly SignatureShareTarget[] = [\n 'link',\n 'email',\n 'whatsapp',\n];\n\n/** One past signature request on the document. */\nexport interface SignatureRecord {\n /** Host id, handed back to every row callback. */\n id: string;\n /**\n * When the request was made: a `Date` or an ISO 8601 string, shown as\n * weekday, date and time in the active locale and the browser's time zone\n * (Italian: \"Mar. il 25/08/2026 ore 12:45\"). An unparseable string is\n * shown as it is.\n */\n createdAt: Date | string;\n /** How the request reached the signer. */\n channel: SignatureChannel;\n /** Omit to show no legal level on this row. */\n legalLevel?: SignatureLegalLevel;\n /** The operator's standing, as on SignatureStatusChip. */\n operator: SignatureParty;\n /** The patient's standing, as on SignatureStatusChip. */\n patient: SignatureParty;\n /** The second signee's standing. Defaults to `notRequired`. */\n secondary?: SignatureParty;\n /**\n * Signer names for the chip's tooltip, including who signed on a\n * party's behalf (a parent for a minor). Same shape as the chip's `names`.\n */\n names?: SignatureSignerNames;\n /** Offer the anonymised file beside the full one on download. */\n hasAnonymisedVersion?: boolean;\n /**\n * Where this document can be shared, e.g. no `'whatsapp'` for a patient\n * with no mobile number. Wins over the list's `shareTargets`. The menu\n * keeps its own order (link, e-mail, WhatsApp); an empty list hides Share\n * on this row.\n */\n shareTargets?: readonly SignatureShareTarget[];\n}\n\nexport interface SignatureHistoryProps {\n signatures?: readonly SignatureRecord[];\n loading?: boolean;\n showLegalLevel?: boolean;\n onView?: (id: string) => void;\n onDownload?: (id: string, version: SignatureDownloadVersion) => void;\n onShare?: (id: string, via: SignatureShareTarget) => void;\n /** Share targets for rows without their own. Default: all three. */\n shareTargets?: readonly SignatureShareTarget[];\n onDelete?: (id: string) => void;\n}\n\nconst LOADING_ROWS = [0, 1];\n\n/*\n * Narrow: date and actions on one line, the signature type under them, no\n * visible column headers. Wide (the person container at 512px, as the form's\n * rows): three columns shared by every row through subgrid, headers shown.\n */\nconst TABLE =\n 'ds:flex ds:flex-col ds:@[512px]/person:grid ds:@[512px]/person:grid-cols-[max-content_minmax(0,1fr)_max-content] ds:@[512px]/person:gap-x-[var(--spacing-md)]';\nconst ROWGROUP =\n 'ds:flex ds:flex-col ds:@[512px]/person:col-span-full ds:@[512px]/person:grid ds:@[512px]/person:grid-cols-subgrid';\nconst ROW =\n 'ds:grid ds:grid-cols-[minmax(0,1fr)_max-content] ds:items-center ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-xs)] ds:py-[var(--spacing-xs)] ds:@[512px]/person:col-span-full ds:@[512px]/person:grid-cols-subgrid ds:@[512px]/person:gap-x-[var(--spacing-md)]';\nconst CELL_DATE =\n 'ds:col-start-1 ds:row-start-1 ds:min-w-0 ds:text-start ds:@[512px]/person:col-start-1 ds:@[512px]/person:whitespace-nowrap';\nconst CELL_TYPE =\n 'ds:col-span-full ds:row-start-2 ds:min-w-0 ds:text-start ds:@[512px]/person:col-span-1 ds:@[512px]/person:col-start-2 ds:@[512px]/person:row-start-1';\nconst CELL_ACTIONS =\n 'ds:col-start-2 ds:row-start-1 ds:flex ds:justify-end ds:@[512px]/person:col-start-3';\n\nfunction timeOf(value: Date | string): number | null {\n const ms = (value instanceof Date ? value : new Date(value)).getTime();\n return Number.isNaN(ms) ? null : ms;\n}\n\n/** Newest first. Equal or unparseable dates keep the host order, last. */\nfunction newestFirst(\n records: readonly SignatureRecord[],\n): readonly SignatureRecord[] {\n return records\n .map((record, index) => ({ record, index, ms: timeOf(record.createdAt) }))\n .sort((a, b) => {\n if (a.ms === b.ms) return a.index - b.index;\n if (a.ms === null) return 1;\n if (b.ms === null) return -1;\n return b.ms - a.ms;\n })\n .map(({ record }) => record);\n}\n\nexport function SignatureHistory({\n signatures,\n loading = false,\n showLegalLevel = true,\n onView,\n onDownload,\n onShare,\n shareTargets = SHARE_TARGETS,\n onDelete,\n}: SignatureHistoryProps) {\n const { t, i18n } = useTranslation();\n const channelMeta = useChannelMeta();\n const headingId = useId();\n const shareMeta: Record<\n SignatureShareTarget,\n { label: string; icon: React.ReactNode }\n > = {\n link: { label: t('signatureRequest.shareLink'), icon: <Link2 /> },\n email: { label: t('signatureRequest.viaEmail'), icon: <Mail /> },\n whatsapp: {\n label: t('signatureRequest.viaWhatsapp'),\n icon: <WhatsAppGlyph />,\n },\n };\n // Platform's date: short weekday, numeric date, time. House English is\n // British, so `en` asks for en-GB (25/08/2026, 24-hour).\n const language = i18n.language || 'en';\n const intlLocale = language === 'en' ? 'en-GB' : language;\n const weekdayFormat = new Intl.DateTimeFormat(intlLocale, {\n weekday: 'short',\n });\n const dayFormat = new Intl.DateTimeFormat(intlLocale, {\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n });\n const timeFormat = new Intl.DateTimeFormat(intlLocale, {\n hour: '2-digit',\n minute: '2-digit',\n });\n const formatWhen = (ms: number) => {\n const weekday = weekdayFormat.format(ms);\n return t('signatureRequest.signedAt', {\n weekday:\n weekday.charAt(0).toLocaleUpperCase(intlLocale) + weekday.slice(1),\n date: dayFormat.format(ms),\n time: timeFormat.format(ms),\n interpolation: { escapeValue: false },\n });\n };\n\n const tableRef = useRef<HTMLDivElement>(null);\n const emptyRef = useRef<HTMLParagraphElement>(null);\n // A confirmed delete, with the row order at that moment, until the host\n // drops the record.\n const pendingDelete = useRef<{ id: string; order: string[] } | null>(null);\n const [deleteStatus, setDeleteStatus] = useState<string>();\n\n // The deleted row takes its Delete button (and Radix's focus target) with\n // it, so focus moves on purpose: next row, else previous, else the empty\n // line.\n useEffect(() => {\n const pending = pendingDelete.current;\n if (!pending || loading) return;\n const remaining = new Set((signatures ?? []).map((record) => record.id));\n if (remaining.has(pending.id)) return;\n pendingDelete.current = null;\n setDeleteStatus(t('signatureRequest.signatureDeleted'));\n const at = pending.order.indexOf(pending.id);\n const targetId =\n pending.order.slice(at + 1).find((id) => remaining.has(id)) ??\n pending.order\n .slice(0, at)\n .reverse()\n .find((id) => remaining.has(id));\n // After Radix's own unmount focus, which runs on a zero timeout.\n window.setTimeout(() => {\n const active = document.activeElement;\n const lost =\n !active ||\n active === document.body ||\n !active.isConnected ||\n active.matches('[role=\"dialog\"], [role=\"alertdialog\"]');\n if (!lost) return;\n if (targetId === undefined) {\n emptyRef.current?.focus();\n return;\n }\n const row = Array.from(\n tableRef.current?.querySelectorAll<HTMLElement>(\n '[data-signature-id]',\n ) ?? [],\n ).find((element) => element.dataset.signatureId === targetId);\n row?.querySelector<HTMLElement>('[role=\"group\"] button')?.focus();\n }, 0);\n }, [signatures, loading, t]);\n\n const sorted = signatures ? newestFirst(signatures) : [];\n\n let content: React.ReactNode;\n if (loading) {\n content = (\n <div\n aria-busy=\"true\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n {LOADING_ROWS.map((row) => (\n <div\n key={row}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\"\n >\n <div className=\"ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <Skeleton size=\"md\" width=\"40%\" />\n <Skeleton size=\"sm\" width=\"70%\" />\n </div>\n <Skeleton variant=\"circular\" size=\"sm\" />\n <Skeleton variant=\"circular\" size=\"sm\" />\n <Skeleton variant=\"circular\" size=\"sm\" />\n </div>\n ))}\n </div>\n );\n } else if (sorted.length === 0) {\n content = (\n <p\n ref={emptyRef}\n // Focus lands here when the last row is deleted.\n tabIndex={-1}\n data-note=\"no-signed-versions\"\n className=\"type-body-sm ds:text-[color:var(--muted-foreground)] ds:outline-none\"\n >\n {t('signatureRequest.noSignedVersions')}\n </p>\n );\n } else {\n const headerCell =\n 'type-label ds:text-[color:var(--muted-foreground)] ds:pb-[var(--spacing-xs)]';\n content = (\n // The chip's tooltip and the icon-button tooltips need a provider; the\n // section brings its own so a host without one does not crash.\n <TooltipProvider>\n <div\n ref={tableRef}\n role=\"table\"\n aria-labelledby={headingId}\n className={TABLE}\n >\n {/* Column headers: visible on wide screens, for assistive tech\n only when the rows stack. */}\n <div\n role=\"rowgroup\"\n className={`${ROWGROUP} ds:sr-only ds:@[512px]/person:not-sr-only`}\n >\n <div\n role=\"row\"\n className={`${ROW} ds:border-b ds:border-[color:var(--border)]`}\n >\n <span\n role=\"columnheader\"\n className={`${CELL_DATE} ${headerCell}`}\n >\n {t('signatureRequest.columnDate')}\n </span>\n <span\n role=\"columnheader\"\n className={`${CELL_TYPE} ${headerCell}`}\n >\n {t('signatureRequest.columnSignatureType')}\n </span>\n <span\n role=\"columnheader\"\n className={`${CELL_ACTIONS} ${headerCell}`}\n >\n {t('signatureRequest.columnActions')}\n </span>\n </div>\n </div>\n <div role=\"rowgroup\" className={ROWGROUP}>\n {sorted.map((record, index) => {\n const ms = timeOf(record.createdAt);\n const when =\n ms === null ? String(record.createdAt) : formatWhen(ms);\n const dateTime =\n ms === null ? undefined : new Date(ms).toISOString();\n const channel = channelMeta[record.channel];\n const allowedTargets = record.shareTargets ?? shareTargets;\n const rowShareTargets = onShare\n ? SHARE_TARGETS.filter((target) =>\n allowedTargets.includes(target),\n )\n : [];\n const hasActions =\n onView !== undefined ||\n onDownload !== undefined ||\n rowShareTargets.length > 0 ||\n onDelete !== undefined;\n return (\n <div\n key={record.id}\n role=\"row\"\n data-signature-id={record.id}\n className={\n index === 0\n ? ROW\n : `${ROW} ds:border-t ds:border-[color:var(--border)]`\n }\n >\n <div role=\"cell\" className={`${CELL_DATE} type-body`}>\n <time dateTime={dateTime}>{when}</time>\n </div>\n <div role=\"cell\" className={CELL_TYPE}>\n <span className=\"type-body-sm ds:flex ds:flex-wrap ds:items-center ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\">\n {showLegalLevel && record.legalLevel ? (\n <span>\n {record.legalLevel === 'advanced'\n ? t('signatureRequest.legalLevelAdvanced')\n : t('signatureRequest.legalLevelSimple')}\n </span>\n ) : null}\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[var(--accent)]\"\n >\n {channel.icon}\n </span>\n {channel.label}\n </span>\n <SignatureStatusChip\n size=\"sm\"\n operator={record.operator}\n patient={record.patient}\n secondary={record.secondary}\n names={record.names}\n tooltip\n />\n </span>\n </div>\n <div role=\"cell\" className={CELL_ACTIONS}>\n {hasActions ? (\n <span\n role=\"group\"\n aria-label={t('signatureRequest.signatureActions', {\n date: when,\n interpolation: { escapeValue: false },\n })}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {onView ? (\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={<Eye />}\n aria-label={t('signatureRequest.viewSignature')}\n tooltip={t('signatureRequest.viewSignature')}\n onClick={() => onView(record.id)}\n />\n ) : null}\n {onDownload && record.hasAnonymisedVersion ? (\n <RowMenu\n id={`signature-download-${record.id}`}\n label={t('signatureRequest.downloadSignature')}\n icon={<Download />}\n >\n <DropdownMenu.Item\n onSelect={() => onDownload(record.id, 'full')}\n >\n {t('signatureRequest.downloadFull')}\n </DropdownMenu.Item>\n <DropdownMenu.Item\n onSelect={() =>\n onDownload(record.id, 'anonymised')\n }\n >\n {t('signatureRequest.downloadAnonymised')}\n </DropdownMenu.Item>\n </RowMenu>\n ) : onDownload ? (\n // One file only: a menu with a single entry would\n // be an extra click for nothing.\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={<Download />}\n aria-label={t('signatureRequest.downloadSignature')}\n tooltip={t('signatureRequest.downloadSignature')}\n onClick={() => onDownload(record.id, 'full')}\n />\n ) : null}\n {onShare && rowShareTargets.length > 0 ? (\n <RowMenu\n id={`signature-share-${record.id}`}\n label={t('signatureRequest.shareSignature')}\n icon={<Share2 />}\n >\n {rowShareTargets.map((target) => (\n <DropdownMenu.Item\n key={target}\n startIcon={shareMeta[target].icon}\n onSelect={() => onShare(record.id, target)}\n >\n {shareMeta[target].label}\n </DropdownMenu.Item>\n ))}\n </RowMenu>\n ) : null}\n {onDelete ? (\n <DeleteConfirm\n id={`signature-delete-${record.id}`}\n when={when}\n dateTime={dateTime}\n onConfirm={() => {\n pendingDelete.current = {\n id: record.id,\n order: sorted.map((item) => item.id),\n };\n setDeleteStatus('');\n onDelete(record.id);\n }}\n />\n ) : null}\n </span>\n ) : null}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n </TooltipProvider>\n );\n }\n\n return (\n <section\n aria-labelledby={headingId}\n data-section=\"signed-versions\"\n className={`${PERSON_SECTION} ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:text-start`}\n >\n <div className={PERSON_GRID}>\n <div className={PERSON_HEADER}>\n <h3\n id={headingId}\n className=\"type-eyebrow ds:m-0 ds:text-[color:var(--muted-foreground)]\"\n >\n {t('signatureRequest.signedVersions')}\n </h3>\n </div>\n </div>\n <div className={PERSON_GRID}>\n {/* From the avatar edge to the selects' end edge, as the form. */}\n <div className=\"ds:col-[1/-2] ds:min-w-0\">\n {/* One status region for loading, loaded and deleted, outside the\n busy container. */}\n <LoadStatus\n loading={loading}\n loadingText={t('signatureRequest.signaturesLoading')}\n loadedText={t('signatureRequest.signaturesLoaded')}\n message={deleteStatus}\n />\n {content}\n </div>\n </div>\n </section>\n );\n}\n\n/**\n * Keeps an icon button's tooltip shut while focus comes back to the button\n * from the menu or dialog it opened. A focused trigger opens its tooltip, so\n * without this the tip pops up unasked. It opens again once the user moves\n * the pointer onto the button or focus leaves it.\n */\nfunction useQuietReturnTooltip() {\n const [tipOpen, setTipOpen] = useState(false);\n const restoringFocus = useRef(false);\n return {\n tooltipProps: {\n open: tipOpen,\n onOpenChange: (next: boolean) => {\n if (next && restoringFocus.current) return;\n setTipOpen(next);\n },\n },\n triggerProps: {\n onPointerMove: () => {\n restoringFocus.current = false;\n },\n onBlur: () => {\n restoringFocus.current = false;\n },\n },\n hideTip: () => setTipOpen(false),\n /** Call just before focus returns to the trigger. */\n markReturning: () => {\n restoringFocus.current = true;\n },\n };\n}\n\ninterface RowMenuProps {\n /** Stable, non-PHI instance id for the dropdown-menu adapter. */\n id: string;\n label: string;\n icon: React.ReactNode;\n children: React.ReactNode;\n}\n\n/** An icon button with a tooltip that opens a menu. */\nfunction RowMenu({ id, label, icon, children }: RowMenuProps) {\n const tip = useQuietReturnTooltip();\n return (\n <DropdownMenu.Root\n id={id}\n onOpenChange={(menuOpen) => {\n if (menuOpen) tip.hideTip();\n }}\n >\n <Tooltip label={label} {...tip.tooltipProps}>\n <DropdownMenu.Trigger asChild>\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={icon}\n aria-label={label}\n {...tip.triggerProps}\n />\n </DropdownMenu.Trigger>\n </Tooltip>\n <DropdownMenu.Content\n align=\"end\"\n // Runs before Radix moves focus back to the trigger.\n onCloseAutoFocus={tip.markReturning}\n >\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\ninterface DeleteConfirmProps {\n /** Stable, non-PHI instance id for the dialog adapter. */\n id: string;\n /** The row's date as shown, repeated in the confirmation. */\n when: string;\n dateTime?: string;\n onConfirm: () => void;\n}\n\n/**\n * The row's Delete button and its confirmation, a forced-choice alert\n * dialog. Cancel, Esc and Delete all put focus back on the button; once the\n * host drops the record, SignatureHistory moves it on.\n */\nfunction DeleteConfirm({ id, when, dateTime, onConfirm }: DeleteConfirmProps) {\n const { t } = useTranslation();\n const tip = useQuietReturnTooltip();\n const [open, setOpen] = useState(false);\n const label = t('signatureRequest.deleteSignature');\n return (\n <Dialog\n id={id}\n open={open}\n onOpenChange={(next) => {\n if (next) tip.hideTip();\n setOpen(next);\n }}\n >\n <Tooltip label={label} {...tip.tooltipProps}>\n <Dialog.Trigger asChild>\n <IconButton\n intent=\"destructiveOutline\"\n size=\"sm\"\n icon={<Trash2 />}\n aria-label={label}\n {...tip.triggerProps}\n />\n </Dialog.Trigger>\n </Tooltip>\n <Dialog.Content\n variant=\"alert\"\n size=\"sm\"\n // Runs before Radix moves focus back to the trigger.\n onCloseAutoFocus={tip.markReturning}\n >\n <Dialog.Header>\n <Dialog.Title>\n {t('signatureRequest.deleteSignatureConfirm')}\n </Dialog.Title>\n {/* Which request this is: the date the row shows. */}\n <Dialog.Description>\n <time dateTime={dateTime}>{when}</time>\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button intent=\"outline\">{t('common.cancel')}</Button>\n </Dialog.Close>\n <Button\n intent=\"destructive\"\n startIcon={<Trash2 />}\n onClick={() => {\n onConfirm();\n setOpen(false);\n }}\n >\n {label}\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog>\n );\n}\n","/**\n * The required documents view: the body of SignatureRequestModal when the\n * host passes `requiredItems` (or `requiredItemsLoading`). It lists every\n * outstanding document and anamnesis interview for one patient, in two\n * groups with counts, each row with the item name and, where an operator must\n * sign, that item's own operator picker. Rows show no signing status: as on\n * platform, the documents API says only whether an item is signed.\n *\n * Renders body content only; the modal owns the header, the signer roster\n * and the footer, and holds the per-item operator assignments.\n */\nimport { useId } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { UserPlus } from 'lucide-react';\nimport { Alert } from '../../components/alert';\nimport { Button } from '../../components/button';\nimport { List } from '../../components/list';\nimport { Select, type SelectOption } from '../../components/select';\nimport { Skeleton } from '../../components/skeleton';\nimport {\n OPERATOR_CHANNELS,\n useChannelMeta,\n type OperatorChannel,\n type SignatureChannel,\n} from './channel-meta';\nimport { LoadStatus } from './load-status';\nimport {\n ChannelColumnSizer,\n PERSON_GRID,\n PERSON_HEADER,\n PERSON_SECTION,\n PERSON_UNDER,\n} from './person-grid';\n\n/** Select value for \"Assign later\" in every operator picker. */\nexport const ASSIGN_LATER = '__assign-later__';\n\n/** What a required item is. Anamnesis interviews never carry a second signee. */\nexport type RequiredSignatureItemKind = 'document' | 'anamnesis';\n\n/** One outstanding document or anamnesis interview in the batch. */\nexport interface RequiredSignatureItem {\n /** Host id, the key of `operatorAssignments` in the submission. */\n id: string;\n kind: RequiredSignatureItemKind;\n /** Display name, e.g. the document template name. */\n name: string;\n /** Whether an operator must sign this item. Shows its operator picker. */\n requiresOperator: boolean;\n /**\n * Whether this document has a field for the second signee. The second\n * signee is offered only when every listed item can carry it. Ignored for\n * `kind: 'anamnesis'`, which never can. Default `false`.\n */\n canCarrySecondary?: boolean;\n /**\n * Preselected operator for this item; `null` preselects \"Assign later\".\n * Omit to use the modal's `initialOperatorId`.\n */\n initialOperatorId?: string | null;\n /**\n * Whether the item is already signed (platform `signed` on a document,\n * `isSigned` on an interview). Signed items are left out. Default `false`.\n * There is no per-party standing: platform's documents API has none.\n */\n signed?: boolean;\n}\n\n/** The items that still need a signature: those not signed. */\nexport function itemsStillToSign(\n items: readonly RequiredSignatureItem[],\n): RequiredSignatureItem[] {\n return items.filter((item) => item.signed !== true);\n}\n\n/**\n * The second signee signs the whole batch in one round, so it is offered\n * only when every item can carry that signature. `[].every()` is true, so an\n * empty batch cannot.\n */\nexport function batchCanCarrySecondary(\n items: readonly RequiredSignatureItem[],\n): boolean {\n return (\n items.length > 0 &&\n items.every(\n (item) => item.kind === 'document' && item.canCarrySecondary === true,\n )\n );\n}\n\n/** Whether an item gets an operator picker: an operator must sign it. */\nexport function needsOperatorPick(item: RequiredSignatureItem): boolean {\n return item.requiresOperator;\n}\n\n/**\n * One option in an operator picker. \"Assign later\" comes first, as on\n * platform (OperatorSignee.js). A `disabled` operator shows greyed out with\n * its `description` (the host's reason); a `deleted` one is hidden unless it\n * is the picker's current value.\n */\nexport interface OperatorPickerOption {\n value: string;\n label: string;\n disabled?: boolean;\n description?: string;\n deleted?: boolean;\n}\n\n/** The options one picker lists, given its current value. */\nexport function operatorPickerOptions(\n options: readonly OperatorPickerOption[],\n selected: string | undefined,\n): SelectOption[] {\n return options\n .filter((option) => option.deleted !== true || option.value === selected)\n .map(({ deleted: _deleted, ...option }) => option);\n}\n\n/** Whether a user could pick this value: listed, not greyed out or deleted. */\nexport function isPickableOperator(\n options: readonly OperatorPickerOption[],\n value: string,\n): boolean {\n return options.some(\n (option) =>\n option.value === value &&\n option.disabled !== true &&\n option.deleted !== true,\n );\n}\n\n/**\n * The greyed-out operators and their reasons, for the picker trigger: a\n * disabled option cannot take focus, so its own description is never heard.\n * `undefined` when none is greyed out.\n */\nexport function operatorReasonsHint(\n options: readonly OperatorPickerOption[],\n locale: string,\n): string | undefined {\n const entries = options\n .filter((option) => option.disabled === true && option.deleted !== true)\n .map((option) =>\n option.description\n ? `${option.label} (${option.description})`\n : option.label,\n );\n if (entries.length === 0) return undefined;\n return new Intl.ListFormat(locale || 'en', { type: 'unit' }).format(entries);\n}\n\n/**\n * Why the second signee is withheld from a batch, first reason first; `null`\n * when it is offered. Mirrors platform (secondarySigneeAvailability.ts and\n * SecondarySignee.tsx): every item can carry it, the batch is signed on this\n * device, and the main signer is a registered signee, not the patient.\n */\nexport type SecondSigneeBlock =\n | 'anamnesis'\n | 'documents'\n | 'patient'\n | 'channel';\n\nexport function secondSigneeBlock({\n items,\n channel,\n primaryIsPatient,\n}: {\n items: readonly RequiredSignatureItem[];\n channel: SignatureChannel;\n primaryIsPatient: boolean;\n}): SecondSigneeBlock | null {\n if (!batchCanCarrySecondary(items)) {\n return items.some((item) => item.kind === 'anamnesis')\n ? 'anamnesis'\n : 'documents';\n }\n if (primaryIsPatient) return 'patient';\n if (channel !== 'on-device') return 'channel';\n return null;\n}\n\n/** What is wrong with the chosen second signee (platform secondarySigneeValidation.ts). */\nexport type SecondSigneeIssue =\n | 'sameAsPrimary'\n | 'unknownSignee'\n | 'missingPhone'\n | 'missingEmail';\n\n/** The parts of a `SignerOption` the second signee checks read. */\nexport interface SecondSigneeCandidate {\n value: string;\n isPatient?: boolean;\n availableChannels?: readonly SignatureChannel[];\n unavailableChannels?: ReadonlyArray<{ channel: SignatureChannel }>;\n}\n\n/**\n * The first issue with a second signee, or `null`. Phone and e-mail are read\n * from channel availability, so no contact data reaches the kit: a person who\n * cannot receive SMS or WhatsApp has no phone, one who cannot receive e-mail\n * has no e-mail. The patient is never a signee, so picking them is unknown.\n */\nexport function secondSigneeIssue({\n primaryId,\n secondId,\n channel,\n options,\n}: {\n primaryId: string | undefined;\n secondId: string;\n channel: SignatureChannel;\n options: readonly SecondSigneeCandidate[];\n}): SecondSigneeIssue | null {\n if (secondId === primaryId) return 'sameAsPrimary';\n const second = options.find((option) => option.value === secondId);\n if (!second || second.isPatient === true) return 'unknownSignee';\n const receives = (wanted: SignatureChannel) =>\n (!second.availableChannels ||\n second.availableChannels.length === 0 ||\n second.availableChannels.includes(wanted)) &&\n !second.unavailableChannels?.some((entry) => entry.channel === wanted);\n if ((channel === 'sms' || channel === 'whatsapp') && !receives(channel)) {\n return 'missingPhone';\n }\n if (channel === 'email' && !receives('email')) return 'missingEmail';\n return null;\n}\n\nexport interface RequiredDocumentsProps {\n /** The items to list, already narrowed to those still to sign. */\n items: readonly RequiredSignatureItem[];\n loading?: boolean;\n /**\n * Operator options, \"Assign later\" first when allowed. Deleted operators\n * show only in a picker whose value they are.\n */\n operatorOptions: readonly OperatorPickerOption[];\n /** The picker value per item id, for items that require an operator. */\n assignments: Readonly<Record<string, string>>;\n onAssign: (itemId: string, operatorValue: string) => void;\n /** Shows \"Assign all to me\" when passed. */\n onAssignAllToMe?: () => void;\n busy?: boolean;\n /**\n * Adds each picked operator's channel beside their picker, in place of\n * the note that their settings decide. Default `false`.\n */\n showOperatorChannels?: boolean;\n /** The channel per item id, for items with an assigned operator. */\n operatorChannels?: Readonly<Record<string, OperatorChannel>>;\n onOperatorChannel?: (itemId: string, channel: OperatorChannel) => void;\n}\n\nconst LOADING_ROWS = [0, 1, 2];\n\n/**\n * One item row: the name, then the operator picker on the same\n * line. Two equal columns, so every picker in the list shares both edges;\n * the picker drops under the name when the section is narrow. With operator\n * channels a third column holds the channel select, as wide as the roster's\n * channel column (the same sizer), so its edges match the rows below.\n */\nconst ITEM_ROW =\n 'ds:grid ds:grid-cols-1 ds:@[512px]/person:grid-cols-2 ds:items-center ds:gap-[var(--spacing-sm)] ds:font-normal';\nconst ITEM_ROW_WITH_CHANNEL =\n 'ds:grid ds:grid-cols-1 ds:@[512px]/person:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_max-content] ds:items-center ds:gap-[var(--spacing-sm)] ds:font-normal';\nconst ITEM_NAME = 'ds:min-w-0 ds:font-medium';\nconst ITEM_NAME_FULL = 'ds:col-span-full ds:min-w-0 ds:font-medium';\nconst ITEM_PICKER = 'ds:block ds:min-w-0';\n\n/** A section note: the info Alert with the row's small padding and gap. */\nconst COMPACT_NOTE = 'ds:!gap-[var(--spacing-sm)] ds:!p-[var(--spacing-sm)]';\n\nexport function RequiredDocuments({\n items,\n loading = false,\n operatorOptions,\n assignments,\n onAssign,\n onAssignAllToMe,\n busy = false,\n showOperatorChannels = false,\n operatorChannels = {},\n onOperatorChannel,\n}: RequiredDocumentsProps) {\n const { t, i18n } = useTranslation();\n const channelMeta = useChannelMeta();\n // SMS, e-mail and on this device, as the request form's operator offers.\n const channelOptions: SelectOption<OperatorChannel>[] = OPERATOR_CHANNELS.map(\n (channel) => ({\n value: channel,\n label: channelMeta[channel].label,\n startAdornment: channelMeta[channel].icon,\n }),\n );\n const documentsHeadingId = useId();\n const interviewsHeadingId = useId();\n const operatorHintId = useId();\n\n // One status region for loading and loaded, outside the busy container.\n const status = (\n <LoadStatus\n loading={loading}\n loadingText={t('signatureRequest.requiredLoading')}\n loadedText={t('signatureRequest.requiredLoaded')}\n />\n );\n\n if (loading) {\n return (\n <>\n {status}\n <div\n aria-busy=\"true\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n {LOADING_ROWS.map((row) => (\n <div\n key={row}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <Skeleton size=\"md\" width=\"50%\" />\n <Skeleton size=\"sm\" width=\"30%\" />\n </div>\n ))}\n </div>\n </>\n );\n }\n\n const documents = items.filter((item) => item.kind === 'document');\n const interviews = items.filter((item) => item.kind === 'anamnesis');\n const anyUnassigned = items.some(\n (item) => needsOperatorPick(item) && assignments[item.id] === ASSIGN_LATER,\n );\n\n // \"Assign all to me\" and the two notes explain every picker, so they sit\n // once, at the top of the first group that has one.\n const operatorGroup = [documents, interviews].find((groupItems) =>\n groupItems.some(needsOperatorPick),\n );\n // One hidden line serves every picker: the greyed-out operators and why.\n const operatorHint = operatorReasonsHint(operatorOptions, i18n.language);\n\n const group = (\n groupItems: RequiredSignatureItem[],\n headingId: string,\n heading: string,\n ) => {\n if (groupItems.length === 0) return null;\n const withOperatorControls = groupItems === operatorGroup;\n return (\n <section\n className={`${PERSON_SECTION} ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]`}\n >\n <div className={PERSON_GRID}>\n <div className={PERSON_HEADER}>\n <p\n id={headingId}\n className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\"\n >\n {heading}\n </p>\n {withOperatorControls && onAssignAllToMe ? (\n <Button\n intent=\"outline\"\n size=\"sm\"\n startIcon={<UserPlus />}\n disabled={busy}\n onClick={onAssignAllToMe}\n >\n {t('signatureRequest.assignAllToMe')}\n </Button>\n ) : null}\n </div>\n {withOperatorControls && anyUnassigned ? (\n <Alert\n variant=\"info\"\n data-note=\"assign-later\"\n className={`${PERSON_UNDER} ${COMPACT_NOTE}`}\n >\n <Alert.Description>\n {t('signatureRequest.assignLaterNote')}\n </Alert.Description>\n </Alert>\n ) : null}\n {/* With the channels on screen the note has nothing to add. */}\n {withOperatorControls && !showOperatorChannels ? (\n <Alert\n variant=\"info\"\n data-note=\"operator-channel\"\n className={`${PERSON_UNDER} ${COMPACT_NOTE}`}\n >\n <Alert.Description>\n {t('signatureRequest.operatorChannelNote')}\n </Alert.Description>\n </Alert>\n ) : null}\n </div>\n {/* The list takes the name to channel columns, so rows start at the\n roster's name edge and end where its selects end. */}\n <div className={PERSON_GRID}>\n <List\n density=\"relaxed\"\n aria-labelledby={headingId}\n className={PERSON_UNDER}\n >\n {groupItems.map((item) => {\n const withPicker = needsOperatorPick(item);\n const withChannel = withPicker && showOperatorChannels;\n const assigned =\n withPicker &&\n assignments[item.id] !== undefined &&\n assignments[item.id] !== ASSIGN_LATER &&\n assignments[item.id] !== '';\n return (\n <List.Item\n key={item.id}\n value={item.id}\n data-required-item-id={item.id}\n className=\"ds:!p-[var(--spacing-none)]\"\n title={\n <span\n className={withChannel ? ITEM_ROW_WITH_CHANNEL : ITEM_ROW}\n >\n <span className={withPicker ? ITEM_NAME : ITEM_NAME_FULL}>\n {item.name}\n </span>\n {withPicker ? (\n <span className={ITEM_PICKER}>\n <Select\n id={`signature-request-item-operator-${item.id}`}\n options={operatorPickerOptions(\n operatorOptions,\n assignments[item.id],\n )}\n value={assignments[item.id]}\n onValueChange={(value) => {\n // The agent's set_value skips the list, so a\n // greyed-out or deleted operator is refused here.\n if (\n value &&\n isPickableOperator(operatorOptions, value)\n ) {\n onAssign(item.id, value);\n }\n }}\n showDescriptions\n aria-describedby={\n operatorHint ? operatorHintId : undefined\n }\n required\n disabled={busy}\n placeholder={t(\n 'signatureRequest.operatorPlaceholder',\n )}\n aria-label={t(\n 'signatureRequest.itemOperatorLabel',\n { name: item.name },\n )}\n />\n </span>\n ) : null}\n {withChannel ? (\n // The chosen operator's channel, from their settings\n // unless changed here. Nobody to deliver to while\n // unassigned, but the column keeps its width.\n <span\n className={\n assigned\n ? ITEM_PICKER\n : `${ITEM_PICKER} ds:hidden ds:@[512px]/person:block`\n }\n >\n {assigned ? (\n <Select<OperatorChannel>\n id={`signature-request-item-operator-channel-${item.id}`}\n options={channelOptions}\n value={operatorChannels[item.id]}\n adornmentInTrigger\n disabled={busy}\n aria-label={t(\n 'signatureRequest.itemOperatorChannelLabel',\n { name: item.name },\n )}\n onValueChange={(value) => {\n // The agent's set_value skips the list.\n if (\n OPERATOR_CHANNELS.includes(\n value as OperatorChannel,\n )\n ) {\n onOperatorChannel?.(\n item.id,\n value as OperatorChannel,\n );\n }\n }}\n />\n ) : null}\n <ChannelColumnSizer meta={channelMeta} />\n </span>\n ) : null}\n </span>\n }\n />\n );\n })}\n </List>\n </div>\n </section>\n );\n };\n\n // The status keeps its place from the loading branch, so it stays mounted\n // and can say the items loaded.\n return (\n <>\n {status}\n {operatorHint ? (\n <span id={operatorHintId} className=\"ds:sr-only\">\n {operatorHint}\n </span>\n ) : null}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)] ds:text-start\">\n {group(\n documents,\n documentsHeadingId,\n t('signatureRequest.requiredDocumentsHeading', {\n count: documents.length,\n }),\n )}\n {group(\n interviews,\n interviewsHeadingId,\n t('signatureRequest.requiredAnamnesisHeading', {\n count: interviews.length,\n }),\n )}\n </div>\n </>\n );\n}\n","/**\n * Outcome states of SignatureRequestModal: a final screen in the same dialog\n * once there is nothing left to fill in. The modal puts the title and the\n * description in its header and its own actions in the footer; this file\n * holds the copy and the decorative body.\n */\nimport type { TFunction } from 'i18next';\nimport { CircleCheck, TriangleAlert } from 'lucide-react';\n\n/**\n * - `linkSent`: the request went out by link (SMS, e-mail, WhatsApp).\n * - `allSigned`: nothing is left to sign.\n * - `creditsExhausted`: the practice has no electronic signature documents\n * left, so the request cannot be sent.\n */\nexport type SignatureRequestOutcome =\n | 'linkSent'\n | 'allSigned'\n | 'creditsExhausted';\n\n/**\n * Title and description for an outcome, in the active locale. `required`\n * (required documents mode) uses platform's batch copy for `linkSent`.\n */\nexport function outcomeCopy(\n outcome: SignatureRequestOutcome,\n t: TFunction,\n { required = false }: { required?: boolean } = {},\n): { title: string; description: string } {\n switch (outcome) {\n case 'linkSent':\n if (required) {\n return {\n title: t('signatureRequest.requiredLinkSentTitle'),\n description: t('signatureRequest.requiredLinkSentDescription'),\n };\n }\n return {\n title: t('signatureRequest.outcomeLinkSentTitle'),\n description: t('signatureRequest.outcomeLinkSentDescription'),\n };\n case 'allSigned':\n return {\n title: t('signatureRequest.outcomeAllSignedTitle'),\n description: t('signatureRequest.outcomeAllSignedDescription'),\n };\n case 'creditsExhausted':\n return {\n title: t('signatureRequest.outcomeCreditsTitle'),\n description: t('signatureRequest.outcomeCreditsDescription'),\n };\n }\n}\n\n/** The outcome's body: a decorative status icon. The header carries the words. */\nexport function SignatureOutcome({\n outcome,\n}: {\n outcome: SignatureRequestOutcome;\n}) {\n const warning = outcome === 'creditsExhausted';\n return (\n <div\n data-outcome={outcome}\n className=\"ds:flex ds:justify-center ds:py-[var(--spacing-md)]\"\n >\n <span\n aria-hidden=\"true\"\n className={\n warning\n ? 'ds:text-[color:var(--warning)]'\n : 'ds:text-[color:var(--success)]'\n }\n >\n {warning ? (\n <TriangleAlert className=\"ds:size-[var(--icon-size-lg)]\" />\n ) : (\n <CircleCheck className=\"ds:size-[var(--icon-size-lg)]\" />\n )}\n </span>\n </div>\n );\n}\n","/**\n * SignatureRequestModal — the practice-side \"Documenti firmati\" modal that\n * dispatches a document-signature request: assign the operator who must\n * counter-sign (or leave the request unassigned) and how their request is\n * delivered (their system-defined default channel arrives preselected),\n * build the patient-side signer roster (up to `maxSigners`, each with their\n * own delivery channel and, for on-device signing, an OTP waiver), and send.\n *\n * Runtime pattern: real consuming apps mount this in production (surfaced via\n * `src/patterns/index.ts` and the `./patterns/signature-request` subpath).\n * The component owns the form state — re-seeded from the `initial*` props\n * every time `open` flips back to `true` — while the host owns `open`, the\n * option lists, and what happens on submit. Multiple on-device signers sign\n * sequentially in roster order — the execution side is the Signing pattern's\n * multi-signer flow; this modal only encodes the intents.\n *\n * Via QR is a second step of the same dialog: after a submit with a `'qr'`\n * signer the dialog stays open and waits, then shows one server-issued code\n * per QR signer once the host passes `qrCodes`. The kit never builds a link.\n *\n * Signed versions: when the host passes `signatures` (or\n * `signaturesLoading`) the form shows the document's past signature requests\n * in a table above the operator and signers, on one screen as platform's\n * \"Documenti firmati\" modal does. A host that passes neither sees the plain\n * form.\n *\n * Required documents mode: when the host passes `requiredItems` (or\n * `requiredItemsLoading`) the form asks the patient to sign every\n * outstanding document and anamnesis interview in one batch. Each item that\n * needs an operator gets its own picker in place of the single operator row\n * (and, with `showOperatorChannels`, that operator's channel); the roster\n * applies to the whole batch. A second signee follows platform's rules:\n * every item can carry it, the main signer signs on this device, and the\n * main signer is a registered signee, not the patient.\n *\n * Channel mode (`channelMode`), in every mode: `'perSigner'` (the default)\n * gives each signer row its own channel; `'batch'` puts one channel on the\n * whole roster (platform's sign mode) with one OTP waiver, and submits\n * `signMode`.\n *\n * Outcome states (`outcome`) replace every other view with a final screen\n * and a Close action; credits used up can also go back to the form.\n *\n * Channel rules: by default the operator may sign on this device only while\n * a patient signer does. A host with its own rules passes `resolveChannels`,\n * which replaces that rule.\n */\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { TFunction } from 'i18next';\nimport { PenLine, Plus, ShoppingCart, UserPlus, X } from 'lucide-react';\nimport { Dialog } from '../../components/dialog';\nimport { QrCode } from '../../components/qr-code';\nimport { Spinner } from '../../components/spinner';\nimport { Button } from '../../components/button';\nimport { IconButton } from '../../components/icon-button';\nimport { Select, type SelectOption } from '../../components/select';\nimport { Switch } from '../../components/switch';\nimport { Alert } from '../../components/alert';\nimport { Separator } from '../../components/separator';\nimport { Avatar } from '../../components/avatar';\nimport { TooltipProvider } from '../../components/tooltip';\nimport {\n OPERATOR_CHANNELS,\n useChannelMeta,\n type OperatorChannel,\n type SignatureChannel,\n} from './channel-meta';\nimport {\n SignatureHistory,\n type SignatureDownloadVersion,\n type SignatureRecord,\n type SignatureShareTarget,\n} from './signature-history';\nimport {\n ASSIGN_LATER,\n RequiredDocuments,\n isPickableOperator,\n itemsStillToSign,\n needsOperatorPick,\n operatorPickerOptions,\n operatorReasonsHint,\n secondSigneeBlock,\n secondSigneeIssue,\n type OperatorPickerOption,\n type RequiredSignatureItem,\n type SecondSigneeBlock,\n type SecondSigneeIssue,\n} from './required-documents';\nimport {\n SignatureOutcome,\n outcomeCopy,\n type SignatureRequestOutcome,\n} from './signature-outcome';\nimport {\n ChannelColumnSizer,\n PERSON_ACTION,\n PERSON_AVATAR,\n PERSON_CHANNEL,\n PERSON_GRID,\n PERSON_HEADER,\n PERSON_LIST,\n PERSON_NAME,\n PERSON_NAME_FULL,\n PERSON_SECTION,\n PERSON_UNDER,\n} from './person-grid';\n\nexport type { OperatorChannel, SignatureChannel } from './channel-meta';\nexport type {\n SignatureDownloadVersion,\n SignatureLegalLevel,\n SignatureRecord,\n SignatureShareTarget,\n} from './signature-history';\nexport type {\n RequiredSignatureItem,\n RequiredSignatureItemKind,\n} from './required-documents';\nexport type { SignatureRequestOutcome } from './signature-outcome';\n\n/**\n * How patient signers get their channel. `'perSigner'`: each signer row has\n * its own channel dropdown beside the name. `'batch'`: one channel for the\n * whole roster, under the signers heading, submitted as `signMode`.\n */\nexport type SignatureChannelMode = 'perSigner' | 'batch';\n\n/** The channel choices on the form, handed to `resolveChannels`. */\nexport interface SignatureChannelDraft {\n /** The assigned operator; `null` with no operator row or on Assign later. */\n operatorId: string | null;\n /** The operator's channel; `null` whenever `operatorId` is. */\n operatorChannel: OperatorChannel | null;\n /** The patient-side roster, in order. Empty when the patient does not sign. */\n signers: SignerRequest[];\n /**\n * What the user just changed: `'operator'` (the operator or their\n * channel) or `'signers'` (a signer's channel or person, or a row added or\n * removed). `null` when the dialog opens, and when the modal reads the\n * available channels while rendering.\n */\n changed: 'operator' | 'signers' | null;\n /**\n * Channels each draft signer has greyed out (`unavailableChannels` on\n * their `SignerOption`), by `signerId`. Absent when no signer has any.\n * The modal never applies one, whatever the rule returns.\n */\n signerUnavailableChannels?: Record<string, SignatureChannel[]>;\n}\n\n/** What `resolveChannels` returns: the channels to use and to offer. */\nexport interface SignatureChannelResolution {\n /** The operator's channel to use. Ignored while the draft's is `null`. */\n operatorChannel: OperatorChannel | null;\n /**\n * The roster with the channels to use. Only `channel` is read, matched by\n * `signerId`; the roster itself never changes here.\n */\n signers: SignerRequest[];\n /** Channels the operator's dropdown offers. Omit to offer all three. */\n operatorAvailableChannels?: OperatorChannel[];\n /**\n * Channels each signer's dropdown offers, by `signerId`. Narrows that\n * person's own `availableChannels`; a list that leaves nothing selectable\n * is ignored. It cannot re-enable a channel in the person's\n * `unavailableChannels`: that one stays greyed out.\n */\n signerAvailableChannels?: Record<string, SignatureChannel[]>;\n}\n\n/** One selectable person/role for the operator or signer selects. */\nexport interface SignerOption {\n value: string;\n label: string;\n /**\n * Delivery channels this person can actually receive. Omit (or pass an\n * empty list) to offer every channel, Via QR included. Hosts gate this\n * from per-patient capability flags — e.g. a patient with no mobile number\n * drops `'sms'` and `'whatsapp'`. Only meaningful for signer options, not\n * operators.\n */\n availableChannels?: SignatureChannel[];\n /**\n * Channels to show greyed out, each with the host-translated reason shown\n * under it (e.g. SMS and WhatsApp with \"No mobile number\"), instead of\n * hiding them. Wins over `availableChannels`; a channel that list leaves\n * out stays hidden. Never selected, seeded or submitted: the row falls\n * back to the first channel still available, and a signer with none\n * shows the reasons under the row and blocks the request. Only meaningful\n * for signer options, not operators.\n */\n unavailableChannels?: ReadonlyArray<{\n channel: SignatureChannel;\n reason: string;\n }>;\n /**\n * The delivery channel this operator's own settings resolve to — the\n * system-defined default, preselected when the operator is assigned and\n * again whenever a different operator is picked (a channel the user\n * changed by hand is kept until then). Falls back to `'email'` when\n * omitted. `'on-device'` applies only where it is offered: in the request\n * form, while a patient signer signs on this device (else e-mail), unless\n * `resolveChannels` decides. Also seeds each item's operator channel with\n * `showOperatorChannels`. Only meaningful for operator options, not\n * signers.\n */\n defaultChannel?: OperatorChannel;\n /**\n * The host has worked out that this person is under 18. A roster row with\n * this person selected shows a warning to check whether a second signee is\n * needed. It never blocks the request; the kit does not compute age. Only\n * meaningful for signer options, not operators.\n */\n isMinor?: boolean;\n /**\n * This option is the patient's own record, not one of their registered\n * signees (a legal guardian, a parent). Read in required documents mode\n * and in `channelMode: 'batch'`, as on platform. Required documents mode:\n * a second signee needs a registered signee as the main signer, and the\n * patient is never offered as a second signee. The OTP waiver (the\n * batch's, or the main signer's row per signer) starts on when the patient\n * cannot receive SMS, and is forced on when the patient is the main signer.\n * Batch mode: the channel defaults to SMS when the patient signs and can\n * receive it, and offers a channel the patient OR the main signer can\n * receive (so pass each person's own channels, not a combined list). Omit\n * it and the person counts as a registered signee. Only meaningful for\n * signer options, not operators.\n */\n isPatient?: boolean;\n}\n\n/**\n * One operator offered in the operator pickers: the single-document form's\n * operator select and, in required documents mode, every item's picker.\n * Operators keep host order. \"Assign later\" comes after them in the request\n * form, and first in required documents mode, as on platform\n * (OperatorSignee.js).\n */\nexport interface OperatorOption extends SignerOption {\n /**\n * Shows the operator greyed out, with `reason` under the name. It cannot\n * be picked, and is never seeded as the first operator. A host-seeded\n * value stays as it is.\n */\n disabled?: boolean;\n /**\n * Why the operator is greyed out, host-translated (e.g. \"non ha un numero\n * di telefono\"). Shown under the name and read on the picker trigger.\n * Ignored unless `disabled`.\n */\n reason?: string;\n /**\n * The operator was deleted. Hidden, unless they are a picker's current\n * value (e.g. an item still assigned to them); once changed they are gone\n * from that picker. Never picked or seeded as the first operator.\n */\n deleted?: boolean;\n}\n\n/** One patient-side signer row in the submission. */\nexport interface SignerRequest {\n signerId: string;\n /** In `channelMode: 'batch'` every row carries the batch channel. */\n channel: SignatureChannel;\n /**\n * Only meaningful when `channel` is `'on-device'`. In batch mode it is set\n * on the main signer (the first row) only: the batch's \"Do not require OTP\n * from the patient\" (platform `doesNotRequireOtp`). In required documents\n * mode the main signer always carries it on this device.\n */\n skipOtp?: boolean;\n}\n\n/** Payload handed to `onRequestSignature`. */\nexport interface SignatureRequestSubmission {\n /**\n * `null` when the counter-signing operator is left unassigned. In required\n * documents mode: the first assigned operator in list order (or `null`),\n * for hosts that still need one operator; `operatorAssignments` is the\n * full picture.\n */\n operatorId: string | null;\n /**\n * How the operator's counter-sign request is delivered. `null` while the\n * operator is unassigned. Defaults to the operator's own system-defined\n * channel unless explicitly changed in the modal. Always `null` in\n * required documents mode: see `operatorChannels`.\n */\n operatorChannel: OperatorChannel | null;\n /** 1..N signers; on-device signers sign sequentially in this order. */\n signers: SignerRequest[];\n /**\n * `channelMode: 'batch'` only: the one channel the whole roster goes out\n * on (platform `signMode`), the same value as every `signers[].channel`.\n * Absent per signer, and when the patient does not sign.\n */\n signMode?: SignatureChannel;\n /**\n * Required documents mode with `showOperatorChannels` only: the operator's\n * channel per item id, for every item with an assigned operator (items on\n * Assign later have none).\n */\n operatorChannels?: Record<string, OperatorChannel>;\n /**\n * Required documents mode only: the operator per listed item id, for every\n * item that `requiresOperator`; `null` means \"Assign later\". Absent in the\n * single-document form.\n */\n operatorAssignments?: Record<string, string | null>;\n /**\n * Required documents mode only: the ids of the items in this batch (the\n * ones still to sign), in list order. Absent in the single-document form.\n */\n requiredItemIds?: string[];\n}\n\n/** One server-issued signing link for a signer on the Via QR channel. */\nexport interface SignatureQrCode {\n /** The roster signer this link belongs to (`SignerRequest.signerId`). */\n signerId: string;\n /** The signing link, encoded byte-for-byte. The kit never builds it. */\n url: string;\n /**\n * When the link stops working: a `Date` or an ISO 8601 string, formatted\n * in the active locale and the browser's time zone. Today shows the time\n * alone; any other day adds the date. An unparseable value hides the line.\n */\n expiresAt: Date | string;\n}\n\nexport interface SignatureRequestModalProps {\n /** Controlled open state. Reopening re-seeds the form from `initial*`. */\n open: boolean;\n /**\n * Fires when the dialog requests a state change (<kbd>Esc</kbd> or the\n * footer Close button). `false` is the dismiss signal — hosts typically\n * persist a \"dismissed this session\" flag there.\n */\n onOpenChange: (open: boolean) => void;\n /**\n * Operators offered as the counter-signing signer, in host order (\"Assign\n * later\" follows them, or leads in required documents mode). `disabled`\n * shows one greyed out with its `reason`; `deleted` hides one unless it\n * is a picker's current value.\n */\n operators: OperatorOption[];\n /** Patient-side people/roles offered in each signer row. */\n signerOptions: SignerOption[];\n /**\n * Enables the \"Assign to me\" shortcut targeting this operator (\"Assign all\n * to me\" in required documents mode, which sets every item's picker).\n */\n currentOperatorId?: string;\n /** Offer an \"Assign later\" option in the operator select. Default `true`. */\n allowAssignLater?: boolean;\n /**\n * Preselected operator; `null` preselects \"Assign later\" (honoured only\n * while `allowAssignLater` — otherwise the first operator is seeded). In\n * required documents mode it seeds every item picker whose item has no\n * `initialOperatorId` of its own.\n */\n initialOperatorId?: string | null;\n /**\n * Preselected operator delivery channel. Defaults to the seeded operator's\n * system-defined `defaultChannel`. `'on-device'` is honoured only while a\n * seeded roster signer also signs on this device, unless `resolveChannels`\n * is passed: then the host decides.\n */\n initialOperatorChannel?: OperatorChannel;\n /**\n * Seed the signer roster. Defaults to the first option, on-device. Each\n * row's `channel` is read per signer; in batch mode only the first row's\n * `skipOtp` is read.\n */\n initialSigners?: SignerRequest[];\n /**\n * Cap on roster size. Default `2`. In required documents mode the roster\n * is the main signer plus at most one second signee, offered only when\n * the second signee rules allow it.\n */\n maxSigners?: number;\n /**\n * How signers get their channel, in the request form and in required\n * documents mode. `'perSigner'` (default): a channel dropdown beside each\n * signer's name. `'batch'`: one \"Signature channel\" select under the\n * signers heading for the whole roster, with one OTP waiver; every\n * `SignerRequest.channel` carries it and the submission gains `signMode`.\n */\n channelMode?: SignatureChannelMode;\n /**\n * `channelMode: 'batch'` only: the channel to start on. Omit it for\n * platform's default: e-mail, or SMS when the main signer `isPatient` and\n * can receive SMS. A channel neither the main signer nor the patient can\n * receive falls back to the first one on offer. Read when the dialog\n * opens only: in required documents mode, changing the main signer\n * returns the batch to platform's default. The channels in\n * `initialSigners` are not read in batch mode. Ignored per signer.\n */\n initialBatchChannel?: SignatureChannel;\n /**\n * Whether an operator must counter-sign. `false` drops the operator\n * section entirely and submits `operatorId: null` — a host whose document\n * does not require a counter-signature must not be asked for one. Default\n * `true`.\n */\n requireOperator?: boolean;\n /**\n * Whether the patient side signs at all. `false` drops the signer roster\n * and submits an empty `signers` array — for documents only an operator\n * signs. Default `true`. Setting BOTH this and `requireOperator` to false\n * leaves nothing to request, so the primary action stays disabled.\n */\n requirePatient?: boolean;\n /** Disables all inputs and shows the primary action as loading. */\n busy?: boolean;\n /** Consumer-translated error shown above the footer (e.g. server failure). */\n error?: string;\n /** Override the dialog title. Defaults to the `ui.*` string. */\n title?: string;\n /** Override the dialog description. Defaults to the `ui.*` string. */\n description?: string;\n /**\n * Receives the completed submission. The host closes via `onOpenChange`,\n * except when a signer chose `'qr'`: then the dialog moves to its QR step\n * and waits, so keep it open and pass `qrCodes` once the server replies\n * (or `error` to send the user back to the form).\n */\n onRequestSignature: (submission: SignatureRequestSubmission) => void;\n /**\n * Server-issued signing links, one per `'qr'` signer. While non-empty the\n * dialog shows the QR step instead of the form, one code at a time. A QR\n * signer with no entry gets an error slot. Clear it when the dialog closes,\n * and drop a server response that arrives after the close.\n */\n qrCodes?: readonly SignatureQrCode[];\n /**\n * Shows the QR step's waiting state without a submit, e.g. when the host\n * remounts the dialog mid-request. The dialog enters this state by itself\n * after a submit with a `'qr'` signer; `qrCodes` arriving ends it. A set\n * `error` always wins and shows the form, even while this stays `true`.\n */\n qrPending?: boolean;\n /**\n * Fires when the user presses Done on the QR step, before\n * `onOpenChange(false)`. Close, Esc and any other dismissal do not fire it.\n */\n onQrDone?: () => void;\n /**\n * The document's past signature requests. Passing it (even empty) adds a\n * signed versions table (Date, Signature type, Actions) at the top of the\n * form, on the same screen, as on platform. Rows show newest first by\n * `createdAt`; records with the same or an unparseable date keep the host\n * order. An empty array shows one line saying there are no signed\n * versions. Omit it (and `signaturesLoading`) for the plain form.\n */\n signatures?: readonly SignatureRecord[];\n /**\n * Shows the signed versions table's loading state (skeleton rows). Also\n * adds the table while `signatures` is still undefined.\n */\n signaturesLoading?: boolean;\n /**\n * Show each row's legal level (simple or advanced). Default `true`. Pass\n * `false` where the level does not apply, e.g. for German practices.\n */\n showLegalLevel?: boolean;\n /** Row action \"View\". The button shows only when this is passed. */\n onViewSignature?: (id: string) => void;\n /**\n * Row action \"Download\". The button shows only when this is passed. It is\n * a menu (full or anonymised) when the record `hasAnonymisedVersion`,\n * otherwise a button that asks for `'full'`.\n */\n onDownloadSignature?: (id: string, version: SignatureDownloadVersion) => void;\n /**\n * Row action \"Share\", a menu of link, e-mail and WhatsApp. The button\n * shows only when this is passed. The host does the sharing.\n */\n onShareSignature?: (id: string, via: SignatureShareTarget) => void;\n /**\n * The share targets for rows whose record has no `shareTargets` of its\n * own. Default: link, e-mail and WhatsApp. An empty list hides Share.\n */\n signatureShareTargets?: readonly SignatureShareTarget[];\n /**\n * Row action \"Delete\". The button shows only when this is passed. It asks\n * for confirmation first; this fires only on confirm. The host deletes and\n * drops the record from `signatures`.\n */\n onDeleteSignature?: (id: string) => void;\n /**\n * The host's channel rules, in place of the built-in one (the operator may\n * sign on this device only while a patient signer does). Called with the\n * choices after every channel change, and when the dialog opens; the\n * modal uses the channels it returns, clamped to what is offered. Also\n * called while rendering, with `changed: null`, to read the available\n * channels, so it must be pure. Omit it to keep the built-in rule.\n */\n resolveChannels?: (\n draft: SignatureChannelDraft,\n ) => SignatureChannelResolution;\n /**\n * Required documents mode: every outstanding document and anamnesis\n * interview for one patient, signed in one batch. Passing it (even empty)\n * replaces the single operator row with one picker per item that\n * `requiresOperator`, seeded from the item's `initialOperatorId`, else the\n * modal's `initialOperatorId`. Fully signed items are left out; when none\n * is left the dialog shows the `'allSigned'` outcome. The roster applies\n * to the whole batch, each signer on their own channel, or on one channel\n * with `channelMode: 'batch'`. A second roster row (the second signee) is\n * offered only when every listed item is a document with\n * `canCarrySecondary`, the main signer's channel (the batch's, or their\n * row's) is on this device and the main signer is not `isPatient`.\n * `signatures`, `requireOperator` and `requirePatient` do not apply. The\n * submission gains `operatorAssignments` and `requiredItemIds`.\n */\n requiredItems?: readonly RequiredSignatureItem[];\n /**\n * Shows required documents mode loading (skeleton rows). Also enters the\n * mode while `requiredItems` is still undefined.\n */\n requiredItemsLoading?: boolean;\n /**\n * Required documents mode: shows each item's operator channel (SMS,\n * e-mail, on this device) beside its operator picker, starting on the\n * chosen operator's `defaultChannel` and following a new operator, and\n * hides the note that each operator's settings decide. The submission\n * gains `operatorChannels`. Default `false`.\n */\n showOperatorChannels?: boolean;\n /**\n * A final screen in place of any other view, with a Close action:\n * `'linkSent'` after a request sent by link, `'allSigned'` when nothing is\n * left to sign, `'creditsExhausted'` when the practice has no electronic\n * signature documents left. The host sets and clears it; reopening does\n * not clear it.\n */\n outcome?: SignatureRequestOutcome;\n /**\n * \"Buy more\" on the `'creditsExhausted'` outcome. The button shows only\n * when this is passed; the host navigates to the purchase page.\n */\n onBuyMoreSignatures?: () => void;\n /**\n * \"Cancel\" on the `'creditsExhausted'` outcome (platform's Annulla). The\n * button shows only when this is passed. It returns the dialog to the view\n * under the outcome (the form) by itself, then calls this so the host\n * clears `outcome`. Clear it here: the modal shows the outcome again only\n * when the prop changes, or on reopen.\n */\n onOutcomeCancel?: () => void;\n /**\n * Required documents mode: a link-style \"Add signatory\" under the Patient\n * signers heading while the patient has no registered signee (no\n * `signerOptions` entry without `isPatient`), as on platform. The host\n * opens its own create-signee flow and passes the new person in\n * `signerOptions`. Hidden when omitted, and in the single-document form.\n */\n onAddSignee?: () => void;\n /**\n * Extra attributes for the portaled dialog surface (e.g. `dir`/`lang`\n * when the host pins a locale below `<html>`, or a test id).\n */\n contentProps?: ComponentPropsWithoutRef<'div'>;\n}\n\n/** Canonical channel display order; per-signer availability filters this. */\nconst CHANNEL_ORDER: SignatureChannel[] = [\n 'sms',\n 'email',\n 'whatsapp',\n 'on-device',\n 'qr',\n];\n\n/** Stable id of the batch channel select in required documents mode. */\nconst BATCH_CHANNEL_ID = 'signature-request-batch-channel';\n\n/** Why the second signee is withheld, as the visible line under the heading. */\nconst SECOND_SIGNEE_HINTS: Record<SecondSigneeBlock, string> = {\n anamnesis: 'signatureRequest.secondSigneeUnavailableAnamnesis',\n documents: 'signatureRequest.secondSigneeUnavailableDocuments',\n patient: 'signatureRequest.secondSigneeUnavailablePatient',\n channel: 'signatureRequest.secondSigneeUnavailableChannel',\n};\n\n/** A second signee's validation message, under their row. */\nconst SECOND_SIGNEE_ISSUES: Record<SecondSigneeIssue, string> = {\n sameAsPrimary: 'signatureRequest.secondSigneeSameAsPrimary',\n unknownSignee: 'signatureRequest.secondSigneeUnknown',\n missingPhone: 'signatureRequest.secondSigneeMissingPhone',\n missingEmail: 'signatureRequest.secondSigneeMissingEmail',\n};\n\n/** Expiry line for a QR code: time alone reads as \"today\", so any other day\n * also shows the date. `null` for an unparseable value. */\nfunction formatQrExpiry(\n expiresAt: Date | string,\n locale: string,\n t: TFunction,\n): string | null {\n const date = expiresAt instanceof Date ? expiresAt : new Date(expiresAt);\n if (Number.isNaN(date.getTime())) return null;\n const time = { hour: '2-digit', minute: '2-digit' } as const;\n if (date.toDateString() === new Date().toDateString()) {\n return t('signatureRequest.qrExpiresAt', {\n time: new Intl.DateTimeFormat(locale, time).format(date),\n });\n }\n return t('signatureRequest.qrExpiresOn', {\n dateTime: new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'short',\n year: 'numeric',\n ...time,\n }).format(date),\n });\n}\n\n/** Internal roster row — `rowId` keys the DOM so editing a row's person\n * never remounts the row (which would drop keyboard focus). */\ninterface RosterRow extends SignerRequest {\n rowId: number;\n}\n\nfunction labelFor(options: SignerOption[], value: string): string {\n return options.find((option) => option.value === value)?.label ?? '';\n}\n\nexport const SignatureRequestModal = forwardRef<\n HTMLDivElement,\n SignatureRequestModalProps\n>(\n (\n {\n open,\n onOpenChange,\n operators,\n signerOptions,\n currentOperatorId,\n allowAssignLater = true,\n requireOperator = true,\n requirePatient = true,\n initialOperatorId,\n initialOperatorChannel,\n initialSigners,\n maxSigners = 2,\n channelMode = 'perSigner',\n initialBatchChannel,\n busy = false,\n error,\n title,\n description,\n onRequestSignature,\n qrCodes,\n qrPending = false,\n onQrDone,\n signatures,\n signaturesLoading = false,\n showLegalLevel = true,\n onViewSignature,\n onDownloadSignature,\n onShareSignature,\n signatureShareTargets,\n onDeleteSignature,\n resolveChannels,\n requiredItems,\n requiredItemsLoading = false,\n showOperatorChannels = false,\n outcome,\n onBuyMoreSignatures,\n onOutcomeCancel,\n onAddSignee,\n contentProps,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n\n const nextRowId = useRef(0);\n const addButtonRef = useRef<HTMLButtonElement>(null);\n const titleRef = useRef<HTMLHeadingElement>(null);\n const qrDescriptionId = useId();\n const qrCountId = useId();\n const outcomeDescriptionId = useId();\n const secondSigneeHintId = useId();\n const operatorHintId = useId();\n const signerChannelHintId = useId();\n const batchChannelHintId = useId();\n const secondSigneeLabelId = useId();\n const secondSigneeIssueId = useId();\n const otpWarningId = useId();\n\n // Required documents mode: the batch replaces the single operator row,\n // the patient always signs, and the signatures list does not apply.\n const requiredMode = requiredItems !== undefined || requiredItemsLoading;\n const listedItems = requiredItems ? itemsStillToSign(requiredItems) : [];\n const withOperator = requireOperator && !requiredMode;\n const withPatient = requirePatient || requiredMode;\n // One channel for the whole roster instead of one per signer.\n const batchMode = channelMode === 'batch';\n\n const isPatientId = (signerId: string | undefined): boolean =>\n signerOptions.find((option) => option.value === signerId)?.isPatient ===\n true;\n // The roster cap for these rows. Required documents mode seats a second\n // signee only when the rules allow one, reading the main signer's\n // channel (the batch's, or the main row's own), and platform has one\n // second signee at most.\n const capFor = (\n rows: readonly SignerRequest[],\n batch: SignatureChannel,\n ): number => {\n if (!requiredMode) return maxSigners;\n const block = secondSigneeBlock({\n items: listedItems,\n channel: batchMode ? batch : (rows[0]?.channel ?? batch),\n primaryIsPatient: isPatientId(rows[0]?.signerId),\n });\n return block === null ? Math.min(maxSigners, 2) : 1;\n };\n\n // Cancel on an outcome hides the host's outcome until the prop changes\n // or the dialog reopens. Adjusted during render, so no frame shows it.\n const [outcomeCancelled, setOutcomeCancelled] = useState(false);\n const [prevOutcome, setPrevOutcome] = useState(outcome);\n if (outcome !== prevOutcome) {\n setPrevOutcome(outcome);\n setOutcomeCancelled(false);\n }\n\n // Nothing left to sign is an outcome of its own; a host outcome wins.\n const shownOutcome: SignatureRequestOutcome | undefined =\n (outcomeCancelled ? undefined : outcome) ??\n (requiredItems !== undefined &&\n !requiredItemsLoading &&\n listedItems.length === 0\n ? 'allSigned'\n : undefined);\n const outcomeText = shownOutcome\n ? outcomeCopy(shownOutcome, t, { required: requiredMode })\n : null;\n\n // A signer's greyed-out channels, each with its host-translated reason.\n const unavailableFor = (signerId: string): Map<SignatureChannel, string> =>\n new Map(\n (\n signerOptions.find((option) => option.value === signerId)\n ?.unavailableChannels ?? []\n ).map(({ channel, reason }) => [channel, reason]),\n );\n\n // Channels a signer's dropdown lists — the person's `availableChannels`\n // filtered into canonical order; omitted/empty means every channel. A\n // host rule's list narrows it, unless nothing selectable would be left.\n // Unavailable channels stay listed (greyed out) and are never selectable.\n const listedChannelsFor = (\n signerId: string,\n hostAllowed?: SignatureChannel[],\n ): SignatureChannel[] => {\n const allowed = signerOptions.find(\n (option) => option.value === signerId,\n )?.availableChannels;\n const own =\n allowed && allowed.length > 0\n ? CHANNEL_ORDER.filter((channel) => allowed.includes(channel))\n : CHANNEL_ORDER;\n if (!hostAllowed) return own;\n const unavailable = unavailableFor(signerId);\n const narrowed = own.filter((channel) => hostAllowed.includes(channel));\n return narrowed.some((channel) => !unavailable.has(channel))\n ? narrowed\n : own;\n };\n\n // Channels a given signer can actually be given: listed and not greyed\n // out. Empty when every listed channel is unavailable.\n const channelsFor = (\n signerId: string,\n hostAllowed?: SignatureChannel[],\n ): SignatureChannel[] => {\n const unavailable = unavailableFor(signerId);\n return listedChannelsFor(signerId, hostAllowed).filter(\n (channel) => !unavailable.has(channel),\n );\n };\n\n // Operator channels a host rule offers; all three without one.\n const operatorChannelsFrom = (\n resolution: SignatureChannelResolution | undefined,\n ): readonly OperatorChannel[] => {\n const allowed = resolution?.operatorAvailableChannels;\n return allowed && allowed.length > 0\n ? OPERATOR_CHANNELS.filter((channel) => allowed.includes(channel))\n : OPERATOR_CHANNELS;\n };\n\n // First available channel for a signer, preferring `preferred` when offered.\n // A signer with none keeps `preferred`: that row blocks the request.\n const resolveChannel = (\n signerId: string,\n preferred: SignatureChannel,\n ): SignatureChannel => {\n const available = channelsFor(signerId);\n return available.includes(preferred)\n ? preferred\n : (available[0] ?? preferred);\n };\n\n // Required documents mode: one channel for the whole batch. As on\n // platform, a channel is on offer when the main signer OR the patient\n // can receive it; on this device always is. Greyed out, with a reason,\n // only when neither can.\n const patientOption = signerOptions.find(\n (option) => option.isPatient === true,\n );\n const batchPeopleFor = (primaryId: string | undefined): string[] => {\n if (primaryId === undefined) return [];\n return patientOption && patientOption.value !== primaryId\n ? [primaryId, patientOption.value]\n : [primaryId];\n };\n const batchUnavailableFor = (\n primaryId: string | undefined,\n ): Map<SignatureChannel, string> => {\n const people = batchPeopleFor(primaryId);\n const unavailable = new Map<SignatureChannel, string>();\n for (const channel of CHANNEL_ORDER) {\n if (channel === 'on-device') continue;\n if (people.some((id) => channelsFor(id).includes(channel))) continue;\n const reason = people\n .map((id) => unavailableFor(id).get(channel))\n .find((text) => text !== undefined);\n if (reason !== undefined) unavailable.set(channel, reason);\n }\n return unavailable;\n };\n const batchListedFor = (\n primaryId: string | undefined,\n hostAllowed?: SignatureChannel[],\n ): SignatureChannel[] => {\n if (primaryId === undefined) return CHANNEL_ORDER;\n const people = batchPeopleFor(primaryId);\n const own = CHANNEL_ORDER.filter((channel) =>\n people.some((id) => listedChannelsFor(id).includes(channel)),\n );\n // A host rule's list narrows it, unless nothing selectable is left.\n const unavailable = batchUnavailableFor(primaryId);\n const narrowed = hostAllowed\n ? own.filter((channel) => hostAllowed.includes(channel))\n : own;\n const listed = narrowed.some((channel) => !unavailable.has(channel))\n ? narrowed\n : own;\n return CHANNEL_ORDER.filter(\n (channel) => channel === 'on-device' || listed.includes(channel),\n );\n };\n const batchChannelsFor = (\n primaryId: string | undefined,\n hostAllowed?: SignatureChannel[],\n ): SignatureChannel[] => {\n const unavailable = batchUnavailableFor(primaryId);\n return batchListedFor(primaryId, hostAllowed).filter(\n (channel) => !unavailable.has(channel),\n );\n };\n // Platform's default with the unified flow on: e-mail, but SMS when the\n // patient signs and can receive it. Never empty: on this device is left.\n // `initialBatchChannel` applies when the dialog opens, not when the main\n // signer changes (platform's _onSigneeIdChanged re-reads its default).\n const seedBatchChannel = (\n primaryId: string | undefined,\n withInitial = true,\n ): SignatureChannel => {\n const available = batchChannelsFor(primaryId);\n const preferred =\n (withInitial ? initialBatchChannel : undefined) ??\n (isPatientId(primaryId) && available.includes('sms') ? 'sms' : 'email');\n return available.includes(preferred) ? preferred : available[0];\n };\n\n // The first operator a user could pick: greyed-out and deleted ones are\n // never seeded in their place.\n const firstOperator = operators.find(\n (option) => option.disabled !== true && option.deleted !== true,\n )?.value;\n const resolveOperatorSeed = (seed: string | null | undefined) => {\n if (seed === null) {\n return allowAssignLater\n ? ASSIGN_LATER\n : (firstOperator ?? ASSIGN_LATER);\n }\n return seed ?? firstOperator ?? (allowAssignLater ? ASSIGN_LATER : '');\n };\n const seedOperator = () => resolveOperatorSeed(initialOperatorId);\n const seedRows = (): RosterRow[] => {\n const seed =\n initialSigners && initialSigners.length > 0\n ? initialSigners\n : signerOptions.length > 0\n ? [\n {\n signerId: signerOptions[0].value,\n channel: resolveChannel(signerOptions[0].value, 'on-device'),\n },\n ]\n : [];\n return seed.map((signer) => {\n // Clamp a seeded channel the signer cannot receive (e.g. `'qr'` on a\n // signer whose `availableChannels` excludes it), so a row never\n // renders with no channel selected.\n const channel = resolveChannel(signer.signerId, signer.channel);\n const { skipOtp, ...rest } = signer;\n return {\n ...rest,\n channel,\n ...(channel === 'on-device' && skipOtp !== undefined\n ? { skipOtp }\n : {}),\n rowId: nextRowId.current++,\n };\n });\n };\n\n // System-defined default for one operator — the channel their own\n // settings resolve to. On this device only where it is offered (the\n // built-in rule passes whether a patient signs here), else e-mail.\n const operatorDefaultChannel = (\n operatorId: string,\n onDeviceOffered = true,\n ): OperatorChannel => {\n const setting =\n operators.find((option) => option.value === operatorId)\n ?.defaultChannel ?? 'email';\n return setting === 'on-device' && !onDeviceOffered ? 'email' : setting;\n };\n\n // Seed clamp: `'on-device'` is honoured only when the seeded roster\n // makes it available, so the option is never checked-and-disabled, not\n // even for a frame.\n const seedOperatorChannel = (\n operatorId: string,\n onDeviceSigner: boolean,\n ): OperatorChannel => {\n if (initialOperatorChannel === 'on-device') {\n return onDeviceSigner\n ? 'on-device'\n : operatorDefaultChannel(operatorId, false);\n }\n return (\n initialOperatorChannel ??\n operatorDefaultChannel(operatorId, onDeviceSigner)\n );\n };\n\n // The operator's channel from a host rule, clamped to what it offers:\n // the wanted channel, else the operator's default, else the first.\n const clampOperatorChannel = (\n resolution: SignatureChannelResolution,\n operatorId: string,\n channel: OperatorChannel,\n ): OperatorChannel => {\n const offered = operatorChannelsFrom(resolution);\n const wanted = resolution.operatorChannel ?? channel;\n const fallback = operatorDefaultChannel(operatorId);\n return offered.includes(wanted)\n ? wanted\n : offered.includes(fallback)\n ? fallback\n : offered[0];\n };\n\n /* ---- Host channel rules (`resolveChannels`) --------------------- */\n const draftOf = (\n operatorId: string,\n channel: OperatorChannel,\n rows: RosterRow[],\n changed: SignatureChannelDraft['changed'],\n // Batch mode: every signer's channel is the batch's.\n batch: SignatureChannel = 'on-device',\n ): SignatureChannelDraft => {\n const hasOperator =\n withOperator && operatorId !== ASSIGN_LATER && operatorId !== '';\n const visible = requiredMode ? rows.slice(0, capFor(rows, batch)) : rows;\n const signerUnavailableChannels: Record<string, SignatureChannel[]> = {};\n if (withPatient) {\n for (const row of visible) {\n const unavailable = [...unavailableFor(row.signerId).keys()];\n if (unavailable.length > 0) {\n signerUnavailableChannels[row.signerId] = unavailable;\n }\n }\n }\n return {\n operatorId: hasOperator ? operatorId : null,\n operatorChannel: hasOperator ? channel : null,\n signers: withPatient\n ? visible.map(({ rowId: _rowId, ...signer }) =>\n batchMode\n ? { signerId: signer.signerId, channel: batch }\n : signer,\n )\n : [],\n changed,\n ...(Object.keys(signerUnavailableChannels).length > 0\n ? { signerUnavailableChannels }\n : {}),\n };\n };\n\n // Runs the host rule over a draft and applies what it returns, clamped\n // to the channels on offer, so no dropdown is ever left without a value.\n const resolveWithHost = (\n rule: NonNullable<SignatureRequestModalProps['resolveChannels']>,\n operatorId: string,\n channel: OperatorChannel,\n rows: RosterRow[],\n changed: SignatureChannelDraft['changed'],\n ): { operatorChannel: OperatorChannel; rows: RosterRow[] } => {\n const draft = draftOf(operatorId, channel, rows, changed);\n const resolution = rule(draft);\n const nextChannel =\n draft.operatorChannel === null\n ? channel\n : clampOperatorChannel(resolution, operatorId, channel);\n const visibleCount = draft.signers.length;\n const nextRows = rows.map((row, index) => {\n if (index >= visibleCount) return row;\n const offered = channelsFor(\n row.signerId,\n resolution.signerAvailableChannels?.[row.signerId],\n );\n const wanted =\n resolution.signers.find((signer) => signer.signerId === row.signerId)\n ?.channel ?? row.channel;\n // Nothing selectable: keep the channel, the row blocks the request.\n const next = offered.includes(wanted)\n ? wanted\n : (offered[0] ?? row.channel);\n return next === row.channel\n ? row\n : { ...row, channel: next, skipOtp: undefined };\n });\n return { operatorChannel: nextChannel, rows: nextRows };\n };\n\n // Batch mode: the batch channel after the host rule, clamped to what the\n // main signer is offered, and the operator's channel the rule returns\n // (only the request form has an operator row). With no rule, just the\n // clamp.\n const resolveBatch = (\n rows: RosterRow[],\n channel: SignatureChannel,\n changed: SignatureChannelDraft['changed'],\n operatorId = '',\n opChannel: OperatorChannel = 'email',\n ): { batch: SignatureChannel; operatorChannel: OperatorChannel } => {\n const primaryId = rows[0]?.signerId;\n if (!resolveChannels) {\n const offered = batchChannelsFor(primaryId);\n return {\n batch: offered.includes(channel) ? channel : offered[0],\n operatorChannel: opChannel,\n };\n }\n const draft = draftOf(operatorId, opChannel, rows, changed, channel);\n const resolution = resolveChannels(draft);\n const offered = batchChannelsFor(\n primaryId,\n primaryId === undefined\n ? undefined\n : resolution.signerAvailableChannels?.[primaryId],\n );\n const wanted =\n resolution.signers.find((signer) => signer.signerId === primaryId)\n ?.channel ?? channel;\n return {\n batch: offered.includes(wanted)\n ? wanted\n : offered.includes(channel)\n ? channel\n : offered[0],\n operatorChannel:\n draft.operatorChannel === null\n ? opChannel\n : clampOperatorChannel(resolution, operatorId, opChannel),\n };\n };\n\n // The whole form seed: operator, roster, operator channel, and in batch\n // mode the batch channel and OTP waiver.\n const seedForm = (): {\n operator: string;\n rows: RosterRow[];\n operatorChannel: OperatorChannel;\n batchChannel: SignatureChannel;\n otpOverride: boolean | null;\n } => {\n const seededOperator = seedOperator();\n const seededRows = seedRows();\n if (batchMode) {\n const seeded = resolveBatch(\n seededRows,\n seedBatchChannel(seededRows[0]?.signerId),\n null,\n seededOperator,\n initialOperatorChannel ?? operatorDefaultChannel(seededOperator),\n );\n return {\n operator: seededOperator,\n rows: seededRows,\n // Required documents mode has no operator row: nothing reads it.\n operatorChannel: resolveChannels\n ? seeded.operatorChannel\n : seedOperatorChannel(\n seededOperator,\n seededRows.length > 0 && seeded.batch === 'on-device',\n ),\n batchChannel: seeded.batch,\n otpOverride: initialSigners?.[0]?.skipOtp ?? null,\n };\n }\n const noBatch = { batchChannel: 'on-device' as const, otpOverride: null };\n if (!resolveChannels) {\n return {\n operator: seededOperator,\n rows: seededRows,\n operatorChannel: seedOperatorChannel(\n seededOperator,\n seededRows.some((signer) => signer.channel === 'on-device'),\n ),\n ...noBatch,\n };\n }\n const resolved = resolveWithHost(\n resolveChannels,\n seededOperator,\n initialOperatorChannel ?? operatorDefaultChannel(seededOperator),\n seededRows,\n null,\n );\n return {\n operator: seededOperator,\n rows: resolved.rows,\n operatorChannel: resolved.operatorChannel,\n ...noBatch,\n };\n };\n\n const [formSeed] = useState(seedForm);\n const [operator, setOperator] = useState<string>(formSeed.operator);\n const [rosterRows, setSigners] = useState<RosterRow[]>(formSeed.rows);\n const [operatorChannel, setOperatorChannel] = useState<OperatorChannel>(\n formSeed.operatorChannel,\n );\n // Required documents mode: the batch channel, and the user's own OTP\n // waiver choice (`null` until they pick, so it follows the main signer).\n const [batchChannel, setBatchChannel] = useState<SignatureChannel>(\n formSeed.batchChannel,\n );\n const [otpOverride, setOtpOverride] = useState<boolean | null>(\n formSeed.otpOverride,\n );\n const rosterCap = capFor(rosterRows, batchChannel);\n // Rows past the cap stay in state but are neither shown nor submitted,\n // so a batch that later allows a second signee gets the row back.\n const signers = requiredMode ? rosterRows.slice(0, rosterCap) : rosterRows;\n\n // Per-item operator picks the user made. Unpicked items read their seed,\n // so items that arrive after the dialog opened are seeded too.\n const [assignmentOverrides, setAssignmentOverrides] = useState<\n Record<string, string>\n >({});\n const assignments: Record<string, string> = {};\n for (const item of listedItems) {\n if (!needsOperatorPick(item)) continue;\n assignments[item.id] =\n assignmentOverrides[item.id] ??\n resolveOperatorSeed(\n item.initialOperatorId !== undefined\n ? item.initialOperatorId\n : initialOperatorId,\n );\n }\n // `showOperatorChannels`: the channel picks the user made, per item. A\n // pick holds until that item's operator changes; otherwise the channel\n // follows the assigned operator's own settings.\n const [operatorChannelOverrides, setOperatorChannelOverrides] = useState<\n Record<string, OperatorChannel>\n >({});\n const itemOperatorChannels: Record<string, OperatorChannel> = {};\n for (const item of listedItems) {\n const value = assignments[item.id];\n if (value === undefined || value === ASSIGN_LATER || value === '') {\n continue;\n }\n itemOperatorChannels[item.id] =\n operatorChannelOverrides[item.id] ?? operatorDefaultChannel(value);\n }\n const dropChannelPicks = (itemIds: readonly string[]) => {\n if (itemIds.length === 0) return;\n setOperatorChannelOverrides((current) =>\n Object.fromEntries(\n Object.entries(current).filter(([id]) => !itemIds.includes(id)),\n ),\n );\n };\n const assignItem = (itemId: string, value: string) => {\n if (assignments[itemId] !== value) dropChannelPicks([itemId]);\n setAssignmentOverrides((current) => ({ ...current, [itemId]: value }));\n };\n const assignAllToMe = () => {\n if (currentOperatorId === undefined) return;\n dropChannelPicks(\n listedItems\n .filter(\n (item) =>\n needsOperatorPick(item) &&\n assignments[item.id] !== currentOperatorId,\n )\n .map((item) => item.id),\n );\n setAssignmentOverrides((current) => {\n const next = { ...current };\n for (const item of listedItems) {\n if (needsOperatorPick(item)) next[item.id] = currentOperatorId;\n }\n return next;\n });\n };\n // Feeds the sr-only live region announcing the automatic channel\n // fallback below; any explicit choice clears it.\n const [revertedTo, setRevertedTo] = useState<OperatorChannel | null>(null);\n // The same region's message when a host rule moves a channel the user\n // did not touch.\n const [hostAnnouncement, setHostAnnouncement] = useState<string | null>(\n null,\n );\n // Set by a submit with a `'qr'` signer: the dialog waits in its QR step\n // for the host's `qrCodes`. `qrIndex` is the code on screen.\n const [awaitingQr, setAwaitingQr] = useState(false);\n const [qrIndex, setQrIndex] = useState(0);\n // The signed versions table tops the form only when the host provides it.\n const hasHistory =\n !requiredMode && (signatures !== undefined || signaturesLoading);\n\n // Reset the step during render on reopen, not in an effect: the first\n // committed render (and Radix's open auto-focus) must see it.\n const [prevOpen, setPrevOpen] = useState(open);\n if (open !== prevOpen) {\n setPrevOpen(open);\n if (open) {\n setAwaitingQr(false);\n setQrIndex(0);\n setOutcomeCancelled(false);\n }\n }\n\n // Re-seed the form whenever the host reopens the (still-mounted) modal,\n // so a previous request's choices never leak into the next one.\n const wasOpen = useRef(open);\n useEffect(() => {\n if (open && !wasOpen.current) {\n const next = seedForm();\n setOperator(next.operator);\n setSigners(next.rows);\n setOperatorChannel(next.operatorChannel);\n setBatchChannel(next.batchChannel);\n setOtpOverride(next.otpOverride);\n setRevertedTo(null);\n setHostAnnouncement(null);\n setAssignmentOverrides({});\n setOperatorChannelOverrides({});\n }\n wasOpen.current = open;\n // The seeds intentionally read the render-time props on the rising\n // edge only — prop changes while open (or closed) don't reset input.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n // Operator on-device signing piggybacks on a patient handover: it is\n // offerable only while a roster signer signs on this device, and falls\n // back to the operator's system default the moment the last on-device\n // row leaves. The fallback is announced via the live region — the\n // trigger lives in the roster section, far from the radio it moves.\n // A host rule (`resolveChannels`) replaces all of this.\n // A signer with no available channel counts for nothing: their row\n // blocks the request.\n const hasNoChannel = (signerId: string) =>\n channelsFor(signerId).length === 0;\n // Batch mode reads the batch channel, which always has a signer to\n // carry it.\n const anySignerOnDevice = batchMode\n ? signers.length > 0 && batchChannel === 'on-device'\n : signers.some(\n (signer) =>\n signer.channel === 'on-device' && !hasNoChannel(signer.signerId),\n );\n const hostRule = resolveChannels !== undefined;\n useEffect(() => {\n // Only the request form has an operator row.\n if (hostRule || !withOperator) return;\n if (operatorChannel === 'on-device' && !anySignerOnDevice) {\n const fallback = operatorDefaultChannel(operator, false);\n setOperatorChannel(fallback);\n setRevertedTo(fallback);\n }\n // `operatorDefaultChannel` reads the render-time `operators` prop.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [operatorChannel, anySignerOnDevice, operator, hostRule, withOperator]);\n\n // Every operator picker's options: greyed-out operators with their\n // reason, and deleted ones kept for pickers that still hold them.\n // \"Assign later\" comes first in required documents mode, as on platform,\n // and last in the request form, as it always has.\n const assignLaterOptions: OperatorPickerOption[] = allowAssignLater\n ? [{ value: ASSIGN_LATER, label: t('signatureRequest.assignLater') }]\n : [];\n const operatorEntries: OperatorPickerOption[] = operators.map(\n ({ value, label, disabled, reason, deleted }) => ({\n value,\n label,\n ...(disabled === true\n ? { disabled: true, ...(reason ? { description: reason } : {}) }\n : {}),\n ...(deleted === true ? { deleted: true } : {}),\n }),\n );\n const operatorPickerList: OperatorPickerOption[] = requiredMode\n ? [...assignLaterOptions, ...operatorEntries]\n : [...operatorEntries, ...assignLaterOptions];\n const operatorHint = operatorReasonsHint(operatorPickerList, i18n.language);\n const operatorPickerHintId = useId();\n const isUnassigned = operator === ASSIGN_LATER;\n\n const channelMeta = useChannelMeta();\n\n // The host rule's offer for the current choices.\n const hostView = resolveChannels\n ? resolveChannels(\n draftOf(operator, operatorChannel, rosterRows, null, batchChannel),\n )\n : undefined;\n\n // Applies a change through the host rule, and announces any channel the\n // rule moved that the user did not touch: it may sit in another section.\n // `extra` joins the announcement (e.g. a second signee hidden or\n // cleared). Batch mode runs the batch through the rule instead.\n const commitWithHost = (\n operatorId: string,\n channel: OperatorChannel,\n rows: RosterRow[],\n changed: 'operator' | 'signers',\n extra: readonly string[] = [],\n ) => {\n if (!resolveChannels) return;\n if (batchMode) {\n commitBatch(rows, batchChannel, {\n operatorId,\n opChannel: channel,\n changed,\n });\n return;\n }\n const resolved = resolveWithHost(\n resolveChannels,\n operatorId,\n channel,\n rows,\n changed,\n );\n setOperatorChannel(resolved.operatorChannel);\n setSigners(resolved.rows);\n setRevertedTo(null);\n const messages: string[] = [];\n const hasOperator =\n withOperator && operatorId !== ASSIGN_LATER && operatorId !== '';\n // `channel` and `rows` already hold the user's own change, so any\n // difference is the rule's doing, whichever section changed.\n if (hasOperator && resolved.operatorChannel !== channel) {\n messages.push(\n t('signatureRequest.operatorChannelChanged', {\n channel: channelMeta[resolved.operatorChannel].label,\n }),\n );\n }\n resolved.rows.forEach((row, index) => {\n if (row.channel === rows[index].channel) return;\n messages.push(\n t('signatureRequest.signerChannelChanged', {\n name: labelFor(signerOptions, row.signerId),\n channel: channelMeta[row.channel].label,\n }),\n );\n });\n messages.push(...extra);\n setHostAnnouncement(messages.length > 0 ? messages.join(' ') : null);\n };\n\n // Batch mode: applies a roster, batch channel or operator change through\n // the host rule. In required documents mode, as platform's\n // _onSigneeIdChanged, a new main signer clears the second signee and\n // returns the batch to its default channel, and a batch that stops\n // allowing a second signee only hides them: they come back with it.\n // What the user did not pick is announced.\n const commitBatch = (\n rows: RosterRow[],\n channel: SignatureChannel,\n {\n primaryChanged = false,\n userChannel = false,\n operatorId = operator,\n opChannel = operatorChannel,\n changed = 'signers',\n }: {\n primaryChanged?: boolean;\n userChannel?: boolean;\n operatorId?: string;\n opChannel?: OperatorChannel;\n changed?: 'operator' | 'signers';\n } = {},\n ) => {\n const resolved = resolveBatch(\n rows,\n primaryChanged ? seedBatchChannel(rows[0]?.signerId, false) : channel,\n changed,\n operatorId,\n opChannel,\n );\n const next = resolved.batch;\n const clear = requiredMode && rows.length > 1 && primaryChanged;\n const messages: string[] = [];\n const hasOperator =\n withOperator && operatorId !== ASSIGN_LATER && operatorId !== '';\n if (hasOperator && resolved.operatorChannel !== opChannel) {\n messages.push(\n t('signatureRequest.operatorChannelChanged', {\n channel: channelMeta[resolved.operatorChannel].label,\n }),\n );\n }\n if (next !== (userChannel ? channel : batchChannel)) {\n messages.push(\n t('signatureRequest.signerChannelChanged', {\n name: labelFor(signerOptions, rows[0]?.signerId ?? ''),\n channel: channelMeta[next].label,\n }),\n );\n }\n // Only a second signee the user could see.\n if (requiredMode && signers.length > 1) {\n const block = secondSigneeBlock({\n items: listedItems,\n channel: next,\n primaryIsPatient: isPatientId(rows[0]?.signerId),\n });\n if (clear) {\n messages.push(t('signatureRequest.secondSigneeCleared'));\n } else if (block !== null && rows.length > 1) {\n messages.push(t(SECOND_SIGNEE_HINTS[block]));\n }\n }\n setSigners(clear ? rows.slice(0, 1) : rows);\n if (withOperator) setOperatorChannel(resolved.operatorChannel);\n // As platform, the waiver re-reads its default when the channel changes.\n if (next !== batchChannel) setOtpOverride(null);\n setBatchChannel(next);\n setRevertedTo(null);\n setHostAnnouncement(messages.length > 0 ? messages.join(' ') : null);\n };\n\n // A channel that stops being available while the dialog is open (the\n // host greys it out or hides it) falls back to the first one still\n // available, through the host rule when there is one. Adjusted during\n // render, like the reopen reset above, so a greyed-out channel is never\n // shown selected. A signer with nothing available keeps their channel:\n // that row blocks the request instead. Batch mode does the same for the\n // batch channel, below.\n // The same list the select offers, host rule included.\n const batchOffered = batchChannelsFor(\n rosterRows[0]?.signerId,\n rosterRows[0] === undefined\n ? undefined\n : hostView?.signerAvailableChannels?.[rosterRows[0].signerId],\n );\n if (batchMode && !batchOffered.includes(batchChannel)) {\n commitBatch(rosterRows, batchOffered[0]);\n }\n const fallbackRows = batchMode\n ? rosterRows\n : rosterRows.map((row) => {\n const available = channelsFor(row.signerId);\n return available.length === 0 || available.includes(row.channel)\n ? row\n : { ...row, channel: available[0], skipOtp: undefined };\n });\n if (fallbackRows.some((row, index) => row !== rosterRows[index])) {\n const resolved = resolveChannels\n ? resolveWithHost(\n resolveChannels,\n operator,\n operatorChannel,\n fallbackRows,\n 'signers',\n )\n : { operatorChannel, rows: fallbackRows };\n setSigners(resolved.rows);\n setOperatorChannel(resolved.operatorChannel);\n setRevertedTo(null);\n const messages = resolved.rows\n .filter((row, index) => row.channel !== rosterRows[index].channel)\n .map((row) =>\n t('signatureRequest.signerChannelChanged', {\n name: labelFor(signerOptions, row.signerId),\n channel: channelMeta[row.channel].label,\n }),\n );\n setHostAnnouncement(messages.length > 0 ? messages.join(' ') : null);\n }\n\n const channelOption = <T extends string>(\n value: T,\n channel: SignatureChannel,\n ): SelectOption<T> => ({\n value,\n label: channelMeta[channel].label,\n startAdornment: channelMeta[channel].icon,\n });\n\n // Operator delivery — the same dropdown as the signer rows, minus\n // WhatsApp and Via QR. No \"system defined\" option: the operator's own\n // default (e-mail or SMS per their settings) arrives preselected instead.\n // On-device greys out while no patient signer signs on this device, with\n // the reason under it in the list and on the trigger for screen readers\n // (a disabled option cannot take focus).\n // A host rule offers its own list instead, with nothing greyed out.\n const onDeviceHint =\n hostRule || anySignerOnDevice\n ? undefined\n : t('signatureRequest.onDeviceUnavailableHint');\n const operatorChannelOptions: SelectOption<OperatorChannel>[] = hostRule\n ? operatorChannelsFrom(hostView).map((channel) =>\n channelOption(channel, channel),\n )\n : [\n channelOption('sms', 'sms'),\n channelOption('email', 'email'),\n {\n ...channelOption('on-device', 'on-device'),\n disabled: !anySignerOnDevice,\n description: onDeviceHint,\n },\n ];\n const channelSizer = <ChannelColumnSizer meta={channelMeta} />;\n\n const chosenIds = signers.map((signer) => signer.signerId);\n // The patient is never a second signee (platform lists signees only).\n const nextFreeOption = signerOptions.find(\n (option) =>\n !chosenIds.includes(option.value) &&\n !(requiredMode && option.isPatient === true),\n );\n const canAddSigner =\n !busy && signers.length < rosterCap && nextFreeOption !== undefined;\n\n // Why the second signee is not on offer in this batch. Only worth saying\n // when there is a second person who could have signed.\n // The platform rules read the main signer: in required documents mode,\n // and in batch mode for the batch channel and waiver.\n const primaryId =\n requiredMode || batchMode ? signers[0]?.signerId : undefined;\n const primaryIsPatient = isPatientId(primaryId);\n // The main signer's channel: the batch's, or the main row's own.\n const mainChannel: SignatureChannel = batchMode\n ? batchChannel\n : (signers[0]?.channel ?? batchChannel);\n const secondBlock = requiredMode\n ? secondSigneeBlock({\n items: listedItems,\n channel: mainChannel,\n primaryIsPatient,\n })\n : null;\n const secondSigneeHint =\n requiredMode &&\n !requiredItemsLoading &&\n listedItems.length > 0 &&\n secondBlock !== null &&\n signerOptions.length > 1\n ? t(SECOND_SIGNEE_HINTS[secondBlock])\n : null;\n // What is wrong with the second signee, shown under their row; it blocks\n // the request, as platform's validation does. It reads the second\n // signee's own channel: the batch's, or their row's.\n const secondIssue =\n requiredMode && signers.length > 1\n ? secondSigneeIssue({\n primaryId,\n secondId: signers[1].signerId,\n channel: batchMode ? batchChannel : signers[1].channel,\n options: signerOptions,\n })\n : null;\n // OTP (platform SignedDocumentsSignMode), on this device only. As\n // platform's _getDoesNotRequireOtp the waiver starts on when the PATIENT\n // cannot receive SMS, whoever signs, and is forced on when the patient\n // is the main signer and cannot. With no `isPatient` option the main\n // signer stands in for the patient. Batch mode has one waiver for the\n // batch; per signer, the main signer's row in required documents mode\n // follows these rules and every other row is the user's own choice.\n const patientSmsPossible = batchChannelsFor(\n patientOption?.value ?? primaryId,\n ).includes('sms');\n const otpForced =\n (requiredMode || batchMode) && primaryIsPatient && !patientSmsPossible;\n const batchSkipOtp =\n batchMode &&\n batchChannel === 'on-device' &&\n (otpForced || (otpOverride ?? !patientSmsPossible));\n // As platform, the batch warning shows whenever the waiver is forced or\n // on, whatever the channel.\n const batchOtpWarning =\n batchMode && signers.length > 0 && (otpForced || batchSkipOtp);\n const followsOtpRules = (index: number) => requiredMode && index === 0;\n // A signer row's waiver, per signer.\n const rowSkipOtp = (signer: SignerRequest, index: number): boolean =>\n signer.channel === 'on-device' &&\n (followsOtpRules(index)\n ? otpForced || (signer.skipOtp ?? !patientSmsPossible)\n : signer.skipOtp === true);\n const rosterVisible =\n withPatient && !(requiredMode && requiredItemsLoading);\n\n const patchSigner = (rowId: number, patch: Partial<SignerRequest>) => {\n setSigners((current) =>\n current.map((signer) =>\n signer.rowId === rowId ? { ...signer, ...patch } : signer,\n ),\n );\n };\n\n const addSigner = () => {\n if (!nextFreeOption) return;\n if (batchMode) {\n commitBatch(\n [\n ...rosterRows,\n {\n signerId: nextFreeOption.value,\n channel: batchChannel,\n rowId: nextRowId.current++,\n },\n ],\n batchChannel,\n );\n return;\n }\n // A second signee joins the main signer on this device.\n const channel = resolveChannel(\n nextFreeOption.value,\n requiredMode ? 'on-device' : 'sms',\n );\n if (resolveChannels) {\n commitWithHost(\n operator,\n operatorChannel,\n [\n ...rosterRows,\n {\n signerId: nextFreeOption.value,\n channel,\n rowId: nextRowId.current++,\n },\n ],\n 'signers',\n );\n return;\n }\n setSigners((current) => [\n ...current,\n {\n signerId: nextFreeOption.value,\n channel,\n rowId: nextRowId.current++,\n },\n ]);\n };\n\n const removeSigner = (rowId: number) => {\n // Move focus BEFORE the row (and the focused remove button) unmounts —\n // otherwise Radix's focus scope dumps focus on the dialog container.\n addButtonRef.current?.focus();\n if (batchMode) {\n commitBatch(\n rosterRows.filter((signer) => signer.rowId !== rowId),\n batchChannel,\n );\n return;\n }\n if (resolveChannels) {\n commitWithHost(\n operator,\n operatorChannel,\n rosterRows.filter((signer) => signer.rowId !== rowId),\n 'signers',\n );\n return;\n }\n setSigners((current) =>\n current.filter((signer) => signer.rowId !== rowId),\n );\n };\n\n // A signer with no available channel cannot be sent anything, so the\n // request waits, as it does with no signer at all.\n // Batch mode reads the batch channel, which always has on this device to\n // offer.\n const anySignerWithoutChannel =\n withPatient &&\n !batchMode &&\n signers.some((signer) => hasNoChannel(signer.signerId));\n const anySignerOnQr =\n withPatient &&\n (batchMode\n ? signers.length > 0 && batchChannel === 'qr'\n : signers.some((signer) => signer.channel === 'qr'));\n // The shared warning per signer; batch mode has its own\n // (`batchOtpWarning`).\n const anySignerSkipsOtp =\n !batchMode &&\n signers.some(\n (signer, index) =>\n rowSkipOtp(signer, index) && !hasNoChannel(signer.signerId),\n );\n\n // Joins host reasons or channel labels the locale's way (\"a, b\").\n const formatList = (items: string[]): string =>\n new Intl.ListFormat(i18n.language || 'en', { type: 'unit' }).format(\n items,\n );\n\n // A channel dropdown's options: greyed-out channels stay listed, with\n // their reason under them, as the operator's on-device option does.\n const channelOptionsFor = (\n listed: SignatureChannel[],\n unavailable: Map<SignatureChannel, string>,\n ): SelectOption<SignatureChannel>[] =>\n listed.map((channel) => {\n const reason = unavailable.get(channel);\n return reason === undefined\n ? channelOption(channel, channel)\n : {\n ...channelOption(channel, channel),\n disabled: true,\n description: reason,\n };\n });\n\n // The reasons, for the trigger: a disabled option cannot take focus.\n // `reasonsOnly` when nothing is available and they show under the row.\n const channelReasons = (\n listed: SignatureChannel[],\n unavailable: Map<SignatureChannel, string>,\n reasonsOnly: boolean,\n ): string | undefined => {\n const byReason = new Map<string, string[]>();\n for (const channel of listed) {\n const reason = unavailable.get(channel);\n if (reason === undefined) continue;\n byReason.set(reason, [\n ...(byReason.get(reason) ?? []),\n channelMeta[channel].label,\n ]);\n }\n if (byReason.size === 0) return undefined;\n return reasonsOnly\n ? formatList([...byReason.keys()])\n : formatList(\n [...byReason].map(\n ([reason, labels]) => `${formatList(labels)} (${reason})`,\n ),\n );\n };\n\n const batchListed = batchListedFor(\n primaryId,\n primaryId === undefined\n ? undefined\n : hostView?.signerAvailableChannels?.[primaryId],\n );\n const batchUnavailable = batchUnavailableFor(primaryId);\n const batchChannelOptions = channelOptionsFor(\n batchListed,\n batchUnavailable,\n );\n const batchChannelHint = channelReasons(\n batchListed,\n batchUnavailable,\n false,\n );\n\n const handleRequest = () => {\n // The button is disabled too; this stops any other route in.\n if (anySignerWithoutChannel || secondIssue !== null) return;\n // Always set: a stale wait from an earlier failed QR submit must not\n // resurface the spinner after a submit without QR signers.\n setAwaitingQr(anySignerOnQr);\n if (anySignerOnQr) {\n // Move focus to the heading BEFORE the form footer unmounts, so it\n // never drops to the dialog container.\n titleRef.current?.focus();\n setQrIndex(0);\n }\n const roster: SignerRequest[] = signers.map(\n ({ rowId: _rowId, ...signer }, index) => {\n if (batchMode) {\n return {\n signerId: signer.signerId,\n channel: batchChannel,\n // The batch's OTP waiver rides on the main signer.\n ...(index === 0 && batchChannel === 'on-device'\n ? { skipOtp: batchSkipOtp }\n : {}),\n };\n }\n // The main signer's waiver follows the patient's SMS.\n return followsOtpRules(index) && signer.channel === 'on-device'\n ? { ...signer, skipOtp: rowSkipOtp(signer, index) }\n : signer;\n },\n );\n const signMode = batchMode ? { signMode: batchChannel } : {};\n if (requiredMode) {\n // Walk the items in list order: object key order puts numeric ids\n // ('87', '1204') first, so it cannot decide the first operator.\n const operatorAssignments: Record<string, string | null> = {};\n let firstOperatorId: string | null = null;\n for (const item of listedItems) {\n if (!needsOperatorPick(item)) continue;\n const value = assignments[item.id];\n const assigned =\n value === ASSIGN_LATER || value === '' || value === undefined\n ? null\n : value;\n operatorAssignments[item.id] = assigned;\n firstOperatorId ??= assigned;\n }\n // Each assigned item's operator channel, when shown.\n const operatorChannels: Record<string, OperatorChannel> = {};\n for (const [itemId, operatorId] of Object.entries(\n operatorAssignments,\n )) {\n if (operatorId !== null) {\n operatorChannels[itemId] = itemOperatorChannels[itemId];\n }\n }\n onRequestSignature({\n operatorId: firstOperatorId,\n operatorChannel: null,\n signers: roster,\n ...signMode,\n operatorAssignments,\n ...(showOperatorChannels ? { operatorChannels } : {}),\n requiredItemIds: listedItems.map((item) => item.id),\n });\n return;\n }\n onRequestSignature({\n operatorId: !requireOperator || isUnassigned ? null : operator,\n operatorChannel:\n !requireOperator || isUnassigned ? null : operatorChannel,\n signers: requirePatient ? roster : [],\n ...(requirePatient ? signMode : {}),\n });\n };\n\n // A host error ends the wait and returns the user to the form, where the\n // error alert shows and they can retry.\n useEffect(() => {\n if (error) setAwaitingQr(false);\n }, [error]);\n\n /* ---- QR step --------------------------------------------------- */\n const hasQrCodes = (qrCodes?.length ?? 0) > 0;\n // `error` wins over any wait (`qrPending` included, and an error string\n // the host left set from an earlier failure), since only the form\n // renders it. Codes that arrive still show.\n const qrStep = hasQrCodes || (!error && (qrPending || awaitingQr));\n // One slot per `'qr'` roster signer, in roster order, plus any code for a\n // signer the roster does not list (e.g. a host that opens on the step).\n const qrSlots = withPatient\n ? signers\n .filter(\n (signer) => (batchMode ? batchChannel : signer.channel) === 'qr',\n )\n .map((signer) => signer.signerId)\n : [];\n for (const code of qrCodes ?? []) {\n if (!qrSlots.includes(code.signerId)) qrSlots.push(code.signerId);\n }\n const qrTotal = qrSlots.length;\n const qrCurrent = Math.min(qrIndex, Math.max(qrTotal - 1, 0));\n const qrSignerId = qrSlots[qrCurrent];\n const qrName =\n qrSignerId === undefined ? '' : labelFor(signerOptions, qrSignerId);\n const qrCode = qrCodes?.find((code) => code.signerId === qrSignerId);\n const qrExpiry = qrCode\n ? formatQrExpiry(qrCode.expiresAt, i18n.language || 'en', t)\n : null;\n const isLastQr = qrCurrent >= qrTotal - 1;\n const showQrCount = hasQrCodes && qrTotal > 1;\n\n // Focus the step heading when the step opens, when the codes arrive and\n // when the code changes, so screen readers hear the new signer and expiry.\n const qrFocusKey =\n open && qrStep && !shownOutcome ? `${hasQrCodes}:${qrCurrent}` : null;\n useEffect(() => {\n if (qrFocusKey !== null) titleRef.current?.focus();\n }, [qrFocusKey]);\n // Same for an outcome: its header holds the message.\n const outcomeFocusKey = open && shownOutcome ? shownOutcome : null;\n useEffect(() => {\n if (outcomeFocusKey !== null) titleRef.current?.focus();\n }, [outcomeFocusKey]);\n\n const qrDescription = !hasQrCodes\n ? t('signatureRequest.qrPending')\n : !qrCode\n ? // The error alert in the body carries the message (and announces\n // itself); the description only names whose slot this is.\n qrName || qrSignerId\n : qrName\n ? t('signatureRequest.qrCaptionNamed', { name: qrName })\n : t('signatureRequest.qrCaption');\n\n return (\n <div ref={ref} className=\"ds:contents\" data-component=\"signature-request\">\n {/* Covers every view, e.g. the signatures list's tooltips. */}\n <TooltipProvider>\n <Dialog open={open} onOpenChange={onOpenChange}>\n {/* Every view keeps its title and actions in view: only the\n body scrolls. */}\n <Dialog.Content\n size=\"lg\"\n scroll=\"body\"\n hideCloseButton\n onOpenAutoFocus={(event) => {\n // Opening on the QR step, an outcome or the signed versions:\n // start at the heading. With signed versions the first\n // focusable is a tooltip trigger, and focusing it on open\n // would pop its tooltip unasked.\n if (!qrStep && !hasHistory && !shownOutcome) return;\n event.preventDefault();\n titleRef.current?.focus();\n }}\n {...contentProps}\n >\n <Dialog.Header>\n {/* One title element for both steps, focusable from script only,\n so focus can land here as the step or code changes. */}\n <Dialog.Title\n ref={titleRef}\n tabIndex={-1}\n aria-describedby={\n outcomeText\n ? outcomeDescriptionId\n : qrStep\n ? showQrCount\n ? `${qrDescriptionId} ${qrCountId}`\n : qrDescriptionId\n : undefined\n }\n className=\"ds:outline-none\"\n >\n {outcomeText\n ? outcomeText.title\n : qrStep\n ? t('signatureRequest.qrTitle')\n : (title ??\n t(\n requiredMode\n ? 'signatureRequest.requiredTitle'\n : 'signatureRequest.title',\n ))}\n </Dialog.Title>\n {outcomeText ? (\n <Dialog.Description asChild>\n {/* Same shape as the QR step: the inner id describes the\n heading, which takes focus when the outcome shows. */}\n <div>\n <p id={outcomeDescriptionId}>{outcomeText.description}</p>\n </div>\n </Dialog.Description>\n ) : qrStep ? (\n <Dialog.Description asChild>\n {/* Radix stamps its own id on this element for the dialog's\n aria-describedby; the inner id describes the heading. */}\n <div>\n <div\n id={qrDescriptionId}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <p>{qrDescription}</p>\n {qrExpiry ? <p>{qrExpiry}</p> : null}\n </div>\n </div>\n </Dialog.Description>\n ) : (\n <Dialog.Description>\n {description ??\n t(\n requiredMode\n ? 'signatureRequest.requiredDescription'\n : hasHistory\n ? // The table says whether there are signed\n // versions, so the header describes the form.\n 'signatureRequest.requestDescription'\n : 'signatureRequest.noSignedVersions',\n )}\n </Dialog.Description>\n )}\n </Dialog.Header>\n\n {shownOutcome ? (\n <>\n <Dialog.Body>\n <SignatureOutcome outcome={shownOutcome} />\n </Dialog.Body>\n <Dialog.Footer>\n {shownOutcome === 'creditsExhausted' &&\n onBuyMoreSignatures ? (\n <Button\n intent=\"primary\"\n startIcon={<ShoppingCart />}\n onClick={onBuyMoreSignatures}\n >\n {t('signatureRequest.buyMoreSignatures')}\n </Button>\n ) : null}\n {/* Back to the form, as platform's Annulla. Focus moves\n to the heading BEFORE this footer unmounts. */}\n {shownOutcome === 'creditsExhausted' &&\n outcome === 'creditsExhausted' &&\n onOutcomeCancel ? (\n <Button\n intent=\"ghost\"\n onClick={() => {\n titleRef.current?.focus();\n setOutcomeCancelled(true);\n onOutcomeCancel();\n }}\n >\n {t('signatureRequest.outcomeCancel')}\n </Button>\n ) : null}\n <Dialog.Close asChild>\n <Button intent=\"outline\">\n {t('signatureRequest.close')}\n </Button>\n </Dialog.Close>\n </Dialog.Footer>\n </>\n ) : qrStep ? (\n <>\n <Dialog.Body className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)] ds:text-center\">\n {!hasQrCodes ? (\n // Waiting for the server: the spinner's status role\n // announces the wait politely.\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)] ds:py-[var(--spacing-xl)]\">\n <Spinner\n size=\"lg\"\n label={t('signatureRequest.qrPending')}\n />\n </div>\n ) : (\n <>\n {showQrCount ? (\n // Also describes the heading, so screen readers hear\n // the position when Previous or Next moves focus there.\n <p\n id={qrCountId}\n className=\"type-label ds:text-[var(--muted-foreground)]\"\n >\n {t('signatureRequest.qrStepCount', {\n current: qrCurrent + 1,\n total: qrTotal,\n })}\n </p>\n ) : null}\n {qrName ? (\n <p className=\"type-title-item ds:break-words\">\n {qrName}\n </p>\n ) : null}\n {qrCode ? (\n // The QrCode's own name speaks of check-in, so the\n // pattern names the code and hides the inner figure.\n // `lg` keeps a long signing link at a module size a\n // phone camera can read off a desk monitor.\n <div\n role=\"img\"\n aria-label={t('signatureRequest.qrCodeLabel')}\n data-signer-id={qrSignerId}\n >\n <QrCode\n value={qrCode.url}\n variant=\"framed\"\n size=\"lg\"\n decorative\n />\n </div>\n ) : (\n <Alert\n variant=\"error\"\n className=\"ds:text-start\"\n data-signer-id={qrSignerId}\n >\n <Alert.Description>\n {t('signatureRequest.qrMissing', {\n name: qrName || qrSignerId,\n })}\n </Alert.Description>\n </Alert>\n )}\n </>\n )}\n </Dialog.Body>\n\n <Dialog.Footer>\n {!hasQrCodes ? (\n <Dialog.Close asChild>\n <Button intent=\"outline\">\n {t('signatureRequest.close')}\n </Button>\n </Dialog.Close>\n ) : (\n <>\n {qrTotal > 1 ? (\n <Button\n intent=\"outline\"\n disabled={qrCurrent === 0}\n onClick={() => setQrIndex(qrCurrent - 1)}\n >\n {t('signatureRequest.qrPrevious')}\n </Button>\n ) : null}\n {isLastQr ? (\n <Button\n intent=\"primary\"\n onClick={() => {\n onQrDone?.();\n onOpenChange(false);\n }}\n >\n {t('signatureRequest.qrDone')}\n </Button>\n ) : (\n <Button\n intent=\"primary\"\n onClick={() => setQrIndex(qrCurrent + 1)}\n >\n {t('signatureRequest.qrNext')}\n </Button>\n )}\n </>\n )}\n </Dialog.Footer>\n </>\n ) : (\n <>\n <Dialog.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n {/* Who signed what and when, above the request form on\n the same screen, as on platform. */}\n {hasHistory ? (\n <>\n <SignatureHistory\n signatures={signatures}\n loading={signaturesLoading}\n showLegalLevel={showLegalLevel}\n onView={onViewSignature}\n onDownload={onDownloadSignature}\n onShare={onShareSignature}\n shareTargets={signatureShareTargets}\n onDelete={onDeleteSignature}\n />\n {withOperator || rosterVisible ? (\n <Separator decorative />\n ) : null}\n </>\n ) : null}\n {requiredMode ? (\n <RequiredDocuments\n items={listedItems}\n loading={requiredItemsLoading}\n operatorOptions={operatorPickerList}\n assignments={assignments}\n onAssign={assignItem}\n showOperatorChannels={showOperatorChannels}\n operatorChannels={itemOperatorChannels}\n onOperatorChannel={(itemId, channel) =>\n setOperatorChannelOverrides((current) => ({\n ...current,\n [itemId]: channel,\n }))\n }\n onAssignAllToMe={\n currentOperatorId !== undefined\n ? assignAllToMe\n : undefined\n }\n busy={busy}\n />\n ) : null}\n {withOperator ? (\n <section\n className={`${PERSON_SECTION} ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:text-start`}\n >\n <div className={PERSON_GRID}>\n <div className={PERSON_HEADER}>\n <p className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {t('signatureRequest.operatorSection')}\n </p>\n {currentOperatorId !== undefined ? (\n <Button\n intent=\"outline\"\n size=\"sm\"\n startIcon={<UserPlus />}\n disabled={busy}\n onClick={() => {\n setOperator(currentOperatorId);\n if (resolveChannels) {\n commitWithHost(\n currentOperatorId,\n operatorDefaultChannel(currentOperatorId),\n rosterRows,\n 'operator',\n );\n return;\n }\n setOperatorChannel(\n operatorDefaultChannel(\n currentOperatorId,\n anySignerOnDevice,\n ),\n );\n setRevertedTo(null);\n }}\n >\n {t('signatureRequest.assignToMe')}\n </Button>\n ) : null}\n </div>\n </div>\n\n {/* The action column stays empty but reserved, and the\n channel column keeps its width while unassigned, so\n both selects end where the signer rows' do. */}\n <div className={PERSON_GRID} data-person-row=\"operator\">\n {/* Mirrors the select value — decorative for AT. No\n name → Avatar's built-in placeholder icon. */}\n <div className={PERSON_AVATAR}>\n <Avatar\n aria-hidden=\"true\"\n name={\n isUnassigned\n ? undefined\n : labelFor(operators, operator)\n }\n size=\"sm\"\n />\n </div>\n <div className={PERSON_NAME}>\n <Select\n options={operatorPickerOptions(\n operatorPickerList,\n operator,\n )}\n value={operator}\n showDescriptions\n aria-describedby={\n operatorHint ? operatorPickerHintId : undefined\n }\n onValueChange={(value) => {\n // A greyed-out or deleted operator (e.g. from\n // the agent's set_value) is refused.\n if (\n !value ||\n !isPickableOperator(operatorPickerList, value)\n )\n return;\n setOperator(value);\n if (resolveChannels) {\n commitWithHost(\n value,\n value === ASSIGN_LATER\n ? 'email'\n : operatorDefaultChannel(value),\n rosterRows,\n 'operator',\n );\n return;\n }\n // A different operator brings their own system\n // default along, replacing a hand-picked one.\n setOperatorChannel(\n value === ASSIGN_LATER\n ? 'email'\n : operatorDefaultChannel(\n value,\n anySignerOnDevice,\n ),\n );\n setRevertedTo(null);\n }}\n required\n disabled={busy}\n placeholder={t(\n 'signatureRequest.operatorPlaceholder',\n )}\n aria-label={t('signatureRequest.operatorSection')}\n />\n {operatorHint ? (\n <span\n id={operatorPickerHintId}\n className=\"ds:sr-only\"\n >\n {operatorHint}\n </span>\n ) : null}\n </div>\n\n {/* One channel for the operator too, in the same\n dropdown as the signer rows. Hidden while the\n request is unassigned: nobody to deliver to. The\n name is for assistive tech only. */}\n <div\n className={\n isUnassigned\n ? `${PERSON_CHANNEL} ds:hidden ds:@[512px]/person:block`\n : PERSON_CHANNEL\n }\n >\n {isUnassigned ? null : (\n <Select<OperatorChannel>\n id=\"signature-request-operator-channel\"\n options={operatorChannelOptions}\n value={operatorChannel}\n adornmentInTrigger\n showDescriptions\n disabled={busy}\n aria-label={t(\n 'signatureRequest.operatorChannelLabel',\n )}\n aria-describedby={\n onDeviceHint ? operatorHintId : undefined\n }\n onValueChange={(value) => {\n // The agent's set_value skips the list, so\n // a disabled option is refused here too.\n const offered = operatorChannelOptions.some(\n (option) =>\n option.value === value &&\n !option.disabled,\n );\n if (!offered) return;\n if (resolveChannels) {\n commitWithHost(\n operator,\n value as OperatorChannel,\n rosterRows,\n 'operator',\n );\n return;\n }\n setOperatorChannel(value as OperatorChannel);\n setRevertedTo(null);\n }}\n />\n )}\n {channelSizer}\n </div>\n {/* Why on this device is greyed out, for screen\n readers on the trigger; sighted users read it\n under the option. */}\n {onDeviceHint && !isUnassigned ? (\n <span id={operatorHintId} className=\"ds:sr-only\">\n {onDeviceHint}\n </span>\n ) : null}\n </div>\n </section>\n ) : null}\n\n {/* Announces a channel moved in a section the user did not\n touch: the built-in on-device fallback or a host rule.\n Outside both sections, so it is there in required\n documents mode too. */}\n {withOperator || rosterVisible ? (\n <span role=\"status\" className=\"ds:sr-only\">\n {revertedTo\n ? t('signatureRequest.operatorChannelReverted', {\n channel: channelMeta[revertedTo].label,\n })\n : hostAnnouncement}\n </span>\n ) : null}\n\n {/* The rule only separates two sections that are both there. */}\n {(withOperator || requiredMode) && rosterVisible ? (\n <Separator decorative />\n ) : null}\n\n {rosterVisible ? (\n <section\n className={`${PERSON_SECTION} ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:text-start`}\n >\n <div className={PERSON_GRID}>\n <div className={PERSON_HEADER}>\n <p className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {t('signatureRequest.signersSection')}\n </p>\n {/* Offered only when the roster holds more than one\n person. A patient with nobody else to sign for\n them saw a permanently greyed action — a promise\n the modal could never keep. With two or more it\n stays, greying (not hiding) once every seat is\n taken so the cap reads. */}\n {signerOptions.length > 1 ? (\n <Button\n ref={addButtonRef}\n intent=\"outline\"\n size=\"sm\"\n startIcon={<Plus />}\n disabled={!canAddSigner}\n aria-describedby={\n secondSigneeHint\n ? secondSigneeHintId\n : undefined\n }\n onClick={addSigner}\n >\n {t('signatureRequest.addSigner')}\n </Button>\n ) : null}\n </div>\n {/* Required documents mode, as platform's Signee:\n with no registered signee, a link to add one,\n at the name column's start edge. */}\n {requiredMode &&\n onAddSignee &&\n !signerOptions.some(\n (option) => option.isPatient !== true,\n ) ? (\n <div className={PERSON_UNDER}>\n <Button\n intent=\"link\"\n size=\"sm\"\n startIcon={<Plus />}\n disabled={busy}\n onClick={onAddSignee}\n >\n {t('signatureRequest.addSignatory')}\n </Button>\n </div>\n ) : null}\n {/* Batch mode: one channel for the whole roster\n (platform's sign mode), on the person grid from\n the name edge to the selects' end edge. */}\n {batchMode ? (\n <div\n className={`${PERSON_UNDER} ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]`}\n >\n <label\n htmlFor={BATCH_CHANNEL_ID}\n className=\"type-label ds:text-foreground\"\n >\n {t('signatureRequest.channelLabel')}\n </label>\n <Select<SignatureChannel>\n id={BATCH_CHANNEL_ID}\n options={batchChannelOptions}\n value={batchChannel}\n adornmentInTrigger\n showDescriptions\n disabled={busy}\n aria-label={t('signatureRequest.channelLabel')}\n aria-describedby={\n batchChannelHint\n ? batchChannelHintId\n : undefined\n }\n onValueChange={(value) => {\n // The agent's set_value skips the list, so\n // a greyed-out channel is refused here too.\n const offered = batchChannelOptions.some(\n (option) =>\n option.value === value &&\n !option.disabled,\n );\n if (!offered) return;\n commitBatch(\n rosterRows,\n value as SignatureChannel,\n { userChannel: true },\n );\n }}\n />\n {batchChannelHint ? (\n <span\n id={batchChannelHintId}\n className=\"ds:sr-only\"\n >\n {batchChannelHint}\n </span>\n ) : null}\n </div>\n ) : null}\n {/* One OTP waiver for the batch, on this device\n only. Forced on (and disabled) when the patient\n signs and cannot receive SMS; the warning right\n under it says what that costs. As on platform,\n a forced waiver warns on every channel. */}\n {batchMode && batchChannel === 'on-device' ? (\n <div className={PERSON_UNDER}>\n <Switch\n label={t('signatureRequest.noOtp')}\n checked={batchSkipOtp}\n disabled={busy || otpForced}\n aria-describedby={\n otpForced ? otpWarningId : undefined\n }\n onCheckedChange={(checked) =>\n setOtpOverride(checked)\n }\n />\n </div>\n ) : null}\n {batchOtpWarning ? (\n <Alert\n variant=\"warning\"\n id={otpWarningId}\n className={PERSON_UNDER}\n >\n <Alert.Description>\n {t('signatureRequest.noOtpWarning')}\n </Alert.Description>\n </Alert>\n ) : null}\n {/* Visible, not a tip: the reason a second signee is\n missing matters before the user looks for one. */}\n {secondSigneeHint ? (\n <p\n id={secondSigneeHintId}\n className={`${PERSON_UNDER} type-body-sm ds:text-[color:var(--muted-foreground)]`}\n >\n {secondSigneeHint}\n </p>\n ) : null}\n </div>\n\n <div className={PERSON_LIST}>\n {signers.map((signer, index) => {\n const rowOptions = signerOptions.filter(\n (option) =>\n option.value === signer.signerId ||\n !chosenIds.includes(option.value),\n );\n const rowLabel = labelFor(\n signerOptions,\n signer.signerId,\n );\n const rowIsMinor =\n signerOptions.find(\n (option) => option.value === signer.signerId,\n )?.isMinor === true;\n // Required documents mode: the main signer, then\n // the second signee, who is never the patient.\n const isSecond = requiredMode && index > 0;\n const personOptions = isSecond\n ? rowOptions.filter(\n (option) => option.isPatient !== true,\n )\n : rowOptions;\n const known = personOptions.some(\n (option) => option.value === signer.signerId,\n );\n const issue = isSecond ? secondIssue : null;\n const issueId = `${secondSigneeIssueId}-${signer.rowId}`;\n const labelId = `${secondSigneeLabelId}-${signer.rowId}`;\n // Per signer: greyed-out channels stay listed with\n // their reason under them, as the operator's\n // on-device option does. Batch mode has no\n // channel beside the name.\n const rowUnavailable = unavailableFor(\n signer.signerId,\n );\n const rowListed = listedChannelsFor(\n signer.signerId,\n hostView?.signerAvailableChannels?.[\n signer.signerId\n ],\n );\n const rowChannelOptions = channelOptionsFor(\n rowListed,\n rowUnavailable,\n );\n const rowNoChannel =\n !batchMode &&\n rowChannelOptions.every(\n (option) => option.disabled,\n );\n // With nothing available the reasons show under\n // the row instead.\n const rowChannelHint = batchMode\n ? undefined\n : channelReasons(\n rowListed,\n rowUnavailable,\n rowNoChannel,\n );\n const rowChannelHintId = `${signerChannelHintId}-${signer.rowId}`;\n const rowOtpForced =\n followsOtpRules(index) && otpForced;\n // Required documents mode keeps the main signer.\n const canRemove = requiredMode\n ? isSecond\n : signers.length > 1;\n\n const changePerson = (value: string) => {\n // Someone already on another row, or the\n // patient as second signee (e.g. from the\n // agent's set_value), is refused.\n if (\n !value ||\n !personOptions.some(\n (option) => option.value === value,\n )\n )\n return;\n if (batchMode) {\n commitBatch(\n rosterRows.map((row) =>\n row.rowId === signer.rowId\n ? { ...row, signerId: value }\n : row,\n ),\n batchChannel,\n { primaryChanged: requiredMode && !isSecond },\n );\n return;\n }\n const channel = resolveChannel(\n value,\n signer.channel,\n );\n // As platform's _onSigneeIdChanged, a new main\n // signer clears the second signee.\n const clearSecond =\n requiredMode &&\n !isSecond &&\n rosterRows.length > 1;\n const nextRows = (\n clearSecond\n ? rosterRows.slice(0, 1)\n : rosterRows\n ).map((row) =>\n row.rowId === signer.rowId\n ? {\n ...row,\n signerId: value,\n channel,\n skipOtp:\n channel === 'on-device'\n ? row.skipOtp\n : undefined,\n }\n : row,\n );\n const extra =\n clearSecond && signers.length > 1\n ? [t('signatureRequest.secondSigneeCleared')]\n : [];\n if (resolveChannels) {\n commitWithHost(\n operator,\n operatorChannel,\n nextRows,\n 'signers',\n extra,\n );\n return;\n }\n setSigners(nextRows);\n if (extra.length > 0) {\n setRevertedTo(null);\n setHostAnnouncement(extra.join(' '));\n }\n };\n\n const changeChannel = (value: string) => {\n // A channel this signer cannot receive, hidden\n // or greyed out (e.g. from the agent's\n // set_value), is refused.\n const offered = rowChannelOptions.some(\n (option) =>\n option.value === value && !option.disabled,\n );\n if (!offered) return;\n const channel = value as SignatureChannel;\n const nextRows = rosterRows.map((row) =>\n row.rowId === signer.rowId\n ? { ...row, channel, skipOtp: undefined }\n : row,\n );\n // A main signer who stops allowing a second\n // signee hides them, and the status says why.\n const block =\n requiredMode && !isSecond && signers.length > 1\n ? secondSigneeBlock({\n items: listedItems,\n channel,\n primaryIsPatient,\n })\n : null;\n const extra =\n block === null\n ? []\n : [t(SECOND_SIGNEE_HINTS[block])];\n if (resolveChannels) {\n commitWithHost(\n operator,\n operatorChannel,\n nextRows,\n 'signers',\n extra,\n );\n return;\n }\n setSigners(nextRows);\n if (extra.length > 0) {\n setRevertedTo(null);\n setHostAnnouncement(extra.join(' '));\n }\n };\n\n const personRow = (\n <div\n key={signer.rowId}\n role=\"group\"\n aria-label={isSecond ? undefined : rowLabel}\n aria-labelledby={isSecond ? labelId : undefined}\n data-signer-id={signer.signerId}\n data-signer-role={\n requiredMode\n ? isSecond\n ? 'second'\n : 'main'\n : undefined\n }\n className={PERSON_GRID}\n >\n {/* Mirrors the select value — decorative for AT. */}\n <div className={PERSON_AVATAR}>\n <Avatar\n aria-hidden=\"true\"\n name={\n requiredMode && !known\n ? undefined\n : rowLabel\n }\n size=\"sm\"\n />\n </div>\n <div\n className={\n batchMode ? PERSON_NAME_FULL : PERSON_NAME\n }\n >\n <Select\n options={personOptions}\n value={\n requiredMode && !known\n ? ''\n : signer.signerId\n }\n tone={issue ? 'error' : 'default'}\n aria-describedby={\n issue ? issueId : undefined\n }\n onValueChange={changePerson}\n required\n disabled={busy}\n placeholder={t(\n 'signatureRequest.signerPlaceholder',\n )}\n aria-label={t(\n 'signatureRequest.signerPlaceholder',\n )}\n />\n </div>\n\n {/* One channel per signer, beside the name. The\n name is for assistive tech only. */}\n {batchMode ? null : (\n <div className={PERSON_CHANNEL}>\n <Select<SignatureChannel>\n id={`signature-request-signer-channel-${signer.rowId}`}\n options={rowChannelOptions}\n value={rowNoChannel ? '' : signer.channel}\n adornmentInTrigger\n showDescriptions\n disabled={busy}\n aria-label={t(\n 'signatureRequest.channelLabel',\n )}\n aria-describedby={\n rowChannelHint\n ? rowChannelHintId\n : undefined\n }\n onValueChange={changeChannel}\n />\n {channelSizer}\n </div>\n )}\n {rowChannelHint && !rowNoChannel ? (\n <span\n id={rowChannelHintId}\n className=\"ds:sr-only\"\n >\n {rowChannelHint}\n </span>\n ) : null}\n\n {canRemove ? (\n <div className={PERSON_ACTION}>\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={<X />}\n disabled={busy}\n aria-label={t(\n 'signatureRequest.removeSigner',\n )}\n onClick={() => removeSigner(signer.rowId)}\n />\n </div>\n ) : null}\n\n {/* Under 18: a reminder to check for a second\n signee, under this person's name. It never\n blocks the request, so it is polite. */}\n {rowIsMinor ? (\n <Alert\n variant=\"warning\"\n announce=\"polite\"\n data-note=\"minor-signer\"\n className={PERSON_UNDER}\n >\n <Alert.Description>\n {t('signatureRequest.minorSignerWarning')}\n </Alert.Description>\n </Alert>\n ) : null}\n\n {/* A status: it can appear with no user action\n (the host drops the person) and disables\n Request signature. */}\n {issue ? (\n <p\n id={issueId}\n role=\"status\"\n data-note=\"second-signee-issue\"\n data-issue={issue}\n className={`${PERSON_UNDER} type-body-sm ds:text-[color:var(--destructive)]`}\n >\n {t(SECOND_SIGNEE_ISSUES[issue])}\n </p>\n ) : null}\n\n {/* Nothing to send this person on: the reasons\n under their name, and the request waits. */}\n {rowNoChannel && rowChannelHint ? (\n <p\n id={rowChannelHintId}\n data-note=\"no-channel\"\n className={`${PERSON_UNDER} type-body-sm ds:text-[color:var(--muted-foreground)]`}\n >\n {rowChannelHint}\n </p>\n ) : null}\n\n {/* The row's OTP waiver, on this device. The\n main signer's in required documents mode\n is forced on (and disabled) when the\n patient signs and cannot receive SMS; the\n warning says what that costs. */}\n {!batchMode &&\n signer.channel === 'on-device' &&\n !rowNoChannel ? (\n <div className={PERSON_UNDER}>\n <Switch\n label={t('signatureRequest.noOtp')}\n checked={rowSkipOtp(signer, index)}\n disabled={busy || rowOtpForced}\n aria-describedby={\n rowOtpForced ? otpWarningId : undefined\n }\n onCheckedChange={(checked) =>\n patchSigner(signer.rowId, {\n skipOtp: checked,\n })\n }\n />\n </div>\n ) : null}\n </div>\n );\n if (!isSecond) return personRow;\n // The second signee's row, under its own label.\n return (\n <div\n key={signer.rowId}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <div className={PERSON_GRID}>\n <p\n id={labelId}\n className={`${PERSON_UNDER} type-label ds:text-[color:var(--muted-foreground)]`}\n >\n {t('signatureRequest.secondSigneeLabel')}\n </p>\n </div>\n {personRow}\n </div>\n );\n })}\n </div>\n </section>\n ) : null}\n\n {/* Dedicated alert area — one warning regardless of how many\n signers waive OTP, stacked with any submission error,\n under the names like everything under a person. Required\n documents mode shows its warning under the batch switch. */}\n {anySignerSkipsOtp || error ? (\n <div className={PERSON_SECTION}>\n <div className={PERSON_GRID}>\n {anySignerSkipsOtp ? (\n <Alert\n variant=\"warning\"\n id={otpWarningId}\n className={PERSON_UNDER}\n >\n <Alert.Description>\n {t('signatureRequest.noOtpWarning')}\n </Alert.Description>\n </Alert>\n ) : null}\n {error ? (\n <Alert variant=\"error\" className={PERSON_UNDER}>\n <Alert.Description>{error}</Alert.Description>\n </Alert>\n ) : null}\n </div>\n </div>\n ) : null}\n </Dialog.Body>\n\n <Dialog.Footer>\n <Button\n intent=\"primary\"\n startIcon={<PenLine />}\n onClick={handleRequest}\n // Why it is disabled, while the second signee has an issue.\n aria-describedby={\n secondIssue !== null && signers[1]\n ? `${secondSigneeIssueId}-${signers[1].rowId}`\n : undefined\n }\n disabled={\n busy ||\n (withPatient && signers.length === 0) ||\n anySignerWithoutChannel ||\n secondIssue !== null ||\n (!withPatient && !withOperator) ||\n (requiredMode &&\n (requiredItemsLoading || listedItems.length === 0))\n }\n loading={busy}\n >\n {t('signatureRequest.requestSignature')}\n </Button>\n <Dialog.Close asChild>\n <Button intent=\"outline\" disabled={busy}>\n {t('signatureRequest.close')}\n </Button>\n </Dialog.Close>\n </Dialog.Footer>\n </>\n )}\n </Dialog.Content>\n </Dialog>\n </TooltipProvider>\n </div>\n );\n },\n);\nSignatureRequestModal.displayName = 'SignatureRequestModal';\n"],"names":["__iconNode","Link2","createLucideIcon","QrCode","ShoppingCart","Tablet","OPERATOR_CHANNELS","useChannelMeta","t","useTranslation","jsx","MessageSquare","Mail","WhatsAppGlyph","QrCodeIcon","LoadStatus","loading","loadingText","loadedText","override","message","setMessage","useState","wasLoading","useRef","useEffect","PERSON_GRID","PERSON_AVATAR","PERSON_NAME","PERSON_NAME_FULL","PERSON_CHANNEL","PERSON_ACTION","PERSON_UNDER","PERSON_HEADER","PERSON_LIST","PERSON_SECTION","ChannelColumnSizer","meta","channel","label","icon","jsxs","selectTriggerVariants","ChevronDown","SHARE_TARGETS","LOADING_ROWS","TABLE","ROWGROUP","ROW","CELL_DATE","CELL_TYPE","CELL_ACTIONS","timeOf","value","ms","newestFirst","records","record","index","a","b","SignatureHistory","signatures","showLegalLevel","onView","onDownload","onShare","shareTargets","onDelete","i18n","channelMeta","headingId","useId","shareMeta","language","intlLocale","weekdayFormat","dayFormat","timeFormat","formatWhen","weekday","tableRef","emptyRef","pendingDelete","deleteStatus","setDeleteStatus","pending","remaining","at","targetId","id","active","_a","row","_b","element","_c","sorted","content","Skeleton","headerCell","TooltipProvider","when","dateTime","allowedTargets","rowShareTargets","target","hasActions","SignatureStatusChip","IconButton","Eye","RowMenu","Download","DropdownMenu","Share2","DeleteConfirm","item","useQuietReturnTooltip","tipOpen","setTipOpen","restoringFocus","next","children","tip","menuOpen","Tooltip","onConfirm","open","setOpen","Dialog","Trash2","Button","ASSIGN_LATER","itemsStillToSign","items","batchCanCarrySecondary","needsOperatorPick","operatorPickerOptions","options","selected","option","_deleted","isPickableOperator","operatorReasonsHint","locale","entries","secondSigneeBlock","primaryIsPatient","secondSigneeIssue","primaryId","secondId","second","receives","wanted","entry","ITEM_ROW","ITEM_ROW_WITH_CHANNEL","ITEM_NAME","ITEM_NAME_FULL","ITEM_PICKER","COMPACT_NOTE","RequiredDocuments","operatorOptions","assignments","onAssign","onAssignAllToMe","busy","showOperatorChannels","operatorChannels","onOperatorChannel","channelOptions","documentsHeadingId","interviewsHeadingId","operatorHintId","status","Fragment","documents","interviews","anyUnassigned","operatorGroup","groupItems","operatorHint","group","heading","withOperatorControls","UserPlus","Alert","List","withPicker","withChannel","assigned","Select","outcomeCopy","outcome","required","SignatureOutcome","warning","TriangleAlert","CircleCheck","CHANNEL_ORDER","BATCH_CHANNEL_ID","SECOND_SIGNEE_HINTS","SECOND_SIGNEE_ISSUES","formatQrExpiry","expiresAt","date","time","labelFor","SignatureRequestModal","forwardRef","onOpenChange","operators","signerOptions","currentOperatorId","allowAssignLater","requireOperator","requirePatient","initialOperatorId","initialOperatorChannel","initialSigners","maxSigners","channelMode","initialBatchChannel","error","title","description","onRequestSignature","qrCodes","qrPending","onQrDone","signaturesLoading","onViewSignature","onDownloadSignature","onShareSignature","signatureShareTargets","onDeleteSignature","resolveChannels","requiredItems","requiredItemsLoading","onBuyMoreSignatures","onOutcomeCancel","onAddSignee","contentProps","ref","nextRowId","addButtonRef","titleRef","qrDescriptionId","qrCountId","outcomeDescriptionId","secondSigneeHintId","signerChannelHintId","batchChannelHintId","secondSigneeLabelId","secondSigneeIssueId","otpWarningId","requiredMode","listedItems","withOperator","withPatient","batchMode","isPatientId","signerId","capFor","rows","batch","outcomeCancelled","setOutcomeCancelled","prevOutcome","setPrevOutcome","shownOutcome","outcomeText","unavailableFor","reason","listedChannelsFor","hostAllowed","allowed","own","unavailable","narrowed","channelsFor","operatorChannelsFrom","resolution","resolveChannel","preferred","available","patientOption","batchPeopleFor","batchUnavailableFor","people","text","batchListedFor","listed","batchChannelsFor","seedBatchChannel","withInitial","firstOperator","resolveOperatorSeed","seed","seedOperator","seedRows","signer","skipOtp","rest","operatorDefaultChannel","operatorId","onDeviceOffered","setting","seedOperatorChannel","onDeviceSigner","clampOperatorChannel","offered","fallback","draftOf","changed","hasOperator","visible","signerUnavailableChannels","_rowId","resolveWithHost","rule","draft","nextChannel","visibleCount","nextRows","resolveBatch","opChannel","seedForm","seededOperator","seededRows","seeded","noBatch","resolved","formSeed","operator","setOperator","rosterRows","setSigners","operatorChannel","setOperatorChannel","batchChannel","setBatchChannel","otpOverride","setOtpOverride","rosterCap","signers","assignmentOverrides","setAssignmentOverrides","operatorChannelOverrides","setOperatorChannelOverrides","itemOperatorChannels","dropChannelPicks","itemIds","current","assignItem","itemId","assignAllToMe","revertedTo","setRevertedTo","hostAnnouncement","setHostAnnouncement","awaitingQr","setAwaitingQr","qrIndex","setQrIndex","hasHistory","prevOpen","setPrevOpen","wasOpen","hasNoChannel","anySignerOnDevice","hostRule","assignLaterOptions","operatorEntries","disabled","deleted","operatorPickerList","operatorPickerHintId","isUnassigned","hostView","commitWithHost","extra","commitBatch","messages","primaryChanged","userChannel","clear","block","batchOffered","fallbackRows","channelOption","onDeviceHint","operatorChannelOptions","channelSizer","chosenIds","nextFreeOption","canAddSigner","_d","mainChannel","_e","secondBlock","secondSigneeHint","secondIssue","patientSmsPossible","otpForced","batchSkipOtp","batchOtpWarning","followsOtpRules","rowSkipOtp","rosterVisible","patchSigner","rowId","patch","addSigner","removeSigner","anySignerWithoutChannel","anySignerOnQr","anySignerSkipsOtp","formatList","channelOptionsFor","channelReasons","reasonsOnly","byReason","labels","batchListed","_f","batchUnavailable","batchChannelOptions","batchChannelHint","handleRequest","roster","signMode","operatorAssignments","firstOperatorId","hasQrCodes","qrStep","qrSlots","code","qrTotal","qrCurrent","qrSignerId","qrName","qrCode","qrExpiry","isLastQr","showQrCount","qrFocusKey","outcomeFocusKey","qrDescription","event","Spinner","Separator","Avatar","Plus","Switch","checked","rowOptions","rowLabel","rowIsMinor","isSecond","personOptions","known","issue","issueId","labelId","rowUnavailable","rowListed","rowChannelOptions","rowNoChannel","rowChannelHint","rowChannelHintId","rowOtpForced","canRemove","changePerson","clearSecond","changeChannel","personRow","X","PenLine"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}
|