@alfadocs/ui-kit-debug 1.112.2 → 1.114.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/{anamnesis-card-BzuluoD1.js → anamnesis-card-Ddnrdfx3.js} +2 -2
- package/dist/_chunks/{anamnesis-card-BzuluoD1.js.map → anamnesis-card-Ddnrdfx3.js.map} +1 -1
- package/dist/_chunks/{anamnesis-summary-card-DdTRdNrQ.js → anamnesis-summary-card-S1H_AARG.js} +2 -2
- package/dist/_chunks/{anamnesis-summary-card-DdTRdNrQ.js.map → anamnesis-summary-card-S1H_AARG.js.map} +1 -1
- package/dist/_chunks/{anamnesis-summary-rows-DfDulR_c.js → anamnesis-summary-rows-DaS-j8Jd.js} +2 -2
- package/dist/_chunks/{anamnesis-summary-rows-DfDulR_c.js.map → anamnesis-summary-rows-DaS-j8Jd.js.map} +1 -1
- package/dist/_chunks/{antenatal-schedule-timeline-DmsY5g28.js → antenatal-schedule-timeline-DmlXxevC.js} +2 -2
- package/dist/_chunks/{antenatal-schedule-timeline-DmsY5g28.js.map → antenatal-schedule-timeline-DmlXxevC.js.map} +1 -1
- package/dist/_chunks/{bishop-score-CnIft4eV.js → bishop-score-QJu-sM1y.js} +2 -2
- package/dist/_chunks/{bishop-score-CnIft4eV.js.map → bishop-score-QJu-sM1y.js.map} +1 -1
- package/dist/_chunks/{bmi-calculator-NMkXc079.js → bmi-calculator-Ba4yoR31.js} +2 -2
- package/dist/_chunks/{bmi-calculator-NMkXc079.js.map → bmi-calculator-Ba4yoR31.js.map} +1 -1
- package/dist/_chunks/{calendar-appointment-editor-dialog-FvdoKZ54.js → calendar-appointment-editor-dialog-iyh9QqNw.js} +6 -6
- package/dist/_chunks/{calendar-appointment-editor-dialog-FvdoKZ54.js.map → calendar-appointment-editor-dialog-iyh9QqNw.js.map} +1 -1
- package/dist/_chunks/{card-C85_Ndhb.js → card-DVO3x8E-.js} +23 -19
- package/dist/_chunks/{card-C85_Ndhb.js.map → card-DVO3x8E-.js.map} +1 -1
- package/dist/_chunks/{clinical-note-card-BVkxGiGl.js → clinical-note-card-Zz5_GEz-.js} +2 -2
- package/dist/_chunks/{clinical-note-card-BVkxGiGl.js.map → clinical-note-card-Zz5_GEz-.js.map} +1 -1
- package/dist/_chunks/{connection-status-CWSU3eiq.js → connection-status-DjarASoU.js} +2 -2
- package/dist/_chunks/{connection-status-CWSU3eiq.js.map → connection-status-DjarASoU.js.map} +1 -1
- package/dist/_chunks/{contact-card-CymtNvy3.js → contact-card-Cv-Nwvac.js} +2 -2
- package/dist/_chunks/{contact-card-CymtNvy3.js.map → contact-card-Cv-Nwvac.js.map} +1 -1
- package/dist/_chunks/{contact-profile-card-CAL66GaH.js → contact-profile-card-DMXWBBkU.js} +2 -2
- package/dist/_chunks/{contact-profile-card-CAL66GaH.js.map → contact-profile-card-DMXWBBkU.js.map} +1 -1
- package/dist/_chunks/{cycle-calculator-ZMDvToIm.js → cycle-calculator-Dd-XbKmZ.js} +2 -2
- package/dist/_chunks/{cycle-calculator-ZMDvToIm.js.map → cycle-calculator-Dd-XbKmZ.js.map} +1 -1
- package/dist/_chunks/{document-preview-5xs64jME.js → document-preview-WvJKHJOP.js} +2 -2
- package/dist/_chunks/{document-preview-5xs64jME.js.map → document-preview-WvJKHJOP.js.map} +1 -1
- package/dist/_chunks/{due-date-calculator-Dr2cDa64.js → due-date-calculator-Dl6SyMHO.js} +3 -3
- package/dist/_chunks/{due-date-calculator-Dr2cDa64.js.map → due-date-calculator-Dl6SyMHO.js.map} +1 -1
- package/dist/_chunks/email-input-DxwbREpx.js +156 -0
- package/dist/_chunks/email-input-DxwbREpx.js.map +1 -0
- package/dist/_chunks/{entity-summary-BbqqYqF1.js → entity-summary-DGCBQDt1.js} +2 -2
- package/dist/_chunks/{entity-summary-BbqqYqF1.js.map → entity-summary-DGCBQDt1.js.map} +1 -1
- package/dist/_chunks/{face-scheme-e2M2HJGz.js → face-scheme-DlcQaQVR.js} +2 -2
- package/dist/_chunks/{face-scheme-e2M2HJGz.js.map → face-scheme-DlcQaQVR.js.map} +1 -1
- package/dist/_chunks/{fetal-weight-CkIwJgiH.js → fetal-weight-DmZzMRzB.js} +2 -2
- package/dist/_chunks/{fetal-weight-CkIwJgiH.js.map → fetal-weight-DmZzMRzB.js.map} +1 -1
- package/dist/_chunks/{finished-terminal-DXVAfhRr.js → finished-terminal-BKTFUk3S.js} +2 -2
- package/dist/_chunks/{finished-terminal-DXVAfhRr.js.map → finished-terminal-BKTFUk3S.js.map} +1 -1
- package/dist/_chunks/{forgot-password-form-vfCO2-Tt.js → forgot-password-form-Bc_UPax6.js} +9 -8
- package/dist/_chunks/{forgot-password-form-vfCO2-Tt.js.map → forgot-password-form-Bc_UPax6.js.map} +1 -1
- package/dist/_chunks/{gestational-age-calculator-Dv3IePb-.js → gestational-age-calculator-DmzYdW5e.js} +3 -3
- package/dist/_chunks/{gestational-age-calculator-Dv3IePb-.js.map → gestational-age-calculator-DmzYdW5e.js.map} +1 -1
- package/dist/_chunks/{hcg-doubling-DdyUt4gz.js → hcg-doubling-Tr72PetS.js} +2 -2
- package/dist/_chunks/{hcg-doubling-DdyUt4gz.js.map → hcg-doubling-Tr72PetS.js.map} +1 -1
- package/dist/_chunks/{heatmap-BiwC7Gdx.js → heatmap-CNxCDl0D.js} +2 -2
- package/dist/_chunks/{heatmap-BiwC7Gdx.js.map → heatmap-CNxCDl0D.js.map} +1 -1
- package/dist/_chunks/isEmail-BfVspSvV.js +248 -0
- package/dist/_chunks/isEmail-BfVspSvV.js.map +1 -0
- package/dist/_chunks/{kit-extensions-BOsUgWnE.js → kit-extensions-DZJRmDI6.js} +7 -7
- package/dist/_chunks/{kit-extensions-BOsUgWnE.js.map → kit-extensions-DZJRmDI6.js.map} +1 -1
- package/dist/_chunks/{login-dev-card-Cz1Clugq.js → login-dev-card-D7orCfJT.js} +48 -47
- package/dist/_chunks/{login-dev-card-Cz1Clugq.js.map → login-dev-card-D7orCfJT.js.map} +1 -1
- package/dist/_chunks/map-view-Bny79cWa.js +856 -0
- package/dist/_chunks/map-view-Bny79cWa.js.map +1 -0
- package/dist/_chunks/{marketplace-app-shell-C-4QF6mp.js → marketplace-app-shell-CPNVBVLH.js} +2 -2
- package/dist/_chunks/{marketplace-app-shell-C-4QF6mp.js.map → marketplace-app-shell-CPNVBVLH.js.map} +1 -1
- package/dist/_chunks/motion-is-off-BvAuNV5O.js +15 -0
- package/dist/_chunks/motion-is-off-BvAuNV5O.js.map +1 -0
- package/dist/_chunks/{notes-panel-Cz621DWV.js → notes-panel-DXMTObBv.js} +3 -3
- package/dist/_chunks/{notes-panel-Cz621DWV.js.map → notes-panel-DXMTObBv.js.map} +1 -1
- package/dist/_chunks/{operator-hero-BELhrv9o.js → operator-hero-BWayX73x.js} +71 -62
- package/dist/_chunks/{operator-hero-BELhrv9o.js.map → operator-hero-BWayX73x.js.map} +1 -1
- package/dist/_chunks/{patient-details-BwkDIm4D.js → patient-details-DdtXBNjt.js} +3 -3
- package/dist/_chunks/{patient-details-BwkDIm4D.js.map → patient-details-DdtXBNjt.js.map} +1 -1
- package/dist/_chunks/{patient-field-row-CBba7w9V.js → patient-field-row-D9rb-QJH.js} +2 -2
- package/dist/_chunks/{patient-field-row-CBba7w9V.js.map → patient-field-row-D9rb-QJH.js.map} +1 -1
- package/dist/_chunks/{patient-search-CxuqVUTB.js → patient-search-DDRDCjZi.js} +439 -482
- package/dist/_chunks/patient-search-DDRDCjZi.js.map +1 -0
- package/dist/_chunks/{patient-summary-card-DtYTo9w_.js → patient-summary-card-CGHz-Bvm.js} +3 -3
- package/dist/_chunks/{patient-summary-card-DtYTo9w_.js.map → patient-summary-card-CGHz-Bvm.js.map} +1 -1
- package/dist/_chunks/{payment-automation-upsell-u5EuFyCY.js → payment-automation-upsell-D7yaD4u1.js} +3 -3
- package/dist/_chunks/{payment-automation-upsell-u5EuFyCY.js.map → payment-automation-upsell-D7yaD4u1.js.map} +1 -1
- package/dist/_chunks/{payment-request-card-IR83TJax.js → payment-request-card-BmV2pLoM.js} +2 -2
- package/dist/_chunks/{payment-request-card-IR83TJax.js.map → payment-request-card-BmV2pLoM.js.map} +1 -1
- package/dist/_chunks/{periodontal-chart-DqdUEFxK.js → periodontal-chart-Bjz7O4wT.js} +2 -2
- package/dist/_chunks/{periodontal-chart-DqdUEFxK.js.map → periodontal-chart-Bjz7O4wT.js.map} +1 -1
- package/dist/_chunks/{periodontal-chart-card-CCkzStlm.js → periodontal-chart-card-CxEXHl2x.js} +2 -2
- package/dist/_chunks/{periodontal-chart-card-CCkzStlm.js.map → periodontal-chart-card-CxEXHl2x.js.map} +1 -1
- package/dist/_chunks/{periodontal-diagnosis-CF1d_0yl.js → periodontal-diagnosis-xheWfi4g.js} +2 -2
- package/dist/_chunks/{periodontal-diagnosis-CF1d_0yl.js.map → periodontal-diagnosis-xheWfi4g.js.map} +1 -1
- package/dist/_chunks/{periodontal-risk-chart-D2zyID0H.js → periodontal-risk-chart-BBPB9wf1.js} +2 -2
- package/dist/_chunks/{periodontal-risk-chart-D2zyID0H.js.map → periodontal-risk-chart-BBPB9wf1.js.map} +1 -1
- package/dist/_chunks/{practice-profile-hero-Bb4YyxHA.js → practice-profile-hero-Cw4NZp0A.js} +2 -2
- package/dist/_chunks/{practice-profile-hero-Bb4YyxHA.js.map → practice-profile-hero-Cw4NZp0A.js.map} +1 -1
- package/dist/_chunks/practice-results-BlxfBx-D.js +2181 -0
- package/dist/_chunks/practice-results-BlxfBx-D.js.map +1 -0
- package/dist/_chunks/{pregnancy-dating-Cs8xpZA8.js → pregnancy-dating-BvorzHrd.js} +3 -3
- package/dist/_chunks/{pregnancy-dating-Cs8xpZA8.js.map → pregnancy-dating-BvorzHrd.js.map} +1 -1
- package/dist/_chunks/{pregnancy-weight-gain-B_Zldlzq.js → pregnancy-weight-gain-DQoOM8QV.js} +2 -2
- package/dist/_chunks/{pregnancy-weight-gain-B_Zldlzq.js.map → pregnancy-weight-gain-DQoOM8QV.js.map} +1 -1
- package/dist/_chunks/{privacy-mask-DbEKI-Jv.js → privacy-mask-Dc3kdkCR.js} +2 -2
- package/dist/_chunks/{privacy-mask-DbEKI-Jv.js.map → privacy-mask-Dc3kdkCR.js.map} +1 -1
- package/dist/_chunks/{public-footer-DGjLTtNK.js → public-footer-CB7ruuLI.js} +295 -260
- package/dist/_chunks/public-footer-CB7ruuLI.js.map +1 -0
- package/dist/_chunks/{public-header.agent-_ArDD1Xr.js → public-header.agent-Db4wm6_S.js} +203 -193
- package/dist/_chunks/public-header.agent-Db4wm6_S.js.map +1 -0
- package/dist/_chunks/{registration-form-DEyUFysm.js → registration-form-Lw9T7IXr.js} +7 -6
- package/dist/_chunks/{registration-form-DEyUFysm.js.map → registration-form-Lw9T7IXr.js.map} +1 -1
- package/dist/_chunks/{reserved.agent-W_Zgj564.js → reserved.agent-D2jwJPac.js} +22 -32
- package/dist/_chunks/reserved.agent-D2jwJPac.js.map +1 -0
- package/dist/_chunks/{reset-password-form-B0acanDD.js → reset-password-form-C93SH0Tx.js} +3 -3
- package/dist/_chunks/{reset-password-form-B0acanDD.js.map → reset-password-form-C93SH0Tx.js.map} +1 -1
- package/dist/_chunks/{reviews-panel-B03auSpQ.js → reviews-panel-CfJPEkH7.js} +2 -2
- package/dist/_chunks/{reviews-panel-B03auSpQ.js.map → reviews-panel-CfJPEkH7.js.map} +1 -1
- package/dist/_chunks/{section-card-D1sV4Voz.js → section-card-DFr2wGal.js} +2 -2
- package/dist/_chunks/{section-card-D1sV4Voz.js.map → section-card-DFr2wGal.js.map} +1 -1
- package/dist/_chunks/{send-registration-link-form-Nn0jf65G.js → send-registration-link-form-DfbTjrEK.js} +9 -8
- package/dist/_chunks/{send-registration-link-form-Nn0jf65G.js.map → send-registration-link-form-DfbTjrEK.js.map} +1 -1
- package/dist/_chunks/{signed-out-frame-CPow3aCZ.js → signed-out-frame-bh7fn_Px.js} +2 -2
- package/dist/_chunks/{signed-out-frame-CPow3aCZ.js.map → signed-out-frame-bh7fn_Px.js.map} +1 -1
- package/dist/_chunks/{stat-BFKZV50y.js → stat-WGLdn5Vn.js} +113 -107
- package/dist/_chunks/stat-WGLdn5Vn.js.map +1 -0
- package/dist/_chunks/{task-card-TSJjuuDe.js → task-card-DqVoitRk.js} +2 -2
- package/dist/_chunks/{task-card-TSJjuuDe.js.map → task-card-DqVoitRk.js.map} +1 -1
- package/dist/_chunks/{task-editor-gqWF1jI6.js → task-editor-D--LwVrg.js} +2 -2
- package/dist/_chunks/{task-editor-gqWF1jI6.js.map → task-editor-D--LwVrg.js.map} +1 -1
- package/dist/_chunks/{task-tray-DrXfMCuf.js → task-tray-C6j8HVMv.js} +2 -2
- package/dist/_chunks/{task-tray-DrXfMCuf.js.map → task-tray-C6j8HVMv.js.map} +1 -1
- package/dist/_chunks/{tasks-panel-OuIaydK5.js → tasks-panel-D6PuF4MQ.js} +2 -2
- package/dist/_chunks/{tasks-panel-OuIaydK5.js.map → tasks-panel-D6PuF4MQ.js.map} +1 -1
- package/dist/_chunks/{timeline-CKUaBZOx.js → timeline-AMqE-c2T.js} +2 -2
- package/dist/_chunks/{timeline-CKUaBZOx.js.map → timeline-AMqE-c2T.js.map} +1 -1
- package/dist/_chunks/{use-appointment-details-read-DYyCYI9f.js → use-appointment-details-read-BK_Gw1GG.js} +5 -5
- package/dist/_chunks/{use-appointment-details-read-DYyCYI9f.js.map → use-appointment-details-read-BK_Gw1GG.js.map} +1 -1
- package/dist/_chunks/verify-identity-types-C85EXNzy.js +707 -0
- package/dist/_chunks/verify-identity-types-C85EXNzy.js.map +1 -0
- package/dist/_chunks/{workflow-map-DWk-rZse.js → workflow-map-B4XkcET0.js} +2 -2
- package/dist/_chunks/{workflow-map-DWk-rZse.js.map → workflow-map-B4XkcET0.js.map} +1 -1
- package/dist/_chunks/{workflow-webhook-action-DILFqAVd.js → workflow-webhook-action-CtBn5JvO.js} +2 -2
- package/dist/_chunks/{workflow-webhook-action-DILFqAVd.js.map → workflow-webhook-action-CtBn5JvO.js.map} +1 -1
- package/dist/agent-catalog.json +111 -7
- package/dist/agent-i18n/en.json +13 -2
- package/dist/components/_shared/motion-is-off.d.ts +7 -0
- package/dist/components/_shared/motion-is-off.d.ts.map +1 -0
- package/dist/components/anamnesis-card/index.js +1 -1
- package/dist/components/anamnesis-summary-card/index.js +1 -1
- package/dist/components/appointment-details-panel/index.js +1 -1
- package/dist/components/bishop-score/index.js +1 -1
- package/dist/components/bmi-calculator/index.js +1 -1
- package/dist/components/booking/index.js +1 -1
- package/dist/components/booking/step-focus.d.ts +0 -6
- package/dist/components/booking/step-focus.d.ts.map +1 -1
- package/dist/components/card/card.d.ts.map +1 -1
- package/dist/components/card/index.js +1 -1
- package/dist/components/clinical-note-card/index.js +1 -1
- package/dist/components/connection-status/index.js +1 -1
- package/dist/components/contact-card/index.js +1 -1
- package/dist/components/contact-profile-card/index.js +1 -1
- package/dist/components/cycle-calculator/index.js +1 -1
- package/dist/components/document-preview/index.js +1 -1
- package/dist/components/due-date-calculator/index.js +2 -2
- package/dist/components/email-input/index.js +1 -1
- package/dist/components/entity-summary/index.js +1 -1
- package/dist/components/face-scheme/index.js +1 -1
- package/dist/components/fetal-weight/index.js +1 -1
- package/dist/components/finished-terminal/index.js +1 -1
- package/dist/components/gestational-age-calculator/index.js +1 -1
- package/dist/components/hcg-doubling/index.js +1 -1
- package/dist/components/heatmap/index.js +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/map-view/index.js +1 -1
- package/dist/components/map-view/map-view.d.ts +16 -0
- package/dist/components/map-view/map-view.d.ts.map +1 -1
- package/dist/components/notes-panel/index.js +1 -1
- package/dist/components/operator-hero/index.js +1 -1
- package/dist/components/operator-hero/operator-hero.d.ts.map +1 -1
- package/dist/components/patient-details/index.js +1 -1
- package/dist/components/patient-search/index.js +1 -1
- package/dist/components/patient-search/patient-search.d.ts +6 -2
- package/dist/components/patient-search/patient-search.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/periodontal-chart/index.js +1 -1
- package/dist/components/periodontal-chart-card/index.js +1 -1
- package/dist/components/periodontal-diagnosis/index.js +1 -1
- package/dist/components/periodontal-risk-chart/index.js +1 -1
- package/dist/components/practice-profile-hero/index.js +1 -1
- package/dist/components/practice-results/index.js +1 -1
- package/dist/components/practice-results/practice-results.agent.d.ts.map +1 -1
- package/dist/components/practice-results/practice-results.d.ts +43 -2
- package/dist/components/practice-results/practice-results.d.ts.map +1 -1
- package/dist/components/pregnancy-dating/index.js +1 -1
- package/dist/components/pregnancy-weight-gain/index.js +1 -1
- package/dist/components/public-footer/index.js +1 -1
- package/dist/components/public-footer/public-footer.d.ts +23 -0
- package/dist/components/public-footer/public-footer.d.ts.map +1 -1
- package/dist/components/public-header/index.js +1 -1
- package/dist/components/public-header/public-header.d.ts +7 -0
- package/dist/components/public-header/public-header.d.ts.map +1 -1
- package/dist/components/reviews-panel/index.js +1 -1
- package/dist/components/rich-text-editor/index.js +1 -1
- package/dist/components/section-card/index.js +1 -1
- package/dist/components/stat/index.js +1 -1
- package/dist/components/stat/stat.d.ts +7 -0
- package/dist/components/stat/stat.d.ts.map +1 -1
- package/dist/components/task-card/index.js +1 -1
- package/dist/components/task-editor/index.js +1 -1
- package/dist/components/task-tray/index.js +1 -1
- package/dist/components/tasks-panel/index.js +1 -1
- package/dist/components/timeline/index.js +1 -1
- package/dist/components/workflow/index.js +1 -1
- package/dist/core.css +1 -1
- package/dist/host-compat.css +4 -1
- package/dist/i18n/locales/ar.d.ts +68 -0
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +70 -2
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +68 -0
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +70 -2
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +68 -0
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +70 -2
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +68 -0
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +68 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +68 -0
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +70 -2
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +68 -0
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +70 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +68 -0
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +70 -2
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +68 -0
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +70 -2
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +68 -0
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +70 -2
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +68 -0
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +70 -2
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +68 -0
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +70 -2
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +68 -0
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +70 -2
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +68 -0
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +70 -2
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +68 -0
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +70 -2
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +68 -0
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +70 -2
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +68 -0
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +70 -2
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +68 -0
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +70 -2
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +68 -0
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +70 -2
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +373 -368
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.json +70 -2
- package/dist/locales/de.json +70 -2
- package/dist/locales/el.json +70 -2
- package/dist/locales/en.json +68 -0
- package/dist/locales/es.json +70 -2
- package/dist/locales/fr.json +70 -2
- package/dist/locales/hi.json +70 -2
- package/dist/locales/it.json +70 -2
- package/dist/locales/ja.json +70 -2
- package/dist/locales/nl.json +70 -2
- package/dist/locales/pl.json +70 -2
- package/dist/locales/pt.json +70 -2
- package/dist/locales/ro.json +70 -2
- package/dist/locales/ru.json +70 -2
- package/dist/locales/sq.json +70 -2
- package/dist/locales/sv.json +70 -2
- package/dist/locales/tr.json +70 -2
- package/dist/locales/zh.json +70 -2
- package/dist/patterns/anamnesis/index.js +1 -1
- package/dist/patterns/calendar/index.js +1 -1
- package/dist/patterns/forgot-password-form/index.js +1 -1
- package/dist/patterns/login-form/index.js +1 -1
- package/dist/patterns/marketplace-app-shell/index.js +1 -1
- package/dist/patterns/payment-automation-upsell/index.js +1 -1
- package/dist/patterns/registration-form/index.js +1 -1
- package/dist/patterns/reset-password-form/index.js +1 -1
- package/dist/patterns/send-registration-link-form/index.js +1 -1
- package/dist/patterns/signed-out-frame/index.js +1 -1
- package/dist/patterns/verify-identity/change-email-dialog.d.ts +26 -0
- package/dist/patterns/verify-identity/change-email-dialog.d.ts.map +1 -0
- package/dist/patterns/verify-identity/index.d.ts +7 -0
- package/dist/patterns/verify-identity/index.d.ts.map +1 -0
- package/dist/patterns/verify-identity/index.js +8 -0
- package/dist/patterns/verify-identity/index.js.map +1 -0
- package/dist/patterns/verify-identity/use-countdown.d.ts +12 -0
- package/dist/patterns/verify-identity/use-countdown.d.ts.map +1 -0
- package/dist/patterns/verify-identity/verify-identity-steps.d.ts +21 -0
- package/dist/patterns/verify-identity/verify-identity-steps.d.ts.map +1 -0
- package/dist/patterns/verify-identity/verify-identity-types.d.ts +47 -0
- package/dist/patterns/verify-identity/verify-identity-types.d.ts.map +1 -0
- package/dist/patterns/verify-identity/verify-identity.d.ts +54 -0
- package/dist/patterns/verify-identity/verify-identity.d.ts.map +1 -0
- package/dist/patterns/workflow-webhook-action/index.js +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +5 -1
- package/dist/_chunks/email-input-BEO3vonE.js +0 -399
- package/dist/_chunks/email-input-BEO3vonE.js.map +0 -1
- package/dist/_chunks/map-view-Dn7aXZJw.js +0 -731
- package/dist/_chunks/map-view-Dn7aXZJw.js.map +0 -1
- package/dist/_chunks/patient-search-CxuqVUTB.js.map +0 -1
- package/dist/_chunks/practice-results-BOpaPaav.js +0 -1923
- package/dist/_chunks/practice-results-BOpaPaav.js.map +0 -1
- package/dist/_chunks/public-footer-DGjLTtNK.js.map +0 -1
- package/dist/_chunks/public-header.agent-_ArDD1Xr.js.map +0 -1
- package/dist/_chunks/reserved.agent-W_Zgj564.js.map +0 -1
- package/dist/_chunks/stat-BFKZV50y.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"map-view-Dn7aXZJw.js","sources":["../../src/components/map-view/map-view.agent.ts","../../src/components/map-view/map-view.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — MapView. */\n/* */\n/* Read-safety actions on the kit's Google Maps wrapper. State is the */\n/* current centre / zoom / selected marker; actions pan, zoom, and */\n/* select markers programmatically. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { MapViewHandle, MapLatLng } from './map-view';\n\nexport const mapViewAgent: AgentAdapter<MapViewHandle> = {\n id: 'map-view',\n // pan → scroll (viewport move); set_zoom → set_value; select_marker → pick\n // (NON-persisting marker focus, no value state slot).\n capabilities: ['scroll', 'set_value', 'pick'],\n // Every action routes through the imperative bridge, which only exists\n // once the map has loaded: consent granted (the default is\n // `consentGranted={false}`) and Google Maps finished loading. Until then\n // all three actions are silent no-ops. `consentGranted` says whether the\n // gate is passed, and a null `center` after it means the map is still\n // loading. `center` / `zoom` are read off the live\n // map because Google clamps zoom and animates pans, so requested is not\n // applied; `selectedMarkerId` is the only confirmation the host accepted\n // a `select_marker` proposal.\n //\n // A9: marker ids only (`MapMarker.id` is a stable opaque id). Never\n // `MapMarker.label`, never the `address` prop (consumer-supplied free\n // text, PII in any patient-address deployment), never `apiKey`.\n state: {\n consentGranted: {\n type: 'boolean',\n descriptionKey: 'ui.agent.mapView.state.consentGranted',\n description:\n 'True when the GDPR consent gate has been passed. Read this FIRST: while it is false every action is a silent no-op against a placeholder, and nothing else in the surface says so. When it is true but `center` is still null, Google Maps is loading; wait for `center` before acting.',\n read: (handle) => handle.isConsentGranted(),\n },\n markerCount: {\n type: 'number',\n descriptionKey: 'ui.agent.mapView.state.markerCount',\n description:\n 'Number of markers the consumer passed. Zero means there is nothing for `select_marker` to select. A count only — no ids, labels or positions.',\n read: (handle) => handle.getMarkerCount(),\n },\n selectedMarkerId: {\n type: 'string | null',\n descriptionKey: 'ui.agent.mapView.state.selectedMarkerId',\n description:\n 'Id of the marker the host currently holds as selected, or null. Selection is fully controlled by the consumer, so `select_marker` only proposes — this slot is the only way to see whether the proposal was accepted.',\n read: (handle) => handle.getSelectedMarkerId(),\n },\n center: {\n type: '{ lat: number; lng: number } | null',\n descriptionKey: 'ui.agent.mapView.state.center',\n description:\n 'Live map centre in lat/lng, or null until the map has loaded (consent not granted, or Google Maps still loading). The read-back for `pan_to`, and the sign that the map is ready.',\n read: (handle) => handle.getCenter(),\n },\n zoom: {\n type: 'number | null',\n descriptionKey: 'ui.agent.mapView.state.zoom',\n description:\n \"Live zoom level, or null until the map has loaded. Google clamps zoom to the map type's range, so this is not necessarily the value last passed to `set_zoom`.\",\n read: (handle) => handle.getZoom(),\n },\n },\n actions: {\n pan_to: {\n // Ephemeral viewport move, no data loss → read.\n safety: 'read',\n argsType: '{ position: { lat: number; lng: number } }',\n argsSchema: {\n type: 'object',\n properties: {\n position: {\n type: 'object',\n properties: {\n lat: { type: 'number', description: 'Latitude in degrees.' },\n lng: { type: 'number', description: 'Longitude in degrees.' },\n },\n required: ['lat', 'lng'],\n },\n },\n required: ['position'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.mapView.actions.panTo',\n description:\n 'Pan the map to a new centre without changing zoom. Read the `center` slot back to confirm — Google animates the pan, so the applied centre settles after the call.',\n errors: [\n 'Silent no-op until the map has loaded: while `consentGranted` is false (only the consent placeholder shows) or while `center` is still null (Google Maps is loading).',\n ],\n invoke: (handle, args: { position: MapLatLng }) => {\n handle.panTo(args.position);\n },\n },\n set_zoom: {\n // Ephemeral viewport zoom, no data loss → read.\n safety: 'read',\n argsType: '{ zoom: number }',\n argsSchema: {\n type: 'object',\n properties: {\n zoom: {\n type: 'number',\n description: 'Zoom level, typical range 1–20.',\n },\n },\n required: ['zoom'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.mapView.actions.setZoom',\n description:\n 'Set the map zoom level (typical range 1–20). Read the `zoom` slot back — Google clamps the request to the map type’s supported range, so requested and applied can differ.',\n errors: [\n 'Silent no-op until the map has loaded: while `consentGranted` is false (only the consent placeholder shows) or while `center` is still null (Google Maps is loading).',\n \"Requested zoom is clamped to the map type's range; `zoom` reports what was actually applied.\",\n ],\n invoke: (handle, args: { zoom: number }) => {\n handle.setZoom(args.zoom);\n },\n },\n select_marker: {\n // Ephemeral marker focus, no data loss → read.\n safety: 'read',\n argsType: '{ id: string | null }',\n argsSchema: {\n type: 'object',\n properties: {\n id: {\n type: ['string', 'null'],\n description: 'Marker id to select, or null to clear the selection.',\n },\n },\n required: ['id'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.mapView.actions.selectMarker',\n description:\n \"Propose a marker selection by id, or pass null to clear it. Fires the host's `onMarkerClick`; selection is controlled by the host, so read the `selectedMarkerId` slot back to see whether it accepted.\",\n errors: [\n 'Silent no-op until the map has loaded: while `consentGranted` is false (only the consent placeholder shows) or while `center` is still null (Google Maps is loading).',\n 'The host owns `selectedMarkerId` and may ignore the proposal; `selectedMarkerId` is unchanged when it does.',\n ],\n invoke: (handle, args: { id: string | null }) => {\n handle.selectMarker(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'map-view',\n description: 'Marks the element as a kit MapView.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* MapView — kit wrapper over @vis.gl/react-google-maps. */\n/* */\n/* - Loads the Google Maps JS API on demand via the library's */\n/* `APIProvider`; consumer supplies the key (no kit-side cache). */\n/* - Defaults to a CONSENT-GATED placeholder (`consentGranted={false}`) */\n/* so the third-party load never happens before the consumer flips */\n/* the opt-in. GDPR-safe by default. */\n/* - Theme-reactive: the Google Maps `styles` JSON re-resolves on every */\n/* `documentElement.class` mutation (same pattern as Sparkline). */\n/* Consumers may pass `mapId` to switch to a cloud-styled map */\n/* instead, in which case `styles` is ignored. */\n/* - `data-component=\"map-view\"` lives on the outer span; the inner */\n/* `<Map>` mounts inside it. */\n/* ------------------------------------------------------------------ */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type MutableRefObject,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { MapPin, ExternalLink } from 'lucide-react';\nimport {\n APIProvider,\n Map as GoogleMap,\n AdvancedMarker,\n Marker,\n Pin,\n useApiIsLoaded,\n useMap,\n useMapsLibrary,\n} from '@vis.gl/react-google-maps';\nimport { Button } from '../button';\nimport { Skeleton } from '../skeleton';\nimport { VisuallyHidden } from '../visually-hidden';\nimport { ErrorBoundary } from '../error-boundary';\nimport { MapsCoreGate } from '../_shared/maps-core-gate';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { mapViewAgent } from './map-view.agent';\nimport { lengthTokenPx } from '../_shared/length-token';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface MapLatLng {\n lat: number;\n lng: number;\n}\n\nexport interface MapBounds {\n north: number;\n south: number;\n east: number;\n west: number;\n}\n\nexport interface MapBoundsChangeDetails {\n /** False for initial load, resizing, fitting and imperative camera moves. */\n userInteraction: boolean;\n}\n\n/**\n * A point to fit the camera to. `id` is its identity (a result id): it\n * decides whether a new set only added points to the old one. Without\n * it the coordinates stand in, so two results at one address count as\n * one.\n */\nexport interface MapFitPoint extends MapLatLng {\n id?: string;\n}\n\nexport interface MapMarker {\n /** Stable id — used for keyed re-rendering and `onMarkerClick`. */\n id: string;\n /** Position in lat/lng. */\n position: MapLatLng;\n /** Optional accessible label — falls back to the id. */\n label?: string;\n}\n\nexport interface MapViewHandle {\n /** Pan the map to a new centre without changing zoom. */\n panTo: (position: MapLatLng) => void;\n /** Set zoom (typical range 1–20). */\n setZoom: (zoom: number) => void;\n /** Programmatically select a marker (fires `onMarkerClick`). */\n selectMarker: (id: string | null) => void;\n /* ---- read-back ------------------------------------------------- */\n /**\n * True once the consent gate has been passed. The map may still be\n * loading: the three actions above stay silent no-ops until\n * `getCenter` returns a value.\n */\n isConsentGranted: () => boolean;\n /** Live map centre, or `null` until the map has loaded. */\n getCenter: () => MapLatLng | null;\n /**\n * Live zoom level, or `null` until the map has loaded.\n * Google clamps to the map type's range, so this is not necessarily\n * the value last passed to `setZoom`.\n */\n getZoom: () => number | null;\n /**\n * The controlled `selectedMarkerId` prop as the host currently holds\n * it. `selectMarker` only proposes a selection — the host is free to\n * ignore it, and this is the only way to see whether it did.\n */\n getSelectedMarkerId: () => string | null;\n /** Number of markers passed to the component. Count only, no ids. */\n getMarkerCount: () => number;\n}\n\n/**\n * The slice of `MapViewHandle` that needs a live `google.maps.Map`.\n * Built inside the `APIProvider` subtree by `MapImperativeBridge`; the\n * outer component composes it with the props-derived getters, and holds\n * `null` whenever the subtree is unmounted.\n */\ntype MapBridgeHandle = Pick<\n MapViewHandle,\n 'panTo' | 'setZoom' | 'selectMarker' | 'getCenter' | 'getZoom'\n> & {\n /** Set centre and zoom in one step, never animated. Internal. */\n jumpTo: (center: MapLatLng, zoom: number) => void;\n};\n\nexport interface MapViewProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onClick'>,\n VariantProps<typeof mapViewVariants> {\n /** Opaque instance id — emitted as `data-component-id`. */\n id?: string;\n /** Google Maps JS API key. Consumer-owned; never cached by the kit. */\n apiKey: string;\n /** Map centre (lat/lng). Required so the consent placeholder can also use it. */\n center: MapLatLng;\n /** Initial zoom. Default 15 (city-block detail, matches booking site). */\n zoom?: number;\n /**\n * Markers to render. The first marker auto-selects when no\n * `selectedMarkerId` is given.\n */\n markers?: MapMarker[];\n /** Controlled selection — fires `onMarkerClick` with the new id (or null on map click). */\n selectedMarkerId?: string | null;\n /** Fires when a marker is clicked, or `null` when the map background is clicked. */\n onMarkerClick?: (id: string | null) => void;\n /**\n * The visible viewport once the map settles, including its first bounds.\n * Fires only when bounds change. `userInteraction` is true after patient\n * input that pans or zooms, never for a kit-initiated camera move.\n * Silent until the consented map has loaded.\n */\n onBoundsChange?: (bounds: MapBounds, details: MapBoundsChangeDetails) => void;\n /**\n * GDPR consent gate. When `false` (default) the component renders a\n * placeholder with a translated CTA — the Maps JS API is **not**\n * loaded. Flip to `true` once the consumer has captured opt-in.\n */\n consentGranted?: boolean;\n /** Fires when the consumer clicks the \"Load map\" CTA in the placeholder. */\n onConsentRequest?: () => void;\n /**\n * Optional address string shown in the consent placeholder so the\n * surface is useful before the map loads. Also used to build the\n * fallback \"Open in Google Maps\" link target.\n */\n address?: string;\n /**\n * Language of the practice's own text (the `address` shown in the\n * placeholder), as a BCP 47 tag such as `\"it\"`. Written as `lang` on that\n * line so a screen reader on a page in another language pronounces it\n * correctly. Leave it out and no `lang` is written. The kit's own labels\n * keep the page language.\n */\n contentLang?: string;\n /**\n * Cloud-styled-map id. When set, takes precedence over the JSON\n * `styles` array and disables the theme-bridge re-fire. Use when\n * you've provisioned a styled map in Google Cloud Console.\n */\n mapId?: string;\n /**\n * Override the consent-placeholder description text. The default\n * (`t('mapView.consentDescription')`) is a generic IP-disclosure\n * line. Consumers operating under specific GDPR / ePrivacy\n * disclosures (jurisdiction, named controller, policy link) should\n * supply their own text via this prop. Pass any `ReactNode` — a\n * paragraph, a localised `<Trans>` instance, etc.\n */\n consentDescription?: ReactNode;\n /**\n * Replace the kit-rendered \"Load map\" button with custom CTA chrome.\n * Use when the consent dialog needs a policy link, a specific\n * jurisdiction phrasing, or a different surface (Tooltip-wrapped\n * button, link to a settings page, etc.). When omitted the kit\n * renders its own `<Button>` — that button calls `onConsentRequest`\n * if provided, otherwise flips MapView's internal opt-in state so\n * the map loads inline.\n */\n consentCta?: ReactNode;\n /**\n * Visual surface. Default `bordered` (current behaviour: 1px\n * `--border` outline + `--radius-md`). `elevated` replaces the\n * border with `--shadow-card`, matching `<Card variant=\"elevated\">`.\n * `bare` drops both — map is flush against the page canvas.\n */\n surface?: 'bordered' | 'elevated' | 'bare';\n /** Accessible label for the map region. Falls back to `t('mapView.label')`. */\n ariaLabel?: string;\n /**\n * Points the camera fits into view, with a margin, once the map has\n * loaded, and again whenever `fitKey` changes. Use it to show every pin\n * of a result list without the patient moving the map.\n *\n * - One point (or several at the same place) centres on it at\n * `fitMaxZoom`.\n * - No points: no fit, the camera shows `center` / `zoom`. If the\n * points run out after a fit, or the prop is removed, the camera\n * goes back there in one step.\n * - Between key changes nothing refits, so a map the patient has\n * panned or zoomed stays where they left it.\n * - A key change that only adds points (a \"load more\": every fitted\n * point is still there, compared by `id`) refits only if the patient\n * has not moved the map. Any other change refits. Give each point the\n * `id` of its result: two results can share an address.\n * - The camera is set in one step, never animated.\n * - While there are points to fit, the fit owns the camera: later\n * changes to `center` or `zoom` do not move it.\n */\n fitToPoints?: MapFitPoint[];\n /**\n * Identity of the fitted set: the camera refits only when this\n * changes. Pass the ids of the listed results, so re-sorting the same\n * results does not refit. Defaults to the points themselves, in any\n * order.\n */\n fitKey?: string;\n /**\n * The closest a fit may zoom in, so one result does not open at street\n * level. Default 15.\n */\n fitMaxZoom?: number;\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst mapViewVariants = cva(\n ['ds:relative ds:overflow-hidden ds:block', 'ds:bg-[var(--muted)]'].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:[--map-block-size:14rem]',\n md: 'ds:[--map-block-size:20rem]',\n lg: 'ds:[--map-block-size:28rem]',\n // `fill` defers sizing to the parent. The outer takes\n // `block-size: 100%` so the inner (also 100%) has something\n // to inherit from. Use inside a viewport-locked column —\n // `<PracticeResults variant=\"map-first\">` wires this through\n // automatically; standalone consumers must give the parent\n // a constrained block-size or the map collapses to 0.\n fill: 'ds:[block-size:100%]',\n },\n surface: {\n bordered:\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n elevated:\n 'ds:rounded-[var(--radius-md)] ds:shadow-[var(--shadow-card)] ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)]',\n bare: 'ds:rounded-none ds:border-0',\n },\n },\n defaultVariants: { size: 'md', surface: 'bordered' },\n },\n);\n\n// Inner block-size: percentage when `size=\"fill\"`, rem-token otherwise.\n// Splitting this out (instead of compound-variants) keeps the size\n// switch readable and avoids enumerating every (size × surface) pair.\nconst innerSurfaceVariants = cva('ds:block ds:w-full', {\n variants: {\n size: {\n sm: 'ds:[block-size:var(--map-block-size)]',\n md: 'ds:[block-size:var(--map-block-size)]',\n lg: 'ds:[block-size:var(--map-block-size)]',\n fill: 'ds:[block-size:100%]',\n },\n },\n defaultVariants: { size: 'md' },\n});\n\nconst consentChromeVariants = cva(\n [\n 'ds:absolute ds:inset-0',\n 'ds:flex ds:flex-col ds:items-center ds:justify-center',\n 'ds:gap-[var(--spacing-sm)]',\n 'ds:p-[var(--spacing-md)]',\n 'ds:bg-[var(--muted)] ds:text-[var(--foreground)]',\n 'ds:text-center',\n ].join(' '),\n);\n\nconst consentTitleVariants = cva('type-heading-3 ds:m-0');\n\nconst consentDescriptionVariants = cva(\n 'type-body-sm ds:text-[var(--muted-foreground)] ds:[max-inline-size:28rem] ds:m-0',\n);\n\n/* ------------------------------------------------------------------ */\n/* Inner imperative bridge */\n/* */\n/* `useMap()` only resolves inside the APIProvider tree, so the */\n/* imperative actions live in a tiny inner component that the outer */\n/* `MapView` mounts conditionally. It exposes the `panTo` / `setZoom` */\n/* etc. to the forwardRef via a `useImperativeHandle` callback prop. */\n/* ------------------------------------------------------------------ */\n\ninterface MapImperativeBridgeProps {\n /** Called with the live handle on mount, and with `null` on unmount. */\n onHandleReady: (handle: MapBridgeHandle | null) => void;\n onMarkerSelect: (id: string | null) => void;\n onCameraMove: () => void;\n}\n\nfunction MapImperativeBridge({\n onHandleReady,\n onMarkerSelect,\n onCameraMove,\n}: MapImperativeBridgeProps): null {\n const map = useMap();\n useEffect(() => {\n if (!map) return;\n onHandleReady({\n panTo: (position) => {\n onCameraMove();\n map.panTo(position);\n },\n setZoom: (zoom) => {\n onCameraMove();\n map.setZoom(zoom);\n },\n jumpTo: (center, zoom) => {\n onCameraMove();\n map.moveCamera({ center, zoom });\n },\n selectMarker: (id) => onMarkerSelect(id),\n // Read straight off the live map: Google clamps `setZoom` to the\n // map type's range and animates `panTo`, so requested and applied\n // are not the same value.\n getCenter: () => map.getCenter()?.toJSON() ?? null,\n getZoom: () => map.getZoom() ?? null,\n });\n // Drop the handle when the subtree unmounts (consent revoked, or the\n // component tears down) so the outer getters answer `null` instead of\n // reporting a dead map's last known position.\n return () => onHandleReady(null);\n }, [map, onHandleReady, onMarkerSelect, onCameraMove]);\n return null;\n}\n\n/** Report once per settled viewport, with patient input kept separate from camera state. */\nfunction MapBoundsBridge({\n onBoundsChange,\n userInteraction,\n}: {\n onBoundsChange: NonNullable<MapViewProps['onBoundsChange']>;\n userInteraction: MutableRefObject<MapInteraction>;\n}): null {\n const map = useMap();\n const callback = useRef(onBoundsChange);\n callback.current = onBoundsChange;\n\n useEffect(() => {\n if (!map) return undefined;\n const div = map.getDiv();\n let previous: {\n bounds: MapBounds;\n center: MapLatLng;\n zoom: number;\n } | null = null;\n const resetInteraction = (): void => {\n userInteraction.current = {\n pendingInput: false,\n moved: false,\n programmatic: false,\n };\n };\n resetInteraction();\n let inputExpiry: ReturnType<typeof setTimeout> | undefined;\n const touchPointers = new Set<number>();\n const markInput = (event: Event): void => {\n if (event instanceof PointerEvent && event.pointerType === 'touch') {\n if (event.type === 'pointerdown') touchPointers.add(event.pointerId);\n if (event.type === 'pointerup' || event.type === 'pointercancel') {\n touchPointers.delete(event.pointerId);\n return;\n }\n }\n if (\n event instanceof PointerEvent &&\n event.type === 'pointermove' &&\n event.buttons === 0 &&\n event.pointerType !== 'touch'\n )\n return;\n if (\n event instanceof KeyboardEvent &&\n ![\n 'ArrowUp',\n 'ArrowDown',\n 'ArrowLeft',\n 'ArrowRight',\n '+',\n '=',\n '-',\n '_',\n 'Enter',\n ' ',\n 'PageUp',\n 'PageDown',\n ].includes(event.key)\n )\n return;\n // A short panTo can keep animating after the imperative call has\n // returned. Ordinary scrolling or clicking the map must not claim\n // that animation. A real camera gesture can interrupt it.\n const fullscreen = document.fullscreenElement;\n const fullscreenMap = Boolean(\n fullscreen && (fullscreen.contains(div) || div.contains(fullscreen)),\n );\n let cameraInput = event.type === 'dblclick';\n if (event instanceof PointerEvent && event.type === 'pointermove')\n cameraInput =\n event.pointerType !== 'touch' ||\n touchPointers.size >= 2 ||\n fullscreenMap;\n if (event.type === 'touchmove')\n cameraInput =\n (event as TouchEvent).touches.length >= 2 || fullscreenMap;\n if (event instanceof KeyboardEvent)\n cameraInput = event.key !== 'Enter' && event.key !== ' ';\n if (event instanceof WheelEvent)\n cameraInput = event.ctrlKey || event.metaKey || fullscreenMap;\n if (event.type === 'click')\n cameraInput =\n event.target instanceof Element &&\n event.target.closest('button, [role=\"button\"]') != null;\n if (cameraInput) userInteraction.current.programmatic = false;\n userInteraction.current.pendingInput = true;\n clearTimeout(inputExpiry);\n // Controls normally start moving the camera immediately. Expire an\n // input that did nothing; once movement starts it stays attributed\n // until idle, including a long drag or zoom animation.\n inputExpiry = setTimeout(() => {\n userInteraction.current.pendingInput = false;\n }, 250);\n };\n const markCameraChange = (): void => {\n if (\n userInteraction.current.pendingInput &&\n !userInteraction.current.programmatic\n )\n userInteraction.current.moved = true;\n };\n const report = (): void => {\n const bounds = map.getBounds()?.toJSON();\n const center = map.getCenter()?.toJSON();\n const zoom = map.getZoom();\n const fromInput = userInteraction.current.moved;\n resetInteraction();\n clearTimeout(inputExpiry);\n if (!bounds || !center || zoom == null) return;\n const changed =\n !previous ||\n (Object.keys(bounds) as (keyof MapBounds)[]).some(\n (key) => bounds[key] !== previous!.bounds[key],\n );\n const moved =\n previous != null &&\n (zoom !== previous.zoom ||\n center.lat !== previous.center.lat ||\n center.lng !== previous.center.lng);\n previous = { bounds, center, zoom };\n if (changed)\n callback.current(bounds, { userInteraction: fromInput && moved });\n };\n // Camera events alone include initial load, refits and resizes. Input\n // also covers touch, keyboard and Google's zoom controls, without\n // preventing their defaults or depending on vendor DOM selectors.\n const inputEvents = [\n 'pointerdown',\n 'pointermove',\n 'pointerup',\n 'pointercancel',\n 'touchstart',\n 'touchmove',\n 'click',\n 'dblclick',\n 'wheel',\n 'keydown',\n ] as const;\n inputEvents.forEach((event) =>\n div.addEventListener(event, markInput, { capture: true, passive: true }),\n );\n const listeners = [\n map.addListener('dragstart', () => {\n userInteraction.current.programmatic = false;\n userInteraction.current.moved = true;\n }),\n map.addListener('center_changed', markCameraChange),\n map.addListener('zoom_changed', markCameraChange),\n map.addListener('idle', report),\n ];\n report();\n return () => {\n listeners.forEach((listener) => listener.remove());\n inputEvents.forEach((event) =>\n div.removeEventListener(event, markInput, true),\n );\n clearTimeout(inputExpiry);\n resetInteraction();\n };\n }, [map, userInteraction]);\n return null;\n}\n\ninterface MapInteraction {\n pendingInput: boolean;\n moved: boolean;\n programmatic: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* Fit to points */\n/* */\n/* Lives inside <GoogleMap>, so it only runs once the `maps` library */\n/* has arrived and `useMap()` holds a real map: the load-race rule */\n/* below applies to it too. The camera is computed here (Web Mercator) */\n/* and set in one step, rather than through fitBounds: fitBounds takes */\n/* no zoom limit, and capping it afterwards needs an `idle` event that */\n/* Google may never send when the view does not change, so the cap */\n/* could fire on the patient's next zoom instead. Setting the camera */\n/* directly is synchronous and never animates (reduced motion). */\n/* */\n/* A map in a hidden column or a sheet still opening has no size yet, */\n/* so the fit waits for the map to be laid out. */\n/* ------------------------------------------------------------------ */\n\n/** Google's world is 256px wide at zoom 0. */\nconst WORLD_PX = 256;\n\nconst toRadians = (degrees: number): number => (degrees * Math.PI) / 180;\n\n/** Web Mercator y of a latitude: the world spans -π..π. */\nfunction mercatorY(lat: number): number {\n const sin = Math.min(Math.max(Math.sin(toRadians(lat)), -0.9999), 0.9999);\n return Math.log((1 + sin) / (1 - sin)) / 2;\n}\n\nconst latitudeOf = (y: number): number =>\n (Math.atan(Math.sinh(y)) * 180) / Math.PI;\n\n/** The box round `points` (not antimeridian-aware: the kit maps Europe). */\nfunction boundsOfPoints(points: MapLatLng[]): google.maps.LatLngBoundsLiteral {\n let north = -90;\n let south = 90;\n let east = -180;\n let west = 180;\n for (const { lat, lng } of points) {\n north = Math.max(north, lat);\n south = Math.min(south, lat);\n east = Math.max(east, lng);\n west = Math.min(west, lng);\n }\n return { north, south, east, west };\n}\n\n/**\n * The centre and the closest whole zoom that shows every point inside a\n * `width` x `height` map, `padding` px in from each edge, no closer than\n * `maxZoom`. Exported for tests.\n */\nexport function cameraForPoints(\n points: MapLatLng[],\n width: number,\n height: number,\n padding: number,\n maxZoom: number,\n): { center: MapLatLng; zoom: number } {\n const { north, south, east, west } = boundsOfPoints(points);\n if (north === south && east === west) {\n return { center: { lat: north, lng: east }, zoom: maxZoom };\n }\n const top = mercatorY(north);\n const bottom = mercatorY(south);\n const center = {\n lat: latitudeOf((top + bottom) / 2),\n lng: (east + west) / 2,\n };\n const fit = (px: number, fraction: number): number =>\n fraction > 0 ? Math.log2(Math.max(px, 1) / WORLD_PX / fraction) : maxZoom;\n const zoom = Math.min(\n fit(width - 2 * padding, (east - west) / 360),\n fit(height - 2 * padding, (top - bottom) / (2 * Math.PI)),\n maxZoom,\n );\n return { center, zoom: Math.max(0, Math.floor(zoom)) };\n}\n\n/** A fit point's identity: its id, or else its coordinates. */\nconst pointKey = ({ id, lat, lng }: MapFitPoint): string =>\n id != null ? `id:${id}` : `at:${lat},${lng}`;\n\ninterface MapFitterProps {\n points: MapFitPoint[];\n fitKey: string;\n maxZoom: number;\n onCameraMove: () => void;\n}\n\nfunction MapFitter({\n points,\n fitKey,\n maxZoom,\n onCameraMove,\n}: MapFitterProps): null {\n const map = useMap();\n const fitted = useRef<{\n map: google.maps.Map;\n key: string;\n points: Set<string>;\n } | null>(null);\n // Whether the patient has panned or zoomed since the last fit: any\n // camera the kit did not set counts. Comparing with the camera the kit\n // last set (rather than flagging the kit's own call) holds whether\n // Google reports the change at once or later, and catches keyboard and\n // control-button pans, which fire no `dragstart`.\n const userMoved = useRef(false);\n const ownCamera = useRef<{ center: MapLatLng; zoom: number } | null>(null);\n\n useEffect(() => {\n if (!map) return undefined;\n const check = (): void => {\n const own = ownCamera.current;\n const center = map.getCenter()?.toJSON();\n const zoom = map.getZoom();\n const same =\n own != null &&\n zoom === own.zoom &&\n center != null &&\n Math.abs(center.lat - own.center.lat) < 1e-6 &&\n Math.abs(center.lng - own.center.lng) < 1e-6;\n if (!same) userMoved.current = true;\n };\n const listeners = [\n map.addListener('dragstart', () => {\n userMoved.current = true;\n }),\n map.addListener('center_changed', check),\n map.addListener('zoom_changed', check),\n ];\n return () => listeners.forEach((listener) => listener.remove());\n }, [map]);\n\n useEffect(() => {\n if (!map) return undefined;\n const last = fitted.current?.map === map ? fitted.current : null;\n if (last?.key === fitKey) return undefined;\n const keys = new Set(points.map(pointKey));\n const moveCamera = (center: MapLatLng, zoom: number): void => {\n ownCamera.current = { center, zoom };\n onCameraMove();\n // One step, never animated.\n map.moveCamera({ center, zoom });\n userMoved.current = false;\n };\n\n if (points.length === 0) {\n // Nothing to fit. MapView returns the camera to center/zoom when\n // fitting ends. Recording the empty set means the same results\n // coming back later count as a change and fit again.\n fitted.current = { map, key: fitKey, points: keys };\n return undefined;\n }\n\n // More of the same results (\"load more\"): every point already fitted\n // is still listed, by identity. If the patient has moved the map,\n // their view wins. A result replaced by another at the same address\n // is a different id, so that set refits.\n const grewOnly =\n last != null &&\n last.points.size > 0 &&\n [...last.points].every((point) => keys.has(point));\n if (grewOnly && userMoved.current) {\n fitted.current = { map, key: fitKey, points: keys };\n return undefined;\n }\n\n const div = map.getDiv();\n // Only a fake map has no element; there is nothing to measure.\n if (!(div instanceof Element)) return undefined;\n const fit = (): void => {\n fitted.current = { map, key: fitKey, points: keys };\n // Never more than a quarter of either side, so a small map still\n // has room to fit the points rather than zooming out to the world.\n const padding = Math.min(\n lengthTokenPx('--spacing-2xl', div, 48),\n div.clientWidth / 4,\n div.clientHeight / 4,\n );\n const { center, zoom } = cameraForPoints(\n points,\n div.clientWidth,\n div.clientHeight,\n padding,\n maxZoom,\n );\n moveCamera(center, zoom);\n };\n const laidOut = (): boolean => div.clientWidth > 0 && div.clientHeight > 0;\n if (laidOut() || typeof ResizeObserver === 'undefined') {\n fit();\n return undefined;\n }\n const observer = new ResizeObserver(() => {\n if (!laidOut()) return;\n observer.disconnect();\n fit();\n });\n observer.observe(div);\n return () => observer.disconnect();\n }, [map, fitKey, points, maxZoom, onCameraMove]);\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Library gates */\n/* */\n/* APIProvider reports LOADED as soon as `google.maps.importLibrary` */\n/* exists when another loader installed it (Google's bootstrap, a host */\n/* Places loader), before the `maps` library itself has arrived. <Map> */\n/* would then run `new google.maps.Map` and throw, taking the host's */\n/* React tree down. The map waits for `maps`, and the markers for */\n/* `marker`, whoever loaded the API. Before the API loads, <Map> only */\n/* renders its empty container, and once a constructor exists nothing */\n/* can throw, so both pass straight through as they always did. */\n/* ------------------------------------------------------------------ */\n\ntype GoogleMapsGlobal = {\n google?: { maps?: { Map?: unknown; Marker?: unknown } };\n};\nconst hasConstructor = (name: 'Map' | 'Marker'): boolean =>\n typeof (globalThis as GoogleMapsGlobal).google?.maps?.[name] === 'function';\n\n/** What the map area shows while Google's map library is on its way.\n * Exported for its story; not part of the public API. */\nexport function MapViewLoading(): ReactNode {\n const { t } = useTranslation('ui');\n return (\n <div\n role=\"status\"\n data-testid=\"map-view-loading\"\n className=\"ds:[inline-size:100%] ds:[block-size:100%]\"\n >\n <Skeleton variant=\"rectangular\" width=\"100%\" height=\"100%\" />\n <VisuallyHidden>{t('common.loading')}</VisuallyHidden>\n </div>\n );\n}\n\nfunction MapsLibraryGate({ children }: { children: ReactNode }): ReactNode {\n const apiIsLoaded = useApiIsLoaded();\n const maps = useMapsLibrary('maps');\n if (maps || !apiIsLoaded || hasConstructor('Map')) return children;\n return <MapViewLoading />;\n}\n\nfunction MarkerLibraryGate({ children }: { children: ReactNode }): ReactNode {\n const marker = useMapsLibrary('marker');\n return marker || hasConstructor('Marker') ? children : null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Consent placeholder */\n/* ------------------------------------------------------------------ */\n\ninterface ConsentPlaceholderProps {\n address: string | undefined;\n contentLang: string | undefined;\n description: ReactNode;\n /**\n * Click handler for the \"Load map\" button. Always rendered. When the\n * consumer provides `onConsentRequest` it owns the state transition\n * (typically: open a GDPR dialog, then flip `consentGranted` to true\n * after acceptance). When omitted, the kit's `MapView` falls back to\n * its own internal opt-in toggle — clicking grants consent for this\n * MapView instance only, no consumer plumbing required. This default\n * fixes a regression where the button was conditionally rendered and\n * any consumer omitting `onConsentRequest` left the patient with no\n * way to load the map (booking-website 0.31.0 hit this).\n */\n onLoadMap: () => void;\n openInGoogleMapsHref: string;\n /**\n * Custom CTA — replaces the kit-rendered `<Button>` when the consumer\n * needs a different surface (e.g. a Tooltip-wrapped button with a\n * policy link). The kit's button is still the recommended path; this\n * slot exists for consumers operating under specific compliance UX\n * requirements (jurisdiction, named controller, policy link). Pass\n * any `ReactNode`.\n */\n consentCta: ReactNode | undefined;\n}\n\nfunction ConsentPlaceholder({\n address,\n contentLang,\n description,\n onLoadMap,\n openInGoogleMapsHref,\n consentCta,\n}: ConsentPlaceholderProps): ReactNode {\n const { t } = useTranslation('ui');\n return (\n <div className={consentChromeVariants()} data-testid=\"map-view-consent\">\n <MapPin\n aria-hidden=\"true\"\n className=\"ds:size-6 ds:text-[var(--muted-foreground)]\"\n />\n <p className={consentTitleVariants()}>{t('mapView.consentTitle')}</p>\n {address ? (\n <p\n className={consentDescriptionVariants()}\n data-testid=\"map-view-address\"\n lang={contentLang}\n >\n {address}\n </p>\n ) : null}\n <p className={consentDescriptionVariants()}>{description}</p>\n <div className=\"ds:flex ds:gap-[var(--spacing-sm)] ds:flex-wrap ds:items-center ds:justify-center\">\n {consentCta ?? (\n <Button\n type=\"button\"\n intent=\"primary\"\n size=\"sm\"\n onClick={onLoadMap}\n data-testid=\"map-view-load-cta\"\n >\n {t('mapView.consentCta')}\n </Button>\n )}\n <a\n href={openInGoogleMapsHref}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)] ds:text-[var(--primary-readable)] ds:underline ds:underline-offset-2\"\n >\n {t('mapView.openInGoogleMaps')}\n <ExternalLink aria-hidden=\"true\" className=\"ds:size-3\" />\n </a>\n </div>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* MapView */\n/* ------------------------------------------------------------------ */\n\nexport const MapView = forwardRef<MapViewHandle, MapViewProps>(\n (\n {\n id,\n apiKey,\n center,\n zoom = 15,\n markers,\n selectedMarkerId,\n onMarkerClick,\n onBoundsChange,\n consentGranted = false,\n onConsentRequest,\n address,\n contentLang,\n consentDescription,\n consentCta,\n mapId,\n size,\n surface,\n ariaLabel,\n fitToPoints,\n fitKey,\n fitMaxZoom = 15,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const fitPoints = useMemo(() => fitToPoints ?? [], [fitToPoints]);\n // Identity and place: a result that keeps its id but moves (a\n // corrected address) still refits. \"Only grew\" uses identity alone.\n const resolvedFitKey = useMemo(\n () =>\n fitKey ??\n fitPoints\n .map((point) => `${pointKey(point)}@${point.lat},${point.lng}`)\n .sort()\n .join('|'),\n [fitKey, fitPoints],\n );\n // While there are points, the fit owns the camera (see `fitToPoints`).\n const fitting = fitPoints.length > 0;\n const wasFitting = useRef(fitting);\n const rawId = useId();\n const instanceId = useMemo(\n () => `map-${rawId.replace(/[^a-zA-Z0-9-_]/g, '')}`,\n [rawId],\n );\n\n // Reduced-motion gating. Google's own pan / zoom animations\n // happen inside the Maps JS API and the kit can't reach into\n // those — but the kit's own programmatic `panTo` calls (triggered\n // by prop changes via the controlled-sync effect below) can be\n // suppressed. When `prefers-reduced-motion: reduce` is set, we\n // skip the synthetic `panTo` so the consumer's prop change\n // results in a hard recenter rather than an animated glide.\n const [reducedMotion, setReducedMotion] = useState(false);\n useEffect(() => {\n if (typeof window === 'undefined') return undefined;\n const mql = window.matchMedia('(prefers-reduced-motion: reduce)');\n const sync = (): void => setReducedMotion(mql.matches);\n sync();\n mql.addEventListener('change', sync);\n return () => mql.removeEventListener('change', sync);\n }, []);\n\n // The \"Open in Google Maps\" fallback link — works without any\n // third-party script load. Uses the modern `?api=1&query=…` form\n // which the booking site already employs.\n const openInGoogleMapsHref = useMemo(() => {\n const query = address\n ? encodeURIComponent(address)\n : `${center.lat},${center.lng}`;\n return `https://www.google.com/maps/search/?api=1&query=${query}`;\n }, [address, center.lat, center.lng]);\n\n // 0.33.5: removed the kit's `getGoogleMapsTheme()` JSON-styles\n // override. Previously, when `mapId` was absent the kit painted\n // water / roads / landscape with kit tokens — a calm muted-grey\n // palette that diverged from the standard Google Maps appearance\n // users expect in every other maps surface they touch. Google's\n // default (blue water, beige land, named-road colours) is more\n // familiar and reads as a \"real map\" rather than a stylised one.\n //\n // Consumers wanting brand-themed colours opt in via `mapId` and\n // configure the palette in Google Cloud Console — that's the\n // Google-recommended path. The `getGoogleMapsTheme` export stays\n // in `src/tokens/google-maps-theme.ts` so consumers wanting the\n // old behaviour can apply the styles themselves, but the kit\n // does NOT install them by default any more.\n //\n // Side benefit: dropped the MutationObserver that previously\n // watched documentElement.class for theme switches — no more\n // observer churn on every theme toggle.\n\n // Imperative handle plumbing — populated by the inner bridge once\n // the APIProvider tree resolves a `Map` instance.\n const handleRef = useRef<MapBridgeHandle | null>(null);\n const userInteraction = useRef<MapInteraction>({\n pendingInput: false,\n moved: false,\n programmatic: false,\n });\n const onCameraMove = useCallback(() => {\n userInteraction.current = {\n pendingInput: false,\n moved: false,\n programmatic: true,\n };\n }, []);\n const handleMarkerClick = useCallback(\n (markerId: string | null) => {\n onCameraMove();\n onMarkerClick?.(markerId);\n },\n [onCameraMove, onMarkerClick],\n );\n const onHandleReady = useCallback((handle: MapBridgeHandle | null) => {\n handleRef.current = handle;\n }, []);\n\n // Read in the OUTER component, not through `handleRef` — these three\n // must still answer when the map subtree is unmounted, which is\n // exactly the situation an agent needs explaining. Assigned during\n // render, below, once `effectiveConsent` exists.\n const consentRef = useRef(false);\n const selectedMarkerIdRef = useRef<string | null>(null);\n const markerCountRef = useRef(0);\n\n const buildHandle = useCallback(\n (): MapViewHandle => ({\n panTo: (position) => handleRef.current?.panTo(position),\n setZoom: (z) => handleRef.current?.setZoom(z),\n selectMarker: (markerId) => handleRef.current?.selectMarker(markerId),\n // Without `isConsentGranted` an agent has no way to learn that\n // its pan / zoom / select was swallowed by the GDPR gate rather\n // than applied: under the default (`consentGranted={false}`) the\n // whole Maps subtree is unmounted and every action optional-chains\n // into nothing.\n isConsentGranted: () => consentRef.current,\n getCenter: () => handleRef.current?.getCenter() ?? null,\n getZoom: () => handleRef.current?.getZoom() ?? null,\n getSelectedMarkerId: () => selectedMarkerIdRef.current,\n getMarkerCount: () => markerCountRef.current,\n }),\n [],\n );\n useImperativeHandle(ref, buildHandle, [buildHandle]);\n\n const agentHandle = useMemo<MapViewHandle>(\n () => buildHandle(),\n [buildHandle],\n );\n useAgentRegistration(mapViewAgent, agentHandle, id);\n\n // Controlled-feeling propagation: vis.gl's `<Map>` reads `center`\n // and `zoom` as initial values only (via `defaultCenter` /\n // `defaultZoom`). To honour the documented \"live prop\" contract\n // we shim post-mount sync through the imperative bridge — a\n // parent that swaps offices by changing `center` re-centres the\n // map. User drag does NOT trigger this because the prop doesn't\n // change on user gesture, so the effect doesn't fire and the\n // map stays where the user left it.\n //\n // While fitting, the fit owns the camera and both syncs stand down.\n // `fitting` is a dependency, so when fitting ends (the points run out\n // or `fitToPoints` is removed) the camera returns to `center` / `zoom`\n // even if neither changed. That return is one step, not animated, so\n // it applies under reduced motion too.\n useEffect(() => {\n const fitEnded = wasFitting.current && !fitting;\n wasFitting.current = fitting;\n if (fitting) return;\n if (fitEnded) {\n handleRef.current?.jumpTo(center, zoom);\n return;\n }\n // Skip the animated pan under reduced-motion preference; the\n // map will still recentre on the next render via the agent\n // handle's `panTo`, but Google's own glide animation runs\n // either way (kit can't reach inside it). At least the kit's\n // own initiated pan is gated.\n if (reducedMotion) return;\n handleRef.current?.panTo(center);\n // Including `center` (the object reference) instead of\n // `center.lat`/`center.lng` would fire on every parent render\n // even when the coordinates are identical, fighting user drag.\n // `zoom` is read only when fitting ends; its own sync is below.\n // The destructured deps are intentional.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [center.lat, center.lng, reducedMotion, fitting]);\n useEffect(() => {\n if (fitting) return;\n handleRef.current?.setZoom(zoom);\n }, [zoom, fitting]);\n\n // Internal opt-in fallback. The `consentGranted` prop is the\n // controlled path — consumer flips it after capturing GDPR\n // acceptance through their own dialog and re-renders. When the\n // consumer omits `onConsentRequest` they're opting out of that\n // workflow, so the kit needs a sensible default click handler on\n // the placeholder's button. `internalConsent` tracks that opt-in\n // for this instance only; the map renders when either signal is\n // truthy. The 0.31.0 regression was conditionally rendering the\n // button on `onConsentRequest` — patients of consumers without the\n // hook saw the placeholder with no way to proceed.\n const [internalConsent, setInternalConsent] = useState(false);\n const effectiveConsent = consentGranted || internalConsent;\n // Mirror the three props-derived agent state slots. Assigned during\n // render so a read immediately after a prop change sees the settled\n // value. Ids and a count only — never `MapMarker.label`, never the\n // `address` prop (consumer-supplied free text, PII in any\n // patient-address deployment), never `apiKey`.\n consentRef.current = effectiveConsent;\n selectedMarkerIdRef.current = selectedMarkerId ?? null;\n markerCountRef.current = (markers ?? []).length;\n const handleLoadMap = useCallback(() => {\n if (onConsentRequest) {\n onConsentRequest();\n // The consumer typically flips `consentGranted` to true on the\n // next render. Flip the internal state too so the map still\n // loads if the consumer forgets to update its prop (the\n // common-case footgun this fallback exists to defuse).\n setInternalConsent(true);\n return;\n }\n setInternalConsent(true);\n }, [onConsentRequest]);\n\n return (\n <div\n className={mapViewVariants({ size, surface, className })}\n data-component=\"map-view\"\n data-component-id={id ?? instanceId}\n role=\"region\"\n aria-label={ariaLabel ?? t('mapView.label')}\n {...rest}\n >\n <div className={innerSurfaceVariants({ size })}>\n {effectiveConsent ? (\n // A provider failure shows the consent placeholder (its \"Open in\n // Google Maps\" link needs no script) with \"Load map\" as the\n // retry, instead of unmounting the host's React tree. The gate\n // starts the provider only once Google's `core` and `maps`\n // libraries have arrived.\n <ErrorBoundary\n fallback={({ reset }) => (\n <ConsentPlaceholder\n address={address}\n contentLang={contentLang}\n description={\n consentDescription ?? t('mapView.consentDescription')\n }\n onLoadMap={reset}\n // Always the kit button: a host's own CTA would not call\n // `reset`, so with consent already granted it would do\n // nothing and the patient could not retry.\n consentCta={undefined}\n openInGoogleMapsHref={openInGoogleMapsHref}\n />\n )}\n >\n <MapsCoreGate libraries={['maps']} pending={<MapViewLoading />}>\n <APIProvider\n apiKey={apiKey}\n // Pull the active i18next locale through so map UI text\n // (zoom controls, attribution) localises to match the\n // surrounding kit chrome.\n language={i18n.language}\n >\n <MapsLibraryGate>\n <GoogleMap\n defaultCenter={center}\n defaultZoom={zoom}\n mapId={mapId}\n gestureHandling=\"cooperative\"\n disableDefaultUI={false}\n onClick={() => handleMarkerClick(null)}\n // `<Map>` reads its own bounding rect for tile sizing.\n // Without explicit dimensions it collapses to 0×0, so\n // we pass kit-class sizing through `className` — vis.gl\n // forwards `className` straight to the rendered root.\n className=\"ds:[inline-size:100%] ds:[block-size:100%]\"\n >\n <MapImperativeBridge\n onHandleReady={onHandleReady}\n onMarkerSelect={handleMarkerClick}\n onCameraMove={onCameraMove}\n />\n {onBoundsChange ? (\n <MapBoundsBridge\n onBoundsChange={onBoundsChange}\n userInteraction={userInteraction}\n />\n ) : null}\n {fitToPoints ? (\n <MapFitter\n points={fitPoints}\n fitKey={resolvedFitKey}\n maxZoom={fitMaxZoom}\n onCameraMove={onCameraMove}\n />\n ) : null}\n <MarkerLibraryGate>\n {(markers ?? []).map((marker) => {\n // Selection state is exposed to the consumer via\n // `data-selected` on the marker root so consumers can\n // style their own InfoWindow / sidebar highlight from\n // it. The kit does NOT swap the Pin's fill colour on\n // selection — `--accent` (magenta-500 in light theme)\n // fails AA on white per 05-accessibility.mdx, and the\n // alternative tokens that pass (`--info`, `--success`)\n // carry semantic baggage. Visual selection state is\n // the consumer's call.\n const isSelected =\n selectedMarkerId != null &&\n selectedMarkerId === marker.id;\n const accessibleLabel = t('mapView.markerLabel', {\n label: marker.label ?? marker.id,\n });\n // Pin implementation switches on whether the\n // consumer supplied `mapId`. Google's\n // AdvancedMarkerElement requires the Map instance to\n // be initialised with a valid Map ID — without one\n // the API logs an error (\"La mappa è stata\n // inizializzata senza un ID mappa valido\") and any\n // AdvancedMarker rendered against that map fails to\n // appear. Cloud Map IDs are an opt-in feature; many\n // consumers (booking-website env without\n // GOOGLE_MAPS_MAP_ID, the OSS demo, etc.) legitimately\n // omit it.\n //\n // Fall back to the classic <Marker> (a thin wrapper\n // around google.maps.Marker) when mapId is absent.\n // Google has formally deprecated google.maps.Marker\n // but it still renders cleanly and produces no\n // console errors; the only loss is the brand-tinted\n // <Pin> chrome (which Marker doesn't accept as a\n // child). When a consumer wants the styled pin they\n // can opt back in by supplying `mapId`.\n if (mapId) {\n return (\n <AdvancedMarker\n key={marker.id}\n position={marker.position}\n // `title` becomes the HTML `title` attribute on\n // Google's marker wrapper — that's a tooltip, not\n // a reliable accessible name. The wrapper also\n // receives `aria-label` which Google honours as\n // the SR-announced name. Both are set so sighted\n // hover tooltips and SR labels stay aligned.\n title={accessibleLabel}\n aria-label={accessibleLabel}\n data-selected={isSelected ? 'true' : 'false'}\n onClick={() => handleMarkerClick(marker.id)}\n >\n <Pin\n background={'var(--primary)'}\n borderColor={'var(--primary)'}\n glyphColor={'var(--primary-foreground)'}\n />\n </AdvancedMarker>\n );\n }\n return (\n <Marker\n key={marker.id}\n position={marker.position}\n title={accessibleLabel}\n onClick={() => handleMarkerClick(marker.id)}\n />\n );\n })}\n </MarkerLibraryGate>\n </GoogleMap>\n </MapsLibraryGate>\n </APIProvider>\n </MapsCoreGate>\n </ErrorBoundary>\n ) : (\n <ConsentPlaceholder\n address={address}\n contentLang={contentLang}\n description={\n consentDescription ?? t('mapView.consentDescription')\n }\n onLoadMap={handleLoadMap}\n consentCta={consentCta}\n openInGoogleMapsHref={openInGoogleMapsHref}\n />\n )}\n </div>\n </div>\n );\n },\n);\nMapView.displayName = 'MapView';\n"],"names":["mapViewAgent","handle","args","mapViewVariants","cva","innerSurfaceVariants","consentChromeVariants","consentTitleVariants","consentDescriptionVariants","MapImperativeBridge","onHandleReady","onMarkerSelect","onCameraMove","map","useMap","useEffect","position","zoom","center","id","_a","MapBoundsBridge","onBoundsChange","userInteraction","callback","useRef","div","previous","resetInteraction","inputExpiry","touchPointers","markInput","event","fullscreen","fullscreenMap","cameraInput","markCameraChange","report","bounds","_b","fromInput","changed","key","moved","inputEvents","listeners","listener","WORLD_PX","toRadians","degrees","mercatorY","lat","sin","latitudeOf","y","boundsOfPoints","points","north","south","east","west","lng","cameraForPoints","width","height","padding","maxZoom","top","bottom","fit","px","fraction","pointKey","MapFitter","fitKey","fitted","userMoved","ownCamera","check","own","last","keys","moveCamera","point","lengthTokenPx","laidOut","observer","hasConstructor","name","MapViewLoading","t","useTranslation","jsxs","jsx","Skeleton","VisuallyHidden","MapsLibraryGate","children","apiIsLoaded","useApiIsLoaded","useMapsLibrary","MarkerLibraryGate","ConsentPlaceholder","address","contentLang","description","onLoadMap","openInGoogleMapsHref","consentCta","MapPin","Button","ExternalLink","MapView","forwardRef","apiKey","markers","selectedMarkerId","onMarkerClick","consentGranted","onConsentRequest","consentDescription","mapId","size","surface","ariaLabel","fitToPoints","fitMaxZoom","className","rest","ref","i18n","fitPoints","useMemo","resolvedFitKey","fitting","wasFitting","rawId","useId","instanceId","reducedMotion","setReducedMotion","useState","mql","sync","handleRef","useCallback","handleMarkerClick","markerId","consentRef","selectedMarkerIdRef","markerCountRef","buildHandle","z","useImperativeHandle","agentHandle","useAgentRegistration","fitEnded","internalConsent","setInternalConsent","effectiveConsent","handleLoadMap","ErrorBoundary","reset","MapsCoreGate","APIProvider","GoogleMap","marker","isSelected","accessibleLabel","AdvancedMarker","Pin","Marker"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"patient-search-CxuqVUTB.js","sources":["../../node_modules/lucide-react/dist/esm/icons/locate-fixed.mjs","../../src/components/patient-search/patient-search.agent.ts","../../src/components/patient-search/patient-search.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"line\", { x1: \"2\", x2: \"5\", y1: \"12\", y2: \"12\", key: \"bvdh0s\" }],\n [\"line\", { x1: \"19\", x2: \"22\", y1: \"12\", y2: \"12\", key: \"1tbv5k\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"2\", y2: \"5\", key: \"11lu5j\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"19\", y2: \"22\", key: \"x3vr5v\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"7\", key: \"fim9np\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n];\nconst LocateFixed = createLucideIcon(\"locate-fixed\", __iconNode);\n\nexport { __iconNode, LocateFixed as default };\n//# sourceMappingURL=locate-fixed.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — PatientSearch. */\n/* */\n/* PatientSearch is a top-of-funnel widget with four variants that vary */\n/* which search dimensions are exposed. The adapter surfaces the active */\n/* variant + lightweight actions (`reset`, `focus_primary`) so an agent */\n/* can drive the form across surfaces without knowing which variant is */\n/* in play. The selection state itself is owned by the consumer via the */\n/* `value` / `onChange` contract — never read here. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { PatientSearchHandle } from './patient-search';\n\nexport const patientSearchAgent: AgentAdapter<PatientSearchHandle> = {\n id: 'patient-search',\n // `filter` is the conceptual capability of this search widget. Building the\n // actual query (WHO/WHERE/WHEN/facets/geo) is host-delegated: selection is\n // owned by the consumer via the `value` / `onChange` contract, so the agent\n // surface here is limited to clearing the query (`reset`) and focusing the\n // primary field. The previous `navigate` / `view_change` capabilities were\n // spurious — the variant is fixed by props (not agent-settable) and no\n // action navigates.\n capabilities: ['filter'],\n state: {\n variant: {\n type: 'string',\n descriptionKey: 'ui.agent.patientSearch.state.variant',\n description:\n 'Active variant — one of `who-where`, `who-where-when`, `faceted`, `discovery`.',\n read: (handle) => handle.getVariant(),\n },\n },\n actions: {\n reset: {\n safety: 'write',\n idempotent: true,\n descriptionKey: 'ui.agent.patientSearch.actions.reset',\n description:\n 'Clear the current search query (WHO, WHERE, WHEN, facets, geo) via the consumer-owned onChange.',\n invoke: (handle) => {\n handle.reset();\n },\n },\n focus_primary: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.patientSearch.actions.focusPrimary',\n description:\n 'Move keyboard focus to the most-relevant search field for the current variant.',\n invoke: (handle) => {\n handle.focusPrimary();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'patient-search',\n description: 'Marks the PatientSearch root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n type MutableRefObject,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport {\n ChevronDown,\n LocateFixed,\n MapPin,\n Search as SearchIcon,\n Stethoscope,\n X,\n} from 'lucide-react';\nimport { Autocomplete } from '../autocomplete/autocomplete';\nimport { Button } from '../button/button';\nimport { Card } from '../card/card';\nimport { Slider } from '../slider/slider';\nimport { toastError } from '../toast/toast';\nimport { DropdownMenu } from '../dropdown-menu/dropdown-menu';\nimport type { OptionShape } from '../_shared/option';\nimport { useAgentRegistration } from '../../agent';\nimport { patientSearchAgent } from './patient-search.agent';\n\n/* -------------------------------------------------------------------- */\n/* PatientSearch */\n/* */\n/* Top-of-funnel search primitive with four A/B-testable variants. Each */\n/* variant exposes a different combination of patient decision-making */\n/* dimensions (WHO, WHERE, WHEN, INSURANCE/LANGUAGE, DISCOVERY) so */\n/* consumers can run PostHog-driven funnel experiments without having to */\n/* re-implement the form per surface. */\n/* */\n/* Every variant's WHERE input bakes in a \"use my location\" affordance — */\n/* a `LocateFixed` crosshair button on the inline-end of the field, with */\n/* a radius slider that appears beneath on grant. Geolocation isn't a */\n/* variant of its own; it's a universal WHERE behaviour the kit always */\n/* offers. */\n/* */\n/* Consumers own the data loaders (`loadObjects`, `loadPlaces`, */\n/* `reverseGeocode`, `discoveryCards`) + the routing logic in */\n/* `onSubmit` / `onObjectSelect` / `onPlaceSelect`. The kit owns layout, */\n/* variant gating, accessibility, telemetry, and the shared `SearchValue`*/\n/* contract that every variant feeds into. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\nexport type PatientSearchVariant =\n | 'who-where'\n | 'who-where-when'\n | 'faceted'\n | 'discovery';\n\nexport type WhenFilter = 'today' | 'tomorrow' | 'this_week' | 'anytime';\n\n/** Result from `loadObjects` — a profession, specialty, operator, or practice. */\nexport interface PatientSearchObject {\n /** Stable opaque key, e.g. `\"profession:dentista\"` or `\"operator:mario-rossi-9001\"`. */\n value: string;\n label: string;\n description?: string;\n /** Opaque consumer payload — used in `onObjectSelect` to route. */\n __payload?: unknown;\n}\n\n/** Selected place, geolocation result, or opted-in typed address. */\nexport interface PatientSearchPlace {\n /** Provider value, `geo:<lat>,<lng>`, or `text:<trimmed address>` with `allowTypedPlace`. */\n value: string;\n /** Display label, e.g. `\"Milano, Italia\"`. */\n label: string;\n lat?: number;\n lng?: number;\n}\n\n/** Curated card for the `discovery` variant. */\nexport interface DiscoveryCard {\n id: string;\n label: string;\n description?: string;\n href: string;\n icon?: ReactNode;\n /**\n * Accent token. `auto` rotates through the brand palette by row index.\n * Defaults to `auto`.\n */\n accent?: 'violet' | 'purple' | 'magenta' | 'blue' | 'auto';\n badge?: string;\n}\n\nexport interface FacetOption {\n value: string;\n label: string;\n}\n\nexport interface FacetGroup {\n /** Stable key — e.g. `\"insurance\"`, `\"language\"`. */\n key: string;\n /** Display label, e.g. `\"Convenzione\"`. */\n label: string;\n /** Empty array = boolean toggle chip. Non-empty = dropdown chip. */\n options: FacetOption[];\n /** Whether multiple options can be selected. Default false. */\n multi?: boolean;\n}\n\nexport interface SearchValue {\n object?: PatientSearchObject;\n place?: PatientSearchPlace;\n when?: WhenFilter;\n facets?: Record<string, string[]>;\n geo?: {\n lat: number;\n lng: number;\n radiusKm: number;\n label?: string;\n };\n}\n\n/** Curated imperative handle — used by the agent adapter. */\nexport interface PatientSearchHandle {\n getVariant: () => PatientSearchVariant;\n reset: () => void;\n /** Move focus to the most-relevant field for the current variant. */\n focusPrimary: () => void;\n}\n\n/* -------------------------------------------------------------------- */\n/* Telemetry */\n/* */\n/* Mirrors the booking-website convention (`window.track?.(event, p)`). */\n/* Soft-fails outside the browser and when no host has wired `track`. */\n/* -------------------------------------------------------------------- */\n\ninterface TrackFn {\n (event: string, payload?: Record<string, unknown>): void;\n}\n\nfunction track(event: string, payload?: Record<string, unknown>): void {\n if (typeof window === 'undefined') return;\n const fn = (window as unknown as { track?: TrackFn }).track;\n try {\n fn?.(event, payload);\n } catch {\n // Telemetry must never throw into the UI. Swallow.\n }\n}\n\n/* -------------------------------------------------------------------- */\n/* Constants */\n/* -------------------------------------------------------------------- */\n\nconst WHEN_OPTIONS: readonly WhenFilter[] = [\n 'today',\n 'tomorrow',\n 'this_week',\n 'anytime',\n] as const;\n\n/** Discrete radius presets per spec (1 / 5 / 10 / 25 / 50 km). */\nconst RADIUS_PRESETS: readonly number[] = [1, 5, 10, 25, 50] as const;\n\nconst DEFAULT_RADIUS_KM = 5;\n\nconst AUTOCOMPLETE_DEBOUNCE_MS = 200;\n\n/** Maps `defaultRadiusKm` to the nearest preset index. */\nfunction radiusToStepIndex(km: number): number {\n let best = 0;\n let bestDelta = Number.POSITIVE_INFINITY;\n RADIUS_PRESETS.forEach((preset, index) => {\n const delta = Math.abs(preset - km);\n if (delta < bestDelta) {\n bestDelta = delta;\n best = index;\n }\n });\n return best;\n}\n\n/* -------------------------------------------------------------------- */\n/* Root variants */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva(\n 'ds:flex ds:w-full ds:flex-col ds:text-[var(--foreground)]',\n {\n variants: {\n variant: {\n 'who-where': 'ds:gap-[var(--spacing-md)]',\n 'who-where-when': 'ds:gap-[var(--spacing-md)]',\n faceted: 'ds:gap-[var(--spacing-md)]',\n discovery: 'ds:gap-[var(--spacing-lg)]',\n },\n },\n defaultVariants: { variant: 'who-where' },\n },\n);\n\n/* -------------------------------------------------------------------- */\n/* Public props */\n/* -------------------------------------------------------------------- */\n\nexport interface PatientSearchProps\n extends\n Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'onChange' | 'onSubmit'\n >,\n VariantProps<typeof rootVariants> {\n variant: PatientSearchVariant;\n\n // Data loaders — consumer-injected; kit calls them debounced.\n loadObjects: (\n query: string,\n ctx: { signal: AbortSignal },\n ) => Promise<PatientSearchObject[]>;\n loadPlaces: (\n query: string,\n ctx: { signal: AbortSignal },\n ) => Promise<PatientSearchPlace[]>;\n\n // Selection callbacks — the consumer decides whether to route.\n onObjectSelect?: (option: PatientSearchObject) => void;\n onPlaceSelect?: (place: PatientSearchPlace) => void;\n\n // Facet config — used by the `faceted` variant; ignored by others.\n facets?: FacetGroup[];\n\n // Geo config — applies to every variant's WHERE input. The crosshair\n // overlay on the inline-end of the input triggers geolocation on click;\n // on success the input fills with the reverse-geocoded label and a\n // radius slider appears beneath. Consumer-supplied `reverseGeocode` is\n // optional — when omitted, `value.geo.label` falls back to the localised\n // \"Vicino a me\" string.\n /** Default radius in km when geolocation is granted. Snaps to the nearest preset. */\n defaultRadiusKm?: number;\n /** Reverse-geocode lat/lng → human label. Optional. */\n reverseGeocode?: (lat: number, lng: number) => Promise<string>;\n /**\n * A short line under the WHERE input that says what the geolocate\n * button does with the position, for example with a link to the privacy\n * notice. Shown only when `reverseGeocode` is wired, so only next to the\n * button. Optional.\n */\n geoHint?: React.ReactNode;\n\n // Discovery cards — used by the `discovery` variant.\n discoveryCards?: DiscoveryCard[];\n /**\n * Heading level (`h2`, `h3` or `h4`) of the discovery section title.\n * Pick the level that follows the heading above the search on the host\n * page, so the page keeps a correct heading order. Used by the\n * `discovery` variant only.\n * @default 3\n */\n discoveryHeadingLevel?: 2 | 3 | 4;\n\n /** Forwarded to the consumer's loaders if they want to constrain by country. */\n countryCode?: 'it' | 'de' | string;\n\n // State — controlled.\n value: SearchValue;\n onChange: (next: SearchValue) => void;\n onSubmit: (value: SearchValue) => void | Promise<void>;\n\n // UX\n submitting?: boolean;\n /**\n * Record unselected, trimmed WHERE text in `value.place` as\n * `{ value: 'text:' + typed, label: typed }`, without coordinates.\n * Empty text clears the place. Applies to every variant.\n * @default false\n */\n allowTypedPlace?: boolean;\n /** Custom CTA label override; defaults to `ui.patientSearch.submit.cta`. */\n submitLabel?: string;\n /**\n * @default false\n * By default the kit disables the submit button until at least one\n * search dimension is set (object, place, geo, non-anytime when, or\n * a facet). Set to `true` to allow an empty submit — useful for\n * \"browse all\" patterns where the consumer wants to show all results\n * with no initial filter.\n */\n allowEmptySubmit?: boolean;\n\n // a11y\n 'aria-label'?: string;\n /** Agent-readiness instance id. */\n id?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Focus tracking shared across a layout change */\n/* -------------------------------------------------------------------- */\n\ntype FieldName = 'who' | 'where';\n\n/**\n * \"Focus event already reported\" flags, owned by `PatientSearch`. A layout\n * change remounts the fields; keeping the flags in the root stops the\n * focus we restore afterwards from being reported a second time.\n */\nconst FocusTrackedContext = createContext<Record<\n FieldName,\n MutableRefObject<boolean>\n> | null>(null);\n\nfunction useFocusTracked(field: FieldName): MutableRefObject<boolean> {\n const shared = useContext(FocusTrackedContext);\n const local = useRef(false);\n return shared ? shared[field] : local;\n}\n\n/* -------------------------------------------------------------------- */\n/* WhoField — Autocomplete over union(profession, specialty, operator, */\n/* practice). */\n/* -------------------------------------------------------------------- */\n\ninterface WhoFieldProps {\n value: SearchValue;\n onChange: (next: SearchValue) => void;\n loadObjects: PatientSearchProps['loadObjects'];\n onObjectSelect?: PatientSearchProps['onObjectSelect'];\n inputRef?: React.Ref<HTMLInputElement>;\n /** Visible text, owned by `PatientSearch` so it survives a layout change. */\n query: string;\n onQueryChange: (next: string) => void;\n}\n\nfunction WhoField({\n value,\n onChange,\n loadObjects,\n onObjectSelect,\n inputRef,\n query,\n onQueryChange: setQuery,\n}: WhoFieldProps) {\n const { t } = useTranslation('ui');\n\n // The Autocomplete owns its own visible text; the kit only intercepts\n // selection events to update `value.object`. We mirror external resets\n // (consumer clears `value.object` programmatically) into the visible text\n // via the controlled `value` prop, but otherwise let typed input flow\n // through Autocomplete's internal state. The local `query` state breaks\n // the controlled-input cycle: typing fires onChange(next), we store\n // `next` locally, the next render passes that exact string back as\n // `value` — no flicker, no truncation. The state itself lives in the stable\n // `PatientSearch` (above the variant switch), so a late `variant` change\n // remounts this field without losing what the patient has typed.\n const selectedValueRef = useRef<string | undefined>(value.object?.value);\n\n useEffect(() => {\n // Sync external selection changes (e.g. consumer-driven reset) into the\n // visible text. We watch `value.object?.value` rather than `label` so an\n // identity update with the same label doesn't clobber a fresh query.\n if (value.object?.value !== selectedValueRef.current) {\n selectedValueRef.current = value.object?.value;\n setQuery(value.object?.label ?? '');\n }\n }, [value.object?.value, value.object?.label, setQuery]);\n\n // Adapt consumer's `loadObjects` to Autocomplete's `loadOptions` signature.\n // PatientSearchObject is structurally a superset of OptionShape, so the\n // returned array is safe to pass through as `OptionShape<string>[]`.\n const loadOptions = useCallback(\n async (q: string, { signal }: { signal: AbortSignal; locale: string }) =>\n (await loadObjects(q, { signal })) as OptionShape<string>[],\n [loadObjects],\n );\n\n const handleSelect = (option: OptionShape<string>) => {\n const next: PatientSearchObject = {\n value: option.value,\n label: option.label,\n description: option.description,\n __payload: (option as PatientSearchObject).__payload,\n };\n setQuery(next.label);\n selectedValueRef.current = next.value;\n onChange({ ...value, object: next });\n track('patient_search_object_selected', {\n value: next.value,\n type:\n next.__payload && typeof next.__payload === 'object'\n ? (next.__payload as { type?: string }).type\n : undefined,\n });\n onObjectSelect?.(next);\n };\n\n // Autocomplete's public props don't include `onFocus`, so we capture focus\n // on a wrapping <div> via the bubbling event from the embedded input.\n // `data-component=\"patient-search-field-who\"` lets agents target the\n // wrapper for instrumentation hooks without depending on Autocomplete's\n // internal structure.\n const focusTrackedRef = useFocusTracked('who');\n return (\n <div\n data-component=\"patient-search-field\"\n data-field=\"who\"\n onFocus={() => {\n if (focusTrackedRef.current) return;\n focusTrackedRef.current = true;\n track('patient_search_object_focused');\n }}\n onBlur={(e) => {\n // Reset the once-per-mount focus flag only when focus leaves the\n // wrapper entirely (no relatedTarget inside our subtree).\n if (\n e.currentTarget &&\n !e.currentTarget.contains(e.relatedTarget as Node | null)\n ) {\n focusTrackedRef.current = false;\n }\n }}\n >\n {/* Large, the same height as the large search button beside it. */}\n <Autocomplete\n ref={inputRef}\n size=\"lg\"\n value={query}\n onChange={(next) => {\n setQuery(next);\n // User edited the input after selection — drop the structured\n // selection so submit can't reuse stale data.\n if (value.object && next !== value.object.label) {\n selectedValueRef.current = undefined;\n onChange({ ...value, object: undefined });\n }\n }}\n onSelect={handleSelect}\n loadOptions={loadOptions}\n debounceMs={AUTOCOMPLETE_DEBOUNCE_MS}\n placeholder={t('patientSearch.who.placeholder')}\n aria-label={t('patientSearch.who.label')}\n startAdornment={<SearchIcon aria-hidden=\"true\" />}\n />\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* WhereField — Autocomplete over the consumer's places provider. */\n/* -------------------------------------------------------------------- */\n\ninterface WhereFieldProps {\n value: SearchValue;\n onChange: (next: SearchValue) => void;\n loadPlaces: PatientSearchProps['loadPlaces'];\n onPlaceSelect?: PatientSearchProps['onPlaceSelect'];\n allowTypedPlace?: boolean;\n inputRef?: React.Ref<HTMLInputElement>;\n /**\n * Default radius (km) applied on a successful geolocate. Snaps to the\n * nearest preset (1 / 5 / 10 / 25 / 50). Defaults to 5 km.\n */\n defaultRadiusKm?: number;\n /** Reverse-geocode lat/lng → human label. Optional. */\n reverseGeocode?: PatientSearchProps['reverseGeocode'];\n geoHint?: PatientSearchProps['geoHint'];\n /** Visible text, owned by `PatientSearch` so it survives a layout change. */\n query: string;\n onQueryChange: (next: string) => void;\n}\n\ntype GeoStatus = 'pristine' | 'requesting' | 'granted';\n\nconst geoTriggerClasses = [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:size-8 ds:rounded-[var(--radius-sm)]',\n 'ds:text-[color:var(--muted-foreground)] ds:hover:text-[color:var(--primary)]',\n 'ds:hover:bg-[color-mix(in_srgb,var(--primary)_8%,transparent)]',\n 'ds:aria-pressed:text-[color:var(--primary)]',\n 'ds:aria-pressed:bg-[color-mix(in_srgb,var(--primary)_12%,transparent)]',\n 'ds:disabled:opacity-50 ds:disabled:cursor-not-allowed',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\n/**\n * Unified WHERE input — every variant uses it.\n *\n * Layout per state:\n * - pristine: `[MapPin] City... [LocateFixed]`\n * - granted : `[MapPin] Milano, Italia [X] [LocateFixed]` + radius slider beneath\n * - denied : back to pristine, with an error toast (the app mounts `Toaster`)\n *\n * The MapPin on the inline-start is the conventional \"this is a location\n * field\" marker. The LocateFixed crosshair on the inline-end is the\n * geolocate trigger — these are deliberately different glyphs (Doctolib /\n * Google Maps / Booking pattern) so users don't conflate the field marker\n * with the action.\n */\nfunction WhereField({\n value,\n onChange,\n loadPlaces,\n onPlaceSelect,\n allowTypedPlace,\n inputRef,\n defaultRadiusKm = DEFAULT_RADIUS_KM,\n reverseGeocode,\n geoHint,\n query,\n onQueryChange: setQuery,\n}: WhereFieldProps) {\n const { t } = useTranslation('ui');\n const selectedValueRef = useRef<string | undefined>(value.place?.value);\n const initialStatus: GeoStatus = value.geo ? 'granted' : 'pristine';\n const [status, setStatus] = useState<GeoStatus>(initialStatus);\n\n useEffect(() => {\n if (value.place?.value !== selectedValueRef.current) {\n selectedValueRef.current = value.place?.value;\n setQuery(value.place?.label ?? '');\n }\n }, [value.place?.value, value.place?.label, setQuery]);\n\n const loadOptions = useCallback(\n async (q: string, { signal }: { signal: AbortSignal; locale: string }) =>\n (await loadPlaces(q, { signal })) as OptionShape<string>[],\n [loadPlaces],\n );\n\n const handleSelect = (option: OptionShape<string>) => {\n const place: PatientSearchPlace = {\n value: option.value,\n label: option.label,\n lat: (option as PatientSearchPlace).lat,\n lng: (option as PatientSearchPlace).lng,\n };\n setQuery(place.label);\n selectedValueRef.current = place.value;\n // Typing or selecting a city through the autocomplete cancels any\n // active geolocate — the consumer's search API should now run plain\n // text search rather than lat/lng-radius.\n onChange({ ...value, place, geo: undefined });\n if (status === 'granted') setStatus('pristine');\n track('patient_search_place_selected', { value: place.value });\n onPlaceSelect?.(place);\n };\n\n // A snackbar, not an inline message: the field keeps its layout and the\n // trigger stays, so the patient can retry after allowing location.\n const denyLocation = (reason: 'unsupported' | 'user') => {\n setStatus('pristine');\n toastError(t('patientSearch.geo.denied'));\n track('patient_search_geo_denied', { reason });\n };\n\n const requestLocation = () => {\n if (typeof window === 'undefined' || !navigator?.geolocation) {\n denyLocation('unsupported');\n return;\n }\n setStatus('requesting');\n track('patient_search_place_focused');\n navigator.geolocation.getCurrentPosition(\n async (position) => {\n const { latitude, longitude } = position.coords;\n let label: string | undefined;\n try {\n label = await reverseGeocode?.(latitude, longitude);\n } catch {\n label = undefined;\n }\n const km = defaultRadiusKm;\n const resolvedLabel = label ?? t('patientSearch.geo.fallbackLabel');\n // Mirror the geo label into `value.place` so the visible input\n // shows the reverse-geocoded text. `value.geo` carries the\n // structured lat/lng/radius the consumer's search API actually\n // needs. The synthetic place carries a `geo:` value prefix so\n // the consumer can distinguish a geo-derived place from a\n // user-selected Google Places entry.\n const syntheticPlace: PatientSearchPlace = {\n value: `geo:${latitude.toFixed(4)},${longitude.toFixed(4)}`,\n label: resolvedLabel,\n lat: latitude,\n lng: longitude,\n };\n onChange({\n ...value,\n place: syntheticPlace,\n geo: {\n lat: latitude,\n lng: longitude,\n radiusKm: km,\n label: resolvedLabel,\n },\n });\n setStatus('granted');\n track('patient_search_geo_granted', { radiusKm: km });\n },\n () => denyLocation('user'),\n { enableHighAccuracy: false, maximumAge: 60_000, timeout: 10_000 },\n );\n };\n\n const clearGeo = () => {\n onChange({ ...value, geo: undefined, place: undefined });\n setQuery('');\n selectedValueRef.current = undefined;\n setStatus('pristine');\n };\n\n const isGranted = status === 'granted' && Boolean(value.geo);\n const isRequesting = status === 'requesting';\n\n const focusTrackedRef = useFocusTracked('where');\n // Overlay button(s) that sit visually inside the inline-end of the\n // input. Rendered as siblings of the Autocomplete (not inside the\n // `endAdornment` slot, which the kit wraps in `aria-hidden` and so\n // cannot host an interactive trigger). The decorative spacer in\n // `endAdornment` carves out room so typed text doesn't run under\n // the overlay.\n // Gate the geo-assist UI on the consumer wiring `reverseGeocode`.\n // Without it, clicking \"Vicino a me\" would set value.geo to lat/lng\n // coordinates the kit can't translate into a human-readable label —\n // the patient sees coordinates or nothing. Presence of the dep\n // implies intent.\n const geoEnabled = Boolean(reverseGeocode);\n const overlay = !geoEnabled ? null : (\n <span className=\"ds:absolute ds:end-[var(--spacing-xs)] ds:top-1/2 ds:-translate-y-1/2 ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {isGranted ? (\n <button\n type=\"button\"\n aria-label={t('patientSearch.geo.clear')}\n onClick={clearGeo}\n className={geoTriggerClasses}\n >\n <X aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label={t('patientSearch.geo.cta')}\n aria-pressed={isGranted || undefined}\n disabled={isRequesting}\n onClick={isGranted ? clearGeo : requestLocation}\n className={geoTriggerClasses}\n >\n {/*\n The geo trigger uses `LocateFixed` (target-with-dot crosshair)\n rather than `MapPin`. The WHERE input's start-adornment is the\n `MapPin` (\"this is a location field\"); reusing the pin glyph\n here would visually conflate the field marker with the action.\n Crosshair = \"centre on me\" — Doctolib / Google Maps / Booking\n all use this distinction.\n */}\n <LocateFixed aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n </span>\n );\n\n return (\n <div\n data-component=\"patient-search-field\"\n data-field=\"where\"\n onFocus={() => {\n if (focusTrackedRef.current) return;\n focusTrackedRef.current = true;\n track('patient_search_place_focused');\n }}\n onBlur={(e) => {\n if (\n e.currentTarget &&\n !e.currentTarget.contains(e.relatedTarget as Node | null)\n ) {\n focusTrackedRef.current = false;\n }\n }}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n <div className=\"ds:relative\">\n {/* Large, the same height as the large search button beside it. */}\n <Autocomplete\n ref={inputRef}\n size=\"lg\"\n value={query}\n onChange={(next) => {\n setQuery(next);\n if (\n (allowTypedPlace || value.place) &&\n next !== value.place?.label\n ) {\n const typed = next.trim();\n const place =\n allowTypedPlace && typed\n ? { value: `text:${typed}`, label: typed }\n : undefined;\n // Recognise our own controlled-state update so the sync effect\n // preserves the raw input, including spaces between words.\n selectedValueRef.current = place?.value;\n // Skip a no-op update (a trailing space, or spaces typed with no\n // place yet) so hosts that search on change are not re-triggered.\n if (place?.value === value.place?.value && !value.geo) return;\n // Manual edit cancels any active geolocate too — the typed\n // text owns the field now.\n onChange({ ...value, place, geo: undefined });\n if (status === 'granted') setStatus('pristine');\n }\n }}\n onSelect={handleSelect}\n loadOptions={loadOptions}\n debounceMs={AUTOCOMPLETE_DEBOUNCE_MS}\n placeholder={t('patientSearch.where.placeholder')}\n aria-label={t('patientSearch.where.label')}\n startAdornment={<MapPin aria-hidden=\"true\" />}\n endAdornment={\n // Decorative spacer — reserves inline-end room so the typed\n // text doesn't run under the absolutely-positioned overlay.\n // Autocomplete wraps endAdornment in `aria-hidden`, which is\n // correct for this empty span. Granted-state shows an extra\n // clear-X chip, so the spacer doubles in width when granted.\n <span\n aria-hidden=\"true\"\n className={\n isGranted\n ? 'ds:inline-block ds:size-[4.5rem]'\n : 'ds:inline-block ds:size-8'\n }\n />\n }\n />\n {overlay}\n </div>\n {geoEnabled && geoHint ? (\n <p\n data-component=\"patient-search-geo-hint\"\n className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\"\n >\n {geoHint}\n </p>\n ) : null}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* GeoRadiusBar — full-width radius slider rendered beneath the top */\n/* row when geo-assist is active. Lifted out of `WhereField` so the */\n/* WHO/WHERE/Submit row stays at single-row height when the slider is */\n/* visible (release notes 0.30.2 — see `ds-kit-followup-from-0.30.0`). */\n/* -------------------------------------------------------------------- */\n\ninterface GeoRadiusBarProps {\n value: SearchValue;\n onChange: (next: SearchValue) => void;\n defaultRadiusKm?: number;\n}\n\nfunction GeoRadiusBar({\n value,\n onChange,\n defaultRadiusKm = DEFAULT_RADIUS_KM,\n}: GeoRadiusBarProps) {\n const { t } = useTranslation('ui');\n const [radiusIndex, setRadiusIndex] = useState<number>(() =>\n radiusToStepIndex(value.geo?.radiusKm ?? defaultRadiusKm),\n );\n if (!value.geo) return null;\n const commitRadius = (index: number) => {\n const km = RADIUS_PRESETS[index] ?? defaultRadiusKm;\n onChange({ ...value, geo: { ...value.geo!, radiusKm: km } });\n track('patient_search_radius_changed', { radiusKm: km });\n };\n const formatRadius = (n: number) => {\n const km = RADIUS_PRESETS[Math.round(n)] ?? defaultRadiusKm;\n return t('patientSearch.geo.radiusFormat', { km });\n };\n return (\n <div\n data-component=\"patient-search-geo-radius-bar\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pb-[var(--spacing-md)]\"\n >\n <span\n id=\"patient-search-radius-label\"\n className=\"type-meta ds:text-[color:var(--muted-foreground)]\"\n >\n {t('patientSearch.geo.radius')}\n </span>\n <Slider\n value={[radiusIndex]}\n min={0}\n max={RADIUS_PRESETS.length - 1}\n step={1}\n marks={RADIUS_PRESETS.map((km, index) => ({\n value: index,\n label: `${km}`,\n }))}\n formatValue={formatRadius}\n alwaysShowValue\n aria-labelledby=\"patient-search-radius-label\"\n onValueChange={(next) => setRadiusIndex(next[0] ?? 0)}\n onValueCommit={(next) => commitRadius(next[0] ?? 0)}\n />\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* WhenChipStrip — radiogroup of {today, tomorrow, this_week, anytime} */\n/* */\n/* Hand-rolled radiogroup: `role=\"radiogroup\"` on the container, button */\n/* children carry `role=\"radio\"` + `aria-checked`, arrow-key navigation */\n/* moves focus + selection. Visually presents as suggestion-style chips. */\n/* -------------------------------------------------------------------- */\n\nconst whenChipVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-h-[var(--min-target-size)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:pt-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-full)]',\n 'type-label ds:font-[var(--font-weight-medium)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' '),\n {\n variants: {\n state: {\n idle: 'ds:bg-[var(--secondary)] ds:text-[var(--foreground)] ds:border ds:border-[color:var(--border)] ds:hover:bg-[color-mix(in_srgb,var(--primary)_8%,var(--secondary))]',\n selected:\n 'ds:bg-[var(--primary)] ds:text-[var(--primary-foreground)] ds:border ds:border-transparent ds:font-[var(--font-weight-semibold)]',\n },\n },\n defaultVariants: { state: 'idle' },\n },\n);\n\ninterface WhenChipStripProps {\n value?: WhenFilter;\n onChange: (next: WhenFilter) => void;\n}\n\nfunction WhenChipStrip({ value, onChange }: WhenChipStripProps) {\n const { t, i18n } = useTranslation('ui');\n const groupId = useId();\n const isRTL = i18n.dir() === 'rtl';\n\n const buttonRefs = useRef<Map<WhenFilter, HTMLButtonElement>>(new Map());\n\n const focusAt = useCallback((opt: WhenFilter) => {\n buttonRefs.current.get(opt)?.focus();\n }, []);\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLButtonElement>, current: WhenFilter) => {\n const idx = WHEN_OPTIONS.indexOf(current);\n const total = WHEN_OPTIONS.length;\n const forwardKey = isRTL ? 'ArrowLeft' : 'ArrowRight';\n const backwardKey = isRTL ? 'ArrowRight' : 'ArrowLeft';\n switch (event.key) {\n case forwardKey:\n case 'ArrowDown': {\n event.preventDefault();\n const next = WHEN_OPTIONS[(idx + 1) % total];\n onChange(next);\n track('patient_search_when_selected', { when: next });\n focusAt(next);\n break;\n }\n case backwardKey:\n case 'ArrowUp': {\n event.preventDefault();\n const next = WHEN_OPTIONS[(idx - 1 + total) % total];\n onChange(next);\n track('patient_search_when_selected', { when: next });\n focusAt(next);\n break;\n }\n case 'Home': {\n event.preventDefault();\n const next = WHEN_OPTIONS[0];\n onChange(next);\n track('patient_search_when_selected', { when: next });\n focusAt(next);\n break;\n }\n case 'End': {\n event.preventDefault();\n const next = WHEN_OPTIONS[total - 1];\n onChange(next);\n track('patient_search_when_selected', { when: next });\n focusAt(next);\n break;\n }\n default:\n break;\n }\n },\n [focusAt, isRTL, onChange],\n );\n\n // Roving tabindex — the selected option (or `anytime` fallback) is the only\n // tab stop. Matches the WAI-ARIA radiogroup pattern.\n const rovingOption: WhenFilter = value ?? 'anytime';\n\n const labelKeyFor: Record<WhenFilter, string> = {\n today: 'patientSearch.when.today',\n tomorrow: 'patientSearch.when.tomorrow',\n this_week: 'patientSearch.when.thisWeek',\n anytime: 'patientSearch.when.anytime',\n };\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={t('patientSearch.when.label')}\n id={groupId}\n className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {WHEN_OPTIONS.map((opt) => {\n const isSelected = value === opt;\n const isRoving = rovingOption === opt;\n const label = t(labelKeyFor[opt]);\n return (\n <button\n key={opt}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n aria-label={label}\n tabIndex={isRoving ? 0 : -1}\n ref={(node) => {\n if (node) buttonRefs.current.set(opt, node);\n else buttonRefs.current.delete(opt);\n }}\n onClick={() => {\n onChange(opt);\n track('patient_search_when_selected', { when: opt });\n }}\n onKeyDown={(e) => handleKeyDown(e, opt)}\n className={whenChipVariants({\n state: isSelected ? 'selected' : 'idle',\n })}\n >\n {label}\n </button>\n );\n })}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* FacetChipRow — faceted variant. One chip per FacetGroup. */\n/* -------------------------------------------------------------------- */\n\nconst facetChipVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:min-h-[var(--min-target-size)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:pt-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-full)]',\n 'type-label',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' '),\n {\n variants: {\n // Matches the WHEN chip strip's `selected` look — solid primary fill,\n // primary-foreground text, transparent border. The earlier\n // `color-mix(primary 12% / secondary)` tint read as a washed-out\n // colour over the grey input row and didn't visually signal \"this\n // filter is active\" with enough weight. Solid fill matches the kit's\n // toggle-button precedent (SuggestionChip's `suggestion` intent + the\n // ServiceGrid radio's selected state in Booking).\n state: {\n idle: 'ds:bg-[var(--secondary)] ds:text-[var(--foreground)] ds:border ds:border-[color:var(--border)] ds:hover:bg-[color-mix(in_srgb,var(--primary)_8%,var(--secondary))]',\n active:\n 'ds:bg-[var(--primary)] ds:text-[var(--primary-foreground)] ds:border ds:border-transparent ds:font-[var(--font-weight-semibold)]',\n },\n },\n defaultVariants: { state: 'idle' },\n },\n);\n\ninterface FacetChipRowProps {\n facets: FacetGroup[];\n value: SearchValue['facets'];\n onChange: (next: Record<string, string[]>) => void;\n}\n\nfunction FacetChipRow({ facets, value, onChange }: FacetChipRowProps) {\n const { t } = useTranslation('ui');\n // `selections` is memoised because `value ?? {}` allocates a fresh `{}`\n // whenever the consumer passes `undefined`, which would otherwise invalidate\n // every downstream useMemo / useCallback that depends on it.\n const selections = useMemo(() => value ?? {}, [value]);\n\n const hasAnyActive = useMemo(\n () => Object.values(selections).some((arr) => arr && arr.length > 0),\n [selections],\n );\n\n const updateFacet = (key: string, values: string[]) => {\n const next = { ...selections };\n if (values.length === 0) delete next[key];\n else next[key] = values;\n onChange(next);\n track('patient_search_facet_changed', { key, values });\n };\n\n const toggleBoolean = (key: string) => {\n const isActive = (selections[key]?.length ?? 0) > 0;\n updateFacet(key, isActive ? [] : ['true']);\n };\n\n const toggleOption = (group: FacetGroup, option: string) => {\n const current = selections[group.key] ?? [];\n const active = current.includes(option);\n let next: string[];\n if (group.multi) {\n next = active\n ? current.filter((v) => v !== option)\n : [...current, option];\n } else {\n next = active ? [] : [option];\n }\n updateFacet(group.key, next);\n };\n\n return (\n <div\n role=\"group\"\n aria-label={t('patientSearch.facets.label')}\n className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {facets.map((group) => {\n const isBoolean = group.options.length === 0;\n const current = selections[group.key] ?? [];\n const isActive = current.length > 0;\n\n if (isBoolean) {\n return (\n <button\n key={group.key}\n type=\"button\"\n aria-pressed={isActive}\n aria-label={group.label}\n onClick={() => toggleBoolean(group.key)}\n className={facetChipVariants({\n state: isActive ? 'active' : 'idle',\n })}\n >\n <span>{group.label}</span>\n </button>\n );\n }\n\n const countSuffix = isActive ? ` (${current.length})` : '';\n\n return (\n <DropdownMenu.Root key={group.key}>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n aria-label={`${group.label}${countSuffix}`}\n className={facetChipVariants({\n state: isActive ? 'active' : 'idle',\n })}\n >\n <span>\n {group.label}\n {countSuffix}\n </span>\n <ChevronDown\n aria-hidden=\"true\"\n className=\"ds:size-3.5 ds:shrink-0\"\n />\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content sideOffset={8} align=\"start\">\n {group.options.map((option) => (\n <DropdownMenu.CheckboxItem\n key={option.value}\n checked={current.includes(option.value)}\n onSelect={(event) => {\n // Keep the menu open for multi-select facets so the user\n // can tick multiple boxes without re-opening.\n if (group.multi) event.preventDefault();\n toggleOption(group, option.value);\n }}\n >\n {option.label}\n </DropdownMenu.CheckboxItem>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n })}\n {hasAnyActive ? (\n <button\n type=\"button\"\n onClick={() => {\n onChange({});\n track('patient_search_facet_changed', { key: '*', values: [] });\n }}\n className={[\n 'ds:ms-[var(--spacing-xs)] ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:min-h-[var(--min-target-size)] ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-xs)]',\n 'type-label ds:text-[color:var(--muted-foreground)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:hover:text-[color:var(--foreground)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n ].join(' ')}\n >\n <X aria-hidden=\"true\" className=\"ds:size-3.5\" />\n {t('patientSearch.facets.clear')}\n </button>\n ) : null}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* DiscoveryGrid — responsive grid of curated cards. */\n/* -------------------------------------------------------------------- */\n\nconst WHEEL_ACCENTS = ['violet', 'purple', 'magenta', 'blue'] as const;\ntype WheelAccent = (typeof WHEEL_ACCENTS)[number];\n\nconst discoveryCardVariants = cva(\n [\n 'ds:relative ds:flex ds:h-full ds:flex-col ds:gap-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-lg)] ds:overflow-hidden',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]',\n 'ds:bg-[var(--card)] ds:text-[var(--card-foreground)]',\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:shadow-[var(--shadow-sm)]',\n 'ds:transition-[transform,box-shadow] ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:motion-safe:hover:-translate-y-0.5',\n 'ds:hover:shadow-[var(--shadow-md)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:no-underline',\n ].join(' '),\n);\n\nconst accentStripVariants = cva(\n // `inset-x-0` compiles to logical `inset-inline`; the `inset-inline-0`\n // spelling is not a Tailwind utility and compiled to nothing.\n 'ds:absolute ds:inset-x-0 ds:top-0 ds:h-[3px] ds:pointer-events-none',\n {\n variants: {\n accent: {\n violet: 'ds:bg-[var(--color-violet-500)]',\n purple: 'ds:bg-[var(--color-purple-500)]',\n magenta: 'ds:bg-[var(--color-magenta-500)]',\n blue: 'ds:bg-[var(--color-blue-500)]',\n },\n },\n defaultVariants: { accent: 'violet' },\n },\n);\n\nconst iconChipVariants = cva(\n 'ds:inline-flex ds:size-9 ds:items-center ds:justify-center ds:rounded-[var(--radius-md)]',\n {\n variants: {\n accent: {\n violet:\n 'ds:bg-[color-mix(in_srgb,var(--color-violet-500)_12%,var(--background))] ds:text-[var(--color-violet-700)]',\n purple:\n 'ds:bg-[color-mix(in_srgb,var(--color-purple-500)_12%,var(--background))] ds:text-[var(--color-purple-700)]',\n magenta:\n 'ds:bg-[color-mix(in_srgb,var(--color-magenta-500)_12%,var(--background))] ds:text-[var(--color-magenta-700)]',\n blue: 'ds:bg-[color-mix(in_srgb,var(--color-blue-500)_12%,var(--background))] ds:text-[var(--color-blue-700)]',\n },\n },\n defaultVariants: { accent: 'violet' },\n },\n);\n\nfunction resolveAccent(\n cardAccent: DiscoveryCard['accent'] | undefined,\n index: number,\n): WheelAccent {\n if (cardAccent && cardAccent !== 'auto') return cardAccent;\n return WHEEL_ACCENTS[index % WHEEL_ACCENTS.length];\n}\n\ninterface DiscoveryGridProps {\n cards: DiscoveryCard[];\n headingLevel: 2 | 3 | 4;\n}\n\nfunction DiscoveryGrid({ cards, headingLevel }: DiscoveryGridProps) {\n const { t } = useTranslation('ui');\n const Heading = `h${headingLevel}` as const;\n const idBase = useId();\n\n if (cards.length === 0) {\n return (\n <p className=\"type-body-sm ds:text-[color:var(--muted-foreground)] ds:m-0\">\n {t('patientSearch.discovery.empty')}\n </p>\n );\n }\n\n return (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <Heading className=\"type-title-card ds:text-[var(--foreground)] ds:m-0\">\n {t('patientSearch.discovery.heading')}\n </Heading>\n <ul\n className={[\n 'ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)]',\n 'ds:md:grid-cols-2 ds:lg:grid-cols-3',\n 'ds:m-0 ds:p-0 ds:list-none',\n ].join(' ')}\n >\n {cards.map((card, index) => {\n const accent = resolveAccent(card.accent, index);\n const descriptionId = card.description\n ? `${idBase}-${card.id}-description`\n : undefined;\n return (\n <li key={card.id}>\n <a\n href={card.href}\n data-component=\"patient-search-card\"\n data-card-id={card.id}\n aria-label={card.label}\n aria-describedby={descriptionId}\n onClick={() =>\n track('patient_search_discovery_card_clicked', {\n cardId: card.id,\n })\n }\n className={discoveryCardVariants()}\n >\n <span\n aria-hidden=\"true\"\n className={accentStripVariants({ accent })}\n />\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span\n aria-hidden=\"true\"\n className={iconChipVariants({ accent })}\n >\n {card.icon ?? (\n <Stethoscope className=\"ds:size-4\" aria-hidden=\"true\" />\n )}\n </span>\n {card.badge ? (\n // The badge sits inside a softly-tinted accent bubble\n // (15% accent + 85% background). The text colour must\n // contrast with that mix, not with the accent's canonical\n // foreground — `--accent-foreground` is calibrated against\n // the 100% accent surface and fails AA on the 15% tint.\n // Use `--foreground` which contrasts with the\n // mostly-background mix in both light and dark themes.\n <span className=\"type-meta ds:ms-auto ds:inline-flex ds:items-center ds:rounded-[var(--radius-full)] ds:border ds:border-[color:var(--foreground)] ds:bg-[color-mix(in_srgb,var(--accent)_15%,var(--background))] ds:text-[color:var(--foreground)] ds:font-[var(--font-weight-semibold)] ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:pt-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]\">\n {card.badge}\n </span>\n ) : null}\n </span>\n <span className=\"type-label ds:font-[var(--font-weight-semibold)] ds:text-[var(--foreground)]\">\n {card.label}\n </span>\n {card.description ? (\n <span\n id={descriptionId}\n className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\"\n >\n {card.description}\n </span>\n ) : null}\n </a>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* SubmitButton — shared CTA. Disabled only when every dimension is unset. */\n/* -------------------------------------------------------------------- */\n\ninterface SubmitButtonProps {\n value: SearchValue;\n variant: PatientSearchVariant;\n submitting?: boolean;\n submitLabel?: string;\n allowEmptySubmit?: boolean;\n onSubmit: (value: SearchValue) => void | Promise<void>;\n}\n\nfunction hasAnyDimension(value: SearchValue): boolean {\n if (value.object) return true;\n if (value.place) return true;\n if (value.geo) return true;\n if (value.when && value.when !== 'anytime') return true;\n if (value.facets) {\n for (const arr of Object.values(value.facets)) {\n if (arr && arr.length > 0) return true;\n }\n }\n return false;\n}\n\nfunction SubmitButton({\n value,\n variant,\n submitting,\n submitLabel,\n allowEmptySubmit,\n onSubmit,\n}: SubmitButtonProps) {\n const { t } = useTranslation('ui');\n // While submitting, `loading` blocks it and keeps focus on it.\n const disabled = !submitting && !allowEmptySubmit && !hasAnyDimension(value);\n const label = submitLabel ?? t('patientSearch.submit.cta');\n return (\n <Button\n type=\"button\"\n intent=\"primary\"\n size=\"lg\"\n startIcon={<SearchIcon aria-hidden=\"true\" />}\n loading={submitting}\n disabled={disabled}\n onClick={() => {\n track('patient_search_submitted', {\n variant,\n hasObject: Boolean(value.object),\n hasPlace: Boolean(value.place),\n hasGeo: Boolean(value.geo),\n when: value.when,\n facetKeys: value.facets ? Object.keys(value.facets) : [],\n });\n void onSubmit(value);\n }}\n >\n {label}\n </Button>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Variant body props */\n/* -------------------------------------------------------------------- */\n\ninterface VariantBodyProps {\n variant: PatientSearchVariant;\n value: SearchValue;\n onChange: (next: SearchValue) => void;\n onSubmit: PatientSearchProps['onSubmit'];\n loadObjects: PatientSearchProps['loadObjects'];\n loadPlaces: PatientSearchProps['loadPlaces'];\n onObjectSelect?: PatientSearchProps['onObjectSelect'];\n onPlaceSelect?: PatientSearchProps['onPlaceSelect'];\n allowTypedPlace?: boolean;\n facets?: FacetGroup[];\n defaultRadiusKm: number;\n reverseGeocode?: PatientSearchProps['reverseGeocode'];\n geoHint?: PatientSearchProps['geoHint'];\n discoveryCards: DiscoveryCard[];\n discoveryHeadingLevel: 2 | 3 | 4;\n submitting?: boolean;\n submitLabel?: string;\n allowEmptySubmit?: boolean;\n whoRef: React.RefObject<HTMLInputElement | null>;\n whereRef: React.RefObject<HTMLInputElement | null>;\n /** WHO and WHERE draft text, kept in `PatientSearch` across variants. */\n whoQuery: string;\n onWhoQueryChange: (next: string) => void;\n whereQuery: string;\n onWhereQueryChange: (next: string) => void;\n /**\n * Accessible name applied to the inner `<Card>` so its underlying\n * `<article>` landmark isn't unnamed when nested inside the\n * `role=\"region\"` root. Without this every variant produces an\n * unnamed article — a `landmark-unique` axe hazard once a consumer\n * page renders adjacent articles. Resolved once at the root with\n * `t('patientSearch.regionLabel')` and threaded through so the\n * variant bodies don't each have to call `useTranslation('ui')`.\n */\n cardLabel: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* WhoWhereBody — baseline variant. WHO + WHERE + submit. */\n/* -------------------------------------------------------------------- */\n\nfunction WhoWhereBody(props: VariantBodyProps) {\n const {\n variant,\n value,\n onChange,\n onSubmit,\n loadObjects,\n loadPlaces,\n onObjectSelect,\n onPlaceSelect,\n allowTypedPlace,\n submitting,\n submitLabel,\n allowEmptySubmit,\n whoRef,\n whereRef,\n whoQuery,\n onWhoQueryChange,\n whereQuery,\n onWhereQueryChange,\n defaultRadiusKm,\n reverseGeocode,\n geoHint,\n cardLabel,\n } = props;\n return (\n <Card variant=\"elevated\" aria-label={cardLabel}>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:md:flex-row ds:md:items-start\">\n <div className=\"ds:flex-1 ds:min-w-0\">\n <WhoField\n value={value}\n onChange={onChange}\n loadObjects={loadObjects}\n onObjectSelect={onObjectSelect}\n inputRef={whoRef}\n query={whoQuery}\n onQueryChange={onWhoQueryChange}\n />\n </div>\n <div className=\"ds:flex-1 ds:min-w-0\">\n <WhereField\n value={value}\n onChange={onChange}\n loadPlaces={loadPlaces}\n onPlaceSelect={onPlaceSelect}\n allowTypedPlace={allowTypedPlace}\n defaultRadiusKm={defaultRadiusKm}\n reverseGeocode={reverseGeocode}\n geoHint={geoHint}\n inputRef={whereRef}\n query={whereQuery}\n onQueryChange={onWhereQueryChange}\n />\n </div>\n <SubmitButton\n value={value}\n variant={variant}\n submitting={submitting}\n submitLabel={submitLabel}\n allowEmptySubmit={allowEmptySubmit}\n onSubmit={onSubmit}\n />\n </div>\n <GeoRadiusBar\n value={value}\n onChange={onChange}\n defaultRadiusKm={defaultRadiusKm}\n />\n </div>\n </Card>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* WhoWhereWhenBody — WHO + WHERE + submit + WHEN chip strip below. */\n/* -------------------------------------------------------------------- */\n\nfunction WhoWhereWhenBody(props: VariantBodyProps) {\n const {\n variant,\n value,\n onChange,\n onSubmit,\n loadObjects,\n loadPlaces,\n onObjectSelect,\n onPlaceSelect,\n allowTypedPlace,\n submitting,\n submitLabel,\n allowEmptySubmit,\n whoRef,\n whereRef,\n whoQuery,\n onWhoQueryChange,\n whereQuery,\n onWhereQueryChange,\n defaultRadiusKm,\n reverseGeocode,\n geoHint,\n cardLabel,\n } = props;\n return (\n <Card variant=\"elevated\" aria-label={cardLabel}>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:p-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:md:flex-row ds:md:items-start\">\n <div className=\"ds:flex-1 ds:min-w-0\">\n <WhoField\n value={value}\n onChange={onChange}\n loadObjects={loadObjects}\n onObjectSelect={onObjectSelect}\n inputRef={whoRef}\n query={whoQuery}\n onQueryChange={onWhoQueryChange}\n />\n </div>\n <div className=\"ds:flex-1 ds:min-w-0\">\n <WhereField\n value={value}\n onChange={onChange}\n loadPlaces={loadPlaces}\n onPlaceSelect={onPlaceSelect}\n allowTypedPlace={allowTypedPlace}\n defaultRadiusKm={defaultRadiusKm}\n reverseGeocode={reverseGeocode}\n geoHint={geoHint}\n inputRef={whereRef}\n query={whereQuery}\n onQueryChange={onWhereQueryChange}\n />\n </div>\n <SubmitButton\n value={value}\n variant={variant}\n submitting={submitting}\n submitLabel={submitLabel}\n allowEmptySubmit={allowEmptySubmit}\n onSubmit={onSubmit}\n />\n </div>\n <GeoRadiusBar\n value={value}\n onChange={onChange}\n defaultRadiusKm={defaultRadiusKm}\n />\n <WhenChipStrip\n value={value.when}\n onChange={(next) => onChange({ ...value, when: next })}\n />\n </div>\n </Card>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* FacetedBody — WHO + WHERE + submit + facet chip row below. */\n/* -------------------------------------------------------------------- */\n\nfunction FacetedBody(props: VariantBodyProps) {\n const {\n variant,\n value,\n onChange,\n onSubmit,\n loadObjects,\n loadPlaces,\n onObjectSelect,\n onPlaceSelect,\n allowTypedPlace,\n facets,\n submitting,\n submitLabel,\n allowEmptySubmit,\n whoRef,\n whereRef,\n whoQuery,\n onWhoQueryChange,\n whereQuery,\n onWhereQueryChange,\n defaultRadiusKm,\n reverseGeocode,\n geoHint,\n cardLabel,\n } = props;\n return (\n <Card variant=\"elevated\" aria-label={cardLabel}>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:p-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:md:flex-row ds:md:items-start\">\n <div className=\"ds:flex-1 ds:min-w-0\">\n <WhoField\n value={value}\n onChange={onChange}\n loadObjects={loadObjects}\n onObjectSelect={onObjectSelect}\n inputRef={whoRef}\n query={whoQuery}\n onQueryChange={onWhoQueryChange}\n />\n </div>\n <div className=\"ds:flex-1 ds:min-w-0\">\n <WhereField\n value={value}\n onChange={onChange}\n loadPlaces={loadPlaces}\n onPlaceSelect={onPlaceSelect}\n allowTypedPlace={allowTypedPlace}\n defaultRadiusKm={defaultRadiusKm}\n reverseGeocode={reverseGeocode}\n geoHint={geoHint}\n inputRef={whereRef}\n query={whereQuery}\n onQueryChange={onWhereQueryChange}\n />\n </div>\n <SubmitButton\n value={value}\n variant={variant}\n submitting={submitting}\n submitLabel={submitLabel}\n allowEmptySubmit={allowEmptySubmit}\n onSubmit={onSubmit}\n />\n </div>\n <GeoRadiusBar\n value={value}\n onChange={onChange}\n defaultRadiusKm={defaultRadiusKm}\n />\n {facets && facets.length > 0 ? (\n <FacetChipRow\n facets={facets}\n value={value.facets}\n onChange={(next) => onChange({ ...value, facets: next })}\n />\n ) : null}\n </div>\n </Card>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* DiscoveryBody — hero search + card grid. */\n/* -------------------------------------------------------------------- */\n\nfunction DiscoveryBody(props: VariantBodyProps) {\n const {\n variant,\n value,\n onChange,\n onSubmit,\n loadObjects,\n loadPlaces,\n onObjectSelect,\n onPlaceSelect,\n allowTypedPlace,\n discoveryCards,\n discoveryHeadingLevel,\n submitting,\n submitLabel,\n allowEmptySubmit,\n whoRef,\n whereRef,\n whoQuery,\n onWhoQueryChange,\n whereQuery,\n onWhereQueryChange,\n defaultRadiusKm,\n reverseGeocode,\n geoHint,\n cardLabel,\n } = props;\n return (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <Card variant=\"elevated\" aria-label={cardLabel}>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-md)] ds:md:flex-row ds:md:items-stretch\">\n <div className=\"ds:flex-1 ds:min-w-0\">\n <WhoField\n value={value}\n onChange={onChange}\n loadObjects={loadObjects}\n onObjectSelect={onObjectSelect}\n inputRef={whoRef}\n query={whoQuery}\n onQueryChange={onWhoQueryChange}\n />\n </div>\n <div className=\"ds:flex-1 ds:min-w-0\">\n <WhereField\n value={value}\n onChange={onChange}\n loadPlaces={loadPlaces}\n onPlaceSelect={onPlaceSelect}\n allowTypedPlace={allowTypedPlace}\n defaultRadiusKm={defaultRadiusKm}\n reverseGeocode={reverseGeocode}\n geoHint={geoHint}\n inputRef={whereRef}\n query={whereQuery}\n onQueryChange={onWhereQueryChange}\n />\n </div>\n <SubmitButton\n value={value}\n variant={variant}\n submitting={submitting}\n submitLabel={submitLabel}\n allowEmptySubmit={allowEmptySubmit}\n onSubmit={onSubmit}\n />\n </div>\n <GeoRadiusBar\n value={value}\n onChange={onChange}\n defaultRadiusKm={defaultRadiusKm}\n />\n </Card>\n <DiscoveryGrid\n cards={discoveryCards}\n headingLevel={discoveryHeadingLevel}\n />\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* PatientSearch */\n/* -------------------------------------------------------------------- */\n\nexport const PatientSearch = forwardRef<\n PatientSearchHandle,\n PatientSearchProps\n>(function PatientSearch(\n {\n variant,\n loadObjects,\n loadPlaces,\n onObjectSelect,\n onPlaceSelect,\n allowTypedPlace = false,\n facets,\n defaultRadiusKm = DEFAULT_RADIUS_KM,\n reverseGeocode,\n geoHint,\n discoveryCards,\n discoveryHeadingLevel = 3,\n countryCode,\n value,\n onChange,\n onSubmit,\n submitting,\n submitLabel,\n allowEmptySubmit,\n 'aria-label': ariaLabel,\n id,\n className,\n ...rest\n },\n ref,\n) {\n const { t } = useTranslation('ui');\n\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Primary-field refs — `focusPrimary` jumps to whichever input the variant\n // emphasises (WHO in most variants; no auto-focus on `discovery`).\n const whoRef = useRef<HTMLInputElement>(null);\n const whereRef = useRef<HTMLInputElement>(null);\n\n // WHO / WHERE draft text. Held here, above the variant switch, because a\n // `variant` change swaps the layout component and remounts both fields; the\n // fields reset it only when the consumer changes the selection (their own\n // sync effects), not when the layout changes.\n const [whoQuery, setWhoQuery] = useState<string>(value.object?.label ?? '');\n const [whereQuery, setWhereQuery] = useState<string>(\n value.place?.label ?? '',\n );\n\n // Which field the patient is typing in, and where the caret is. A `variant`\n // change removes the focused input from the page, so by the time any effect\n // runs the browser has already dropped focus and the caret. We record them\n // while they still exist and put them back on the new input.\n const focusedRef = useRef<{\n field: FieldName;\n start: number | null;\n end: number | null;\n } | null>(null);\n const focusTrackedRefs = useRef<Record<FieldName, MutableRefObject<boolean>>>(\n { who: { current: false }, where: { current: false } },\n );\n\n const recordFocus = (target: EventTarget | null) => {\n const field: FieldName | null =\n target === whoRef.current\n ? 'who'\n : target === whereRef.current\n ? 'where'\n : null;\n if (!field) {\n focusedRef.current = null;\n return;\n }\n const input = target as HTMLInputElement;\n focusedRef.current = {\n field,\n start: input.selectionStart,\n end: input.selectionEnd,\n };\n };\n\n const forgetFocus = (target: EventTarget, relatedTarget: Node | null) => {\n if (relatedTarget && rootRef.current?.contains(relatedTarget)) return;\n // Some browsers also send a blur when the focused input is removed by a\n // layout change; that is not the patient leaving. A removed input is no\n // longer in the document once the event has settled, so only a node that\n // is still there counts as a real blur.\n setTimeout(() => {\n if ((target as Node).isConnected) focusedRef.current = null;\n }, 0);\n };\n\n // After a restore, the new inputs can pull focus off each other for a moment:\n // the suggestion list (cmdk) focuses its own input when it mounts with text\n // in it. For a short window, and until the patient presses or clicks\n // something, focus is put back on the field we restored.\n const guardRef = useRef<{\n field: FieldName;\n start: number | null;\n end: number | null;\n until: number;\n } | null>(null);\n\n const focusField = (\n field: FieldName,\n start: number | null,\n end: number | null,\n ) => {\n const input = (field === 'who' ? whoRef : whereRef).current;\n if (!input) return;\n input.focus();\n const length = input.value.length;\n input.setSelectionRange(\n Math.min(start ?? length, length),\n Math.min(end ?? length, length),\n );\n };\n\n // Native listeners on the root: the root is a landmark, not a control, so it\n // takes no React event props. `focusin` / `focusout` bubble, like React's.\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n const onFocusIn = (e: Event) => {\n const guard = guardRef.current;\n if (guard && performance.now() < guard.until) {\n const stolen =\n (e.target === whoRef.current && guard.field === 'where') ||\n (e.target === whereRef.current && guard.field === 'who');\n if (stolen) {\n focusField(guard.field, guard.start, guard.end);\n return;\n }\n }\n recordFocus(e.target);\n };\n const onRecord = (e: Event) => recordFocus(e.target);\n const onUser = () => {\n guardRef.current = null;\n };\n const onLeave = (e: FocusEvent) =>\n forgetFocus(e.target as EventTarget, e.relatedTarget as Node | null);\n const events = ['select', 'keyup', 'input'] as const;\n root.addEventListener('focusin', onFocusIn);\n events.forEach((name) => root.addEventListener(name, onRecord));\n root.addEventListener('pointerdown', onUser);\n root.addEventListener('keydown', onUser);\n root.addEventListener('focusout', onLeave);\n return () => {\n root.removeEventListener('focusin', onFocusIn);\n events.forEach((name) => root.removeEventListener(name, onRecord));\n root.removeEventListener('pointerdown', onUser);\n root.removeEventListener('keydown', onUser);\n root.removeEventListener('focusout', onLeave);\n };\n // The handlers only read refs, so they are stable for the life of the root.\n }, []);\n\n const previousVariantRef = useRef(variant);\n useLayoutEffect(() => {\n if (previousVariantRef.current === variant) return;\n previousVariantRef.current = variant;\n const last = focusedRef.current;\n if (!last) return;\n // Only put focus back if nothing else has taken it.\n const active = document.activeElement;\n if (active && active !== document.body) return;\n guardRef.current = { ...last, until: performance.now() + 500 };\n focusField(last.field, last.start, last.end);\n }, [variant]);\n\n // Apply `when: anytime` default once on mount, but only for the variant\n // that actually renders the WHEN chip strip (`who-where-when`). The\n // `faceted` variant exposes facets, not WHEN — seeding `when: 'anytime'`\n // for it would silently pollute the consumer's value with a field the\n // form never displays.\n const seededWhenRef = useRef(false);\n useEffect(() => {\n if (seededWhenRef.current) return;\n if (variant !== 'who-where-when') return;\n if (value.when !== undefined) {\n seededWhenRef.current = true;\n return;\n }\n seededWhenRef.current = true;\n onChange({ ...value, when: 'anytime' });\n // We intentionally seed only on first render — the consumer can clear\n // back to `undefined` if they want, and we won't re-seed.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [variant]);\n\n // Apply `facets: {}` default once on mount for the faceted variant so\n // the chip row treats undefined and empty consistently.\n const seededFacetsRef = useRef(false);\n useEffect(() => {\n if (seededFacetsRef.current) return;\n if (variant !== 'faceted') return;\n if (value.facets !== undefined) {\n seededFacetsRef.current = true;\n return;\n }\n seededFacetsRef.current = true;\n onChange({ ...value, facets: {} });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [variant]);\n\n // Exposure event — fired once per variant assignment so PostHog can\n // record A/B assignment even for users who bounce before submitting.\n const exposedRef = useRef<PatientSearchVariant | null>(null);\n useEffect(() => {\n if (exposedRef.current === variant) return;\n exposedRef.current = variant;\n track('patient_search_variant_exposed', { variant, country: countryCode });\n }, [variant, countryCode]);\n\n // Imperative handle — minimal surface (`getVariant`, `reset`,\n // `focusPrimary`). The `value` reset goes through the consumer-owned\n // `onChange` so the parent's state stays the source of truth.\n //\n // The same handle is surfaced two ways: through the React `ref` (for\n // consumers driving the kit directly) and through `useAgentRegistration`\n // (for the future agent / MCP runtime). Both reach the same object so a\n // direct `ref.current?.reset()` and an `agentRegistry.invoke('reset')`\n // do the same thing.\n const handle = useMemo<PatientSearchHandle>(\n () => ({\n getVariant: () => variant,\n reset: () => {\n onChange({});\n },\n focusPrimary: () => {\n // Discovery deliberately doesn't auto-focus the search field on\n // mount; agents hitting `focus_primary` still get pulled into WHO\n // since that's the natural starting point for any keyboard-driven\n // flow once the user opts in.\n requestAnimationFrame(() => {\n whoRef.current?.focus();\n });\n },\n }),\n [variant, onChange],\n );\n useImperativeHandle(ref, () => handle, [handle]);\n useAgentRegistration(patientSearchAgent, handle, id);\n\n const resolvedAriaLabel = ariaLabel ?? t('patientSearch.regionLabel');\n\n const bodyProps: VariantBodyProps = {\n variant,\n value,\n onChange,\n onSubmit,\n loadObjects,\n loadPlaces,\n onObjectSelect,\n onPlaceSelect,\n allowTypedPlace,\n facets,\n defaultRadiusKm,\n reverseGeocode,\n geoHint,\n discoveryCards: discoveryCards ?? [],\n discoveryHeadingLevel,\n submitting,\n submitLabel,\n allowEmptySubmit,\n whoRef,\n whereRef,\n whoQuery,\n onWhoQueryChange: setWhoQuery,\n whereQuery,\n onWhereQueryChange: setWhereQuery,\n cardLabel: resolvedAriaLabel,\n };\n\n const body = (() => {\n switch (variant) {\n case 'who-where':\n return <WhoWhereBody {...bodyProps} />;\n case 'who-where-when':\n return <WhoWhereWhenBody {...bodyProps} />;\n case 'faceted':\n return <FacetedBody {...bodyProps} />;\n case 'discovery':\n return <DiscoveryBody {...bodyProps} />;\n /* c8 ignore next 2 */\n default:\n return null;\n }\n })();\n\n return (\n <FocusTrackedContext.Provider value={focusTrackedRefs.current}>\n <div\n ref={rootRef}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n id={id}\n data-component=\"patient-search\"\n data-component-id={id}\n data-variant={variant}\n className={rootVariants({ variant, className })}\n {...rest}\n >\n {body}\n </div>\n </FocusTrackedContext.Provider>\n );\n});\n\nPatientSearch.displayName = 'PatientSearch';\n"],"names":["__iconNode","LocateFixed","createLucideIcon","patientSearchAgent","handle","track","event","payload","fn","WHEN_OPTIONS","RADIUS_PRESETS","DEFAULT_RADIUS_KM","AUTOCOMPLETE_DEBOUNCE_MS","radiusToStepIndex","km","best","bestDelta","preset","index","delta","rootVariants","cva","FocusTrackedContext","createContext","useFocusTracked","field","shared","useContext","local","useRef","WhoField","value","onChange","loadObjects","onObjectSelect","inputRef","query","setQuery","t","useTranslation","selectedValueRef","_a","useEffect","_b","_c","loadOptions","useCallback","q","signal","handleSelect","option","next","focusTrackedRef","jsx","e","Autocomplete","SearchIcon","geoTriggerClasses","WhereField","loadPlaces","onPlaceSelect","allowTypedPlace","defaultRadiusKm","reverseGeocode","geoHint","initialStatus","status","setStatus","useState","place","denyLocation","reason","toastError","requestLocation","position","latitude","longitude","label","resolvedLabel","syntheticPlace","clearGeo","isGranted","isRequesting","geoEnabled","overlay","jsxs","X","typed","MapPin","GeoRadiusBar","radiusIndex","setRadiusIndex","commitRadius","formatRadius","n","Slider","whenChipVariants","WhenChipStrip","i18n","groupId","useId","isRTL","buttonRefs","focusAt","opt","handleKeyDown","current","idx","total","forwardKey","backwardKey","rovingOption","labelKeyFor","isSelected","isRoving","node","facetChipVariants","FacetChipRow","facets","selections","useMemo","hasAnyActive","arr","updateFacet","key","values","toggleBoolean","isActive","toggleOption","group","active","v","isBoolean","countSuffix","DropdownMenu","ChevronDown","WHEEL_ACCENTS","discoveryCardVariants","accentStripVariants","iconChipVariants","resolveAccent","cardAccent","DiscoveryGrid","cards","headingLevel","Heading","idBase","card","accent","descriptionId","Stethoscope","hasAnyDimension","SubmitButton","variant","submitting","submitLabel","allowEmptySubmit","onSubmit","disabled","Button","WhoWhereBody","props","whoRef","whereRef","whoQuery","onWhoQueryChange","whereQuery","onWhereQueryChange","cardLabel","Card","WhoWhereWhenBody","FacetedBody","DiscoveryBody","discoveryCards","discoveryHeadingLevel","PatientSearch","forwardRef","countryCode","ariaLabel","id","className","rest","ref","rootRef","setWhoQuery","setWhereQuery","focusedRef","focusTrackedRefs","recordFocus","target","input","forgetFocus","relatedTarget","guardRef","focusField","start","end","length","root","onFocusIn","guard","onRecord","onUser","onLeave","events","name","previousVariantRef","useLayoutEffect","last","seededWhenRef","seededFacetsRef","exposedRef","useImperativeHandle","useAgentRegistration","resolvedAriaLabel","bodyProps","body"],"mappings":"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","x_google_ignoreList":[0]}
|