@alfadocs/ui-kit-debug 1.113.0 → 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.
Files changed (308) hide show
  1. package/dist/_chunks/{anamnesis-card-BzuluoD1.js → anamnesis-card-Ddnrdfx3.js} +2 -2
  2. package/dist/_chunks/{anamnesis-card-BzuluoD1.js.map → anamnesis-card-Ddnrdfx3.js.map} +1 -1
  3. package/dist/_chunks/{anamnesis-summary-card-DdTRdNrQ.js → anamnesis-summary-card-S1H_AARG.js} +2 -2
  4. package/dist/_chunks/{anamnesis-summary-card-DdTRdNrQ.js.map → anamnesis-summary-card-S1H_AARG.js.map} +1 -1
  5. package/dist/_chunks/{anamnesis-summary-rows-DfDulR_c.js → anamnesis-summary-rows-DaS-j8Jd.js} +2 -2
  6. package/dist/_chunks/{anamnesis-summary-rows-DfDulR_c.js.map → anamnesis-summary-rows-DaS-j8Jd.js.map} +1 -1
  7. package/dist/_chunks/{antenatal-schedule-timeline-DmsY5g28.js → antenatal-schedule-timeline-DmlXxevC.js} +2 -2
  8. package/dist/_chunks/{antenatal-schedule-timeline-DmsY5g28.js.map → antenatal-schedule-timeline-DmlXxevC.js.map} +1 -1
  9. package/dist/_chunks/{bishop-score-CnIft4eV.js → bishop-score-QJu-sM1y.js} +2 -2
  10. package/dist/_chunks/{bishop-score-CnIft4eV.js.map → bishop-score-QJu-sM1y.js.map} +1 -1
  11. package/dist/_chunks/{bmi-calculator-NMkXc079.js → bmi-calculator-Ba4yoR31.js} +2 -2
  12. package/dist/_chunks/{bmi-calculator-NMkXc079.js.map → bmi-calculator-Ba4yoR31.js.map} +1 -1
  13. package/dist/_chunks/{calendar-appointment-editor-dialog-CaZm5wGR.js → calendar-appointment-editor-dialog-iyh9QqNw.js} +6 -6
  14. package/dist/_chunks/{calendar-appointment-editor-dialog-CaZm5wGR.js.map → calendar-appointment-editor-dialog-iyh9QqNw.js.map} +1 -1
  15. package/dist/_chunks/{card-C85_Ndhb.js → card-DVO3x8E-.js} +23 -19
  16. package/dist/_chunks/{card-C85_Ndhb.js.map → card-DVO3x8E-.js.map} +1 -1
  17. package/dist/_chunks/{clinical-note-card-BVkxGiGl.js → clinical-note-card-Zz5_GEz-.js} +2 -2
  18. package/dist/_chunks/{clinical-note-card-BVkxGiGl.js.map → clinical-note-card-Zz5_GEz-.js.map} +1 -1
  19. package/dist/_chunks/{connection-status-CWSU3eiq.js → connection-status-DjarASoU.js} +2 -2
  20. package/dist/_chunks/{connection-status-CWSU3eiq.js.map → connection-status-DjarASoU.js.map} +1 -1
  21. package/dist/_chunks/{contact-card-CymtNvy3.js → contact-card-Cv-Nwvac.js} +2 -2
  22. package/dist/_chunks/{contact-card-CymtNvy3.js.map → contact-card-Cv-Nwvac.js.map} +1 -1
  23. package/dist/_chunks/{contact-profile-card-CAL66GaH.js → contact-profile-card-DMXWBBkU.js} +2 -2
  24. package/dist/_chunks/{contact-profile-card-CAL66GaH.js.map → contact-profile-card-DMXWBBkU.js.map} +1 -1
  25. package/dist/_chunks/{cycle-calculator-ZMDvToIm.js → cycle-calculator-Dd-XbKmZ.js} +2 -2
  26. package/dist/_chunks/{cycle-calculator-ZMDvToIm.js.map → cycle-calculator-Dd-XbKmZ.js.map} +1 -1
  27. package/dist/_chunks/{document-preview-5xs64jME.js → document-preview-WvJKHJOP.js} +2 -2
  28. package/dist/_chunks/{document-preview-5xs64jME.js.map → document-preview-WvJKHJOP.js.map} +1 -1
  29. package/dist/_chunks/{due-date-calculator-Dr2cDa64.js → due-date-calculator-Dl6SyMHO.js} +3 -3
  30. package/dist/_chunks/{due-date-calculator-Dr2cDa64.js.map → due-date-calculator-Dl6SyMHO.js.map} +1 -1
  31. package/dist/_chunks/{entity-summary-BbqqYqF1.js → entity-summary-DGCBQDt1.js} +2 -2
  32. package/dist/_chunks/{entity-summary-BbqqYqF1.js.map → entity-summary-DGCBQDt1.js.map} +1 -1
  33. package/dist/_chunks/{face-scheme-e2M2HJGz.js → face-scheme-DlcQaQVR.js} +2 -2
  34. package/dist/_chunks/{face-scheme-e2M2HJGz.js.map → face-scheme-DlcQaQVR.js.map} +1 -1
  35. package/dist/_chunks/{fetal-weight-CkIwJgiH.js → fetal-weight-DmZzMRzB.js} +2 -2
  36. package/dist/_chunks/{fetal-weight-CkIwJgiH.js.map → fetal-weight-DmZzMRzB.js.map} +1 -1
  37. package/dist/_chunks/{finished-terminal-DXVAfhRr.js → finished-terminal-BKTFUk3S.js} +2 -2
  38. package/dist/_chunks/{finished-terminal-DXVAfhRr.js.map → finished-terminal-BKTFUk3S.js.map} +1 -1
  39. package/dist/_chunks/{forgot-password-form-YQVzSskq.js → forgot-password-form-Bc_UPax6.js} +2 -2
  40. package/dist/_chunks/{forgot-password-form-YQVzSskq.js.map → forgot-password-form-Bc_UPax6.js.map} +1 -1
  41. package/dist/_chunks/{gestational-age-calculator-Dv3IePb-.js → gestational-age-calculator-DmzYdW5e.js} +3 -3
  42. package/dist/_chunks/{gestational-age-calculator-Dv3IePb-.js.map → gestational-age-calculator-DmzYdW5e.js.map} +1 -1
  43. package/dist/_chunks/{hcg-doubling-DdyUt4gz.js → hcg-doubling-Tr72PetS.js} +2 -2
  44. package/dist/_chunks/{hcg-doubling-DdyUt4gz.js.map → hcg-doubling-Tr72PetS.js.map} +1 -1
  45. package/dist/_chunks/{heatmap-BiwC7Gdx.js → heatmap-CNxCDl0D.js} +2 -2
  46. package/dist/_chunks/{heatmap-BiwC7Gdx.js.map → heatmap-CNxCDl0D.js.map} +1 -1
  47. package/dist/_chunks/{kit-extensions-BOsUgWnE.js → kit-extensions-DZJRmDI6.js} +7 -7
  48. package/dist/_chunks/{kit-extensions-BOsUgWnE.js.map → kit-extensions-DZJRmDI6.js.map} +1 -1
  49. package/dist/_chunks/{login-dev-card-B6-zCFq3.js → login-dev-card-D7orCfJT.js} +2 -2
  50. package/dist/_chunks/{login-dev-card-B6-zCFq3.js.map → login-dev-card-D7orCfJT.js.map} +1 -1
  51. package/dist/_chunks/map-view-Bny79cWa.js +856 -0
  52. package/dist/_chunks/map-view-Bny79cWa.js.map +1 -0
  53. package/dist/_chunks/{marketplace-app-shell-C-4QF6mp.js → marketplace-app-shell-CPNVBVLH.js} +2 -2
  54. package/dist/_chunks/{marketplace-app-shell-C-4QF6mp.js.map → marketplace-app-shell-CPNVBVLH.js.map} +1 -1
  55. package/dist/_chunks/motion-is-off-BvAuNV5O.js +15 -0
  56. package/dist/_chunks/motion-is-off-BvAuNV5O.js.map +1 -0
  57. package/dist/_chunks/{notes-panel-Cz621DWV.js → notes-panel-DXMTObBv.js} +3 -3
  58. package/dist/_chunks/{notes-panel-Cz621DWV.js.map → notes-panel-DXMTObBv.js.map} +1 -1
  59. package/dist/_chunks/{operator-hero-BELhrv9o.js → operator-hero-BWayX73x.js} +71 -62
  60. package/dist/_chunks/{operator-hero-BELhrv9o.js.map → operator-hero-BWayX73x.js.map} +1 -1
  61. package/dist/_chunks/{patient-details-RsT3SaYh.js → patient-details-DdtXBNjt.js} +2 -2
  62. package/dist/_chunks/{patient-details-RsT3SaYh.js.map → patient-details-DdtXBNjt.js.map} +1 -1
  63. package/dist/_chunks/{patient-search-CxuqVUTB.js → patient-search-DDRDCjZi.js} +439 -482
  64. package/dist/_chunks/patient-search-DDRDCjZi.js.map +1 -0
  65. package/dist/_chunks/{patient-summary-card-BjZErlbt.js → patient-summary-card-CGHz-Bvm.js} +2 -2
  66. package/dist/_chunks/{patient-summary-card-BjZErlbt.js.map → patient-summary-card-CGHz-Bvm.js.map} +1 -1
  67. package/dist/_chunks/{payment-automation-upsell-u5EuFyCY.js → payment-automation-upsell-D7yaD4u1.js} +3 -3
  68. package/dist/_chunks/{payment-automation-upsell-u5EuFyCY.js.map → payment-automation-upsell-D7yaD4u1.js.map} +1 -1
  69. package/dist/_chunks/{payment-request-card-IR83TJax.js → payment-request-card-BmV2pLoM.js} +2 -2
  70. package/dist/_chunks/{payment-request-card-IR83TJax.js.map → payment-request-card-BmV2pLoM.js.map} +1 -1
  71. package/dist/_chunks/{periodontal-chart-DqdUEFxK.js → periodontal-chart-Bjz7O4wT.js} +2 -2
  72. package/dist/_chunks/{periodontal-chart-DqdUEFxK.js.map → periodontal-chart-Bjz7O4wT.js.map} +1 -1
  73. package/dist/_chunks/{periodontal-chart-card-CCkzStlm.js → periodontal-chart-card-CxEXHl2x.js} +2 -2
  74. package/dist/_chunks/{periodontal-chart-card-CCkzStlm.js.map → periodontal-chart-card-CxEXHl2x.js.map} +1 -1
  75. package/dist/_chunks/{periodontal-diagnosis-CF1d_0yl.js → periodontal-diagnosis-xheWfi4g.js} +2 -2
  76. package/dist/_chunks/{periodontal-diagnosis-CF1d_0yl.js.map → periodontal-diagnosis-xheWfi4g.js.map} +1 -1
  77. package/dist/_chunks/{periodontal-risk-chart-D2zyID0H.js → periodontal-risk-chart-BBPB9wf1.js} +2 -2
  78. package/dist/_chunks/{periodontal-risk-chart-D2zyID0H.js.map → periodontal-risk-chart-BBPB9wf1.js.map} +1 -1
  79. package/dist/_chunks/{practice-profile-hero-Bb4YyxHA.js → practice-profile-hero-Cw4NZp0A.js} +2 -2
  80. package/dist/_chunks/{practice-profile-hero-Bb4YyxHA.js.map → practice-profile-hero-Cw4NZp0A.js.map} +1 -1
  81. package/dist/_chunks/practice-results-BlxfBx-D.js +2181 -0
  82. package/dist/_chunks/practice-results-BlxfBx-D.js.map +1 -0
  83. package/dist/_chunks/{pregnancy-dating-Cs8xpZA8.js → pregnancy-dating-BvorzHrd.js} +3 -3
  84. package/dist/_chunks/{pregnancy-dating-Cs8xpZA8.js.map → pregnancy-dating-BvorzHrd.js.map} +1 -1
  85. package/dist/_chunks/{pregnancy-weight-gain-B_Zldlzq.js → pregnancy-weight-gain-DQoOM8QV.js} +2 -2
  86. package/dist/_chunks/{pregnancy-weight-gain-B_Zldlzq.js.map → pregnancy-weight-gain-DQoOM8QV.js.map} +1 -1
  87. package/dist/_chunks/{privacy-mask-DbEKI-Jv.js → privacy-mask-Dc3kdkCR.js} +2 -2
  88. package/dist/_chunks/{privacy-mask-DbEKI-Jv.js.map → privacy-mask-Dc3kdkCR.js.map} +1 -1
  89. package/dist/_chunks/{public-footer-DGjLTtNK.js → public-footer-CB7ruuLI.js} +295 -260
  90. package/dist/_chunks/public-footer-CB7ruuLI.js.map +1 -0
  91. package/dist/_chunks/{public-header.agent-_ArDD1Xr.js → public-header.agent-Db4wm6_S.js} +203 -193
  92. package/dist/_chunks/public-header.agent-Db4wm6_S.js.map +1 -0
  93. package/dist/_chunks/{registration-form-Cq5_OSIL.js → registration-form-Lw9T7IXr.js} +2 -2
  94. package/dist/_chunks/{registration-form-Cq5_OSIL.js.map → registration-form-Lw9T7IXr.js.map} +1 -1
  95. package/dist/_chunks/{reserved.agent-BMkapgom.js → reserved.agent-D2jwJPac.js} +21 -31
  96. package/dist/_chunks/reserved.agent-D2jwJPac.js.map +1 -0
  97. package/dist/_chunks/{reset-password-form-BVsL2fOJ.js → reset-password-form-C93SH0Tx.js} +2 -2
  98. package/dist/_chunks/{reset-password-form-BVsL2fOJ.js.map → reset-password-form-C93SH0Tx.js.map} +1 -1
  99. package/dist/_chunks/{reviews-panel-B03auSpQ.js → reviews-panel-CfJPEkH7.js} +2 -2
  100. package/dist/_chunks/{reviews-panel-B03auSpQ.js.map → reviews-panel-CfJPEkH7.js.map} +1 -1
  101. package/dist/_chunks/{section-card-D1sV4Voz.js → section-card-DFr2wGal.js} +2 -2
  102. package/dist/_chunks/{section-card-D1sV4Voz.js.map → section-card-DFr2wGal.js.map} +1 -1
  103. package/dist/_chunks/{send-registration-link-form-OgPomrZN.js → send-registration-link-form-DfbTjrEK.js} +2 -2
  104. package/dist/_chunks/{send-registration-link-form-OgPomrZN.js.map → send-registration-link-form-DfbTjrEK.js.map} +1 -1
  105. package/dist/_chunks/{signed-out-frame-CPow3aCZ.js → signed-out-frame-bh7fn_Px.js} +2 -2
  106. package/dist/_chunks/{signed-out-frame-CPow3aCZ.js.map → signed-out-frame-bh7fn_Px.js.map} +1 -1
  107. package/dist/_chunks/{stat-BFKZV50y.js → stat-WGLdn5Vn.js} +113 -107
  108. package/dist/_chunks/stat-WGLdn5Vn.js.map +1 -0
  109. package/dist/_chunks/{task-card-TSJjuuDe.js → task-card-DqVoitRk.js} +2 -2
  110. package/dist/_chunks/{task-card-TSJjuuDe.js.map → task-card-DqVoitRk.js.map} +1 -1
  111. package/dist/_chunks/{task-editor-gqWF1jI6.js → task-editor-D--LwVrg.js} +2 -2
  112. package/dist/_chunks/{task-editor-gqWF1jI6.js.map → task-editor-D--LwVrg.js.map} +1 -1
  113. package/dist/_chunks/{task-tray-DrXfMCuf.js → task-tray-C6j8HVMv.js} +2 -2
  114. package/dist/_chunks/{task-tray-DrXfMCuf.js.map → task-tray-C6j8HVMv.js.map} +1 -1
  115. package/dist/_chunks/{tasks-panel-OuIaydK5.js → tasks-panel-D6PuF4MQ.js} +2 -2
  116. package/dist/_chunks/{tasks-panel-OuIaydK5.js.map → tasks-panel-D6PuF4MQ.js.map} +1 -1
  117. package/dist/_chunks/{timeline-CKUaBZOx.js → timeline-AMqE-c2T.js} +2 -2
  118. package/dist/_chunks/{timeline-CKUaBZOx.js.map → timeline-AMqE-c2T.js.map} +1 -1
  119. package/dist/_chunks/{use-appointment-details-read-DvK7Looa.js → use-appointment-details-read-BK_Gw1GG.js} +5 -5
  120. package/dist/_chunks/{use-appointment-details-read-DvK7Looa.js.map → use-appointment-details-read-BK_Gw1GG.js.map} +1 -1
  121. package/dist/_chunks/{workflow-map-DWk-rZse.js → workflow-map-B4XkcET0.js} +2 -2
  122. package/dist/_chunks/{workflow-map-DWk-rZse.js.map → workflow-map-B4XkcET0.js.map} +1 -1
  123. package/dist/_chunks/{workflow-webhook-action-DILFqAVd.js → workflow-webhook-action-CtBn5JvO.js} +2 -2
  124. package/dist/_chunks/{workflow-webhook-action-DILFqAVd.js.map → workflow-webhook-action-CtBn5JvO.js.map} +1 -1
  125. package/dist/agent-catalog.json +6 -6
  126. package/dist/agent-i18n/en.json +2 -2
  127. package/dist/components/_shared/motion-is-off.d.ts +7 -0
  128. package/dist/components/_shared/motion-is-off.d.ts.map +1 -0
  129. package/dist/components/anamnesis-card/index.js +1 -1
  130. package/dist/components/anamnesis-summary-card/index.js +1 -1
  131. package/dist/components/appointment-details-panel/index.js +1 -1
  132. package/dist/components/bishop-score/index.js +1 -1
  133. package/dist/components/bmi-calculator/index.js +1 -1
  134. package/dist/components/booking/index.js +1 -1
  135. package/dist/components/booking/step-focus.d.ts +0 -6
  136. package/dist/components/booking/step-focus.d.ts.map +1 -1
  137. package/dist/components/card/card.d.ts.map +1 -1
  138. package/dist/components/card/index.js +1 -1
  139. package/dist/components/clinical-note-card/index.js +1 -1
  140. package/dist/components/connection-status/index.js +1 -1
  141. package/dist/components/contact-card/index.js +1 -1
  142. package/dist/components/contact-profile-card/index.js +1 -1
  143. package/dist/components/cycle-calculator/index.js +1 -1
  144. package/dist/components/document-preview/index.js +1 -1
  145. package/dist/components/due-date-calculator/index.js +2 -2
  146. package/dist/components/entity-summary/index.js +1 -1
  147. package/dist/components/face-scheme/index.js +1 -1
  148. package/dist/components/fetal-weight/index.js +1 -1
  149. package/dist/components/finished-terminal/index.js +1 -1
  150. package/dist/components/gestational-age-calculator/index.js +1 -1
  151. package/dist/components/hcg-doubling/index.js +1 -1
  152. package/dist/components/heatmap/index.js +1 -1
  153. package/dist/components/map-view/index.js +1 -1
  154. package/dist/components/map-view/map-view.d.ts +16 -0
  155. package/dist/components/map-view/map-view.d.ts.map +1 -1
  156. package/dist/components/notes-panel/index.js +1 -1
  157. package/dist/components/operator-hero/index.js +1 -1
  158. package/dist/components/operator-hero/operator-hero.d.ts.map +1 -1
  159. package/dist/components/patient-details/index.js +1 -1
  160. package/dist/components/patient-search/index.js +1 -1
  161. package/dist/components/patient-search/patient-search.d.ts +6 -2
  162. package/dist/components/patient-search/patient-search.d.ts.map +1 -1
  163. package/dist/components/patient-summary-card/index.js +1 -1
  164. package/dist/components/payment-card/index.js +1 -1
  165. package/dist/components/periodontal-chart/index.js +1 -1
  166. package/dist/components/periodontal-chart-card/index.js +1 -1
  167. package/dist/components/periodontal-diagnosis/index.js +1 -1
  168. package/dist/components/periodontal-risk-chart/index.js +1 -1
  169. package/dist/components/practice-profile-hero/index.js +1 -1
  170. package/dist/components/practice-results/index.js +1 -1
  171. package/dist/components/practice-results/practice-results.agent.d.ts.map +1 -1
  172. package/dist/components/practice-results/practice-results.d.ts +15 -2
  173. package/dist/components/practice-results/practice-results.d.ts.map +1 -1
  174. package/dist/components/pregnancy-dating/index.js +1 -1
  175. package/dist/components/pregnancy-weight-gain/index.js +1 -1
  176. package/dist/components/public-footer/index.js +1 -1
  177. package/dist/components/public-footer/public-footer.d.ts +23 -0
  178. package/dist/components/public-footer/public-footer.d.ts.map +1 -1
  179. package/dist/components/public-header/index.js +1 -1
  180. package/dist/components/public-header/public-header.d.ts +7 -0
  181. package/dist/components/public-header/public-header.d.ts.map +1 -1
  182. package/dist/components/reviews-panel/index.js +1 -1
  183. package/dist/components/rich-text-editor/index.js +1 -1
  184. package/dist/components/section-card/index.js +1 -1
  185. package/dist/components/stat/index.js +1 -1
  186. package/dist/components/stat/stat.d.ts +7 -0
  187. package/dist/components/stat/stat.d.ts.map +1 -1
  188. package/dist/components/task-card/index.js +1 -1
  189. package/dist/components/task-editor/index.js +1 -1
  190. package/dist/components/task-tray/index.js +1 -1
  191. package/dist/components/tasks-panel/index.js +1 -1
  192. package/dist/components/timeline/index.js +1 -1
  193. package/dist/components/workflow/index.js +1 -1
  194. package/dist/core.css +1 -1
  195. package/dist/host-compat.css +4 -1
  196. package/dist/i18n/locales/ar.d.ts +1 -0
  197. package/dist/i18n/locales/ar.d.ts.map +1 -1
  198. package/dist/i18n/locales/ar.js +2 -1
  199. package/dist/i18n/locales/ar.js.map +1 -1
  200. package/dist/i18n/locales/de.d.ts +1 -0
  201. package/dist/i18n/locales/de.d.ts.map +1 -1
  202. package/dist/i18n/locales/de.js +2 -1
  203. package/dist/i18n/locales/de.js.map +1 -1
  204. package/dist/i18n/locales/el.d.ts +1 -0
  205. package/dist/i18n/locales/el.d.ts.map +1 -1
  206. package/dist/i18n/locales/el.js +2 -1
  207. package/dist/i18n/locales/el.js.map +1 -1
  208. package/dist/i18n/locales/en.d.ts +1 -0
  209. package/dist/i18n/locales/en.d.ts.map +1 -1
  210. package/dist/i18n/locales/en.js +1 -0
  211. package/dist/i18n/locales/en.js.map +1 -1
  212. package/dist/i18n/locales/es.d.ts +1 -0
  213. package/dist/i18n/locales/es.d.ts.map +1 -1
  214. package/dist/i18n/locales/es.js +2 -1
  215. package/dist/i18n/locales/es.js.map +1 -1
  216. package/dist/i18n/locales/fr.d.ts +1 -0
  217. package/dist/i18n/locales/fr.d.ts.map +1 -1
  218. package/dist/i18n/locales/fr.js +2 -1
  219. package/dist/i18n/locales/fr.js.map +1 -1
  220. package/dist/i18n/locales/hi.d.ts +1 -0
  221. package/dist/i18n/locales/hi.d.ts.map +1 -1
  222. package/dist/i18n/locales/hi.js +2 -1
  223. package/dist/i18n/locales/hi.js.map +1 -1
  224. package/dist/i18n/locales/it.d.ts +1 -0
  225. package/dist/i18n/locales/it.d.ts.map +1 -1
  226. package/dist/i18n/locales/it.js +2 -1
  227. package/dist/i18n/locales/it.js.map +1 -1
  228. package/dist/i18n/locales/ja.d.ts +1 -0
  229. package/dist/i18n/locales/ja.d.ts.map +1 -1
  230. package/dist/i18n/locales/ja.js +2 -1
  231. package/dist/i18n/locales/ja.js.map +1 -1
  232. package/dist/i18n/locales/nl.d.ts +1 -0
  233. package/dist/i18n/locales/nl.d.ts.map +1 -1
  234. package/dist/i18n/locales/nl.js +2 -1
  235. package/dist/i18n/locales/nl.js.map +1 -1
  236. package/dist/i18n/locales/pl.d.ts +1 -0
  237. package/dist/i18n/locales/pl.d.ts.map +1 -1
  238. package/dist/i18n/locales/pl.js +2 -1
  239. package/dist/i18n/locales/pl.js.map +1 -1
  240. package/dist/i18n/locales/pt.d.ts +1 -0
  241. package/dist/i18n/locales/pt.d.ts.map +1 -1
  242. package/dist/i18n/locales/pt.js +2 -1
  243. package/dist/i18n/locales/pt.js.map +1 -1
  244. package/dist/i18n/locales/ro.d.ts +1 -0
  245. package/dist/i18n/locales/ro.d.ts.map +1 -1
  246. package/dist/i18n/locales/ro.js +2 -1
  247. package/dist/i18n/locales/ro.js.map +1 -1
  248. package/dist/i18n/locales/ru.d.ts +1 -0
  249. package/dist/i18n/locales/ru.d.ts.map +1 -1
  250. package/dist/i18n/locales/ru.js +2 -1
  251. package/dist/i18n/locales/ru.js.map +1 -1
  252. package/dist/i18n/locales/sq.d.ts +1 -0
  253. package/dist/i18n/locales/sq.d.ts.map +1 -1
  254. package/dist/i18n/locales/sq.js +2 -1
  255. package/dist/i18n/locales/sq.js.map +1 -1
  256. package/dist/i18n/locales/sv.d.ts +1 -0
  257. package/dist/i18n/locales/sv.d.ts.map +1 -1
  258. package/dist/i18n/locales/sv.js +2 -1
  259. package/dist/i18n/locales/sv.js.map +1 -1
  260. package/dist/i18n/locales/tr.d.ts +1 -0
  261. package/dist/i18n/locales/tr.d.ts.map +1 -1
  262. package/dist/i18n/locales/tr.js +2 -1
  263. package/dist/i18n/locales/tr.js.map +1 -1
  264. package/dist/i18n/locales/zh.d.ts +1 -0
  265. package/dist/i18n/locales/zh.d.ts.map +1 -1
  266. package/dist/i18n/locales/zh.js +2 -1
  267. package/dist/i18n/locales/zh.js.map +1 -1
  268. package/dist/index.js +60 -60
  269. package/dist/locales/ar.json +2 -1
  270. package/dist/locales/de.json +2 -1
  271. package/dist/locales/el.json +2 -1
  272. package/dist/locales/en.json +1 -0
  273. package/dist/locales/es.json +2 -1
  274. package/dist/locales/fr.json +2 -1
  275. package/dist/locales/hi.json +2 -1
  276. package/dist/locales/it.json +2 -1
  277. package/dist/locales/ja.json +2 -1
  278. package/dist/locales/nl.json +2 -1
  279. package/dist/locales/pl.json +2 -1
  280. package/dist/locales/pt.json +2 -1
  281. package/dist/locales/ro.json +2 -1
  282. package/dist/locales/ru.json +2 -1
  283. package/dist/locales/sq.json +2 -1
  284. package/dist/locales/sv.json +2 -1
  285. package/dist/locales/tr.json +2 -1
  286. package/dist/locales/zh.json +2 -1
  287. package/dist/patterns/anamnesis/index.js +1 -1
  288. package/dist/patterns/calendar/index.js +1 -1
  289. package/dist/patterns/forgot-password-form/index.js +1 -1
  290. package/dist/patterns/login-form/index.js +1 -1
  291. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  292. package/dist/patterns/payment-automation-upsell/index.js +1 -1
  293. package/dist/patterns/registration-form/index.js +1 -1
  294. package/dist/patterns/reset-password-form/index.js +1 -1
  295. package/dist/patterns/send-registration-link-form/index.js +1 -1
  296. package/dist/patterns/signed-out-frame/index.js +1 -1
  297. package/dist/patterns/workflow-webhook-action/index.js +1 -1
  298. package/dist/tokens.css +1 -1
  299. package/package.json +1 -1
  300. package/dist/_chunks/map-view-Dn7aXZJw.js +0 -731
  301. package/dist/_chunks/map-view-Dn7aXZJw.js.map +0 -1
  302. package/dist/_chunks/patient-search-CxuqVUTB.js.map +0 -1
  303. package/dist/_chunks/practice-results-BByRCIuR.js +0 -1977
  304. package/dist/_chunks/practice-results-BByRCIuR.js.map +0 -1
  305. package/dist/_chunks/public-footer-DGjLTtNK.js.map +0 -1
  306. package/dist/_chunks/public-header.agent-_ArDD1Xr.js.map +0 -1
  307. package/dist/_chunks/reserved.agent-BMkapgom.js.map +0 -1
  308. package/dist/_chunks/stat-BFKZV50y.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"periodontal-risk-chart-D2zyID0H.js","sources":["../../src/components/periodontal-risk-chart/periodontal-risk-chart.agent.ts","../../src/components/periodontal-risk-chart/periodontal-risk-data.ts","../../src/components/periodontal-risk-chart/periodontal-risk-chart.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { PeriodontalRiskChartHandle } from './periodontal-risk-chart';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalRiskChart — agent adapter */\n/* */\n/* Read-only. Exposes the derived risk verdict and per-factor levels — */\n/* ordinal risk bands only, never the raw clinical inputs or any patient */\n/* identity. */\n/* -------------------------------------------------------------------- */\n\nexport const periodontalRiskChartAgent: AgentAdapter<PeriodontalRiskChartHandle> =\n {\n id: 'periodontal-risk-chart',\n capabilities: [],\n state: {\n overall: {\n type: 'string',\n descriptionKey: 'ui.agent.periodontalRiskChart.state.overall',\n description:\n 'Overall periodontal risk verdict — \"low\" | \"moderate\" | \"high\". Aggregate only.',\n read: (handle) => handle.getOverall(),\n },\n factorLevels: {\n type: 'object',\n descriptionKey: 'ui.agent.periodontalRiskChart.state.factorLevels',\n description:\n 'Per-factor risk levels keyed by factor (bleeding, pockets, toothLoss, boneLossAge, smoking, systemic) — each \"low\" | \"moderate\" | \"high\". No raw values.',\n read: (handle) => handle.getFactorLevels(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'periodontal-risk-chart',\n description: 'Marks the PeriodontalRiskChart root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n };\n","/* -------------------------------------------------------------------- */\n/* PeriodontalRiskChart — data model */\n/* */\n/* The Lang & Tonetti (2003) periodontal risk assessment — six vectors, */\n/* each scored low / moderate / high, drawn as a hexagon \"spider web\". */\n/* This module owns the thresholds and the pure scoring function; the */\n/* component owns only the geometry + a11y presentation. */\n/* -------------------------------------------------------------------- */\n\n/** The six risk vectors of the Lang & Tonetti diagram. */\nexport const PERIODONTAL_RISK_FACTORS = [\n 'bleeding',\n 'pockets',\n 'toothLoss',\n 'boneLossAge',\n 'smoking',\n 'systemic',\n] as const;\n\nexport type PeriodontalRiskFactor = (typeof PERIODONTAL_RISK_FACTORS)[number];\n\n/** Ordinal risk level for one factor and for the whole assessment. */\nexport type PeriodontalRiskLevel = 'low' | 'moderate' | 'high';\n\n/** Environmental (smoking) exposure bands. */\nexport type SmokingExposure =\n | 'none'\n | 'former'\n | 'light'\n | 'moderate'\n | 'heavy';\n\n/** Consumer-supplied risk inputs. All optional — an absent factor scores low. */\nexport interface PeriodontalRiskInputs {\n /** Bleeding on probing, % of sites (0–100). */\n bleedingPercent?: number;\n /** Number of residual pockets ≥ 5 mm. */\n pocketsOver5mm?: number;\n /** Number of teeth lost (of 28, third molars excluded). */\n toothLoss?: number;\n /** % bone loss at the worst site — combined with `ageYears` into BL/age. */\n boneLossPercent?: number;\n /** Patient age in years (denominator of the bone-loss/age ratio). */\n ageYears?: number;\n /** Smoking exposure band. */\n smoking?: SmokingExposure;\n /** A relevant systemic / genetic factor is present (e.g. diabetes, IL-1). */\n systemic?: boolean;\n}\n\n/** Scored result for one factor. */\nexport interface PeriodontalRiskFactorScore {\n factor: PeriodontalRiskFactor;\n level: PeriodontalRiskLevel;\n /** 0 (best) → 1 (worst): the normalised radius used to plot the vertex. */\n radius: number;\n /** Raw value formatted for the accessible summary, or null when unset. */\n valueText: string | null;\n}\n\n/** The whole assessment. */\nexport interface PeriodontalRiskResult {\n factors: PeriodontalRiskFactorScore[];\n overall: PeriodontalRiskLevel;\n}\n\nconst LEVEL_RADIUS: Record<PeriodontalRiskLevel, number> = {\n low: 0.4,\n moderate: 0.7,\n high: 1,\n};\n\n/** Order a level to an ordinal (low 0 … high 2). */\nexport function riskOrdinal(level: PeriodontalRiskLevel): 0 | 1 | 2 {\n return level === 'high' ? 2 : level === 'moderate' ? 1 : 0;\n}\n\nfunction band(\n value: number,\n moderateAt: number,\n highAt: number,\n): PeriodontalRiskLevel {\n if (value >= highAt) return 'high';\n if (value >= moderateAt) return 'moderate';\n return 'low';\n}\n\nconst SMOKING_LEVEL: Record<SmokingExposure, PeriodontalRiskLevel> = {\n none: 'low',\n former: 'low',\n light: 'moderate',\n moderate: 'high',\n heavy: 'high',\n};\n\n/**\n * Score the six vectors and the overall risk. Overall follows the Lang &\n * Tonetti reading: high if any vector is high or two-or-more are moderate;\n * low only when every vector is low; moderate otherwise.\n */\nexport function computePeriodontalRisk(\n inputs: PeriodontalRiskInputs,\n): PeriodontalRiskResult {\n const scores: PeriodontalRiskFactorScore[] = [];\n\n const push = (\n factor: PeriodontalRiskFactor,\n level: PeriodontalRiskLevel,\n valueText: string | null,\n ) => scores.push({ factor, level, radius: LEVEL_RADIUS[level], valueText });\n\n // Bleeding on probing (%): <10 low, 10–25 moderate, >25 high.\n {\n const v = inputs.bleedingPercent;\n push(\n 'bleeding',\n v == null ? 'low' : band(v, 10, 26),\n v == null ? null : `${Math.round(v)}%`,\n );\n }\n // Residual pockets ≥5 mm: ≤4 low, 5–8 moderate, ≥9 high.\n {\n const v = inputs.pocketsOver5mm;\n push(\n 'pockets',\n v == null ? 'low' : band(v, 5, 9),\n v == null ? null : String(v),\n );\n }\n // Tooth loss: ≤4 low, 5–8 moderate, ≥9 high.\n {\n const v = inputs.toothLoss;\n push(\n 'toothLoss',\n v == null ? 'low' : band(v, 5, 9),\n v == null ? null : String(v),\n );\n }\n // Bone loss / age ratio: <0.5 low, 0.5–1.0 moderate, >1.0 high.\n {\n const bl = inputs.boneLossPercent;\n const age = inputs.ageYears;\n if (bl == null || age == null || age <= 0) {\n push('boneLossAge', 'low', null);\n } else {\n const ratio = bl / age;\n push(\n 'boneLossAge',\n ratio > 1 ? 'high' : ratio >= 0.5 ? 'moderate' : 'low',\n ratio.toFixed(2),\n );\n }\n }\n // Environmental (smoking).\n {\n const v = inputs.smoking;\n push('smoking', v == null ? 'low' : SMOKING_LEVEL[v], v ?? null);\n }\n // Systemic / genetic: present → high.\n {\n const v = inputs.systemic;\n push('systemic', v ? 'high' : 'low', v == null ? null : v ? 'yes' : 'no');\n }\n\n const highs = scores.filter((s) => s.level === 'high').length;\n const moderates = scores.filter((s) => s.level === 'moderate').length;\n const overall: PeriodontalRiskLevel =\n highs > 0 || moderates >= 2 ? 'high' : moderates === 1 ? 'moderate' : 'low';\n\n return { factors: scores, overall };\n}\n","import {\n forwardRef,\n useId,\n useMemo,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '../badge/badge';\nimport { Card } from '../card/card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { periodontalRiskChartAgent } from './periodontal-risk-chart.agent';\nimport {\n computePeriodontalRisk,\n PERIODONTAL_RISK_FACTORS,\n type PeriodontalRiskFactor,\n type PeriodontalRiskInputs,\n type PeriodontalRiskLevel,\n} from './periodontal-risk-data';\nimport { formatNumber } from '../_shared/format-number';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalRiskChart */\n/* */\n/* The Lang & Tonetti (2003) periodontal risk \"spider web\": six vectors */\n/* (bleeding, residual pockets, tooth loss, bone-loss/age, smoking, */\n/* systemic) each scored low / moderate / high, drawn as a hexagon. */\n/* */\n/* The hexagon SVG is DECORATIVE (aria-hidden) — the accessible source */\n/* of truth is the worded summary: an overall-risk Badge plus a <dl> of */\n/* the six factors with their level and value. Colour is never the sole */\n/* cue (every band and the overall verdict is also worded). */\n/* -------------------------------------------------------------------- */\n\nconst VIEW = 240;\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n surface: { flat: '', elevated: '' },\n },\n defaultVariants: { surface: 'elevated' },\n});\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\nexport interface PeriodontalRiskChartHandle {\n /** The overall risk verdict. */\n getOverall: () => PeriodontalRiskLevel;\n /** Per-factor risk levels, keyed by factor. */\n getFactorLevels: () => Record<PeriodontalRiskFactor, PeriodontalRiskLevel>;\n}\n\nexport interface PeriodontalRiskChartProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children'\n> {\n /** The six risk inputs. Absent factors score low. */\n inputs: PeriodontalRiskInputs;\n /** `'elevated'` (default) wraps in a Card; `'flat'` drops the chrome. */\n surface?: 'flat' | 'elevated';\n /** Locale for number formatting. Falls back to `i18n.language`. */\n locale?: string;\n /** Override the default region aria-label. */\n 'aria-label'?: string;\n /** Agent-readiness consumer id, surfaced as `data-component-id`. */\n id?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Geometry */\n/* -------------------------------------------------------------------- */\n\nconst CENTER = VIEW / 2;\nconst RADIUS = VIEW / 2 - 16;\n\n/** Vertex `i` (0 = top, clockwise) at a given radius. */\nfunction vertex(i: number, r: number): { x: number; y: number } {\n const angle = ((-90 + i * 60) * Math.PI) / 180;\n return { x: CENTER + r * Math.cos(angle), y: CENTER + r * Math.sin(angle) };\n}\n\n/** The six-point polygon string for a ring at fraction `f` of the radius. */\nfunction hexPoints(f: number): string {\n return PERIODONTAL_RISK_FACTORS.map((_, i) => {\n const v = vertex(i, RADIUS * f);\n return `${v.x.toFixed(1)},${v.y.toFixed(1)}`;\n }).join(' ');\n}\n\nconst BADGE_TONE: Record<\n PeriodontalRiskLevel,\n 'success' | 'warning' | 'error'\n> = {\n low: 'success',\n moderate: 'warning',\n high: 'error',\n};\n\nconst LEVEL_DEFAULT: Record<PeriodontalRiskLevel, string> = {\n low: 'Low',\n moderate: 'Moderate',\n high: 'High',\n};\n\nconst FACTOR_DEFAULT: Record<PeriodontalRiskFactor, string> = {\n bleeding: 'Bleeding on probing',\n pockets: 'Residual pockets ≥5 mm',\n toothLoss: 'Tooth loss',\n boneLossAge: 'Bone loss / age',\n smoking: 'Smoking',\n systemic: 'Systemic / genetic',\n};\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const PeriodontalRiskChart = forwardRef<\n HTMLDivElement,\n PeriodontalRiskChartProps\n>(\n (\n {\n inputs,\n surface = 'elevated',\n locale,\n 'aria-label': ariaLabel,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const headingId = useId();\n const resolvedLocale = locale ?? i18n.language ?? 'en';\n\n const result = useMemo(() => computePeriodontalRisk(inputs), [inputs]);\n\n useAgentRegistration(\n periodontalRiskChartAgent,\n {\n getOverall: () => result.overall,\n getFactorLevels: () =>\n Object.fromEntries(\n result.factors.map((f) => [f.factor, f.level]),\n ) as Record<PeriodontalRiskFactor, PeriodontalRiskLevel>,\n },\n id,\n );\n\n const patientPoints = result.factors\n .map((f, i) => {\n const v = vertex(i, RADIUS * f.radius);\n return `${v.x.toFixed(1)},${v.y.toFixed(1)}`;\n })\n .join(' ');\n\n const levelLabel = (level: PeriodontalRiskLevel): string =>\n t(`periodontalRiskChart.level.${level}`, {\n defaultValue: LEVEL_DEFAULT[level],\n });\n\n const factorValueText = (\n factor: PeriodontalRiskFactor,\n raw: string | null,\n ): string => {\n if (raw == null)\n return t('periodontalRiskChart.valueUnset', 'not recorded');\n if (factor === 'smoking')\n return t(`periodontalRiskChart.smoking.${raw}`, { defaultValue: raw });\n if (factor === 'systemic')\n return t(`periodontalRiskChart.systemic.${raw}`, { defaultValue: raw });\n if (factor === 'boneLossAge') {\n // The data layer writes the ratio with a dot (\"0.50\"); show it in\n // the UI language's separator (\"0,50\" in Italian).\n const n = Number.parseFloat(raw);\n return Number.isFinite(n)\n ? formatNumber(n, resolvedLocale, {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n : raw;\n }\n if (factor === 'bleeding') {\n // raw already carries the '%' glyph from the data layer; localise digits.\n const n = Number.parseFloat(raw);\n if (Number.isFinite(n)) {\n try {\n return t('periodontalRiskChart.percent', {\n value: formatNumber(n, resolvedLocale, {\n maximumFractionDigits: 0,\n }),\n defaultValue: '{{value}}%',\n });\n } catch {\n return raw;\n }\n }\n }\n return raw;\n };\n\n const heading = t('periodontalRiskChart.heading', 'Periodontal risk');\n const resolvedAriaLabel = ariaLabel ?? heading;\n\n const inner = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <h2\n id={headingId}\n className=\"type-title-card ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {heading}\n </h2>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {t('periodontalRiskChart.overall.label', 'Overall')}\n </span>\n <Badge variant={BADGE_TONE[result.overall]} size=\"sm\">\n {levelLabel(result.overall)}\n </Badge>\n </span>\n </div>\n\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-lg)]\">\n {/* Decorative hexagon — the <dl> below is the accessible source. */}\n <svg\n viewBox={`0 0 ${VIEW} ${VIEW}`}\n className=\"ds:w-full ds:max-w-[240px] ds:aspect-square\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <polygon\n points={hexPoints(1)}\n fill=\"var(--destructive)\"\n fillOpacity={0.1}\n />\n <polygon\n points={hexPoints(0.7)}\n fill=\"var(--warning)\"\n fillOpacity={0.12}\n />\n <polygon\n points={hexPoints(0.4)}\n fill=\"var(--success)\"\n fillOpacity={0.14}\n />\n {[1, 0.7, 0.4].map((f) => (\n <polygon\n key={f}\n points={hexPoints(f)}\n fill=\"none\"\n stroke=\"var(--border)\"\n strokeWidth={1}\n />\n ))}\n {PERIODONTAL_RISK_FACTORS.map((_, i) => {\n const v = vertex(i, RADIUS);\n return (\n <line\n key={i}\n x1={CENTER}\n y1={CENTER}\n x2={v.x}\n y2={v.y}\n stroke=\"var(--border)\"\n strokeWidth={1}\n />\n );\n })}\n <polygon\n points={patientPoints}\n fill=\"var(--primary)\"\n fillOpacity={0.18}\n stroke=\"var(--primary)\"\n strokeWidth={2}\n strokeLinejoin=\"round\"\n />\n {result.factors.map((f, i) => {\n const v = vertex(i, RADIUS * f.radius);\n return (\n <circle\n key={f.factor}\n cx={v.x}\n cy={v.y}\n r={3}\n fill=\"var(--primary)\"\n />\n );\n })}\n </svg>\n\n <dl\n className=\"type-body-sm ds:grid ds:min-w-[12rem] ds:flex-1 ds:grid-cols-[auto_1fr] ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-2xs)] ds:m-0\"\n aria-label={t('periodontalRiskChart.factors.label', 'Risk factors')}\n >\n {result.factors.map((f) => (\n <div key={f.factor} className=\"ds:contents\">\n <dt className=\"ds:text-[color:var(--muted-foreground)]\">\n {t(`periodontalRiskChart.factor.${f.factor}`, {\n defaultValue: FACTOR_DEFAULT[f.factor],\n })}\n </dt>\n <dd className=\"ds:m-0 ds:flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <Badge variant={BADGE_TONE[f.level]} size=\"sm\">\n {levelLabel(f.level)}\n </Badge>\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {factorValueText(f.factor, f.valueText)}\n </span>\n </dd>\n </div>\n ))}\n </dl>\n </div>\n </div>\n );\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={resolvedAriaLabel}\n data-component=\"periodontal-risk-chart\"\n data-component-id={id}\n id={id}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {surface === 'elevated' ? (\n <Card variant=\"elevated\">\n <Card.Body>{inner}</Card.Body>\n </Card>\n ) : (\n inner\n )}\n </div>\n );\n },\n);\n\nPeriodontalRiskChart.displayName = 'PeriodontalRiskChart';\n\nexport type PeriodontalRiskChartSurface = NonNullable<\n VariantProps<typeof rootVariants>['surface']\n>;\n"],"names":["periodontalRiskChartAgent","handle","PERIODONTAL_RISK_FACTORS","LEVEL_RADIUS","riskOrdinal","level","band","value","moderateAt","highAt","SMOKING_LEVEL","computePeriodontalRisk","inputs","scores","push","factor","valueText","v","bl","age","ratio","highs","s","moderates","overall","VIEW","rootVariants","cva","CENTER","RADIUS","vertex","i","r","angle","hexPoints","f","_","BADGE_TONE","LEVEL_DEFAULT","FACTOR_DEFAULT","PeriodontalRiskChart","forwardRef","surface","locale","ariaLabel","id","className","rest","ref","t","i18n","useTranslation","headingId","useId","resolvedLocale","result","useMemo","useAgentRegistration","patientPoints","levelLabel","factorValueText","raw","formatNumber","heading","resolvedAriaLabel","inner","jsxs","jsx","Badge","Card"],"mappings":"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"}
