@alfadocs/ui-kit-debug 1.132.0 → 1.134.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-B8hV3dZV.js → agenda-card-B9wgX_Ed.js} +2 -2
- package/dist/_chunks/{agenda-card-B8hV3dZV.js.map → agenda-card-B9wgX_Ed.js.map} +1 -1
- package/dist/_chunks/{agenda-tray-Bu46s3dI.js → agenda-tray-CGcS_qoM.js} +2 -2
- package/dist/_chunks/{agenda-tray-Bu46s3dI.js.map → agenda-tray-CGcS_qoM.js.map} +1 -1
- package/dist/_chunks/appointment-card-DG3m9yN-.js +504 -0
- package/dist/_chunks/appointment-card-DG3m9yN-.js.map +1 -0
- package/dist/_chunks/{appointment-peek-DZa6xyUb.js → appointment-peek-BK0tDs4C.js} +2 -2
- package/dist/_chunks/{appointment-peek-DZa6xyUb.js.map → appointment-peek-BK0tDs4C.js.map} +1 -1
- package/dist/_chunks/{appointment-timeline-DQePqpyH.js → appointment-timeline-BiI2riRZ.js} +2 -2
- package/dist/_chunks/{appointment-timeline-DQePqpyH.js.map → appointment-timeline-BiI2riRZ.js.map} +1 -1
- package/dist/_chunks/appointment-tray-ClJCtYQj.js +200 -0
- package/dist/_chunks/appointment-tray-ClJCtYQj.js.map +1 -0
- package/dist/_chunks/{appointment-workflow-status-DMjuIK90.js → appointment-workflow-status-S-lx81Yz.js} +2 -2
- package/dist/_chunks/{appointment-workflow-status-DMjuIK90.js.map → appointment-workflow-status-S-lx81Yz.js.map} +1 -1
- package/dist/_chunks/ban-CiSCCcOE.js +15 -0
- package/dist/_chunks/ban-CiSCCcOE.js.map +1 -0
- package/dist/_chunks/{calendar-BIoOeBTT.js → calendar-CyLtLBNP.js} +2 -2
- package/dist/_chunks/{calendar-BIoOeBTT.js.map → calendar-CyLtLBNP.js.map} +1 -1
- package/dist/_chunks/calendar-appointment-editor-dialog-BSkIYGlW.js +13773 -0
- package/dist/_chunks/calendar-appointment-editor-dialog-BSkIYGlW.js.map +1 -0
- package/dist/_chunks/{calendar-event-card-BNEzkjm-.js → calendar-event-card-BJifpYZQ.js} +7 -6
- package/dist/_chunks/{calendar-event-card-BNEzkjm-.js.map → calendar-event-card-BJifpYZQ.js.map} +1 -1
- package/dist/_chunks/{care-plan-card-DKScH9Ss.js → care-plan-card-CjHq6PLo.js} +6 -6
- package/dist/_chunks/{care-plan-card-DKScH9Ss.js.map → care-plan-card-CjHq6PLo.js.map} +1 -1
- package/dist/_chunks/{care-plan-entry-card-AG1y3nyW.js → care-plan-entry-card-DY1toF6E.js} +2 -2
- package/dist/_chunks/{care-plan-entry-card-AG1y3nyW.js.map → care-plan-entry-card-DY1toF6E.js.map} +1 -1
- package/dist/_chunks/{care-plan-header-Dx5OMkc9.js → care-plan-header-CeFXUDnL.js} +6 -6
- package/dist/_chunks/{care-plan-header-Dx5OMkc9.js.map → care-plan-header-CeFXUDnL.js.map} +1 -1
- package/dist/_chunks/check-in-documents-CEVcgcYZ.js +136 -0
- package/dist/_chunks/check-in-documents-CEVcgcYZ.js.map +1 -0
- package/dist/_chunks/{clinical-note-card-pPaeWWnu.js → clinical-note-card-D--IwbZa.js} +2 -2
- package/dist/_chunks/{clinical-note-card-pPaeWWnu.js.map → clinical-note-card-D--IwbZa.js.map} +1 -1
- package/dist/_chunks/document-preview-DLVIrOYV.js +385 -0
- package/dist/_chunks/document-preview-DLVIrOYV.js.map +1 -0
- package/dist/_chunks/{entity-card-fpm-KUKc.js → entity-card-p-LANpYt.js} +18 -17
- package/dist/_chunks/{entity-card-fpm-KUKc.js.map → entity-card-p-LANpYt.js.map} +1 -1
- package/dist/_chunks/{error-page-B0fGNTRB.js → error-page-WLhmWUTq.js} +100 -115
- package/dist/_chunks/error-page-WLhmWUTq.js.map +1 -0
- package/dist/_chunks/finished-terminal-unDnXT4j.js +191 -0
- package/dist/_chunks/finished-terminal-unDnXT4j.js.map +1 -0
- package/dist/_chunks/house-DGCypGTo.js +21 -0
- package/dist/_chunks/house-DGCypGTo.js.map +1 -0
- package/dist/_chunks/is-safe-url-CEy9CEml.js +8 -0
- package/dist/_chunks/is-safe-url-CEy9CEml.js.map +1 -0
- package/dist/_chunks/keypad-DBH_keVs.js +152 -0
- package/dist/_chunks/keypad-DBH_keVs.js.map +1 -0
- package/dist/_chunks/keypad-button-mOaPQRrH.js +114 -0
- package/dist/_chunks/keypad-button-mOaPQRrH.js.map +1 -0
- package/dist/_chunks/{message-card-BG3_3nN1.js → message-card-Bw_q1qKx.js} +2 -2
- package/dist/_chunks/{message-card-BG3_3nN1.js.map → message-card-Bw_q1qKx.js.map} +1 -1
- package/dist/_chunks/{message-tray-BjZv0Fsk.js → message-tray-pLGgLmoG.js} +2 -2
- package/dist/_chunks/{message-tray-BjZv0Fsk.js.map → message-tray-pLGgLmoG.js.map} +1 -1
- package/dist/_chunks/{note-attachment-MNTIqdSz.js → note-attachment-JTIy9iXN.js} +2 -2
- package/dist/_chunks/{note-attachment-MNTIqdSz.js.map → note-attachment-JTIy9iXN.js.map} +1 -1
- package/dist/_chunks/{note-timeline-BQeW0VZY.js → note-timeline-BbjHMhkL.js} +2 -2
- package/dist/_chunks/{note-timeline-BQeW0VZY.js.map → note-timeline-BbjHMhkL.js.map} +1 -1
- package/dist/_chunks/{notes-panel-Cm-_pCRJ.js → notes-panel-BAyPOr8N.js} +2 -2
- package/dist/_chunks/{notes-panel-Cm-_pCRJ.js.map → notes-panel-BAyPOr8N.js.map} +1 -1
- package/dist/_chunks/{operator-hero-CnfWckNQ.js → operator-hero-D4wfVu2l.js} +2 -2
- package/dist/_chunks/{operator-hero-CnfWckNQ.js.map → operator-hero-D4wfVu2l.js.map} +1 -1
- package/dist/_chunks/otp-input-BNOTlxq3.js +342 -0
- package/dist/_chunks/otp-input-BNOTlxq3.js.map +1 -0
- package/dist/_chunks/patient-account-settings-BkAtIxJW.js +546 -0
- package/dist/_chunks/patient-account-settings-BkAtIxJW.js.map +1 -0
- package/dist/_chunks/patient-card-DTh3QTyS.js +125 -0
- package/dist/_chunks/patient-card-DTh3QTyS.js.map +1 -0
- package/dist/_chunks/patient-check-in-resume-xhqjC6gf.js +742 -0
- package/dist/_chunks/patient-check-in-resume-xhqjC6gf.js.map +1 -0
- package/dist/_chunks/patient-sign-in-pin-CDBqV254.js +432 -0
- package/dist/_chunks/patient-sign-in-pin-CDBqV254.js.map +1 -0
- package/dist/_chunks/patient-sign-in-steps-C2JSqlok.js +199 -0
- package/dist/_chunks/patient-sign-in-steps-C2JSqlok.js.map +1 -0
- package/dist/_chunks/{patient-summary-card-BUcZ-gaL.js → patient-summary-card-Bl2NknPe.js} +2 -2
- package/dist/_chunks/{patient-summary-card-BUcZ-gaL.js.map → patient-summary-card-Bl2NknPe.js.map} +1 -1
- package/dist/_chunks/{payment-request-card-Dv4WbRBe.js → payment-request-card-CNW00DCx.js} +6 -6
- package/dist/_chunks/{payment-request-card-Dv4WbRBe.js.map → payment-request-card-CNW00DCx.js.map} +1 -1
- package/dist/_chunks/{pdf-viewer-BnBKdx0y.js → pdf-viewer-TRC5jEm5.js} +472 -425
- package/dist/_chunks/pdf-viewer-TRC5jEm5.js.map +1 -0
- package/dist/_chunks/pin-entry-BugWQMOS.js +219 -0
- package/dist/_chunks/pin-entry-BugWQMOS.js.map +1 -0
- package/dist/_chunks/pin-indicator-Cb-n40UI.js +124 -0
- package/dist/_chunks/pin-indicator-Cb-n40UI.js.map +1 -0
- package/dist/_chunks/portal-details-CTEsm705.js +478 -0
- package/dist/_chunks/portal-details-CTEsm705.js.map +1 -0
- package/dist/_chunks/portal-documents-D8skew0h.js +902 -0
- package/dist/_chunks/portal-documents-D8skew0h.js.map +1 -0
- package/dist/_chunks/portal-parts-BdR29P7z.js +285 -0
- package/dist/_chunks/portal-parts-BdR29P7z.js.map +1 -0
- package/dist/_chunks/{privacy-mask-DJ1gee4c.js → privacy-mask-C19dJFMk.js} +5 -5
- package/dist/_chunks/{privacy-mask-DJ1gee4c.js.map → privacy-mask-C19dJFMk.js.map} +1 -1
- package/dist/_chunks/{product-hub-panel-a8wdVOUt.js → product-hub-panel-K4QbULG7.js} +2 -2
- package/dist/_chunks/{product-hub-panel-a8wdVOUt.js.map → product-hub-panel-K4QbULG7.js.map} +1 -1
- package/dist/_chunks/{registration-form-CwbhtKcy.js → registration-form-DS3RuKHu.js} +2 -2
- package/dist/_chunks/{registration-form-CwbhtKcy.js.map → registration-form-DS3RuKHu.js.map} +1 -1
- package/dist/_chunks/{reserved.agent-W8mR179D.js → reserved.agent-DOzOBUW7.js} +2 -2
- package/dist/_chunks/{reserved.agent-W8mR179D.js.map → reserved.agent-DOzOBUW7.js.map} +1 -1
- package/dist/_chunks/session-countdown-DOx1IBUB.js +232 -0
- package/dist/_chunks/session-countdown-DOx1IBUB.js.map +1 -0
- package/dist/_chunks/{sign-document-CQZVzfpk.js → sign-document-DDZbmYHu.js} +2 -2
- package/dist/_chunks/{sign-document-CQZVzfpk.js.map → sign-document-DDZbmYHu.js.map} +1 -1
- package/dist/_chunks/{signature-field-DjabvRZm.js → signature-field-BjlY_yXH.js} +39 -34
- package/dist/_chunks/signature-field-BjlY_yXH.js.map +1 -0
- package/dist/_chunks/{signature-request-4pGq3YBe.js → signature-request-CHsM_iWi.js} +2 -2
- package/dist/_chunks/{signature-request-4pGq3YBe.js.map → signature-request-CHsM_iWi.js.map} +1 -1
- package/dist/_chunks/{signature-status-chip-pIoQjvH8.js → signature-status-chip-DS9hHwIt.js} +66 -69
- package/dist/_chunks/signature-status-chip-DS9hHwIt.js.map +1 -0
- package/dist/_chunks/signing-end-screen-an9P8DOT.js +1041 -0
- package/dist/_chunks/signing-end-screen-an9P8DOT.js.map +1 -0
- package/dist/_chunks/sms-code-entry-Dgp4GwlM.js +316 -0
- package/dist/_chunks/sms-code-entry-Dgp4GwlM.js.map +1 -0
- package/dist/_chunks/step-up-dialog-C2JqJmCA.js +132 -0
- package/dist/_chunks/step-up-dialog-C2JqJmCA.js.map +1 -0
- package/dist/_chunks/{task-editor-BL2hHxNz.js → task-editor-g1AGfxhr.js} +38 -38
- package/dist/_chunks/{task-editor-BL2hHxNz.js.map → task-editor-g1AGfxhr.js.map} +1 -1
- package/dist/_chunks/{use-appointment-details-read-_b7FRB1x.js → use-appointment-details-read-Dzc6fEzG.js} +6 -6
- package/dist/_chunks/{use-appointment-details-read-_b7FRB1x.js.map → use-appointment-details-read-Dzc6fEzG.js.map} +1 -1
- package/dist/_chunks/use-zoom-drilldown-Cr1baU5X.js +221 -0
- package/dist/_chunks/use-zoom-drilldown-Cr1baU5X.js.map +1 -0
- package/dist/_chunks/{user-x-DYszNtIg.js → user-x-BJZg4kaP.js} +8 -19
- package/dist/_chunks/user-x-BJZg4kaP.js.map +1 -0
- package/dist/_chunks/{verify-identity-types-CxtrBXsZ.js → verify-identity-types-C6Bam8v6.js} +2 -2
- package/dist/_chunks/{verify-identity-types-CxtrBXsZ.js.map → verify-identity-types-C6Bam8v6.js.map} +1 -1
- package/dist/agent-catalog.json +723 -364
- package/dist/agent-i18n/en.json +75 -18
- package/dist/browser-support.js +1 -1
- package/dist/components/_shared/is-safe-url.d.ts +3 -1
- package/dist/components/_shared/is-safe-url.d.ts.map +1 -1
- package/dist/components/agenda-card/index.js +2 -2
- package/dist/components/agenda-tray/index.js +1 -1
- package/dist/components/appointment-card/appointment-card.d.ts +45 -0
- package/dist/components/appointment-card/appointment-card.d.ts.map +1 -1
- package/dist/components/appointment-card/appointment-tray.agent.d.ts.map +1 -1
- package/dist/components/appointment-card/appointment-tray.d.ts +11 -0
- package/dist/components/appointment-card/appointment-tray.d.ts.map +1 -1
- package/dist/components/appointment-card/index.js +3 -3
- 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/booking/index.js +1 -1
- package/dist/components/calendar/index.js +1 -1
- package/dist/components/calendar-event-card/index.js +1 -1
- package/dist/components/care-plan-card/index.js +1 -1
- package/dist/components/care-plan-entry-card/index.js +1 -1
- package/dist/components/care-plan-header/index.js +1 -1
- package/dist/components/clinical-note-card/index.js +1 -1
- package/dist/components/document-preview/document-preview.agent.d.ts.map +1 -1
- package/dist/components/document-preview/document-preview.d.ts +61 -7
- package/dist/components/document-preview/document-preview.d.ts.map +1 -1
- package/dist/components/document-preview/index.js +1 -1
- package/dist/components/finished-terminal/finished-terminal.d.ts +63 -6
- package/dist/components/finished-terminal/finished-terminal.d.ts.map +1 -1
- package/dist/components/finished-terminal/index.d.ts +1 -1
- package/dist/components/finished-terminal/index.d.ts.map +1 -1
- package/dist/components/finished-terminal/index.js +1 -1
- package/dist/components/index.d.ts +12 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/keypad/index.d.ts +3 -0
- package/dist/components/keypad/index.d.ts.map +1 -0
- package/dist/components/keypad/index.js +6 -0
- package/dist/components/keypad/index.js.map +1 -0
- package/dist/components/keypad/keypad.d.ts +54 -0
- package/dist/components/keypad/keypad.d.ts.map +1 -0
- package/dist/components/keypad-button/index.d.ts +3 -0
- package/dist/components/keypad-button/index.d.ts.map +1 -0
- package/dist/components/keypad-button/index.js +6 -0
- package/dist/components/keypad-button/index.js.map +1 -0
- package/dist/components/keypad-button/keypad-button.d.ts +33 -0
- package/dist/components/keypad-button/keypad-button.d.ts.map +1 -0
- package/dist/components/message-card/index.js +2 -2
- package/dist/components/message-tray/index.js +1 -1
- package/dist/components/note-timeline/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/otp-input/index.js +1 -1
- package/dist/components/otp-input/otp-input.d.ts +11 -0
- package/dist/components/otp-input/otp-input.d.ts.map +1 -1
- package/dist/components/patient-summary-card/index.js +1 -1
- package/dist/components/payment-card/index.js +1 -1
- package/dist/components/pdf-viewer/index.js +1 -1
- package/dist/components/pdf-viewer/pdf-viewer.agent.d.ts.map +1 -1
- package/dist/components/pdf-viewer/pdf-viewer.d.ts +7 -0
- package/dist/components/pdf-viewer/pdf-viewer.d.ts.map +1 -1
- package/dist/components/pin-entry/index.d.ts +3 -0
- package/dist/components/pin-entry/index.d.ts.map +1 -0
- package/dist/components/pin-entry/index.js +5 -0
- package/dist/components/pin-entry/index.js.map +1 -0
- package/dist/components/pin-entry/pin-entry.agent.d.ts +4 -0
- package/dist/components/pin-entry/pin-entry.agent.d.ts.map +1 -0
- package/dist/components/pin-entry/pin-entry.d.ts +64 -0
- package/dist/components/pin-entry/pin-entry.d.ts.map +1 -0
- package/dist/components/pin-indicator/index.d.ts +3 -0
- package/dist/components/pin-indicator/index.d.ts.map +1 -0
- package/dist/components/pin-indicator/index.js +9 -0
- package/dist/components/pin-indicator/index.js.map +1 -0
- package/dist/components/pin-indicator/pin-indicator.d.ts +34 -0
- package/dist/components/pin-indicator/pin-indicator.d.ts.map +1 -0
- package/dist/components/product-hub-tray/index.js +2 -2
- package/dist/components/session-countdown/index.js +1 -1
- package/dist/components/session-countdown/session-countdown.d.ts +19 -0
- package/dist/components/session-countdown/session-countdown.d.ts.map +1 -1
- package/dist/components/sign-document/index.js +1 -1
- package/dist/components/signature-field/index.js +1 -1
- package/dist/components/signature-field/signature-field.d.ts +17 -6
- package/dist/components/signature-field/signature-field.d.ts.map +1 -1
- package/dist/components/signature-status-chip/index.js +1 -1
- package/dist/components/signature-status-chip/signature-status-chip.d.ts +3 -2
- package/dist/components/signature-status-chip/signature-status-chip.d.ts.map +1 -1
- package/dist/components/sms-code-entry/index.d.ts +3 -0
- package/dist/components/sms-code-entry/index.d.ts.map +1 -0
- package/dist/components/sms-code-entry/index.js +5 -0
- package/dist/components/sms-code-entry/index.js.map +1 -0
- package/dist/components/sms-code-entry/sms-code-entry.agent.d.ts +4 -0
- package/dist/components/sms-code-entry/sms-code-entry.agent.d.ts.map +1 -0
- package/dist/components/sms-code-entry/sms-code-entry.d.ts +156 -0
- package/dist/components/sms-code-entry/sms-code-entry.d.ts.map +1 -0
- package/dist/components/step-up-dialog/index.d.ts +3 -0
- package/dist/components/step-up-dialog/index.d.ts.map +1 -0
- package/dist/components/step-up-dialog/index.js +5 -0
- package/dist/components/step-up-dialog/index.js.map +1 -0
- package/dist/components/step-up-dialog/step-up-dialog.d.ts +108 -0
- package/dist/components/step-up-dialog/step-up-dialog.d.ts.map +1 -0
- package/dist/components/task-editor/index.js +1 -1
- package/dist/components/workflow-status/index.js +1 -1
- package/dist/core.css +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/use-signing-session.d.ts +7 -2
- package/dist/hooks/use-signing-session.d.ts.map +1 -1
- package/dist/host-compat.css +10 -1
- package/dist/i18n/locales/ar.d.ts +514 -1
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +512 -4
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +514 -1
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +520 -5
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +514 -1
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +515 -5
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +516 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +522 -4
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +514 -1
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +513 -5
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +514 -1
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +513 -5
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +514 -1
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +513 -5
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +514 -1
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +520 -5
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +514 -1
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +513 -5
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +514 -1
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +520 -5
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +514 -1
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +520 -5
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +514 -1
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +520 -5
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +514 -1
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +520 -5
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +514 -1
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +512 -4
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +514 -1
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +513 -5
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +514 -1
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +513 -5
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +514 -1
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +515 -5
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +514 -1
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +513 -5
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +1271 -1204
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.json +516 -3
- package/dist/locales/de.json +517 -4
- package/dist/locales/el.json +517 -4
- package/dist/locales/en.json +516 -3
- package/dist/locales/es.json +517 -4
- package/dist/locales/fr.json +517 -4
- package/dist/locales/hi.json +517 -4
- package/dist/locales/it.json +517 -4
- package/dist/locales/ja.json +517 -4
- package/dist/locales/nl.json +517 -4
- package/dist/locales/pl.json +517 -4
- package/dist/locales/pt.json +517 -4
- package/dist/locales/ro.json +517 -4
- package/dist/locales/ru.json +516 -3
- package/dist/locales/sq.json +517 -4
- package/dist/locales/sv.json +517 -4
- package/dist/locales/tr.json +517 -4
- package/dist/locales/zh.json +517 -4
- package/dist/patterns/calendar/calendar-workspace.d.ts.map +1 -1
- package/dist/patterns/calendar/calendar-workspace.model.d.ts.map +1 -1
- package/dist/patterns/calendar/calendar.journey.d.ts +4 -0
- package/dist/patterns/calendar/calendar.journey.d.ts.map +1 -1
- package/dist/patterns/calendar/calendar.sheets.d.ts.map +1 -1
- package/dist/patterns/calendar/calendar.surface.d.ts +15 -1
- package/dist/patterns/calendar/calendar.surface.d.ts.map +1 -1
- package/dist/patterns/calendar/calendar.types.d.ts +4 -0
- package/dist/patterns/calendar/calendar.types.d.ts.map +1 -1
- package/dist/patterns/calendar/index.js +1 -1
- package/dist/patterns/check-in-documents/check-in-documents.d.ts +61 -0
- package/dist/patterns/check-in-documents/check-in-documents.d.ts.map +1 -0
- package/dist/patterns/check-in-documents/check-in-signable-document.d.ts +32 -0
- package/dist/patterns/check-in-documents/check-in-signable-document.d.ts.map +1 -0
- package/dist/patterns/check-in-documents/index.d.ts +4 -0
- package/dist/patterns/check-in-documents/index.d.ts.map +1 -0
- package/dist/patterns/check-in-documents/index.js +5 -0
- package/dist/patterns/check-in-documents/index.js.map +1 -0
- package/dist/patterns/error-page/index.js +1 -1
- package/dist/patterns/patient-account-settings/index.d.ts +4 -0
- package/dist/patterns/patient-account-settings/index.d.ts.map +1 -0
- package/dist/patterns/patient-account-settings/index.js +5 -0
- package/dist/patterns/patient-account-settings/index.js.map +1 -0
- package/dist/patterns/patient-account-settings/patient-account-settings-panels.d.ts +36 -0
- package/dist/patterns/patient-account-settings/patient-account-settings-panels.d.ts.map +1 -0
- package/dist/patterns/patient-account-settings/patient-account-settings.d.ts +94 -0
- package/dist/patterns/patient-account-settings/patient-account-settings.d.ts.map +1 -0
- package/dist/patterns/patient-account-settings/patient-account-settings.types.d.ts +91 -0
- package/dist/patterns/patient-account-settings/patient-account-settings.types.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/index.d.ts +20 -0
- package/dist/patterns/patient-check-in/index.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/index.js +13 -0
- package/dist/patterns/patient-check-in/index.js.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-changed.d.ts +33 -0
- package/dist/patterns/patient-check-in/patient-check-in-changed.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-connection-notice.d.ts +29 -0
- package/dist/patterns/patient-check-in/patient-check-in-connection-notice.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-done.d.ts +25 -0
- package/dist/patterns/patient-check-in/patient-check-in-done.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-entry.d.ts +29 -0
- package/dist/patterns/patient-check-in/patient-check-in-entry.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-hub-empty.d.ts +23 -0
- package/dist/patterns/patient-check-in/patient-check-in-hub-empty.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-hub.d.ts +61 -0
- package/dist/patterns/patient-check-in/patient-check-in-hub.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-personal-data.d.ts +73 -0
- package/dist/patterns/patient-check-in/patient-check-in-personal-data.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-privacy.d.ts +9 -0
- package/dist/patterns/patient-check-in/patient-check-in-privacy.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-resume.d.ts +29 -0
- package/dist/patterns/patient-check-in/patient-check-in-resume.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-shell.d.ts +60 -0
- package/dist/patterns/patient-check-in/patient-check-in-shell.d.ts.map +1 -0
- package/dist/patterns/patient-check-in/patient-check-in-types.d.ts +92 -0
- package/dist/patterns/patient-check-in/patient-check-in-types.d.ts.map +1 -0
- package/dist/patterns/patient-portal/index.d.ts +12 -0
- package/dist/patterns/patient-portal/index.d.ts.map +1 -0
- package/dist/patterns/patient-portal/index.js +13 -0
- package/dist/patterns/patient-portal/index.js.map +1 -0
- package/dist/patterns/patient-portal/portal-appointments.d.ts +70 -0
- package/dist/patterns/patient-portal/portal-appointments.d.ts.map +1 -0
- package/dist/patterns/patient-portal/portal-details.d.ts +148 -0
- package/dist/patterns/patient-portal/portal-details.d.ts.map +1 -0
- package/dist/patterns/patient-portal/portal-documents.d.ts +74 -0
- package/dist/patterns/patient-portal/portal-documents.d.ts.map +1 -0
- package/dist/patterns/patient-portal/portal-format.d.ts +14 -0
- package/dist/patterns/patient-portal/portal-format.d.ts.map +1 -0
- package/dist/patterns/patient-portal/portal-home.d.ts +71 -0
- package/dist/patterns/patient-portal/portal-home.d.ts.map +1 -0
- package/dist/patterns/patient-portal/portal-parts.d.ts +107 -0
- package/dist/patterns/patient-portal/portal-parts.d.ts.map +1 -0
- package/dist/patterns/patient-portal/portal-shell.d.ts +84 -0
- package/dist/patterns/patient-portal/portal-shell.d.ts.map +1 -0
- package/dist/patterns/patient-portal/portal-types.d.ts +157 -0
- package/dist/patterns/patient-portal/portal-types.d.ts.map +1 -0
- package/dist/patterns/patient-sign-in/index.d.ts +7 -0
- package/dist/patterns/patient-sign-in/index.d.ts.map +1 -0
- package/dist/patterns/patient-sign-in/index.js +15 -0
- package/dist/patterns/patient-sign-in/index.js.map +1 -0
- package/dist/patterns/patient-sign-in/patient-card.d.ts +74 -0
- package/dist/patterns/patient-sign-in/patient-card.d.ts.map +1 -0
- package/dist/patterns/patient-sign-in/patient-sign-in-email.d.ts +109 -0
- package/dist/patterns/patient-sign-in/patient-sign-in-email.d.ts.map +1 -0
- package/dist/patterns/patient-sign-in/patient-sign-in-pin.d.ts +157 -0
- package/dist/patterns/patient-sign-in/patient-sign-in-pin.d.ts.map +1 -0
- package/dist/patterns/patient-sign-in/patient-sign-in-steps.d.ts +143 -0
- package/dist/patterns/patient-sign-in/patient-sign-in-steps.d.ts.map +1 -0
- package/dist/patterns/registration-form/index.js +1 -1
- package/dist/patterns/signature-request/index.js +1 -1
- package/dist/patterns/signing/index.d.ts +25 -0
- package/dist/patterns/signing/index.d.ts.map +1 -0
- package/dist/patterns/signing/index.js +16 -0
- package/dist/patterns/signing/index.js.map +1 -0
- package/dist/patterns/signing/multi-field-signer.d.ts +117 -0
- package/dist/patterns/signing/multi-field-signer.d.ts.map +1 -0
- package/dist/patterns/signing/signing-awaiting-screen.d.ts +25 -0
- package/dist/patterns/signing/signing-awaiting-screen.d.ts.map +1 -0
- package/dist/patterns/signing/signing-chrome.d.ts +30 -0
- package/dist/patterns/signing/signing-chrome.d.ts.map +1 -0
- package/dist/patterns/signing/signing-document-screen.d.ts +87 -0
- package/dist/patterns/signing/signing-document-screen.d.ts.map +1 -0
- package/dist/patterns/signing/signing-end-screen.d.ts +27 -0
- package/dist/patterns/signing/signing-end-screen.d.ts.map +1 -0
- package/dist/patterns/signing/signing-finished-screen.d.ts +34 -0
- package/dist/patterns/signing/signing-finished-screen.d.ts.map +1 -0
- package/dist/patterns/signing/signing-footer.d.ts +56 -0
- package/dist/patterns/signing/signing-footer.d.ts.map +1 -0
- package/dist/patterns/signing/signing-handoff-screen.d.ts +37 -0
- package/dist/patterns/signing/signing-handoff-screen.d.ts.map +1 -0
- package/dist/patterns/signing/signing-message-dialog.d.ts +29 -0
- package/dist/patterns/signing/signing-message-dialog.d.ts.map +1 -0
- package/dist/patterns/signing/signing-progress-chip.d.ts +27 -0
- package/dist/patterns/signing/signing-progress-chip.d.ts.map +1 -0
- package/dist/patterns/signing/signing-roster.d.ts +44 -0
- package/dist/patterns/signing/signing-roster.d.ts.map +1 -0
- package/dist/patterns/signing/signing-staff-id-confirmation.d.ts +49 -0
- package/dist/patterns/signing/signing-staff-id-confirmation.d.ts.map +1 -0
- package/dist/patterns/verify-identity/index.js +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +49 -1
- package/dist/_chunks/appointment-card-OAOur8lH.js +0 -434
- package/dist/_chunks/appointment-card-OAOur8lH.js.map +0 -1
- package/dist/_chunks/appointment-tray-DSFqO5Rm.js +0 -193
- package/dist/_chunks/appointment-tray-DSFqO5Rm.js.map +0 -1
- package/dist/_chunks/calendar-appointment-editor-dialog-WW6V1SGh.js +0 -13663
- package/dist/_chunks/calendar-appointment-editor-dialog-WW6V1SGh.js.map +0 -1
- package/dist/_chunks/document-preview-_kQ9QvZV.js +0 -291
- package/dist/_chunks/document-preview-_kQ9QvZV.js.map +0 -1
- package/dist/_chunks/error-page-B0fGNTRB.js.map +0 -1
- package/dist/_chunks/finished-terminal-FR8uc_Ws.js +0 -122
- package/dist/_chunks/finished-terminal-FR8uc_Ws.js.map +0 -1
- package/dist/_chunks/is-safe-url-DkETxeHz.js +0 -7
- package/dist/_chunks/is-safe-url-DkETxeHz.js.map +0 -1
- package/dist/_chunks/otp-input-gV1446Dw.js +0 -301
- package/dist/_chunks/otp-input-gV1446Dw.js.map +0 -1
- package/dist/_chunks/pdf-viewer-BnBKdx0y.js.map +0 -1
- package/dist/_chunks/session-countdown-C4tzbJVc.js +0 -223
- package/dist/_chunks/session-countdown-C4tzbJVc.js.map +0 -1
- package/dist/_chunks/signature-field-DjabvRZm.js.map +0 -1
- package/dist/_chunks/signature-status-chip-pIoQjvH8.js.map +0 -1
- package/dist/_chunks/use-zoom-drilldown-qCX34w9I.js +0 -210
- package/dist/_chunks/use-zoom-drilldown-qCX34w9I.js.map +0 -1
- package/dist/_chunks/user-x-DYszNtIg.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-documents-D8skew0h.js","sources":["../../src/patterns/patient-portal/portal-shell.tsx","../../src/patterns/patient-portal/portal-home.tsx","../../src/patterns/patient-portal/portal-appointments.tsx","../../src/patterns/patient-portal/portal-documents.tsx"],"sourcesContent":["import { useEffect, useRef, type ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { CalendarDays, FileText, House, LogOut, User } from 'lucide-react';\nimport { Button } from '../../components/button';\nimport { TabBar, type TabBarProps } from '../../components/tab-bar';\nimport { privacyMask } from '../../components/_shared/privacy-mask';\nimport { PatientSessionBar, PatientSessionEnded } from '../patient-sign-in';\nimport {\n PortalLiveRegion,\n PortalLoading,\n PortalMessage,\n ScreenFocus,\n} from './portal-parts';\nimport type { PortalListStatus, PortalNavItem } from './portal-types';\n\nexport interface PortalShellProps {\n /** The id of the tab on screen. Matched against the ids of `tabs`. */\n activeTab: string;\n /** Called with the tab id when a button tab is chosen (a tab with no `href`). */\n onTabChange?: (tabId: string) => void;\n /**\n * The tabs, in order. Default: Home, Appointments, Documents and My\n * details, with ids `home`, `appointments`, `documents` and `details`.\n * There is no Messages tab (D108). HTP-6917 adds its Account settings\n * entry through this prop.\n */\n tabs?: PortalNavItem[];\n /**\n * Renders an `href` tab with the host's router link. Passed to the kit\n * `TabBar` as it is: apply the given `className` and `aria-current`.\n */\n renderLink?: TabBarProps['renderLink'];\n /**\n * The patient's name, shown above the tabs. Masked under `privacy`.\n * Absent: no name line.\n */\n patientName?: string;\n /** Called by \"Sign out\", which is always visible. The host ends the session. */\n onSignOut: () => void;\n /**\n * Milliseconds left in the session, counted by the host. Given, the shell\n * shows the shared session banner (`PatientSessionBar`: running, warning,\n * then expired). Absent: no banner, only Sign out. The shell runs no timer.\n */\n remainingMs?: number;\n /** Full session length in ms, for the banner. */\n totalMs?: number;\n /** Remaining ms at or below which the banner turns to its warning tone. Default: the banner's own. */\n sessionWarnAtMs?: number;\n /** Called once when `remainingMs` reaches 0. The host ends the session. */\n onSessionExpire?: () => void;\n /**\n * Why the session ended. Set, the shell renders the end screen\n * (`PatientSessionEnded`) and unmounts everything else: the tabs, the\n * children, any draft and every name and date are gone from the page.\n * Null or absent: the portal shows. Only the 30 minute idle sign-out is\n * sourced; an 8 hour maximum is to confirm and is not offered here.\n */\n sessionEnded?: 'signed-out' | 'timed-out' | null;\n /**\n * The idle length in minutes. Needed with `sessionEnded=\"timed-out\"`;\n * without it the screen falls back to the signed-out text rather than\n * show a wrong number.\n */\n idleMinutes?: number;\n /**\n * Called by \"Sign in again\" on the end screen. Required: the end screen\n * has no other way out, and a button must always do something.\n */\n onSignInAgain: () => void;\n /** The state of the area under the tabs. Default `ready`: `children` show. */\n status?: PortalListStatus;\n /** Called by \"Try again\" in the error state. The button shows only when given. */\n onRetry?: () => void;\n /** The active screen: one of the portal screens, or the host's own. */\n children?: ReactNode;\n /**\n * Move focus to the first heading in the content area when the shell\n * shows (to the end screen's heading when the session has ended). Default\n * false. Set it on the shell or on the screen inside it, not on both.\n */\n focusOnMount?: boolean;\n /** Privacy mode: the patient's name is masked. The screens take their own `privacy`. */\n privacy?: boolean;\n /** Extra classes for the root. */\n className?: string;\n}\n\n/**\n * The frame inside the app header (D141, HTP-6904 AC, HTP-6932): the\n * patient's name, the shared session banner with a visible Sign out, the\n * tabs, and the active screen as children, with an area loading and error\n * state. It is only placement. It owns no route, no timer and no session:\n * the host's app picks the screen, counts the time and signs out.\n */\nexport function PortalShell({\n activeTab,\n onTabChange,\n tabs,\n renderLink,\n patientName,\n onSignOut,\n remainingMs,\n totalMs,\n sessionWarnAtMs,\n onSessionExpire,\n sessionEnded = null,\n idleMinutes,\n onSignInAgain,\n status = 'ready',\n onRetry,\n children,\n focusOnMount = false,\n privacy = false,\n className,\n}: PortalShellProps) {\n const { t } = useTranslation('ui');\n const content = useRef<HTMLDivElement>(null);\n const ended = sessionEnded !== null;\n useEffect(() => {\n if (!focusOnMount || ended) return;\n const target =\n content.current?.querySelector<HTMLElement>('h1, h2') ?? content.current;\n target?.focus({ preventScroll: true });\n // Mount only; a later change of `focusOnMount` pulls no focus.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const rootClass = [\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-md)]',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n if (sessionEnded !== null) {\n return (\n <div\n data-component=\"portal-shell\"\n data-state=\"ended\"\n data-privacy={privacy ? 'masked' : undefined}\n className={rootClass}\n >\n {sessionEnded === 'timed-out' && idleMinutes !== undefined ? (\n <PatientSessionEnded\n reason=\"timed-out\"\n idleMinutes={idleMinutes}\n onSignIn={onSignInAgain}\n focusOnMount={focusOnMount}\n />\n ) : (\n <PatientSessionEnded\n reason=\"signed-out\"\n onSignIn={onSignInAgain}\n focusOnMount={focusOnMount}\n />\n )}\n </div>\n );\n }\n\n const items: PortalNavItem[] = tabs ?? [\n {\n id: 'home',\n label: t('patientPortal.nav.home'),\n icon: <House aria-hidden=\"true\" />,\n },\n {\n id: 'appointments',\n label: t('patientPortal.nav.appointments'),\n icon: <CalendarDays aria-hidden=\"true\" />,\n },\n {\n id: 'documents',\n label: t('patientPortal.nav.documents'),\n icon: <FileText aria-hidden=\"true\" />,\n },\n {\n id: 'details',\n label: t('patientPortal.nav.details'),\n icon: <User aria-hidden=\"true\" />,\n },\n ];\n const name = patientName?.trim();\n\n return (\n <div\n data-component=\"portal-shell\"\n data-privacy={privacy ? 'masked' : undefined}\n className={rootClass}\n >\n {name ? (\n <p\n dir=\"auto\"\n className=\"type-body-sm ds:m-0 ds:break-words ds:text-[color:var(--muted-foreground)]\"\n >\n {privacy ? privacyMask() : name}\n </p>\n ) : null}\n {remainingMs !== undefined ? (\n <PatientSessionBar\n remainingMs={remainingMs}\n totalMs={totalMs}\n warnAtMs={sessionWarnAtMs}\n onSignOut={onSignOut}\n onExpire={onSessionExpire}\n />\n ) : (\n <div>\n <Button\n type=\"button\"\n intent=\"outline\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n startIcon={<LogOut aria-hidden=\"true\" />}\n data-action=\"sign-out\"\n onClick={onSignOut}\n >\n {t('patientSignIn.session.signOut')}\n </Button>\n </div>\n )}\n <TabBar\n fill\n collapseToMenu\n ariaLabel={t('patientPortal.nav.label')}\n items={items.map((item) => ({\n id: item.id,\n label: item.label,\n icon: item.icon,\n href: item.href,\n isActive: item.id === activeTab,\n }))}\n renderLink={renderLink}\n onSelect={onTabChange}\n />\n <div\n ref={content}\n tabIndex={-1}\n data-state={status}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:outline-none\"\n >\n <PortalLiveRegion\n message={\n status === 'loading'\n ? t('patientPortal.shell.loading')\n : status === 'error'\n ? t('patientPortal.shell.errorTitle')\n : ''\n }\n />\n {status === 'loading' ? (\n <PortalLoading />\n ) : status === 'error' ? (\n <ScreenFocus.Provider\n value={() => content.current?.focus({ preventScroll: true })}\n >\n <PortalMessage\n kind=\"error\"\n title={t('patientPortal.shell.errorTitle')}\n body={t('patientPortal.shell.errorBody')}\n headingLevel={1}\n onRetry={onRetry}\n />\n </ScreenFocus.Provider>\n ) : (\n children\n )}\n </div>\n </div>\n );\n}\n","import { useId } from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { Phone } from 'lucide-react';\nimport { Button } from '../../components/button';\nimport { WhatsAppButton } from '../../components/whatsapp-button';\nimport { formatPortalDay, telHref, usePortalLocale } from './portal-format';\nimport {\n PortalAppointmentList,\n PortalAppointmentRow,\n PortalLoading,\n PortalMessage,\n PortalScreen,\n PortalSection,\n} from './portal-parts';\nimport type {\n PortalAppointment,\n PortalHeadingLevel,\n PortalListStatus,\n PortalPractice,\n} from './portal-types';\n\n/* -------------------------------------------------------------------- */\n/* Practice contact */\n/* -------------------------------------------------------------------- */\n\nexport interface PortalPracticeContactProps {\n /**\n * The practices to offer a contact for, in the host's order. One block\n * each. Empty: nothing renders.\n */\n practices: PortalPractice[];\n /**\n * Heading level of \"Questions for the practice?\". Default 2 (under the\n * screen's own h1); use 3 under an h2.\n */\n headingLevel?: 2 | 3;\n /** Extra classes for the root. */\n className?: string;\n}\n\n/**\n * The practice contact (HTP-6904 AC, HTP-6936 AC, D141): one WhatsApp\n * click-to-chat button per practice, the kit `WhatsAppButton`. A practice\n * with no WhatsApp number gets its phone as a `tel:` link (a proposal, to\n * confirm); with neither, nothing shows. There is no messages\n * area (D108): the chat happens in WhatsApp.\n */\nexport function PortalPracticeContact({\n practices,\n headingLevel = 2,\n className,\n}: PortalPracticeContactProps) {\n const { t } = useTranslation('ui');\n const headingId = useId();\n // A practice with neither a WhatsApp number nor a phone has no contact to\n // offer; a name-only fallback is to confirm and is not built.\n const reachable = practices.filter(\n (practice) => practice.whatsAppNumber || telHref(practice.phone),\n );\n if (reachable.length === 0) return null;\n const Heading = headingLevel === 2 ? 'h2' : 'h3';\n return (\n <section\n data-component=\"portal-practice-contact\"\n aria-labelledby={headingId}\n className={['ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]', className]\n .filter(Boolean)\n .join(' ')}\n >\n <Heading id={headingId} className=\"type-title-card ds:m-0\">\n {t('patientPortal.contact.title')}\n </Heading>\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-md)] ds:p-0\">\n {reachable.map((practice) => {\n const tel = telHref(practice.phone);\n const name = practice.name;\n return (\n <li\n key={practice.id}\n data-practice-id={practice.id}\n className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-xs)]\"\n >\n {practice.whatsAppNumber ? (\n <>\n <p className=\"type-body-sm ds:m-0 ds:break-words ds:text-[color:var(--muted-foreground)]\">\n <Trans\n t={t}\n ns=\"ui\"\n i18nKey=\"patientPortal.contact.whatsAppBody\"\n values={{ practice: name }}\n components={{ practice: <bdi /> }}\n />\n </p>\n <WhatsAppButton\n size=\"lg\"\n phoneNumber={practice.whatsAppNumber}\n message={\n practice.whatsAppMessage ??\n t('patientPortal.contact.whatsAppMessage')\n }\n label={t('patientPortal.contact.whatsAppLabel', {\n practice: name,\n })}\n data-action=\"whatsapp\"\n />\n </>\n ) : tel ? (\n <>\n <p className=\"type-body-sm ds:m-0 ds:break-words ds:text-[color:var(--muted-foreground)]\">\n <Trans\n t={t}\n ns=\"ui\"\n i18nKey=\"patientPortal.contact.phoneBody\"\n values={{ practice: name }}\n components={{ practice: <bdi /> }}\n />\n </p>\n <Button\n asChild\n intent=\"secondary\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n startIcon={<Phone aria-hidden=\"true\" />}\n >\n <a href={tel} data-action=\"call-practice\">\n <Trans\n t={t}\n ns=\"ui\"\n i18nKey=\"patientPortal.contact.call\"\n values={{\n phone: practice.phoneDisplay ?? practice.phone ?? '',\n }}\n components={{ phone: <bdi dir=\"ltr\" /> }}\n />\n </a>\n </Button>\n </>\n ) : null}\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Home */\n/* -------------------------------------------------------------------- */\n\nexport interface PortalHomeProps {\n /**\n * The patient's appointments, in the host's order (the earliest first).\n * Home shows every one that is not `past`. Nothing is pre-selected.\n * A cancelled one shows its state and no Check in.\n */\n appointments?: PortalAppointment[];\n /** The practices for the contact block. */\n practices?: PortalPractice[];\n /**\n * The patient's first name for the greeting. Absent, or under `privacy`,\n * the greeting has no name.\n */\n patientName?: string;\n /** The state of the read. Default `ready`. */\n status?: PortalListStatus;\n /** Called by \"Try again\" in the error state. The button shows only when given. */\n onRetry?: () => void;\n /**\n * Called with the appointment id by \"Check in\". The button shows only when\n * given, and only on an upcoming appointment with `checkInDue`.\n */\n onCheckIn?: (appointmentId: string) => void;\n /**\n * BCP 47 locale for the dates, for example `\"it-IT\"`. Default: the UI\n * language. Pass it together with each practice's `timeZone`.\n */\n locale?: string;\n /** Heading level of the title. Default 1; use 2 inside a page with an h1. */\n headingLevel?: PortalHeadingLevel;\n /** Move focus to the heading when the screen shows. Default false. */\n focusOnMount?: boolean;\n /**\n * Privacy mode: the greeting drops the name, and each card masks what is\n * personal and keeps time, place and status. The clinician's name stays\n * (it is the card's title, PHASE4 s7 \"operator stays\"); the care name goes.\n */\n privacy?: boolean;\n /** Extra classes for the root. */\n className?: string;\n}\n\n/**\n * The portal's first screen (HTP-6911, HTP-6904 AC): a greeting, the upcoming\n * appointments with \"Check in\" where paperwork is due, and the practice\n * contact. The last past appointment is held, not built (PORTAL-06).\n */\nexport function PortalHome({\n appointments = [],\n practices = [],\n patientName,\n status = 'ready',\n onRetry,\n onCheckIn,\n locale,\n headingLevel = 1,\n focusOnMount = false,\n privacy = false,\n className,\n}: PortalHomeProps) {\n const { t } = useTranslation('ui');\n const formatLocale = usePortalLocale(locale);\n const name = patientName?.trim();\n const shown = appointments.filter(\n (appointment) => appointment.status !== 'past',\n );\n return (\n <PortalScreen\n component=\"portal-home\"\n title={\n name && !privacy ? (\n <Trans\n t={t}\n ns=\"ui\"\n i18nKey=\"patientPortal.home.title\"\n values={{ name }}\n components={{ name: <bdi /> }}\n />\n ) : (\n t('patientPortal.home.titleNoName')\n )\n }\n headingLevel={headingLevel}\n focusOnMount={focusOnMount}\n privacy={privacy}\n className={className}\n status={status}\n loadingLabel={t('patientPortal.home.loading')}\n errorLabel={t('patientPortal.home.error.title')}\n >\n {status === 'loading' ? (\n <PortalLoading />\n ) : status === 'error' ? (\n <PortalMessage\n kind=\"error\"\n title={t('patientPortal.home.error.title')}\n body={t('patientPortal.home.error.body')}\n headingLevel={headingLevel}\n onRetry={onRetry}\n />\n ) : (\n <>\n {shown.length === 0 ? (\n <PortalMessage\n kind=\"empty\"\n title={t('patientPortal.home.empty.title')}\n body={t('patientPortal.home.empty.body')}\n headingLevel={headingLevel}\n />\n ) : (\n <PortalSection\n title={t('patientPortal.home.upcoming')}\n headingLevel={headingLevel}\n section=\"upcoming\"\n >\n <PortalAppointmentList>\n {shown.map((appointment) => (\n <PortalAppointmentRow\n key={appointment.id}\n appointment={appointment}\n locale={formatLocale}\n privacy={privacy}\n >\n {appointment.checkInDue &&\n appointment.status === 'upcoming' ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:rounded-[var(--radius-md)] ds:bg-[var(--primary-soft)] ds:p-[var(--spacing-md)]\">\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--primary-soft-foreground)]\">\n {t('patientPortal.home.checkInDue')}\n </p>\n {onCheckIn ? (\n <Button\n type=\"button\"\n intent=\"primary\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n data-action=\"check-in\"\n // WCAG 2.5.3: the visible label comes first, so the\n // name always contains it, in every language.\n aria-label={`${t('patientPortal.home.checkIn')}. ${t(\n 'patientPortal.appointments.confirmWhen',\n {\n when: formatPortalDay(\n appointment.startIso,\n formatLocale,\n appointment.practice.timeZone,\n ),\n practice: appointment.practice.name,\n },\n )}`}\n onClick={() => onCheckIn(appointment.id)}\n >\n {t('patientPortal.home.checkIn')}\n </Button>\n ) : null}\n </div>\n ) : null}\n </PortalAppointmentRow>\n ))}\n </PortalAppointmentList>\n </PortalSection>\n )}\n <PortalPracticeContact\n practices={practices}\n headingLevel={headingLevel === 1 ? 2 : 3}\n />\n </>\n )}\n </PortalScreen>\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { Phone } from 'lucide-react';\nimport { isSafeAppointmentUrl } from '../../components/appointment-card';\nimport { Button } from '../../components/button';\nimport { Dialog } from '../../components/dialog';\nimport { VisuallyHidden } from '../../components/visually-hidden';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { formatPortalDate, telHref, usePortalLocale } from './portal-format';\nimport {\n PortalAppointmentList,\n PortalAppointmentRow,\n PortalLoading,\n PortalMessage,\n PortalNote,\n PortalScreen,\n PortalSection,\n PortalStepUp,\n} from './portal-parts';\nimport type {\n PortalAppointment,\n PortalHeadingLevel,\n PortalListStatus,\n StepUpConfig,\n} from './portal-types';\n\nexport interface PortalAppointmentsProps {\n /**\n * Every appointment to list, in the host's order. The screen groups them\n * by `status`: upcoming, cancelled and past (the host trims past to the\n * last 12 months).\n */\n appointments?: PortalAppointment[];\n /** The state of the read. Default `ready`. */\n status?: PortalListStatus;\n /** Called by \"Try again\" in the error state. The button shows only when given. */\n onRetry?: () => void;\n /**\n * The id of the appointment whose cancel is being confirmed, or null.\n * Controlled; pair with `onConfirmingChange`. Dialog open state follows\n * it, and the confirm step hides while `stepUp` is open.\n */\n confirmingId?: string | null;\n /** Initial value of `confirmingId` when uncontrolled. Default null. */\n defaultConfirmingId?: string | null;\n /**\n * Called with the appointment id when \"Cancel appointment\" is pressed\n * (nothing is sent: it only opens the confirm step), and with null when\n * the person keeps the appointment or closes the confirm step.\n */\n onConfirmingChange?: (appointmentId: string | null) => void;\n /**\n * Called with the appointment id by \"Yes, cancel it\" (PORTAL-03). The host\n * decides whether an SMS check comes first (it sets `stepUp`) or cancels\n * at once, and updates the data afterwards. When the visit comes back as\n * `cancelled` the screen says so politely and moves focus to its row.\n */\n onCancelAppointment: (appointmentId: string) => void;\n /**\n * The SMS check before the cancel goes through (D95). The dialog is open\n * while this is not null. The host binds the step and decides the code:\n * the screen compares nothing. Without a `subject` the dialog says which\n * appointment it is for.\n *\n * Give `onCancel` and let it set `stepUp` back to `null`: the dialog is\n * forced open, so without it Escape and Cancel cannot close it (WCAG 2.1.2).\n */\n stepUp?: StepUpConfig | null;\n /**\n * BCP 47 locale for the dates, for example `\"it-IT\"`. Default: the UI\n * language. Pass it together with each practice's `timeZone`.\n */\n locale?: string;\n /** Heading level of the title. Default 1; use 2 inside a page with an h1. */\n headingLevel?: PortalHeadingLevel;\n /** Move focus to the heading when the screen shows. Default false. */\n focusOnMount?: boolean;\n /**\n * Privacy mode: each card masks what is personal and keeps time, place and\n * status. The clinician's name stays (it is the card's title, PHASE4 s7\n * \"operator stays\"); the care name goes.\n */\n privacy?: boolean;\n /** Extra classes for the root. */\n className?: string;\n}\n\n/**\n * The portal's appointments (HTP-6904 QA, HTP-6916, HTP-6950): upcoming,\n * cancelled (with \"Book a new appointment\" when the practice gave a booking\n * link) and past, each card naming its practice. Cancel opens a confirm\n * step; the confirm calls the host. An appointment inside the practice's\n * cut-off shows \"call the practice\" and no Cancel and no Move (D92, D141).\n */\nexport function PortalAppointments({\n appointments = [],\n status = 'ready',\n onRetry,\n confirmingId,\n defaultConfirmingId = null,\n onConfirmingChange,\n onCancelAppointment,\n stepUp = null,\n locale,\n headingLevel = 1,\n focusOnMount = false,\n privacy = false,\n className,\n}: PortalAppointmentsProps) {\n const { t } = useTranslation('ui');\n const formatLocale = usePortalLocale(locale);\n const [confirmingValue, setConfirming] = useControllableState<string | null>({\n value: confirmingId,\n defaultValue: defaultConfirmingId,\n onChange: onConfirmingChange,\n });\n const confirming = confirmingValue ?? null;\n const target =\n confirming === null\n ? undefined\n : appointments.find(\n (appointment) =>\n appointment.id === confirming && appointment.status === 'upcoming',\n );\n const confirmOpen = target !== undefined && !stepUp;\n\n const upcoming = appointments.filter((a) => a.status === 'upcoming');\n const cancelled = appointments.filter((a) => a.status === 'cancelled');\n const past = appointments.filter((a) => a.status === 'past');\n\n // Focus: the confirm and the SMS check have no trigger Radix could hand\n // focus back to, so the screen does it. A cancelled visit gets focus on\n // its row; a visit still booked gets focus on its Cancel button.\n const root = useRef<HTMLDivElement>(null);\n const lastId = useRef<string | null>(null);\n if (confirming !== null) lastId.current = confirming;\n const restoreFocus = (id: string | null) => {\n if (id === null) return;\n const row = Array.from(\n root.current?.querySelectorAll<HTMLElement>('[data-appointment-id]') ??\n [],\n ).find((el) => el.dataset.appointmentId === id);\n if (!row) return;\n const cancelButton = row.querySelector<HTMLElement>(\n '[data-action=\"cancel-appointment\"]',\n );\n (cancelButton ?? row).focus({ preventScroll: true });\n };\n\n // Which visits were upcoming before: a change to cancelled is announced.\n const known = useRef<Map<string, PortalAppointment['status']>>(new Map());\n const [announcement, setAnnouncement] = useState('');\n useEffect(() => {\n let cancelledId: string | null = null;\n for (const appointment of appointments) {\n if (\n appointment.status === 'cancelled' &&\n known.current.get(appointment.id) === 'upcoming'\n ) {\n cancelledId = appointment.id;\n }\n }\n known.current = new Map(appointments.map((a) => [a.id, a.status]));\n if (cancelledId === null) return;\n setAnnouncement(t('patientPortal.appointments.cancelledStatus'));\n restoreFocus(cancelledId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [appointments]);\n\n // The SMS check closed and the visit is still booked: back to its button.\n const hadStepUp = useRef(false);\n useEffect(() => {\n const closed = hadStepUp.current && !stepUp;\n hadStepUp.current = Boolean(stepUp);\n if (!closed) return;\n restoreFocus(lastId.current);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [stepUp]);\n\n const whenOf = (appointment: PortalAppointment) =>\n formatPortalDate(\n appointment.startIso,\n formatLocale,\n appointment.practice.timeZone,\n );\n\n return (\n <PortalScreen\n component=\"portal-appointments\"\n title={t('patientPortal.appointments.title')}\n headingLevel={headingLevel}\n focusOnMount={focusOnMount}\n privacy={privacy}\n className={className}\n rootRef={root}\n status={status}\n loadingLabel={t('patientPortal.appointments.loading')}\n errorLabel={t('patientPortal.appointments.error.title')}\n message={announcement}\n >\n {status === 'loading' ? (\n <PortalLoading />\n ) : status === 'error' ? (\n <PortalMessage\n kind=\"error\"\n title={t('patientPortal.appointments.error.title')}\n body={t('patientPortal.home.error.body')}\n headingLevel={headingLevel}\n onRetry={onRetry}\n />\n ) : appointments.length === 0 ? (\n <PortalMessage\n kind=\"empty\"\n title={t('patientPortal.appointments.empty.title')}\n body={t('patientPortal.appointments.empty.body')}\n headingLevel={headingLevel}\n />\n ) : (\n <>\n {upcoming.length > 0 ? (\n <PortalSection\n title={t('patientPortal.appointments.upcoming')}\n headingLevel={headingLevel}\n section=\"upcoming\"\n >\n <PortalAppointmentList>\n {upcoming.map((appointment) => {\n const tel = telHref(appointment.practice.phone);\n return (\n <PortalAppointmentRow\n key={appointment.id}\n appointment={appointment}\n locale={formatLocale}\n privacy={privacy}\n >\n {appointment.insideCutOff ? (\n <>\n <PortalNote>\n {appointment.cutOffHours !== undefined\n ? t('patientPortal.appointments.cutOff', {\n count: appointment.cutOffHours,\n })\n : t('patientPortal.appointments.cutOffNoHours')}\n </PortalNote>\n {tel ? (\n <div>\n <Button\n asChild\n intent=\"secondary\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n startIcon={<Phone aria-hidden=\"true\" />}\n >\n <a href={tel} data-action=\"call-practice\">\n <Trans\n t={t}\n ns=\"ui\"\n i18nKey=\"patientPortal.appointments.call\"\n values={{\n phone:\n appointment.practice.phoneDisplay ??\n appointment.practice.phone ??\n '',\n }}\n components={{ phone: <bdi dir=\"ltr\" /> }}\n />\n </a>\n </Button>\n </div>\n ) : null}\n </>\n ) : (\n <div>\n {/* The first press only opens the confirm step:\n nothing is sent and no code is asked yet. */}\n <Button\n type=\"button\"\n intent=\"destructiveOutline\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n data-action=\"cancel-appointment\"\n aria-label={t(\n 'patientPortal.appointments.cancelFor',\n {\n when: whenOf(appointment),\n practice: appointment.practice.name,\n },\n )}\n onClick={() => setConfirming(appointment.id)}\n >\n {t('patientPortal.appointments.cancel')}\n </Button>\n </div>\n )}\n </PortalAppointmentRow>\n );\n })}\n </PortalAppointmentList>\n </PortalSection>\n ) : null}\n {cancelled.length > 0 ? (\n <PortalSection\n title={t('patientPortal.appointments.cancelledHeading')}\n headingLevel={headingLevel}\n section=\"cancelled\"\n >\n <PortalAppointmentList>\n {cancelled.map((appointment) => {\n const bookingUrl = appointment.practice.bookingUrl;\n return (\n <PortalAppointmentRow\n key={appointment.id}\n appointment={appointment}\n locale={formatLocale}\n privacy={privacy}\n >\n <PortalNote>\n {t('patientPortal.appointments.cancelled')}\n </PortalNote>\n {bookingUrl && isSafeAppointmentUrl(bookingUrl) ? (\n <div>\n <Button\n asChild\n intent=\"primary\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n >\n <a\n href={bookingUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-action=\"rebook\"\n >\n {t('patientPortal.appointments.rebook')}\n <VisuallyHidden>\n {' '}\n {t('patientPortal.appointments.rebookAt', {\n practice: appointment.practice.name,\n })}{' '}\n {t('link.opensInNewTab')}\n </VisuallyHidden>\n </a>\n </Button>\n </div>\n ) : null}\n </PortalAppointmentRow>\n );\n })}\n </PortalAppointmentList>\n </PortalSection>\n ) : null}\n {past.length > 0 ? (\n <PortalSection\n title={t('patientPortal.appointments.past')}\n headingLevel={headingLevel}\n section=\"past\"\n >\n <PortalAppointmentList>\n {past.map((appointment) => (\n <PortalAppointmentRow\n key={appointment.id}\n appointment={appointment}\n locale={formatLocale}\n privacy={privacy}\n />\n ))}\n </PortalAppointmentList>\n </PortalSection>\n ) : null}\n </>\n )}\n\n <Dialog.Root\n open={confirmOpen}\n onOpenChange={(open) => {\n if (!open) setConfirming(null);\n }}\n >\n <Dialog.Content\n size=\"sm\"\n // A cancel cannot be undone: an alert dialog, with no X.\n variant=\"alert\"\n onCloseAutoFocus={(event) => {\n // Handed to the SMS check: it takes focus itself.\n if (stepUp) return;\n event.preventDefault();\n restoreFocus(lastId.current);\n }}\n >\n <Dialog.Header>\n <Dialog.Title>\n {t('patientPortal.appointments.confirmTitle')}\n </Dialog.Title>\n <Dialog.Description>\n {t('patientPortal.appointments.confirmBody')}\n {target ? (\n <>\n {' '}\n <Trans\n t={t}\n ns=\"ui\"\n i18nKey=\"patientPortal.appointments.confirmWhenRich\"\n values={{\n when: whenOf(target),\n practice: target.practice.name,\n }}\n components={{ practice: <bdi /> }}\n />\n </>\n ) : null}\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Body>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {target ? (\n <PortalAppointmentRow\n standalone\n appointment={target}\n locale={formatLocale}\n privacy={privacy}\n />\n ) : null}\n </div>\n </Dialog.Body>\n <Dialog.Footer>\n <Button\n type=\"button\"\n intent=\"ghost\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n data-action=\"keep-appointment\"\n onClick={() => setConfirming(null)}\n >\n {t('patientPortal.appointments.keep')}\n </Button>\n <Button\n type=\"button\"\n intent=\"destructive\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n data-action=\"confirm-cancel\"\n onClick={() => {\n if (target) onCancelAppointment(target.id);\n }}\n >\n {t('patientPortal.appointments.confirm')}\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n\n <PortalStepUp\n config={stepUp}\n privacy={privacy}\n defaultSubject={\n target\n ? t('patientPortal.appointments.stepUp.cancelSubject', {\n date: formatPortalDate(\n target.startIso,\n formatLocale,\n target.practice.timeZone,\n ),\n })\n : undefined\n }\n />\n </PortalScreen>\n );\n}\n","import { useEffect, useId, useRef } from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { Download, FileText } from 'lucide-react';\nimport { Alert } from '../../components/alert';\nimport { Button } from '../../components/button';\nimport { DocumentPreview } from '../../components/document-preview';\nimport { privacyMask } from '../../components/_shared/privacy-mask';\nimport { formatPortalDate, usePortalLocale } from './portal-format';\nimport {\n PortalLoading,\n PortalMessage,\n PortalNote,\n PortalScreen,\n PortalSection,\n PortalStepUp,\n} from './portal-parts';\nimport type {\n PortalHeadingLevel,\n PortalListStatus,\n PortalOpenDocument,\n PortalSharedDocument,\n StepUpConfig,\n} from './portal-types';\n\nexport interface PortalDocumentsProps {\n /** The files the practices shared with the patient, in the host's order. */\n documents?: PortalSharedDocument[];\n /** The state of the read. Default `ready`. */\n status?: PortalListStatus;\n /** Called by \"Try again\" in the error state. The button shows only when given. */\n onRetry?: () => void;\n /**\n * Called with the document id by \"Open\". The host decides whether an SMS\n * check comes first (it sets `stepUp`) or opens at once (it sets\n * `openDocument`). The screen never opens a new tab (D86).\n */\n onOpenDocument: (documentId: string) => void;\n /**\n * Called with the document id by \"Download\". The \"Download\" button shows\n * only when this is given. Whether it sits in the rows or only in the\n * viewer is to confirm (PORTAL-DS-01:118): it shows in both.\n */\n onDownloadDocument?: (documentId: string) => void;\n /**\n * The file on screen, or null. While set, the file shows inside the page\n * in the kit `DocumentPreview` and the list is hidden. The host owns the\n * address and its auth.\n */\n openDocument?: PortalOpenDocument | null;\n /**\n * Called by the viewer's Close button, which shows only when this is given.\n * The host sets `openDocument` to null. The screen moves focus itself: to\n * the viewer's heading when a file opens, and back to that file's Open\n * button when it closes.\n */\n onCloseDocument?: () => void;\n /**\n * The SMS check before a file opens or downloads (D95, D102). The dialog\n * is open while this is not null. The host binds the step, so it also\n * gives the `subject` (which file, open or download). Under `privacy` the\n * subject must not contain the file name or anything from it: the dialog\n * shows the subject as given. The screen compares nothing.\n *\n * Give `onCancel` and let it set `stepUp` back to `null`: the dialog is\n * forced open, so without it Escape and Cancel cannot close it (WCAG 2.1.2).\n */\n stepUp?: StepUpConfig | null;\n /**\n * BCP 47 locale for the dates, for example `\"it-IT\"`. Default: the UI\n * language.\n */\n locale?: string;\n /**\n * IANA time zone the \"shared on\" dates read in, for example\n * `\"Europe/Rome\"`. Default: the browser's.\n */\n timeZone?: string;\n /** Heading level of the title. Default 1; use 2 inside a page with an h1. */\n headingLevel?: PortalHeadingLevel;\n /** Move focus to the heading when the screen shows. Default false. */\n focusOnMount?: boolean;\n /**\n * Privacy mode: file names are masked (and drop out of accessible names),\n * and the open file's body is withheld by `DocumentPreview`. The practice,\n * the date and the actions stay.\n */\n privacy?: boolean;\n /** Extra classes for the root. */\n className?: string;\n}\n\n/**\n * The \"Shared with you\" documents (HTP-6904 QA test 2, HTP-6919): name,\n * practice and date, with Open and, when the host gives a handler, Download.\n * An opened file shows inside the page. There are no uploads.\n */\nexport function PortalDocuments({\n documents = [],\n status = 'ready',\n onRetry,\n onOpenDocument,\n onDownloadDocument,\n openDocument = null,\n onCloseDocument,\n stepUp = null,\n locale,\n timeZone,\n headingLevel = 1,\n focusOnMount = false,\n privacy = false,\n className,\n}: PortalDocumentsProps) {\n const { t } = useTranslation('ui');\n const formatLocale = usePortalLocale(locale);\n const uid = useId();\n const shownName = (name: string) => (privacy ? privacyMask() : name);\n\n // Open swaps the list for the viewer and Close swaps it back, so the\n // pressed button is gone: focus follows (never on mount).\n const root = useRef<HTMLDivElement>(null);\n const lastOpened = useRef<string | null>(openDocument?.id ?? null);\n const wasOpen = useRef(openDocument !== null);\n const openId = openDocument?.id ?? null;\n useEffect(() => {\n const isOpen = openId !== null;\n if (isOpen === wasOpen.current) return;\n wasOpen.current = isOpen;\n if (isOpen) {\n lastOpened.current = openId;\n root.current\n ?.querySelector<HTMLElement>('[data-section=\"opened\"] > :first-child')\n ?.focus({ preventScroll: true });\n } else {\n const row = Array.from(\n root.current?.querySelectorAll<HTMLElement>('[data-document-id]') ?? [],\n ).find((el) => el.dataset.documentId === lastOpened.current);\n row\n ?.querySelector<HTMLElement>('[data-action=\"open-document\"]')\n ?.focus({ preventScroll: true });\n }\n }, [openId]);\n\n return (\n <PortalScreen\n component=\"portal-documents\"\n title={t('patientPortal.documents.title')}\n headingLevel={headingLevel}\n focusOnMount={focusOnMount}\n privacy={privacy}\n className={className}\n rootRef={root}\n message={\n openDocument\n ? t('patientPortal.documents.opened', {\n name: shownName(openDocument.name),\n interpolation: { escapeValue: false },\n }).replace(/<\\/?name>/g, '')\n : undefined\n }\n status={status}\n loadingLabel={t('patientPortal.documents.loading')}\n errorLabel={t('patientPortal.documents.error.title')}\n >\n {status === 'loading' ? (\n <PortalLoading />\n ) : status === 'error' ? (\n <PortalMessage\n kind=\"error\"\n title={t('patientPortal.documents.error.title')}\n body={t('patientPortal.home.error.body')}\n headingLevel={headingLevel}\n onRetry={onRetry}\n />\n ) : openDocument ? (\n <PortalSection\n title={t('patientPortal.documents.section')}\n headingLevel={headingLevel}\n section=\"opened\"\n >\n {/* The always-mounted live region says it; this one stays quiet. */}\n <Alert variant=\"success\" announce=\"off\">\n <Alert.Description>\n <Trans\n t={t}\n ns=\"ui\"\n i18nKey=\"patientPortal.documents.opened\"\n values={{ name: shownName(openDocument.name) }}\n components={{ name: <bdi /> }}\n />\n </Alert.Description>\n </Alert>\n <DocumentPreview\n name={openDocument.name}\n mimeType={openDocument.mimeType}\n src={openDocument.src}\n // No `sharedAt`: the viewer would show it in the browser's zone and\n // the list in the practice's, a day apart near midnight. The\n // list still says when it was shared.\n metadata={{ createdBy: openDocument.practiceName }}\n onClose={onCloseDocument}\n onDownload={\n onDownloadDocument\n ? () => onDownloadDocument(openDocument.id)\n : undefined\n }\n privacy={privacy}\n locale={formatLocale}\n />\n </PortalSection>\n ) : documents.length === 0 ? (\n <PortalMessage\n kind=\"empty\"\n title={t('patientPortal.documents.empty.title')}\n body={t('patientPortal.documents.empty.body')}\n headingLevel={headingLevel}\n />\n ) : (\n <PortalSection\n title={t('patientPortal.documents.section')}\n headingLevel={headingLevel}\n section=\"shared\"\n >\n <PortalNote>{t('patientPortal.documents.intro')}</PortalNote>\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-0\">\n {documents.map((document) => (\n <li\n key={document.id}\n data-document-id={document.id}\n className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)] ds:p-[var(--spacing-md)]\"\n >\n <span className=\"ds:flex ds:min-w-0 ds:items-start ds:gap-[var(--spacing-sm)]\">\n <FileText\n aria-hidden=\"true\"\n className=\"ds:size-5 ds:shrink-0 ds:text-[color:var(--muted-foreground)]\"\n />\n <span className=\"ds:flex ds:min-w-0 ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <span\n dir=\"auto\"\n className=\"type-title-item ds:min-w-0 ds:break-words\"\n >\n {shownName(document.name)}\n </span>\n <span\n id={`${uid}-${document.id}-meta`}\n className=\"type-meta ds:flex ds:flex-wrap ds:gap-x-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\"\n >\n <span dir=\"auto\">{document.practiceName}</span>\n <span>\n {t('patientPortal.documents.sharedOn', {\n date: formatPortalDate(\n document.sharedAt,\n formatLocale,\n timeZone,\n ),\n })}\n </span>\n </span>\n </span>\n </span>\n <span className=\"ds:flex ds:flex-wrap ds:gap-[var(--spacing-xs)]\">\n <Button\n type=\"button\"\n intent=\"secondary\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n data-action=\"open-document\"\n // Under privacy the name is hidden, so the practice and\n // date line tells the files apart.\n aria-describedby={\n privacy ? `${uid}-${document.id}-meta` : undefined\n }\n aria-label={\n privacy\n ? undefined\n : t('patientPortal.documents.openLabel', {\n name: document.name,\n })\n }\n onClick={() => onOpenDocument(document.id)}\n >\n {t('patientPortal.documents.open')}\n </Button>\n {onDownloadDocument ? (\n <Button\n type=\"button\"\n intent=\"outline\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n startIcon={<Download aria-hidden=\"true\" />}\n data-action=\"download-document\"\n aria-describedby={\n privacy ? `${uid}-${document.id}-meta` : undefined\n }\n aria-label={\n privacy\n ? undefined\n : t('patientPortal.documents.downloadLabel', {\n name: document.name,\n })\n }\n onClick={() => onDownloadDocument(document.id)}\n >\n {t('patientPortal.documents.download')}\n </Button>\n ) : null}\n </span>\n </li>\n ))}\n </ul>\n </PortalSection>\n )}\n\n <PortalStepUp config={stepUp} privacy={privacy} />\n </PortalScreen>\n );\n}\n"],"names":["PortalShell","activeTab","onTabChange","tabs","renderLink","patientName","onSignOut","remainingMs","totalMs","sessionWarnAtMs","onSessionExpire","sessionEnded","idleMinutes","onSignInAgain","status","onRetry","children","focusOnMount","privacy","className","t","useTranslation","content","useRef","ended","useEffect","target","_a","rootClass","jsx","PatientSessionEnded","items","House","CalendarDays","FileText","User","name","jsxs","privacyMask","PatientSessionBar","Button","LogOut","TabBar","item","PortalLiveRegion","PortalLoading","ScreenFocus","PortalMessage","PortalPracticeContact","practices","headingLevel","headingId","useId","reachable","practice","telHref","Heading","tel","Fragment","Trans","WhatsAppButton","Phone","PortalHome","appointments","onCheckIn","locale","formatLocale","usePortalLocale","shown","appointment","PortalScreen","PortalSection","PortalAppointmentList","PortalAppointmentRow","formatPortalDay","PortalAppointments","confirmingId","defaultConfirmingId","onConfirmingChange","onCancelAppointment","stepUp","confirmingValue","setConfirming","useControllableState","confirming","confirmOpen","upcoming","a","cancelled","past","root","lastId","restoreFocus","id","row","el","known","announcement","setAnnouncement","useState","cancelledId","hadStepUp","closed","whenOf","formatPortalDate","PortalNote","bookingUrl","isSafeAppointmentUrl","VisuallyHidden","Dialog","open","event","PortalStepUp","PortalDocuments","documents","onOpenDocument","onDownloadDocument","openDocument","onCloseDocument","timeZone","uid","shownName","lastOpened","wasOpen","openId","isOpen","_b","_c","_d","Alert","DocumentPreview","document","Download"],"mappings":"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"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect as m, useRef as T, useContext as w, useId as A, useState as D, createContext as I } from "react";
|
|
3
|
+
import { useTranslation as v } from "react-i18next";
|
|
4
|
+
import { B as U } from "./button-DohK_Ak_.js";
|
|
5
|
+
import { C as p } from "./card-n6W6LW-N.js";
|
|
6
|
+
import { E as d } from "./empty-state-DwJ5YNzz.js";
|
|
7
|
+
import { S as L } from "./skeleton-tTWJpvAq.js";
|
|
8
|
+
import { S as j } from "./step-up-dialog-C2JqJmCA.js";
|
|
9
|
+
import { i as k } from "./is-development-CLUAnsU7.js";
|
|
10
|
+
import { A as E } from "./appointment-card-DG3m9yN-.js";
|
|
11
|
+
import { c as B } from "./intl-locale-FWh-Y5_3.js";
|
|
12
|
+
function Y(e) {
|
|
13
|
+
const { i18n: t } = v("ui");
|
|
14
|
+
return B(e ?? t.language);
|
|
15
|
+
}
|
|
16
|
+
function h(e, t, a, n) {
|
|
17
|
+
const s = new Date(e);
|
|
18
|
+
if (Number.isNaN(s.getTime())) return e;
|
|
19
|
+
try {
|
|
20
|
+
return new Intl.DateTimeFormat(t, { ...a, timeZone: n }).format(
|
|
21
|
+
s
|
|
22
|
+
);
|
|
23
|
+
} catch {
|
|
24
|
+
return new Intl.DateTimeFormat(t, a).format(s);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function F(e, t, a) {
|
|
28
|
+
return h(
|
|
29
|
+
e,
|
|
30
|
+
t,
|
|
31
|
+
{ weekday: "long", day: "numeric", month: "long", year: "numeric" },
|
|
32
|
+
a
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
function M(e, t, a) {
|
|
36
|
+
return h(
|
|
37
|
+
e,
|
|
38
|
+
t,
|
|
39
|
+
{ day: "numeric", month: "long", year: "numeric" },
|
|
40
|
+
a
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
function ee(e, t) {
|
|
44
|
+
const a = /^\d{4}-\d{2}-\d{2}$/.test(e) ? `${e}T12:00:00Z` : e;
|
|
45
|
+
return M(a, t, "UTC");
|
|
46
|
+
}
|
|
47
|
+
function te(e) {
|
|
48
|
+
if (!e) return null;
|
|
49
|
+
const t = e.replace(/(?!^\+)[^\d]/g, "");
|
|
50
|
+
return /\d/.test(t) ? `tel:${t}` : null;
|
|
51
|
+
}
|
|
52
|
+
const g = (e) => e === 1 ? 2 : 3, x = I(null);
|
|
53
|
+
function R({ message: e }) {
|
|
54
|
+
const [t, a] = D("");
|
|
55
|
+
return m(() => {
|
|
56
|
+
a(e);
|
|
57
|
+
}, [e]), /* @__PURE__ */ r("span", { role: "status", "data-live": "portal", className: "ds:sr-only", children: t });
|
|
58
|
+
}
|
|
59
|
+
function ae({
|
|
60
|
+
component: e,
|
|
61
|
+
title: t,
|
|
62
|
+
description: a,
|
|
63
|
+
headingLevel: n,
|
|
64
|
+
focusOnMount: s,
|
|
65
|
+
privacy: o = !1,
|
|
66
|
+
className: l,
|
|
67
|
+
rootRef: y,
|
|
68
|
+
status: f = "ready",
|
|
69
|
+
loadingLabel: N = "",
|
|
70
|
+
errorLabel: S = "",
|
|
71
|
+
message: P,
|
|
72
|
+
children: b
|
|
73
|
+
}) {
|
|
74
|
+
const u = T(null);
|
|
75
|
+
m(() => {
|
|
76
|
+
var c;
|
|
77
|
+
s && ((c = u.current) == null || c.focus({ preventScroll: !0 }));
|
|
78
|
+
}, []);
|
|
79
|
+
const C = n === 1 ? "h1" : "h2";
|
|
80
|
+
return /* @__PURE__ */ i(
|
|
81
|
+
"div",
|
|
82
|
+
{
|
|
83
|
+
ref: y,
|
|
84
|
+
"data-component": e,
|
|
85
|
+
"data-privacy": o ? "masked" : void 0,
|
|
86
|
+
className: l,
|
|
87
|
+
children: [
|
|
88
|
+
/* @__PURE__ */ r(R, { message: f === "loading" ? N : f === "error" ? S : P ?? "" }),
|
|
89
|
+
/* @__PURE__ */ r(p, { variant: "elevated", className: "ds:w-full", children: /* @__PURE__ */ r(p.Body, { children: /* @__PURE__ */ i("div", { className: "ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]", children: [
|
|
90
|
+
/* @__PURE__ */ i("div", { className: "ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]", children: [
|
|
91
|
+
/* @__PURE__ */ r(
|
|
92
|
+
C,
|
|
93
|
+
{
|
|
94
|
+
ref: u,
|
|
95
|
+
tabIndex: -1,
|
|
96
|
+
className: n === 1 ? "type-title-page ds:m-0 ds:text-foreground ds:outline-none" : "type-title-card ds:m-0 ds:text-foreground ds:outline-none",
|
|
97
|
+
children: t
|
|
98
|
+
}
|
|
99
|
+
),
|
|
100
|
+
a ? /* @__PURE__ */ r("div", { className: "type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]", children: a }) : null
|
|
101
|
+
] }),
|
|
102
|
+
/* @__PURE__ */ r(
|
|
103
|
+
x.Provider,
|
|
104
|
+
{
|
|
105
|
+
value: () => {
|
|
106
|
+
var c;
|
|
107
|
+
return (c = u.current) == null ? void 0 : c.focus({ preventScroll: !0 });
|
|
108
|
+
},
|
|
109
|
+
children: b
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
] }) }) })
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
function re({
|
|
118
|
+
title: e,
|
|
119
|
+
headingLevel: t,
|
|
120
|
+
section: a,
|
|
121
|
+
sectionId: n,
|
|
122
|
+
children: s
|
|
123
|
+
}) {
|
|
124
|
+
const o = A(), l = g(t) === 2 ? "h2" : "h3";
|
|
125
|
+
return /* @__PURE__ */ i(
|
|
126
|
+
"section",
|
|
127
|
+
{
|
|
128
|
+
"aria-labelledby": o,
|
|
129
|
+
"data-section": a,
|
|
130
|
+
"data-section-id": n,
|
|
131
|
+
className: "ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]",
|
|
132
|
+
children: [
|
|
133
|
+
/* @__PURE__ */ r(
|
|
134
|
+
l,
|
|
135
|
+
{
|
|
136
|
+
id: o,
|
|
137
|
+
tabIndex: -1,
|
|
138
|
+
className: "type-title-card ds:m-0 ds:outline-none",
|
|
139
|
+
children: e
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
s
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
function ne({ children: e }) {
|
|
148
|
+
return /* @__PURE__ */ r("p", { className: "type-meta ds:m-0 ds:break-words ds:text-[color:var(--muted-foreground)]", children: e });
|
|
149
|
+
}
|
|
150
|
+
function se() {
|
|
151
|
+
return /* @__PURE__ */ r("div", { "aria-hidden": "true", "data-state": "loading", children: /* @__PURE__ */ r(L, { variant: "text", lines: 4 }) });
|
|
152
|
+
}
|
|
153
|
+
function oe({
|
|
154
|
+
kind: e,
|
|
155
|
+
title: t,
|
|
156
|
+
body: a,
|
|
157
|
+
headingLevel: n,
|
|
158
|
+
onRetry: s
|
|
159
|
+
}) {
|
|
160
|
+
const { t: o } = v("ui"), l = w(x);
|
|
161
|
+
return /* @__PURE__ */ r("div", { "data-state": e, children: /* @__PURE__ */ i(
|
|
162
|
+
d,
|
|
163
|
+
{
|
|
164
|
+
variant: e === "error" ? "error" : "first-use",
|
|
165
|
+
size: "sm",
|
|
166
|
+
headingLevel: g(n),
|
|
167
|
+
children: [
|
|
168
|
+
/* @__PURE__ */ r(d.Title, { children: t }),
|
|
169
|
+
a ? /* @__PURE__ */ r(d.Description, { children: a }) : null,
|
|
170
|
+
e === "error" && s ? /* @__PURE__ */ r(d.Actions, { children: /* @__PURE__ */ r(
|
|
171
|
+
U,
|
|
172
|
+
{
|
|
173
|
+
type: "button",
|
|
174
|
+
intent: "secondary",
|
|
175
|
+
className: "ds:min-h-[var(--min-target-size)]",
|
|
176
|
+
"data-action": "retry",
|
|
177
|
+
onClick: () => {
|
|
178
|
+
s(), l == null || l();
|
|
179
|
+
},
|
|
180
|
+
children: o("patientSignIn.tryAgain")
|
|
181
|
+
}
|
|
182
|
+
) }) : null
|
|
183
|
+
]
|
|
184
|
+
}
|
|
185
|
+
) });
|
|
186
|
+
}
|
|
187
|
+
function le({
|
|
188
|
+
config: e,
|
|
189
|
+
privacy: t,
|
|
190
|
+
defaultSubject: a
|
|
191
|
+
}) {
|
|
192
|
+
const n = !!e && !(e != null && e.onCancel);
|
|
193
|
+
return m(() => {
|
|
194
|
+
n && k() && console.warn(
|
|
195
|
+
"PortalStepUp: `stepUp.onCancel` is not set, so Cancel, Escape and the scrim cannot close the SMS dialog (WCAG 2.1.2). Give `onCancel` and set `stepUp` back to null in it."
|
|
196
|
+
);
|
|
197
|
+
}, [n]), e ? /* @__PURE__ */ r(
|
|
198
|
+
j,
|
|
199
|
+
{
|
|
200
|
+
...e,
|
|
201
|
+
open: !0,
|
|
202
|
+
subject: e.subject ?? a,
|
|
203
|
+
privacy: t || e.privacy === !0
|
|
204
|
+
}
|
|
205
|
+
) : null;
|
|
206
|
+
}
|
|
207
|
+
const Z = {
|
|
208
|
+
upcoming: "confirmed",
|
|
209
|
+
cancelled: "cancelled",
|
|
210
|
+
past: "done"
|
|
211
|
+
};
|
|
212
|
+
function H(e, t = !1) {
|
|
213
|
+
return {
|
|
214
|
+
id: e.id,
|
|
215
|
+
startIso: e.startIso,
|
|
216
|
+
durationMin: e.durationMin,
|
|
217
|
+
state: Z[e.status],
|
|
218
|
+
type: e.type ?? "inPractice",
|
|
219
|
+
practiceName: e.practice.name,
|
|
220
|
+
operator: e.providerName ? { name: e.providerName } : void 0,
|
|
221
|
+
// The card masks only what belongs to the patient it shows; here the
|
|
222
|
+
// patient is implied, so the care name is dropped under privacy.
|
|
223
|
+
treatments: e.careName && !t ? [{ careName: e.careName }] : void 0,
|
|
224
|
+
dimmed: e.status === "past" ? !0 : void 0
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function ie({ children: e }) {
|
|
228
|
+
return /* @__PURE__ */ r("ul", { className: "ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-md)] ds:p-0", children: e });
|
|
229
|
+
}
|
|
230
|
+
function ce({
|
|
231
|
+
appointment: e,
|
|
232
|
+
locale: t,
|
|
233
|
+
privacy: a,
|
|
234
|
+
standalone: n = !1,
|
|
235
|
+
children: s
|
|
236
|
+
}) {
|
|
237
|
+
return /* @__PURE__ */ i(
|
|
238
|
+
n ? "div" : "li",
|
|
239
|
+
{
|
|
240
|
+
"data-appointment-id": e.id,
|
|
241
|
+
tabIndex: -1,
|
|
242
|
+
className: "ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:outline-none",
|
|
243
|
+
children: [
|
|
244
|
+
/* @__PURE__ */ r("p", { className: "type-label ds:m-0 ds:text-[color:var(--muted-foreground)]", children: F(
|
|
245
|
+
e.startIso,
|
|
246
|
+
t,
|
|
247
|
+
e.practice.timeZone
|
|
248
|
+
) }),
|
|
249
|
+
/* @__PURE__ */ r(
|
|
250
|
+
E,
|
|
251
|
+
{
|
|
252
|
+
role: "presentation",
|
|
253
|
+
item: H(e, a),
|
|
254
|
+
showPatient: !1,
|
|
255
|
+
surface: "elevated",
|
|
256
|
+
hideDefaultStatus: !0,
|
|
257
|
+
locale: t,
|
|
258
|
+
timeZone: e.practice.timeZone,
|
|
259
|
+
privacy: a,
|
|
260
|
+
wrapText: !0
|
|
261
|
+
}
|
|
262
|
+
),
|
|
263
|
+
s
|
|
264
|
+
]
|
|
265
|
+
}
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
export {
|
|
269
|
+
ae as P,
|
|
270
|
+
x as S,
|
|
271
|
+
se as a,
|
|
272
|
+
oe as b,
|
|
273
|
+
ne as c,
|
|
274
|
+
le as d,
|
|
275
|
+
re as e,
|
|
276
|
+
ee as f,
|
|
277
|
+
R as g,
|
|
278
|
+
ie as h,
|
|
279
|
+
ce as i,
|
|
280
|
+
F as j,
|
|
281
|
+
M as k,
|
|
282
|
+
te as t,
|
|
283
|
+
Y as u
|
|
284
|
+
};
|
|
285
|
+
//# sourceMappingURL=portal-parts-BdR29P7z.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-parts-BdR29P7z.js","sources":["../../src/patterns/patient-portal/portal-format.ts","../../src/patterns/patient-portal/portal-parts.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Private formatters of the patient portal. Dates read on the practice's */\n/* clock (`timeZone`) in the given `locale`; neither is guessed from the */\n/* browser when the host gives them. Not exported from the pattern. */\n/* -------------------------------------------------------------------- */\n\nimport { useTranslation } from 'react-i18next';\nimport { canonicalLocale } from '../../components/_shared/intl-locale';\n\n/** The locale to format with: the `locale` prop, else the UI language. */\nexport function usePortalLocale(locale?: string): string {\n const { i18n } = useTranslation('ui');\n return canonicalLocale(locale ?? i18n.language);\n}\n\n/**\n * Formats with a zone, and without one when `Intl` rejects the zone (an\n * unknown zone would otherwise throw and take the screen down).\n */\nfunction format(\n iso: string,\n locale: string,\n options: Intl.DateTimeFormatOptions,\n timeZone?: string,\n): string {\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) return iso;\n try {\n return new Intl.DateTimeFormat(locale, { ...options, timeZone }).format(\n date,\n );\n } catch {\n return new Intl.DateTimeFormat(locale, options).format(date);\n }\n}\n\n/** \"Thursday 12 November 2026\", on the given clock. */\nexport function formatPortalDay(\n iso: string,\n locale: string,\n timeZone?: string,\n): string {\n return format(\n iso,\n locale,\n { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' },\n timeZone,\n );\n}\n\n/** \"12 November 2026\", on the given clock. */\nexport function formatPortalDate(\n iso: string,\n locale: string,\n timeZone?: string,\n): string {\n return format(\n iso,\n locale,\n { day: 'numeric', month: 'long', year: 'numeric' },\n timeZone,\n );\n}\n\n/** A date with no time (`YYYY-MM-DD`), read as that day in any zone. */\nexport function formatPortalCalendarDate(\n dateIso: string,\n locale: string,\n): string {\n const instant = /^\\d{4}-\\d{2}-\\d{2}$/.test(dateIso)\n ? `${dateIso}T12:00:00Z`\n : dateIso;\n return formatPortalDate(instant, locale, 'UTC');\n}\n\n/**\n * A `tel:` address from a phone number as typed: digits and a leading plus\n * only, so nothing else can ride in the link. Null when no digit is left.\n */\nexport function telHref(phone: string | undefined): string | null {\n if (!phone) return null;\n const cleaned = phone.replace(/(?!^\\+)[^\\d]/g, '');\n return /\\d/.test(cleaned) ? `tel:${cleaned}` : null;\n}\n","/* -------------------------------------------------------------------- */\n/* Internal pieces shared by the patient portal screens. Not exported */\n/* from the pattern's index. */\n/* -------------------------------------------------------------------- */\n\nimport {\n createContext,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n type Ref,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { EmptyState } from '../../components/empty-state';\nimport { Skeleton } from '../../components/skeleton';\nimport { StepUpDialog } from '../../components/step-up-dialog';\nimport { isDevelopment } from '../../components/_shared/is-development';\nimport {\n AppointmentCard,\n type AppointmentItem,\n} from '../../components/appointment-card';\nimport { formatPortalDay } from './portal-format';\nimport type {\n PortalAppointment,\n PortalHeadingLevel,\n PortalListStatus,\n StepUpConfig,\n} from './portal-types';\n\n/** The section heading level under a screen at `headingLevel`. */\nconst sectionLevel = (level: PortalHeadingLevel): 2 | 3 =>\n level === 1 ? 2 : 3;\n\n/* -------------------------------------------------------------------- */\n/* Screen and section */\n/* -------------------------------------------------------------------- */\n\nexport interface PortalScreenProps {\n /** Value for the root's `data-component`. */\n component: string;\n /** The screen's heading. A name inside it sits in a `<bdi>` (R23). */\n title: ReactNode;\n /** A line under the heading. */\n description?: ReactNode;\n headingLevel: PortalHeadingLevel;\n /** Move focus to the heading when the screen first shows. */\n focusOnMount: boolean;\n /** Stamps `data-privacy=\"masked\"` on the root when true. */\n privacy?: boolean;\n className?: string;\n /** Ref to the root, for a screen that moves focus inside itself. */\n rootRef?: Ref<HTMLDivElement>;\n /** The state of the read: loading and error are announced politely. */\n status?: PortalListStatus;\n /** Said when `status` is `loading`. */\n loadingLabel?: string;\n /** Said when `status` is `error`. */\n errorLabel?: string;\n /** Any other polite message, for example that a visit was cancelled. */\n message?: string;\n children?: ReactNode;\n}\n\n/** What a message's \"Try again\" needs: somewhere stable to put focus. */\nexport const ScreenFocus = createContext<(() => void) | null>(null);\n\n/**\n * A polite status that stays mounted and starts empty, so the text is\n * heard as a change (the kit's LoadStatus pattern). It sits outside the\n * busy placeholder: screen readers hold back a busy region.\n */\nexport function PortalLiveRegion({ message }: { message: string }) {\n const [text, setText] = useState('');\n useEffect(() => {\n setText(message);\n }, [message]);\n return (\n <span role=\"status\" data-live=\"portal\" className=\"ds:sr-only\">\n {text}\n </span>\n );\n}\n\n/**\n * The titled card every portal screen wears. The heading takes focus only\n * when asked, so a state story or a screen mounted with the page pulls none.\n */\nexport function PortalScreen({\n component,\n title,\n description,\n headingLevel,\n focusOnMount,\n privacy = false,\n className,\n rootRef,\n status = 'ready',\n loadingLabel = '',\n errorLabel = '',\n message,\n children,\n}: PortalScreenProps) {\n const heading = useRef<HTMLHeadingElement>(null);\n useEffect(() => {\n if (focusOnMount) heading.current?.focus({ preventScroll: true });\n // Mount only; a later change of `focusOnMount` pulls no focus.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n const Heading = headingLevel === 1 ? 'h1' : 'h2';\n const live =\n status === 'loading'\n ? loadingLabel\n : status === 'error'\n ? errorLabel\n : (message ?? '');\n return (\n <div\n ref={rootRef}\n data-component={component}\n data-privacy={privacy ? 'masked' : undefined}\n className={className}\n >\n <PortalLiveRegion message={live} />\n <Card variant=\"elevated\" className=\"ds:w-full\">\n <Card.Body>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <Heading\n ref={heading}\n tabIndex={-1}\n className={\n headingLevel === 1\n ? 'type-title-page ds:m-0 ds:text-foreground ds:outline-none'\n : 'type-title-card ds:m-0 ds:text-foreground ds:outline-none'\n }\n >\n {title}\n </Heading>\n {description ? (\n <div className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {description}\n </div>\n ) : null}\n </div>\n <ScreenFocus.Provider\n value={() => heading.current?.focus({ preventScroll: true })}\n >\n {children}\n </ScreenFocus.Provider>\n </div>\n </Card.Body>\n </Card>\n </div>\n );\n}\n\nexport interface PortalSectionProps {\n title: string;\n /** The level of the screen this section sits in. */\n headingLevel: PortalHeadingLevel;\n /** Extra attribute for host hooks, for example `upcoming`. */\n section?: string;\n /**\n * The host's opaque id for a repeated section (R22: `data-<entity>-id`).\n * Kept apart from `section`, which holds the portal's own fixed names.\n */\n sectionId?: string;\n children: ReactNode;\n}\n\n/** A labelled group inside a screen: a heading and its content. */\nexport function PortalSection({\n title,\n headingLevel,\n section,\n sectionId,\n children,\n}: PortalSectionProps) {\n const id = useId();\n const Heading = sectionLevel(headingLevel) === 2 ? 'h2' : 'h3';\n return (\n <section\n aria-labelledby={id}\n data-section={section}\n data-section-id={sectionId}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n <Heading\n id={id}\n tabIndex={-1}\n className=\"type-title-card ds:m-0 ds:outline-none\"\n >\n {title}\n </Heading>\n {children}\n </section>\n );\n}\n\n/** A muted note under a heading or a card. */\nexport function PortalNote({ children }: { children: ReactNode }) {\n return (\n <p className=\"type-meta ds:m-0 ds:break-words ds:text-[color:var(--muted-foreground)]\">\n {children}\n </p>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Read states */\n/* -------------------------------------------------------------------- */\n\n/**\n * The loading placeholder: calm lines only. The words are said by the\n * screen's live region (`PortalScreen` `loadingLabel`), which stays mounted.\n */\nexport function PortalLoading() {\n return (\n <div aria-hidden=\"true\" data-state=\"loading\">\n <Skeleton variant=\"text\" lines={4} />\n </div>\n );\n}\n\nexport interface PortalMessageProps {\n kind: 'empty' | 'error';\n title: string;\n body?: string;\n headingLevel: PortalHeadingLevel;\n /** Error only: called by \"Try again\". The button shows only when given. */\n onRetry?: () => void;\n}\n\n/** An empty list or a failed read, with an optional retry button. */\nexport function PortalMessage({\n kind,\n title,\n body,\n headingLevel,\n onRetry,\n}: PortalMessageProps) {\n const { t } = useTranslation('ui');\n const focusScreen = useContext(ScreenFocus);\n return (\n <div data-state={kind}>\n <EmptyState\n variant={kind === 'error' ? 'error' : 'first-use'}\n size=\"sm\"\n headingLevel={sectionLevel(headingLevel)}\n >\n <EmptyState.Title>{title}</EmptyState.Title>\n {body ? <EmptyState.Description>{body}</EmptyState.Description> : null}\n {kind === 'error' && onRetry ? (\n <EmptyState.Actions>\n <Button\n type=\"button\"\n intent=\"secondary\"\n className=\"ds:min-h-[var(--min-target-size)]\"\n data-action=\"retry\"\n onClick={() => {\n onRetry();\n // The button goes when the host reads again: keep focus here.\n focusScreen?.();\n }}\n >\n {t('patientSignIn.tryAgain')}\n </Button>\n </EmptyState.Actions>\n ) : null}\n </EmptyState>\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Step-up */\n/* -------------------------------------------------------------------- */\n\n/**\n * The SMS check, open while `config` is not null. The host binds which\n * sensitive step it is for; the screen only gives a default subject when the\n * host gave none. Privacy is on when the screen's is, or the host's config\n * turns it on; a config can never switch the screen's privacy off.\n */\nexport function PortalStepUp({\n config,\n privacy,\n defaultSubject,\n}: {\n config: StepUpConfig | null | undefined;\n privacy: boolean;\n defaultSubject?: ReactNode;\n}) {\n const unclosable = Boolean(config) && !config?.onCancel;\n useEffect(() => {\n // The dialog is forced open, so without `onCancel` nothing can close it.\n if (unclosable && isDevelopment()) {\n console.warn(\n 'PortalStepUp: `stepUp.onCancel` is not set, so Cancel, Escape and the scrim cannot close the SMS dialog (WCAG 2.1.2). Give `onCancel` and set `stepUp` back to null in it.',\n );\n }\n }, [unclosable]);\n if (!config) return null;\n return (\n <StepUpDialog\n {...config}\n open\n subject={config.subject ?? defaultSubject}\n // The screen's privacy wins: a host can turn masking on, never off.\n privacy={privacy || config.privacy === true}\n />\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Appointment row */\n/* -------------------------------------------------------------------- */\n\nconst STATE_OF_STATUS = {\n upcoming: 'confirmed',\n cancelled: 'cancelled',\n past: 'done',\n} as const;\n\n/** A portal appointment as the kit `AppointmentCard` takes it. */\nexport function toAppointmentItem(\n appointment: PortalAppointment,\n privacy = false,\n): AppointmentItem {\n return {\n id: appointment.id,\n startIso: appointment.startIso,\n durationMin: appointment.durationMin,\n state: STATE_OF_STATUS[appointment.status],\n type: appointment.type ?? 'inPractice',\n practiceName: appointment.practice.name,\n operator: appointment.providerName\n ? { name: appointment.providerName }\n : undefined,\n // The card masks only what belongs to the patient it shows; here the\n // patient is implied, so the care name is dropped under privacy.\n treatments:\n appointment.careName && !privacy\n ? [{ careName: appointment.careName }]\n : undefined,\n dimmed: appointment.status === 'past' ? true : undefined,\n };\n}\n\n/** A list of appointment rows: one list per section, one item per visit. */\nexport function PortalAppointmentList({ children }: { children: ReactNode }) {\n return (\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-md)] ds:p-0\">\n {children}\n </ul>\n );\n}\n\n/**\n * One appointment: the day above (on the practice's clock), the card with\n * its practice name, and `children` (actions) under it. It is a list item\n * of `PortalAppointmentList`, or a plain block when `standalone`.\n */\nexport function PortalAppointmentRow({\n appointment,\n locale,\n privacy,\n standalone = false,\n children,\n}: {\n appointment: PortalAppointment;\n locale: string;\n privacy: boolean;\n standalone?: boolean;\n children?: ReactNode;\n}) {\n const Root = standalone ? 'div' : 'li';\n return (\n <Root\n data-appointment-id={appointment.id}\n // Focusable by script only: the pattern moves focus here after a cancel.\n tabIndex={-1}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:outline-none\"\n >\n <p className=\"type-label ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {formatPortalDay(\n appointment.startIso,\n locale,\n appointment.practice.timeZone,\n )}\n </p>\n {/* The row is the list item, so the card adds no list semantics. */}\n <AppointmentCard\n role=\"presentation\"\n item={toAppointmentItem(appointment, privacy)}\n showPatient={false}\n surface=\"elevated\"\n hideDefaultStatus\n locale={locale}\n timeZone={appointment.practice.timeZone}\n privacy={privacy}\n // A cut title or status loses content at 320 px (WCAG 1.4.10, R24).\n wrapText\n />\n {children}\n </Root>\n );\n}\n"],"names":["usePortalLocale","locale","i18n","useTranslation","canonicalLocale","format","iso","options","timeZone","date","formatPortalDay","formatPortalDate","formatPortalCalendarDate","dateIso","instant","telHref","phone","cleaned","sectionLevel","level","ScreenFocus","createContext","PortalLiveRegion","message","text","setText","useState","useEffect","jsx","PortalScreen","component","title","description","headingLevel","focusOnMount","privacy","className","rootRef","status","loadingLabel","errorLabel","children","heading","useRef","_a","Heading","jsxs","Card","PortalSection","section","sectionId","id","useId","PortalNote","PortalLoading","Skeleton","PortalMessage","kind","body","onRetry","t","focusScreen","useContext","EmptyState","Button","PortalStepUp","config","defaultSubject","unclosable","isDevelopment","StepUpDialog","STATE_OF_STATUS","toAppointmentItem","appointment","PortalAppointmentList","PortalAppointmentRow","standalone","AppointmentCard"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsxs as s, jsx as e } from "react/jsx-runtime";
|
|
2
2
|
import { useTranslation as t } from "react-i18next";
|
|
3
3
|
import { E as c } from "./empty-state-DwJ5YNzz.js";
|
|
4
4
|
import { P as o } from "./panel-header-CbtlTe85.js";
|
|
@@ -70,9 +70,9 @@ function E({
|
|
|
70
70
|
);
|
|
71
71
|
}
|
|
72
72
|
export {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
u as P,
|
|
74
|
+
f as a,
|
|
75
|
+
b,
|
|
76
76
|
E as c
|
|
77
77
|
};
|
|
78
|
-
//# sourceMappingURL=privacy-mask-
|
|
78
|
+
//# sourceMappingURL=privacy-mask-C19dJFMk.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"privacy-mask-
|
|
1
|
+
{"version":3,"file":"privacy-mask-C19dJFMk.js","sources":["../../src/components/_shared/privacy-mask.tsx"],"sourcesContent":["/* Privacy mode. The rule is the grid's and the hover peek's: mask the\n identity, drop what is personal, keep time, place and status. These are\n the pieces every surface shares to say so. */\n/* Shared so published components can use them; calendar-privacy re-exports\n them. The notices carry their own markers; the line and the card render\n inside the caller's marked root. */\nimport { EyeOff } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { EmptyState } from '../empty-state';\nimport { PanelHeader } from '../panel-header';\nimport { SectionCard } from '../section-card';\nimport { VisuallyHidden } from '../visually-hidden';\nimport { privacyMask } from './privacy-mask-text';\n\nconst privacyKey = (suffix: string): string =>\n `calendarWorkspace.privacy.${suffix}`;\n\nexport { privacyMask };\n\n/** One muted line where a personal value would have been. */\nexport function PrivacyHiddenLine({ block }: { block?: string }) {\n const { t } = useTranslation('ui');\n return (\n <p\n data-privacy=\"hidden\"\n data-block={block}\n className=\"ds:m-0 ds:flex ds:items-center ds:gap-[var(--spacing-xs)] type-body-sm ds:text-[color:var(--muted-foreground)]\"\n >\n <EyeOff aria-hidden=\"true\" className=\"ds:size-4 ds:shrink-0\" />\n {t(privacyKey('hidden'))}\n </p>\n );\n}\n\n/** The patient card under privacy: the grid's mask, no photo, no contact\n * fields and no chips. Keeps `data-card=\"patient\"` for host hooks. */\nexport function PrivacyIdentityCard({ mask }: { mask?: string }) {\n const { t } = useTranslation('ui');\n return (\n <SectionCard\n data-card=\"patient\"\n data-privacy=\"masked\"\n headingLevel={3}\n title={\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <EyeOff aria-hidden=\"true\" className=\"ds:size-4 ds:shrink-0\" />\n {/* A reader hears what the mask stands for, as TaskCard does, so\n no Latin colon lands between the two in ja or zh. */}\n <VisuallyHidden>{t('appointmentPeek.hiddenName')}</VisuallyHidden>\n <span aria-hidden=\"true\">{privacyMask(mask)}</span>\n </span>\n }\n >\n <PrivacyHiddenLine />\n </SectionCard>\n );\n}\n\ninterface PrivacyNoticeProps {\n /** Absent: the notice explains, and the toolbar's toggle is the way out. */\n onTurnOff?: () => void;\n}\n\n/** The notice alone, with no heading of its own: for a surface that already\n * has one, such as a PanelSubview body. */\nexport function PrivacyNotice({ onTurnOff }: PrivacyNoticeProps) {\n const { t } = useTranslation('ui');\n return (\n <div data-component=\"privacy-notice\" className=\"ds:p-[var(--spacing-md)]\">\n <EmptyState\n variant=\"first-use\"\n size=\"sm\"\n title={t(privacyKey('hidden'))}\n description={t(privacyKey('noticeBody'))}\n primaryAction={\n onTurnOff\n ? { label: t(privacyKey('turnOff')), onClick: onTurnOff }\n : undefined\n }\n />\n </div>\n );\n}\n\n/** A whole rail panel withheld under privacy: a form or a notes list that\n * could only open by showing what the mask hides. */\nexport function PrivacyNoticePanel({\n title,\n icon,\n onTurnOff,\n}: PrivacyNoticeProps & {\n /** The panel's own title, so the rail still says which tool this is. */\n title: string;\n icon?: ReactNode;\n}) {\n return (\n <div\n data-component=\"privacy-notice-panel\"\n className=\"ds:flex ds:h-full ds:flex-col\"\n >\n <PanelHeader title={title} icon={icon} sticky divider />\n <PrivacyNotice onTurnOff={onTurnOff} />\n </div>\n );\n}\n"],"names":["privacyKey","suffix","PrivacyHiddenLine","block","t","useTranslation","jsxs","jsx","EyeOff","PrivacyIdentityCard","mask","SectionCard","VisuallyHidden","privacyMask","PrivacyNotice","onTurnOff","EmptyState","PrivacyNoticePanel","title","icon","PanelHeader"],"mappings":";;;;;;;;AAeA,MAAMA,IAAa,CAACC,MAClB,6BAA6BA,CAAM;AAK9B,SAASC,EAAkB,EAAE,OAAAC,KAA6B;AAC/D,QAAM,EAAE,GAAAC,EAAA,IAAMC,EAAe,IAAI;AACjC,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,gBAAa;AAAA,MACb,cAAYH;AAAA,MACZ,WAAU;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAI,EAACC,GAAA,EAAO,eAAY,QAAO,WAAU,yBAAwB;AAAA,QAC5DJ,EAAEJ,EAAW,QAAQ,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG7B;AAIO,SAASS,EAAoB,EAAE,MAAAC,KAA2B;AAC/D,QAAM,EAAE,GAAAN,EAAA,IAAMC,EAAe,IAAI;AACjC,SACE,gBAAAE;AAAA,IAACI;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAa;AAAA,MACb,cAAc;AAAA,MACd,OACE,gBAAAL,EAAC,QAAA,EAAK,WAAU,6DACd,UAAA;AAAA,QAAA,gBAAAC,EAACC,GAAA,EAAO,eAAY,QAAO,WAAU,yBAAwB;AAAA,QAG7D,gBAAAD,EAACK,GAAA,EAAgB,UAAAR,EAAE,4BAA4B,EAAA,CAAE;AAAA,0BAChD,QAAA,EAAK,eAAY,QAAQ,UAAAS,EAAYH,CAAI,EAAA,CAAE;AAAA,MAAA,GAC9C;AAAA,MAGF,4BAACR,GAAA,CAAA,CAAkB;AAAA,IAAA;AAAA,EAAA;AAGzB;AASO,SAASY,EAAc,EAAE,WAAAC,KAAiC;AAC/D,QAAM,EAAE,GAAAX,EAAA,IAAMC,EAAe,IAAI;AACjC,SACE,gBAAAE,EAAC,OAAA,EAAI,kBAAe,kBAAiB,WAAU,4BAC7C,UAAA,gBAAAA;AAAA,IAACS;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,OAAOZ,EAAEJ,EAAW,QAAQ,CAAC;AAAA,MAC7B,aAAaI,EAAEJ,EAAW,YAAY,CAAC;AAAA,MACvC,eACEe,IACI,EAAE,OAAOX,EAAEJ,EAAW,SAAS,CAAC,GAAG,SAASe,MAC5C;AAAA,IAAA;AAAA,EAAA,GAGV;AAEJ;AAIO,SAASE,EAAmB;AAAA,EACjC,OAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAJ;AACF,GAIG;AACD,SACE,gBAAAT;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,kBAAe;AAAA,MACf,WAAU;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAC,EAACa,KAAY,OAAAF,GAAc,MAAAC,GAAY,QAAM,IAAC,SAAO,IAAC;AAAA,QACtD,gBAAAZ,EAACO,KAAc,WAAAC,EAAA,CAAsB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG3C;"}
|
|
@@ -5,7 +5,7 @@ import { useTranslation as L } from "react-i18next";
|
|
|
5
5
|
import { E as re } from "./empty-state-DwJ5YNzz.js";
|
|
6
6
|
import { L as X } from "./link-CeV7FoI6.js";
|
|
7
7
|
import { S as E } from "./separator-Bdc9bqoJ.js";
|
|
8
|
-
import { i as W } from "./is-safe-url-
|
|
8
|
+
import { i as W } from "./is-safe-url-CEy9CEml.js";
|
|
9
9
|
import { u as J } from "./registry-DvAUVLHh.js";
|
|
10
10
|
import * as j from "@radix-ui/react-popover";
|
|
11
11
|
import { u as te, f as de } from "./non-modal-tab-exit-j3CPOuE3.js";
|
|
@@ -682,4 +682,4 @@ export {
|
|
|
682
682
|
me as b,
|
|
683
683
|
Ne as p
|
|
684
684
|
};
|
|
685
|
-
//# sourceMappingURL=product-hub-panel-
|
|
685
|
+
//# sourceMappingURL=product-hub-panel-K4QbULG7.js.map
|