1
+ {"version":3,"file":"periodontal-risk-chart-BBPB9wf1.js","sources":["../../src/components/periodontal-risk-chart/periodontal-risk-chart.agent.ts","../../src/components/periodontal-risk-chart/periodontal-risk-data.ts","../../src/components/periodontal-risk-chart/periodontal-risk-chart.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { PeriodontalRiskChartHandle } from './periodontal-risk-chart';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalRiskChart — agent adapter */\n/* */\n/* Read-only. Exposes the derived risk verdict and per-factor levels — */\n/* ordinal risk bands only, never the raw clinical inputs or any patient */\n/* identity. */\n/* -------------------------------------------------------------------- */\n\nexport const periodontalRiskChartAgent: AgentAdapter<PeriodontalRiskChartHandle> =\n {\n id: 'periodontal-risk-chart',\n capabilities: [],\n state: {\n overall: {\n type: 'string',\n descriptionKey: 'ui.agent.periodontalRiskChart.state.overall',\n description:\n 'Overall periodontal risk verdict — \"low\" | \"moderate\" | \"high\". Aggregate only.',\n read: (handle) => handle.getOverall(),\n },\n factorLevels: {\n type: 'object',\n descriptionKey: 'ui.agent.periodontalRiskChart.state.factorLevels',\n description:\n 'Per-factor risk levels keyed by factor (bleeding, pockets, toothLoss, boneLossAge, smoking, systemic) — each \"low\" | \"moderate\" | \"high\". No raw values.',\n read: (handle) => handle.getFactorLevels(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'periodontal-risk-chart',\n description: 'Marks the PeriodontalRiskChart root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n };\n","/* -------------------------------------------------------------------- */\n/* PeriodontalRiskChart — data model */\n/* */\n/* The Lang & Tonetti (2003) periodontal risk assessment — six vectors, */\n/* each scored low / moderate / high, drawn as a hexagon \"spider web\". */\n/* This module owns the thresholds and the pure scoring function; the */\n/* component owns only the geometry + a11y presentation. */\n/* -------------------------------------------------------------------- */\n\n/** The six risk vectors of the Lang & Tonetti diagram. */\nexport const PERIODONTAL_RISK_FACTORS = [\n 'bleeding',\n 'pockets',\n 'toothLoss',\n 'boneLossAge',\n 'smoking',\n 'systemic',\n] as const;\n\nexport type PeriodontalRiskFactor = (typeof PERIODONTAL_RISK_FACTORS)[number];\n\n/** Ordinal risk level for one factor and for the whole assessment. */\nexport type PeriodontalRiskLevel = 'low' | 'moderate' | 'high';\n\n/** Environmental (smoking) exposure bands. */\nexport type SmokingExposure =\n | 'none'\n | 'former'\n | 'light'\n | 'moderate'\n | 'heavy';\n\n/** Consumer-supplied risk inputs. All optional — an absent factor scores low. */\nexport interface PeriodontalRiskInputs {\n /** Bleeding on probing, % of sites (0–100). */\n bleedingPercent?: number;\n /** Number of residual pockets ≥ 5 mm. */\n pocketsOver5mm?: number;\n /** Number of teeth lost (of 28, third molars excluded). */\n toothLoss?: number;\n /** % bone loss at the worst site — combined with `ageYears` into BL/age. */\n boneLossPercent?: number;\n /** Patient age in years (denominator of the bone-loss/age ratio). */\n ageYears?: number;\n /** Smoking exposure band. */\n smoking?: SmokingExposure;\n /** A relevant systemic / genetic factor is present (e.g. diabetes, IL-1). */\n systemic?: boolean;\n}\n\n/** Scored result for one factor. */\nexport interface PeriodontalRiskFactorScore {\n factor: PeriodontalRiskFactor;\n level: PeriodontalRiskLevel;\n /** 0 (best) → 1 (worst): the normalised radius used to plot the vertex. */\n radius: number;\n /** Raw value formatted for the accessible summary, or null when unset. */\n valueText: string | null;\n}\n\n/** The whole assessment. */\nexport interface PeriodontalRiskResult {\n factors: PeriodontalRiskFactorScore[];\n overall: PeriodontalRiskLevel;\n}\n\nconst LEVEL_RADIUS: Record<PeriodontalRiskLevel, number> = {\n low: 0.4,\n moderate: 0.7,\n high: 1,\n};\n\n/** Order a level to an ordinal (low 0 … high 2). */\nexport function riskOrdinal(level: PeriodontalRiskLevel): 0 | 1 | 2 {\n return level === 'high' ? 2 : level === 'moderate' ? 1 : 0;\n}\n\nfunction band(\n value: number,\n moderateAt: number,\n highAt: number,\n): PeriodontalRiskLevel {\n if (value >= highAt) return 'high';\n if (value >= moderateAt) return 'moderate';\n return 'low';\n}\n\nconst SMOKING_LEVEL: Record<SmokingExposure, PeriodontalRiskLevel> = {\n none: 'low',\n former: 'low',\n light: 'moderate',\n moderate: 'high',\n heavy: 'high',\n};\n\n/**\n * Score the six vectors and the overall risk. Overall follows the Lang &\n * Tonetti reading: high if any vector is high or two-or-more are moderate;\n * low only when every vector is low; moderate otherwise.\n */\nexport function computePeriodontalRisk(\n inputs: PeriodontalRiskInputs,\n): PeriodontalRiskResult {\n const scores: PeriodontalRiskFactorScore[] = [];\n\n const push = (\n factor: PeriodontalRiskFactor,\n level: PeriodontalRiskLevel,\n valueText: string | null,\n ) => scores.push({ factor, level, radius: LEVEL_RADIUS[level], valueText });\n\n // Bleeding on probing (%): <10 low, 10–25 moderate, >25 high.\n {\n const v = inputs.bleedingPercent;\n push(\n 'bleeding',\n v == null ? 'low' : band(v, 10, 26),\n v == null ? null : `${Math.round(v)}%`,\n );\n }\n // Residual pockets ≥5 mm: ≤4 low, 5–8 moderate, ≥9 high.\n {\n const v = inputs.pocketsOver5mm;\n push(\n 'pockets',\n v == null ? 'low' : band(v, 5, 9),\n v == null ? null : String(v),\n );\n }\n // Tooth loss: ≤4 low, 5–8 moderate, ≥9 high.\n {\n const v = inputs.toothLoss;\n push(\n 'toothLoss',\n v == null ? 'low' : band(v, 5, 9),\n v == null ? null : String(v),\n );\n }\n // Bone loss / age ratio: <0.5 low, 0.5–1.0 moderate, >1.0 high.\n {\n const bl = inputs.boneLossPercent;\n const age = inputs.ageYears;\n if (bl == null || age == null || age <= 0) {\n push('boneLossAge', 'low', null);\n } else {\n const ratio = bl / age;\n push(\n 'boneLossAge',\n ratio > 1 ? 'high' : ratio >= 0.5 ? 'moderate' : 'low',\n ratio.toFixed(2),\n );\n }\n }\n // Environmental (smoking).\n {\n const v = inputs.smoking;\n push('smoking', v == null ? 'low' : SMOKING_LEVEL[v], v ?? null);\n }\n // Systemic / genetic: present → high.\n {\n const v = inputs.systemic;\n push('systemic', v ? 'high' : 'low', v == null ? null : v ? 'yes' : 'no');\n }\n\n const highs = scores.filter((s) => s.level === 'high').length;\n const moderates = scores.filter((s) => s.level === 'moderate').length;\n const overall: PeriodontalRiskLevel =\n highs > 0 || moderates >= 2 ? 'high' : moderates === 1 ? 'moderate' : 'low';\n\n return { factors: scores, overall };\n}\n","import {\n forwardRef,\n useId,\n useMemo,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '../badge/badge';\nimport { Card } from '../card/card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { periodontalRiskChartAgent } from './periodontal-risk-chart.agent';\nimport {\n computePeriodontalRisk,\n PERIODONTAL_RISK_FACTORS,\n type PeriodontalRiskFactor,\n type PeriodontalRiskInputs,\n type PeriodontalRiskLevel,\n} from './periodontal-risk-data';\nimport { formatNumber } from '../_shared/format-number';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalRiskChart */\n/* */\n/* The Lang & Tonetti (2003) periodontal risk \"spider web\": six vectors */\n/* (bleeding, residual pockets, tooth loss, bone-loss/age, smoking, */\n/* systemic) each scored low / moderate / high, drawn as a hexagon. */\n/* */\n/* The hexagon SVG is DECORATIVE (aria-hidden) — the accessible source */\n/* of truth is the worded summary: an overall-risk Badge plus a <dl> of */\n/* the six factors with their level and value. Colour is never the sole */\n/* cue (every band and the overall verdict is also worded). */\n/* -------------------------------------------------------------------- */\n\nconst VIEW = 240;\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n surface: { flat: '', elevated: '' },\n },\n defaultVariants: { surface: 'elevated' },\n});\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\nexport interface PeriodontalRiskChartHandle {\n /** The overall risk verdict. */\n getOverall: () => PeriodontalRiskLevel;\n /** Per-factor risk levels, keyed by factor. */\n getFactorLevels: () => Record<PeriodontalRiskFactor, PeriodontalRiskLevel>;\n}\n\nexport interface PeriodontalRiskChartProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children'\n> {\n /** The six risk inputs. Absent factors score low. */\n inputs: PeriodontalRiskInputs;\n /** `'elevated'` (default) wraps in a Card; `'flat'` drops the chrome. */\n surface?: 'flat' | 'elevated';\n /** Locale for number formatting. Falls back to `i18n.language`. */\n locale?: string;\n /** Override the default region aria-label. */\n 'aria-label'?: string;\n /** Agent-readiness consumer id, surfaced as `data-component-id`. */\n id?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Geometry */\n/* -------------------------------------------------------------------- */\n\nconst CENTER = VIEW / 2;\nconst RADIUS = VIEW / 2 - 16;\n\n/** Vertex `i` (0 = top, clockwise) at a given radius. */\nfunction vertex(i: number, r: number): { x: number; y: number } {\n const angle = ((-90 + i * 60) * Math.PI) / 180;\n return { x: CENTER + r * Math.cos(angle), y: CENTER + r * Math.sin(angle) };\n}\n\n/** The six-point polygon string for a ring at fraction `f` of the radius. */\nfunction hexPoints(f: number): string {\n return PERIODONTAL_RISK_FACTORS.map((_, i) => {\n const v = vertex(i, RADIUS * f);\n return `${v.x.toFixed(1)},${v.y.toFixed(1)}`;\n }).join(' ');\n}\n\nconst BADGE_TONE: Record<\n PeriodontalRiskLevel,\n 'success' | 'warning' | 'error'\n> = {\n low: 'success',\n moderate: 'warning',\n high: 'error',\n};\n\nconst LEVEL_DEFAULT: Record<PeriodontalRiskLevel, string> = {\n low: 'Low',\n moderate: 'Moderate',\n high: 'High',\n};\n\nconst FACTOR_DEFAULT: Record<PeriodontalRiskFactor, string> = {\n bleeding: 'Bleeding on probing',\n pockets: 'Residual pockets ≥5 mm',\n toothLoss: 'Tooth loss',\n boneLossAge: 'Bone loss / age',\n smoking: 'Smoking',\n systemic: 'Systemic / genetic',\n};\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const PeriodontalRiskChart = forwardRef<\n HTMLDivElement,\n PeriodontalRiskChartProps\n>(\n (\n {\n inputs,\n surface = 'elevated',\n locale,\n 'aria-label': ariaLabel,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const headingId = useId();\n const resolvedLocale = locale ?? i18n.language ?? 'en';\n\n const result = useMemo(() => computePeriodontalRisk(inputs), [inputs]);\n\n useAgentRegistration(\n periodontalRiskChartAgent,\n {\n getOverall: () => result.overall,\n getFactorLevels: () =>\n Object.fromEntries(\n result.factors.map((f) => [f.factor, f.level]),\n ) as Record<PeriodontalRiskFactor, PeriodontalRiskLevel>,\n },\n id,\n );\n\n const patientPoints = result.factors\n .map((f, i) => {\n const v = vertex(i, RADIUS * f.radius);\n return `${v.x.toFixed(1)},${v.y.toFixed(1)}`;\n })\n .join(' ');\n\n const levelLabel = (level: PeriodontalRiskLevel): string =>\n t(`periodontalRiskChart.level.${level}`, {\n defaultValue: LEVEL_DEFAULT[level],\n });\n\n const factorValueText = (\n factor: PeriodontalRiskFactor,\n raw: string | null,\n ): string => {\n if (raw == null)\n return t('periodontalRiskChart.valueUnset', 'not recorded');\n if (factor === 'smoking')\n return t(`periodontalRiskChart.smoking.${raw}`, { defaultValue: raw });\n if (factor === 'systemic')\n return t(`periodontalRiskChart.systemic.${raw}`, { defaultValue: raw });\n if (factor === 'boneLossAge') {\n // The data layer writes the ratio with a dot (\"0.50\"); show it in\n // the UI language's separator (\"0,50\" in Italian).\n const n = Number.parseFloat(raw);\n return Number.isFinite(n)\n ? formatNumber(n, resolvedLocale, {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n : raw;\n }\n if (factor === 'bleeding') {\n // raw already carries the '%' glyph from the data layer; localise digits.\n const n = Number.parseFloat(raw);\n if (Number.isFinite(n)) {\n try {\n return t('periodontalRiskChart.percent', {\n value: formatNumber(n, resolvedLocale, {\n maximumFractionDigits: 0,\n }),\n defaultValue: '{{value}}%',\n });\n } catch {\n return raw;\n }\n }\n }\n return raw;\n };\n\n const heading = t('periodontalRiskChart.heading', 'Periodontal risk');\n const resolvedAriaLabel = ariaLabel ?? heading;\n\n const inner = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <h2\n id={headingId}\n className=\"type-title-card ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {heading}\n </h2>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {t('periodontalRiskChart.overall.label', 'Overall')}\n </span>\n <Badge variant={BADGE_TONE[result.overall]} size=\"sm\">\n {levelLabel(result.overall)}\n </Badge>\n </span>\n </div>\n\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-lg)]\">\n {/* Decorative hexagon — the <dl> below is the accessible source. */}\n <svg\n viewBox={`0 0 ${VIEW} ${VIEW}`}\n className=\"ds:w-full ds:max-w-[240px] ds:aspect-square\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <polygon\n points={hexPoints(1)}\n fill=\"var(--destructive)\"\n fillOpacity={0.1}\n />\n <polygon\n points={hexPoints(0.7)}\n fill=\"var(--warning)\"\n fillOpacity={0.12}\n />\n <polygon\n points={hexPoints(0.4)}\n fill=\"var(--success)\"\n fillOpacity={0.14}\n />\n {[1, 0.7, 0.4].map((f) => (\n <polygon\n key={f}\n points={hexPoints(f)}\n fill=\"none\"\n stroke=\"var(--border)\"\n strokeWidth={1}\n />\n ))}\n {PERIODONTAL_RISK_FACTORS.map((_, i) => {\n const v = vertex(i, RADIUS);\n return (\n <line\n key={i}\n x1={CENTER}\n y1={CENTER}\n x2={v.x}\n y2={v.y}\n stroke=\"var(--border)\"\n strokeWidth={1}\n />\n );\n })}\n <polygon\n points={patientPoints}\n fill=\"var(--primary)\"\n fillOpacity={0.18}\n stroke=\"var(--primary)\"\n strokeWidth={2}\n strokeLinejoin=\"round\"\n />\n {result.factors.map((f, i) => {\n const v = vertex(i, RADIUS * f.radius);\n return (\n <circle\n key={f.factor}\n cx={v.x}\n cy={v.y}\n r={3}\n fill=\"var(--primary)\"\n />\n );\n })}\n </svg>\n\n <dl\n className=\"type-body-sm ds:grid ds:min-w-[12rem] ds:flex-1 ds:grid-cols-[auto_1fr] ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-2xs)] ds:m-0\"\n aria-label={t('periodontalRiskChart.factors.label', 'Risk factors')}\n >\n {result.factors.map((f) => (\n <div key={f.factor} className=\"ds:contents\">\n <dt className=\"ds:text-[color:var(--muted-foreground)]\">\n {t(`periodontalRiskChart.factor.${f.factor}`, {\n defaultValue: FACTOR_DEFAULT[f.factor],\n })}\n </dt>\n <dd className=\"ds:m-0 ds:flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <Badge variant={BADGE_TONE[f.level]} size=\"sm\">\n {levelLabel(f.level)}\n </Badge>\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {factorValueText(f.factor, f.valueText)}\n </span>\n </dd>\n </div>\n ))}\n </dl>\n </div>\n </div>\n );\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={resolvedAriaLabel}\n data-component=\"periodontal-risk-chart\"\n data-component-id={id}\n id={id}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {surface === 'elevated' ? (\n <Card variant=\"elevated\">\n <Card.Body>{inner}</Card.Body>\n </Card>\n ) : (\n inner\n )}\n </div>\n );\n },\n);\n\nPeriodontalRiskChart.displayName = 'PeriodontalRiskChart';\n\nexport type PeriodontalRiskChartSurface = NonNullable<\n VariantProps<typeof rootVariants>['surface']\n>;\n"],"names":["periodontalRiskChartAgent","handle","PERIODONTAL_RISK_FACTORS","LEVEL_RADIUS","riskOrdinal","level","band","value","moderateAt","highAt","SMOKING_LEVEL","computePeriodontalRisk","inputs","scores","push","factor","valueText","v","bl","age","ratio","highs","s","moderates","overall","VIEW","rootVariants","cva","CENTER","RADIUS","vertex","i","r","angle","hexPoints","f","_","BADGE_TONE","LEVEL_DEFAULT","FACTOR_DEFAULT","PeriodontalRiskChart","forwardRef","surface","locale","ariaLabel","id","className","rest","ref","t","i18n","useTranslation","headingId","useId","resolvedLocale","result","useMemo","useAgentRegistration","patientPoints","levelLabel","factorValueText","raw","formatNumber","heading","resolvedAriaLabel","inner","jsxs","jsx","Badge","Card"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { forwardRef as A, useId as E, useState as K, useEffect as M, useMemo as
3
3
  import { c as L } from "./index-D2ZczOXr.js";
4
4
  import { A as b } from "./avatar-Dp5apm1d.js";
5
5
  import { B as W } from "./badge-BUk4RjTS.js";
6
- import { C } from "./card-C85_Ndhb.js";
6
+ import { C } from "./card-DVO3x8E-.js";
7
7
  import { R as $ } from "./rating-CGYpg5dj.js";
8
8
  import { u as q } from "./use-isomorphic-layout-effect-BGfaCOP1.js";
9
9
  import { u as D } from "./registry-DvAUVLHh.js";
@@ -242,4 +242,4 @@ export {
242
242
  O as P,
243
243
  G as p
244
244
  };
245
- //# sourceMappingURL=practice-profile-hero-Bb4YyxHA.js.map
245
+ //# sourceMappingURL=practice-profile-hero-Cw4NZp0A.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"practice-profile-hero-Bb4YyxHA.js","sources":["../../src/components/practice-profile-hero/practice-profile-hero.agent.ts","../../src/components/practice-profile-hero/practice-profile-hero.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { PracticeProfileHeroHandle } from './practice-profile-hero';\n\nexport const practiceProfileHeroAgent: AgentAdapter<PracticeProfileHeroHandle> =\n {\n id: 'practice-profile-hero',\n // Purely observable hero region — no interactive affordances and no\n // imperative actions on the handle (getName / getHasCover are read-only\n // projections).\n capabilities: [],\n state: {\n name: {\n type: 'string',\n descriptionKey: 'ui.agent.practiceProfileHero.state.name',\n description: 'Practice display name currently rendered.',\n read: (handle) => handle.getName(),\n },\n hasCover: {\n type: 'boolean',\n descriptionKey: 'ui.agent.practiceProfileHero.state.hasCover',\n description:\n 'Whether a cover-image strip is rendered. Structural flag only — never the image URL or any PHI.',\n read: (handle) => handle.getHasCover(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'practice-profile-hero',\n description: 'Marks the PracticeProfileHero 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 forwardRef,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { Avatar } from '../avatar/avatar';\nimport { Badge } from '../badge/badge';\nimport { Card } from '../card/card';\nimport { Rating } from '../rating/rating';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { practiceProfileHeroAgent } from './practice-profile-hero.agent';\n\n/* -------------------------------------------------------------------- */\n/* PracticeProfileHero */\n/* */\n/* The practice-page counterpart to `<OperatorHero>` — the top-of-page */\n/* hero for a practice profile (booking site `/p/<seoUrl>`, marketplace */\n/* practice views). Differences from the operator hero: */\n/* */\n/* - Optional cover strip: renders ONLY when `coverImageUrl` is set. */\n/* A practice without a configured cover image gets no strip at all */\n/* — never an empty brand-gradient band eating page space. */\n/* - Larger avatar at desktop widths (3xl), stepped down to xl and */\n/* stacked above the text on small viewports so the practice name, */\n/* tagline and rating keep the full line width on phones. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n // Matches the kit's other `surface` props (Booking, ReviewsPanel,\n // OperatorHero). `'elevated'` wraps in `<Card>`.\n surface: {\n flat: '',\n elevated: '',\n },\n },\n defaultVariants: {\n surface: 'elevated',\n },\n});\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\nexport interface PracticeProfileHeroBadge {\n /** Display key — i18n is up to the consumer. */\n key: string;\n /** Display label. */\n label: string;\n /** Badge variant — falls back to `neutral`. */\n variant?: 'neutral' | 'info' | 'success' | 'warning' | 'error';\n}\n\nexport interface PracticeProfileHeroRating {\n /** Mean rating, 0–5. */\n value: number;\n /** Total number of reviews. */\n count: number;\n}\n\nexport interface PracticeProfileHeroHandle {\n getName: () => string;\n /** Structural flag — whether a cover strip is rendered. No PHI. */\n getHasCover: () => boolean;\n}\n\nexport interface PracticeProfileHeroProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children'\n> {\n /** Practice display name. Rendered as the H1 heading. */\n name: string;\n /** Slogan / tagline subtitle (e.g. \"15 anni di esperienza nel cuore di Brera\"). */\n tagline?: string;\n /**\n * Language of the practice's own text (the tagline), as a BCP 47 tag such\n * as `\"it\"`. Written as `lang` on the tagline so a screen reader on a page\n * in another language pronounces it correctly. Leave it out and no `lang`\n * is written. The kit's own labels keep the page language.\n */\n contentLang?: string;\n /**\n * Optional practice photo / logo URL. The kit always renders an\n * `<Avatar>` — when `imageUrl` is missing the avatar falls back to\n * initials.\n */\n imageUrl?: string;\n /**\n * Text alternative for the photo's `<img>`, for image search and crawlers.\n * Pass the practice name. Leave it out and the photo stays decorative\n * (`alt=\"\"`), as before. Added in 1.91.0.\n */\n imageAlt?: string;\n /**\n * Optional cover image painted as a full-width strip above the body.\n * The strip renders ONLY when this is set — a practice without a cover\n * image gets no strip (and no empty gradient band). While the image\n * loads, the brand gradient shows in the strip. If it fails to load\n * (404, 401, not an image), the strip goes, as if no cover had been\n * passed, and `data-has-cover` reads `\"false\"`. A different URL tries\n * again.\n */\n coverImageUrl?: string;\n /** Rating summary — when present, renders a Rating + numeric breakdown line. */\n rating?: PracticeProfileHeroRating;\n /**\n * Optional badge row beneath the rating. Use sparingly — 1–3 chips\n * suit the hero's density; longer lists belong in `<ContactProfileCard>`.\n */\n badges?: PracticeProfileHeroBadge[];\n\n /* ----- Slots ----- */\n\n /**\n * Rendered at the inline-end of the heading row (right side on LTR)\n * from `sm` up. The heading row wraps, so on a phone the action drops\n * onto its own line, starts flush with the practice name, and is free\n * to shrink into the column rather than overflow it.\n *\n * Use for a \"Book an appointment\" `<Button>` or a share action.\n */\n actionSlot?: ReactNode;\n\n /* ----- Styling ----- */\n\n /**\n * `elevated` (default) wraps in `<Card variant=\"elevated\">`. `flat`\n * drops the Card — use inside another card / sheet.\n */\n surface?: 'flat' | 'elevated';\n\n /* ----- a11y ----- */\n\n 'aria-label'?: string;\n id?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const PracticeProfileHero = forwardRef<\n HTMLDivElement,\n PracticeProfileHeroProps\n>(\n (\n {\n name,\n tagline,\n contentLang,\n imageUrl,\n imageAlt,\n coverImageUrl,\n rating,\n badges,\n actionSlot,\n surface = 'elevated',\n 'aria-label': ariaLabel,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const headingId = useId();\n\n // HTP-6708. A CSS background cannot report a failed load, so the URL\n // is probed with an Image (the browser serves both from one request).\n // The strip reserves its height while the image loads, with the brand\n // gradient showing: a cover that loads causes no layout shift, and one\n // that fails removes the strip in a single step. The outcome is kept\n // per URL, so a new URL starts loading again and is retried.\n const [coverOutcome, setCoverOutcome] = useState<{\n url: string;\n status: 'loaded' | 'error';\n } | null>(null);\n const coverStatus =\n coverImageUrl && coverOutcome?.url === coverImageUrl\n ? coverOutcome.status\n : 'loading';\n useEffect(() => {\n if (!coverImageUrl || typeof Image === 'undefined') return undefined;\n let current = true;\n const probe = new Image();\n probe.onload = () => {\n if (current) setCoverOutcome({ url: coverImageUrl, status: 'loaded' });\n };\n probe.onerror = () => {\n if (current) setCoverOutcome({ url: coverImageUrl, status: 'error' });\n };\n probe.src = coverImageUrl;\n return () => {\n current = false;\n probe.onload = null;\n probe.onerror = null;\n };\n }, [coverImageUrl]);\n const hasCover = Boolean(coverImageUrl) && coverStatus !== 'error';\n\n // Memoised so the registry doesn't see a fresh handle identity (and\n // fire unregister+register) on every render — mirrors Booking.\n const agentHandle = useMemo(\n () => ({ getName: () => name, getHasCover: () => hasCover }),\n [name, hasCover],\n );\n useAgentRegistration(practiceProfileHeroAgent, agentHandle, id);\n\n // Cover image URL lands as a component-scoped CSS custom property set\n // imperatively on a ref — mirrors the Avatar `--avatar-color-override`\n // idiom so no `style={{…}}` attribute lands on the JSX (constraint §4).\n const coverRef = useRef<HTMLDivElement>(null);\n useIsomorphicLayoutEffect(() => {\n const el = coverRef.current;\n if (!el) return;\n if (coverImageUrl) {\n el.style.setProperty(\n '--practice-profile-hero-cover',\n `url(\"${coverImageUrl.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\")`,\n );\n } else {\n el.style.removeProperty('--practice-profile-hero-cover');\n }\n // `hasCover`: the strip can come back (a new URL after a failure),\n // and the new element needs the property too.\n }, [coverImageUrl, hasCover]);\n\n const cover = hasCover ? (\n <div\n ref={coverRef}\n aria-hidden=\"true\"\n data-slot=\"cover\"\n data-state={coverStatus}\n className={[\n 'ds:h-32 ds:sm:h-40 ds:w-full',\n // Cover image layered over the brand gradient — the gradient is\n // the visible underlay while the image streams in. A failed image\n // removes the strip (see above). The `none` fallback keeps the\n // declaration valid before the layout effect sets the custom\n // property (SSR / first paint).\n 'ds:bg-[image:var(--practice-profile-hero-cover,none),var(--gradient-hero-brand)]',\n 'ds:bg-cover ds:bg-center',\n ].join(' ')}\n />\n ) : null;\n\n // Decorative unless the caller wrote alt text for a photo that shows.\n const photoHidden = !(imageUrl && imageAlt);\n\n const body = (\n <div\n className={[\n // Phones: stacked column, smaller avatar — the practice name,\n // tagline and rating keep the full line width instead of being\n // squeezed beside a 3xl avatar. sm+: classic row layout.\n 'ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-md)]',\n 'ds:sm:flex-row ds:sm:gap-[var(--spacing-lg)]',\n ].join(' ')}\n >\n {/* Responsive avatar — `ds:hidden` removes the inactive size from\n both the layout and the accessibility tree. Without `imageAlt`\n both renders are aria-hidden: the H1 right beside them already\n carries the practice name, so the avatar is decorative. With\n `imageAlt` (and a photo) the photo is reachable and its alt is\n what a screen reader reads (HTP-7074). */}\n {/* HTP-6712: the practice photo is a 4:3 rounded rectangle, filled\n and cropped from the centre. It keeps the old circle's height\n (64px on phones, 192px from sm), so the hero does not grow. */}\n <div className=\"ds:shrink-0 ds:sm:hidden\">\n <Avatar\n size=\"xl\"\n shape=\"rounded\"\n ratio=\"4:3\"\n width={85}\n height={64}\n name={name}\n src={imageUrl}\n alt={imageAlt}\n aria-hidden={photoHidden ? 'true' : undefined}\n />\n </div>\n <div className=\"ds:hidden ds:shrink-0 ds:sm:block\">\n <Avatar\n size=\"3xl\"\n shape=\"rounded\"\n ratio=\"4:3\"\n width={256}\n height={192}\n name={name}\n src={imageUrl}\n alt={imageAlt}\n aria-hidden={photoHidden ? 'true' : undefined}\n />\n </div>\n <div className=\"ds:flex ds:w-full ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-start ds:gap-[var(--spacing-md)]\">\n {/* The practice's own words (name, tagline) keep the direction\n they were typed in, not the page's: `dir=\"auto\"`. */}\n <h1\n id={headingId}\n dir=\"auto\"\n className=\"type-title-page ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {name}\n </h1>\n {actionSlot ? (\n // `ms-auto` + `shrink-0` are the desktop contract, and both are\n // wrong once the row wraps on a phone: they stranded the action\n // at the inline-end of a start-aligned stack and stopped a wide\n // control fitting the column. Hence `sm:` and up only.\n <div className=\"ds:flex ds:min-w-0 ds:items-center ds:gap-[var(--spacing-xs)] ds:sm:ms-auto ds:sm:shrink-0\">\n {actionSlot}\n </div>\n ) : null}\n </div>\n {tagline ? (\n <p\n lang={contentLang}\n dir=\"auto\"\n className=\"type-body ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {tagline}\n </p>\n ) : null}\n {rating ? (\n // Rating owns the whole line: locale-formatted value, plural-\n // aware review count, and a single role=\"img\" announcement.\n <Rating\n value={rating.value}\n max={5}\n size=\"md\"\n reviews={{ count: rating.count }}\n />\n ) : null}\n {badges && badges.length > 0 ? (\n <div\n role=\"list\"\n className=\"ds:mt-[var(--spacing-2xs)] ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-2xs)]\"\n >\n {badges.map((badge) => (\n <Badge\n key={badge.key}\n variant={badge.variant ?? 'neutral'}\n role=\"listitem\"\n >\n {badge.label}\n </Badge>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n );\n\n return (\n <div\n ref={ref}\n role=\"region\"\n // A consumer-supplied aria-label wins; otherwise the region is\n // named by the practice-name H1 via aria-labelledby.\n aria-label={ariaLabel}\n aria-labelledby={ariaLabel ? undefined : headingId}\n data-component=\"practice-profile-hero\"\n data-component-id={id}\n data-has-cover={hasCover ? 'true' : 'false'}\n id={id}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {surface === 'elevated' ? (\n <Card variant=\"elevated\">\n {cover}\n <Card.Body>{body}</Card.Body>\n </Card>\n ) : (\n <>\n {cover}\n <div className=\"ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]\">\n {body}\n </div>\n </>\n )}\n </div>\n );\n },\n);\n\nPracticeProfileHero.displayName = 'PracticeProfileHero';\n"],"names":["practiceProfileHeroAgent","handle","rootVariants","cva","PracticeProfileHero","forwardRef","name","tagline","contentLang","imageUrl","imageAlt","coverImageUrl","rating","badges","actionSlot","surface","ariaLabel","id","className","rest","ref","headingId","useId","coverOutcome","setCoverOutcome","useState","coverStatus","useEffect","current","probe","hasCover","agentHandle","useMemo","useAgentRegistration","coverRef","useRef","useIsomorphicLayoutEffect","el","cover","jsx","photoHidden","body","jsxs","Avatar","Rating","badge","Badge","Card","Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"practice-profile-hero-Cw4NZp0A.js","sources":["../../src/components/practice-profile-hero/practice-profile-hero.agent.ts","../../src/components/practice-profile-hero/practice-profile-hero.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { PracticeProfileHeroHandle } from './practice-profile-hero';\n\nexport const practiceProfileHeroAgent: AgentAdapter<PracticeProfileHeroHandle> =\n {\n id: 'practice-profile-hero',\n // Purely observable hero region — no interactive affordances and no\n // imperative actions on the handle (getName / getHasCover are read-only\n // projections).\n capabilities: [],\n state: {\n name: {\n type: 'string',\n descriptionKey: 'ui.agent.practiceProfileHero.state.name',\n description: 'Practice display name currently rendered.',\n read: (handle) => handle.getName(),\n },\n hasCover: {\n type: 'boolean',\n descriptionKey: 'ui.agent.practiceProfileHero.state.hasCover',\n description:\n 'Whether a cover-image strip is rendered. Structural flag only — never the image URL or any PHI.',\n read: (handle) => handle.getHasCover(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'practice-profile-hero',\n description: 'Marks the PracticeProfileHero 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 forwardRef,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { Avatar } from '../avatar/avatar';\nimport { Badge } from '../badge/badge';\nimport { Card } from '../card/card';\nimport { Rating } from '../rating/rating';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { practiceProfileHeroAgent } from './practice-profile-hero.agent';\n\n/* -------------------------------------------------------------------- */\n/* PracticeProfileHero */\n/* */\n/* The practice-page counterpart to `<OperatorHero>` — the top-of-page */\n/* hero for a practice profile (booking site `/p/<seoUrl>`, marketplace */\n/* practice views). Differences from the operator hero: */\n/* */\n/* - Optional cover strip: renders ONLY when `coverImageUrl` is set. */\n/* A practice without a configured cover image gets no strip at all */\n/* — never an empty brand-gradient band eating page space. */\n/* - Larger avatar at desktop widths (3xl), stepped down to xl and */\n/* stacked above the text on small viewports so the practice name, */\n/* tagline and rating keep the full line width on phones. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n // Matches the kit's other `surface` props (Booking, ReviewsPanel,\n // OperatorHero). `'elevated'` wraps in `<Card>`.\n surface: {\n flat: '',\n elevated: '',\n },\n },\n defaultVariants: {\n surface: 'elevated',\n },\n});\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\nexport interface PracticeProfileHeroBadge {\n /** Display key — i18n is up to the consumer. */\n key: string;\n /** Display label. */\n label: string;\n /** Badge variant — falls back to `neutral`. */\n variant?: 'neutral' | 'info' | 'success' | 'warning' | 'error';\n}\n\nexport interface PracticeProfileHeroRating {\n /** Mean rating, 0–5. */\n value: number;\n /** Total number of reviews. */\n count: number;\n}\n\nexport interface PracticeProfileHeroHandle {\n getName: () => string;\n /** Structural flag — whether a cover strip is rendered. No PHI. */\n getHasCover: () => boolean;\n}\n\nexport interface PracticeProfileHeroProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children'\n> {\n /** Practice display name. Rendered as the H1 heading. */\n name: string;\n /** Slogan / tagline subtitle (e.g. \"15 anni di esperienza nel cuore di Brera\"). */\n tagline?: string;\n /**\n * Language of the practice's own text (the tagline), as a BCP 47 tag such\n * as `\"it\"`. Written as `lang` on the tagline so a screen reader on a page\n * in another language pronounces it correctly. Leave it out and no `lang`\n * is written. The kit's own labels keep the page language.\n */\n contentLang?: string;\n /**\n * Optional practice photo / logo URL. The kit always renders an\n * `<Avatar>` — when `imageUrl` is missing the avatar falls back to\n * initials.\n */\n imageUrl?: string;\n /**\n * Text alternative for the photo's `<img>`, for image search and crawlers.\n * Pass the practice name. Leave it out and the photo stays decorative\n * (`alt=\"\"`), as before. Added in 1.91.0.\n */\n imageAlt?: string;\n /**\n * Optional cover image painted as a full-width strip above the body.\n * The strip renders ONLY when this is set — a practice without a cover\n * image gets no strip (and no empty gradient band). While the image\n * loads, the brand gradient shows in the strip. If it fails to load\n * (404, 401, not an image), the strip goes, as if no cover had been\n * passed, and `data-has-cover` reads `\"false\"`. A different URL tries\n * again.\n */\n coverImageUrl?: string;\n /** Rating summary — when present, renders a Rating + numeric breakdown line. */\n rating?: PracticeProfileHeroRating;\n /**\n * Optional badge row beneath the rating. Use sparingly — 1–3 chips\n * suit the hero's density; longer lists belong in `<ContactProfileCard>`.\n */\n badges?: PracticeProfileHeroBadge[];\n\n /* ----- Slots ----- */\n\n /**\n * Rendered at the inline-end of the heading row (right side on LTR)\n * from `sm` up. The heading row wraps, so on a phone the action drops\n * onto its own line, starts flush with the practice name, and is free\n * to shrink into the column rather than overflow it.\n *\n * Use for a \"Book an appointment\" `<Button>` or a share action.\n */\n actionSlot?: ReactNode;\n\n /* ----- Styling ----- */\n\n /**\n * `elevated` (default) wraps in `<Card variant=\"elevated\">`. `flat`\n * drops the Card — use inside another card / sheet.\n */\n surface?: 'flat' | 'elevated';\n\n /* ----- a11y ----- */\n\n 'aria-label'?: string;\n id?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const PracticeProfileHero = forwardRef<\n HTMLDivElement,\n PracticeProfileHeroProps\n>(\n (\n {\n name,\n tagline,\n contentLang,\n imageUrl,\n imageAlt,\n coverImageUrl,\n rating,\n badges,\n actionSlot,\n surface = 'elevated',\n 'aria-label': ariaLabel,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const headingId = useId();\n\n // HTP-6708. A CSS background cannot report a failed load, so the URL\n // is probed with an Image (the browser serves both from one request).\n // The strip reserves its height while the image loads, with the brand\n // gradient showing: a cover that loads causes no layout shift, and one\n // that fails removes the strip in a single step. The outcome is kept\n // per URL, so a new URL starts loading again and is retried.\n const [coverOutcome, setCoverOutcome] = useState<{\n url: string;\n status: 'loaded' | 'error';\n } | null>(null);\n const coverStatus =\n coverImageUrl && coverOutcome?.url === coverImageUrl\n ? coverOutcome.status\n : 'loading';\n useEffect(() => {\n if (!coverImageUrl || typeof Image === 'undefined') return undefined;\n let current = true;\n const probe = new Image();\n probe.onload = () => {\n if (current) setCoverOutcome({ url: coverImageUrl, status: 'loaded' });\n };\n probe.onerror = () => {\n if (current) setCoverOutcome({ url: coverImageUrl, status: 'error' });\n };\n probe.src = coverImageUrl;\n return () => {\n current = false;\n probe.onload = null;\n probe.onerror = null;\n };\n }, [coverImageUrl]);\n const hasCover = Boolean(coverImageUrl) && coverStatus !== 'error';\n\n // Memoised so the registry doesn't see a fresh handle identity (and\n // fire unregister+register) on every render — mirrors Booking.\n const agentHandle = useMemo(\n () => ({ getName: () => name, getHasCover: () => hasCover }),\n [name, hasCover],\n );\n useAgentRegistration(practiceProfileHeroAgent, agentHandle, id);\n\n // Cover image URL lands as a component-scoped CSS custom property set\n // imperatively on a ref — mirrors the Avatar `--avatar-color-override`\n // idiom so no `style={{…}}` attribute lands on the JSX (constraint §4).\n const coverRef = useRef<HTMLDivElement>(null);\n useIsomorphicLayoutEffect(() => {\n const el = coverRef.current;\n if (!el) return;\n if (coverImageUrl) {\n el.style.setProperty(\n '--practice-profile-hero-cover',\n `url(\"${coverImageUrl.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\")`,\n );\n } else {\n el.style.removeProperty('--practice-profile-hero-cover');\n }\n // `hasCover`: the strip can come back (a new URL after a failure),\n // and the new element needs the property too.\n }, [coverImageUrl, hasCover]);\n\n const cover = hasCover ? (\n <div\n ref={coverRef}\n aria-hidden=\"true\"\n data-slot=\"cover\"\n data-state={coverStatus}\n className={[\n 'ds:h-32 ds:sm:h-40 ds:w-full',\n // Cover image layered over the brand gradient — the gradient is\n // the visible underlay while the image streams in. A failed image\n // removes the strip (see above). The `none` fallback keeps the\n // declaration valid before the layout effect sets the custom\n // property (SSR / first paint).\n 'ds:bg-[image:var(--practice-profile-hero-cover,none),var(--gradient-hero-brand)]',\n 'ds:bg-cover ds:bg-center',\n ].join(' ')}\n />\n ) : null;\n\n // Decorative unless the caller wrote alt text for a photo that shows.\n const photoHidden = !(imageUrl && imageAlt);\n\n const body = (\n <div\n className={[\n // Phones: stacked column, smaller avatar — the practice name,\n // tagline and rating keep the full line width instead of being\n // squeezed beside a 3xl avatar. sm+: classic row layout.\n 'ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-md)]',\n 'ds:sm:flex-row ds:sm:gap-[var(--spacing-lg)]',\n ].join(' ')}\n >\n {/* Responsive avatar — `ds:hidden` removes the inactive size from\n both the layout and the accessibility tree. Without `imageAlt`\n both renders are aria-hidden: the H1 right beside them already\n carries the practice name, so the avatar is decorative. With\n `imageAlt` (and a photo) the photo is reachable and its alt is\n what a screen reader reads (HTP-7074). */}\n {/* HTP-6712: the practice photo is a 4:3 rounded rectangle, filled\n and cropped from the centre. It keeps the old circle's height\n (64px on phones, 192px from sm), so the hero does not grow. */}\n <div className=\"ds:shrink-0 ds:sm:hidden\">\n <Avatar\n size=\"xl\"\n shape=\"rounded\"\n ratio=\"4:3\"\n width={85}\n height={64}\n name={name}\n src={imageUrl}\n alt={imageAlt}\n aria-hidden={photoHidden ? 'true' : undefined}\n />\n </div>\n <div className=\"ds:hidden ds:shrink-0 ds:sm:block\">\n <Avatar\n size=\"3xl\"\n shape=\"rounded\"\n ratio=\"4:3\"\n width={256}\n height={192}\n name={name}\n src={imageUrl}\n alt={imageAlt}\n aria-hidden={photoHidden ? 'true' : undefined}\n />\n </div>\n <div className=\"ds:flex ds:w-full ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-start ds:gap-[var(--spacing-md)]\">\n {/* The practice's own words (name, tagline) keep the direction\n they were typed in, not the page's: `dir=\"auto\"`. */}\n <h1\n id={headingId}\n dir=\"auto\"\n className=\"type-title-page ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {name}\n </h1>\n {actionSlot ? (\n // `ms-auto` + `shrink-0` are the desktop contract, and both are\n // wrong once the row wraps on a phone: they stranded the action\n // at the inline-end of a start-aligned stack and stopped a wide\n // control fitting the column. Hence `sm:` and up only.\n <div className=\"ds:flex ds:min-w-0 ds:items-center ds:gap-[var(--spacing-xs)] ds:sm:ms-auto ds:sm:shrink-0\">\n {actionSlot}\n </div>\n ) : null}\n </div>\n {tagline ? (\n <p\n lang={contentLang}\n dir=\"auto\"\n className=\"type-body ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {tagline}\n </p>\n ) : null}\n {rating ? (\n // Rating owns the whole line: locale-formatted value, plural-\n // aware review count, and a single role=\"img\" announcement.\n <Rating\n value={rating.value}\n max={5}\n size=\"md\"\n reviews={{ count: rating.count }}\n />\n ) : null}\n {badges && badges.length > 0 ? (\n <div\n role=\"list\"\n className=\"ds:mt-[var(--spacing-2xs)] ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-2xs)]\"\n >\n {badges.map((badge) => (\n <Badge\n key={badge.key}\n variant={badge.variant ?? 'neutral'}\n role=\"listitem\"\n >\n {badge.label}\n </Badge>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n );\n\n return (\n <div\n ref={ref}\n role=\"region\"\n // A consumer-supplied aria-label wins; otherwise the region is\n // named by the practice-name H1 via aria-labelledby.\n aria-label={ariaLabel}\n aria-labelledby={ariaLabel ? undefined : headingId}\n data-component=\"practice-profile-hero\"\n data-component-id={id}\n data-has-cover={hasCover ? 'true' : 'false'}\n id={id}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {surface === 'elevated' ? (\n <Card variant=\"elevated\">\n {cover}\n <Card.Body>{body}</Card.Body>\n </Card>\n ) : (\n <>\n {cover}\n <div className=\"ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]\">\n {body}\n </div>\n </>\n )}\n </div>\n );\n },\n);\n\nPracticeProfileHero.displayName = 'PracticeProfileHero';\n"],"names":["practiceProfileHeroAgent","handle","rootVariants","cva","PracticeProfileHero","forwardRef","name","tagline","contentLang","imageUrl","imageAlt","coverImageUrl","rating","badges","actionSlot","surface","ariaLabel","id","className","rest","ref","headingId","useId","coverOutcome","setCoverOutcome","useState","coverStatus","useEffect","current","probe","hasCover","agentHandle","useMemo","useAgentRegistration","coverRef","useRef","useIsomorphicLayoutEffect","el","cover","jsx","photoHidden","body","jsxs","Avatar","Rating","badge","Badge","Card","Fragment"],"mappings":";;;;;;;;;AAGO,MAAMA,IACX;AAAA,EACE,IAAI;AAAA;AAAA;AAAA;AAAA,EAIJ,cAAc,CAAA;AAAA,EACd,OAAO;AAAA,IACL,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACC,MAAWA,EAAO,QAAA;AAAA,IAAQ;AAAA,IAEnC,UAAU;AAAA,MACR,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACA,MAAWA,EAAO,YAAA;AAAA,IAAY;AAAA,EACvC;AAAA,EAEF,SAAS,CAAA;AAAA,EACT,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,IAEf,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,aAAa;AAAA,IAAA;AAAA,EACf;AAEJ,GCAIC,IAAeC,EAAI,+CAA+C;AAAA,EACtE,UAAU;AAAA;AAAA;AAAA,IAGR,SAAS;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,EACZ;AAAA,EAEF,iBAAiB;AAAA,IACf,SAAS;AAAA,EAAA;AAEb,CAAC,GAuGYC,IAAsBC;AAAA,EAIjC,CACE;AAAA,IACE,MAAAC;AAAA,IACA,SAAAC;AAAA,IACA,aAAAC;AAAA,IACA,UAAAC;AAAA,IACA,UAAAC;AAAA,IACA,eAAAC;AAAA,IACA,QAAAC;AAAA,IACA,QAAAC;AAAA,IACA,YAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,cAAcC;AAAA,IACd,IAAAC;AAAA,IACA,WAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAMC,IAAYC,EAAA,GAQZ,CAACC,GAAcC,CAAe,IAAIC,EAG9B,IAAI,GACRC,IACJf,MAAiBY,KAAA,gBAAAA,EAAc,SAAQZ,IACnCY,EAAa,SACb;AACN,IAAAI,EAAU,MAAM;AACd,UAAI,CAAChB,KAAiB,OAAO,QAAU,IAAa;AACpD,UAAIiB,IAAU;AACd,YAAMC,IAAQ,IAAI,MAAA;AAClB,aAAAA,EAAM,SAAS,MAAM;AACnB,QAAID,KAASJ,EAAgB,EAAE,KAAKb,GAAe,QAAQ,UAAU;AAAA,MACvE,GACAkB,EAAM,UAAU,MAAM;AACpB,QAAID,KAASJ,EAAgB,EAAE,KAAKb,GAAe,QAAQ,SAAS;AAAA,MACtE,GACAkB,EAAM,MAAMlB,GACL,MAAM;AACX,QAAAiB,IAAU,IACVC,EAAM,SAAS,MACfA,EAAM,UAAU;AAAA,MAClB;AAAA,IACF,GAAG,CAAClB,CAAa,CAAC;AAClB,UAAMmB,IAAW,EAAQnB,KAAkBe,MAAgB,SAIrDK,IAAcC;AAAA,MAClB,OAAO,EAAE,SAAS,MAAM1B,GAAM,aAAa,MAAMwB,EAAA;AAAA,MACjD,CAACxB,GAAMwB,CAAQ;AAAA,IAAA;AAEjB,IAAAG,EAAqBjC,GAA0B+B,GAAad,CAAE;AAK9D,UAAMiB,IAAWC,EAAuB,IAAI;AAC5C,IAAAC,EAA0B,MAAM;AAC9B,YAAMC,IAAKH,EAAS;AACpB,MAAKG,MACD1B,IACF0B,EAAG,MAAM;AAAA,QACP;AAAA,QACA,QAAQ1B,EAAc,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK,CAAC;AAAA,MAAA,IAGnE0B,EAAG,MAAM,eAAe,+BAA+B;AAAA,IAI3D,GAAG,CAAC1B,GAAemB,CAAQ,CAAC;AAE5B,UAAMQ,IAAQR,IACZ,gBAAAS;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKL;AAAA,QACL,eAAY;AAAA,QACZ,aAAU;AAAA,QACV,cAAYR;AAAA,QACZ,WAAW;AAAA,UACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,MAAA;AAAA,IAAA,IAEV,MAGEc,IAAc,EAAE/B,KAAYC,IAE5B+B,IACJ,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW;AAAA;AAAA;AAAA;AAAA,UAIT;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,QAWV,UAAA;AAAA,UAAA,gBAAAH,EAAC,OAAA,EAAI,WAAU,4BACb,UAAA,gBAAAA;AAAA,YAACI;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAM;AAAA,cACN,OAAM;AAAA,cACN,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,MAAArC;AAAA,cACA,KAAKG;AAAA,cACL,KAAKC;AAAA,cACL,eAAa8B,IAAc,SAAS;AAAA,YAAA;AAAA,UAAA,GAExC;AAAA,UACA,gBAAAD,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA,gBAAAA;AAAA,YAACI;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAM;AAAA,cACN,OAAM;AAAA,cACN,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,MAAArC;AAAA,cACA,KAAKG;AAAA,cACL,KAAKC;AAAA,cACL,eAAa8B,IAAc,SAAS;AAAA,YAAA;AAAA,UAAA,GAExC;AAAA,UACA,gBAAAE,EAAC,OAAA,EAAI,WAAU,iFACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,kEAGb,UAAA;AAAA,cAAA,gBAAAH;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAIlB;AAAA,kBACJ,KAAI;AAAA,kBACJ,WAAU;AAAA,kBAET,UAAAf;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEFQ;AAAA;AAAA;AAAA;AAAA;AAAA,gBAKC,gBAAAyB,EAAC,OAAA,EAAI,WAAU,8FACZ,UAAAzB,EAAA,CACH;AAAA,kBACE;AAAA,YAAA,GACN;AAAA,YACCP,IACC,gBAAAgC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAM/B;AAAA,gBACN,KAAI;AAAA,gBACJ,WAAU;AAAA,gBAET,UAAAD;AAAA,cAAA;AAAA,YAAA,IAED;AAAA,YACHK;AAAA;AAAA;AAAA,cAGC,gBAAA2B;AAAA,gBAACK;AAAA,gBAAA;AAAA,kBACC,OAAOhC,EAAO;AAAA,kBACd,KAAK;AAAA,kBACL,MAAK;AAAA,kBACL,SAAS,EAAE,OAAOA,EAAO,MAAA;AAAA,gBAAM;AAAA,cAAA;AAAA,gBAE/B;AAAA,YACHC,KAAUA,EAAO,SAAS,IACzB,gBAAA0B;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBAET,UAAA1B,EAAO,IAAI,CAACgC,MACX,gBAAAN;AAAA,kBAACO;AAAA,kBAAA;AAAA,oBAEC,SAASD,EAAM,WAAW;AAAA,oBAC1B,MAAK;AAAA,oBAEJ,UAAAA,EAAM;AAAA,kBAAA;AAAA,kBAJFA,EAAM;AAAA,gBAAA,CAMd;AAAA,cAAA;AAAA,YAAA,IAED;AAAA,UAAA,EAAA,CACN;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAIJ,WACE,gBAAAN;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAnB;AAAA,QACA,MAAK;AAAA,QAGL,cAAYJ;AAAA,QACZ,mBAAiBA,IAAY,SAAYK;AAAA,QACzC,kBAAe;AAAA,QACf,qBAAmBJ;AAAA,QACnB,kBAAgBa,IAAW,SAAS;AAAA,QACpC,IAAAb;AAAA,QACA,WAAWf,EAAa,EAAE,SAAAa,GAAS,WAAAG,GAAW;AAAA,QAC7C,GAAGC;AAAA,QAEH,UAAAJ,MAAY,aACX,gBAAA2B,EAACK,GAAA,EAAK,SAAQ,YACX,UAAA;AAAA,UAAAT;AAAA,UACD,gBAAAC,EAACQ,EAAK,MAAL,EAAW,UAAAN,EAAA,CAAK;AAAA,QAAA,EAAA,CACnB,IAEA,gBAAAC,EAAAM,GAAA,EACG,UAAA;AAAA,UAAAV;AAAA,UACD,gBAAAC,EAAC,OAAA,EAAI,WAAU,uDACZ,UAAAE,EAAA,CACH;AAAA,QAAA,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEArC,EAAoB,cAAc;"}