@alfadocs/ui-kit-debug 1.128.0 → 1.130.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 (300) hide show
  1. package/dist/_chunks/{appointment-card-0PebvrOS.js → appointment-card-vbUsDh70.js} +49 -72
  2. package/dist/_chunks/appointment-card-vbUsDh70.js.map +1 -0
  3. package/dist/_chunks/{appointment-timeline-Czd4PBkF.js → appointment-timeline-B5pfBl-b.js} +2 -2
  4. package/dist/_chunks/{appointment-timeline-Czd4PBkF.js.map → appointment-timeline-B5pfBl-b.js.map} +1 -1
  5. package/dist/_chunks/{appointment-tray-B04zKY7g.js → appointment-tray-BhiXetjs.js} +2 -2
  6. package/dist/_chunks/{appointment-tray-B04zKY7g.js.map → appointment-tray-BhiXetjs.js.map} +1 -1
  7. package/dist/_chunks/{calendar-_sgjuH3L.js → calendar-DzR-vdJ5.js} +614 -563
  8. package/dist/_chunks/calendar-DzR-vdJ5.js.map +1 -0
  9. package/dist/_chunks/calendar-appointment-editor-dialog-CXch4Pmu.js +13663 -0
  10. package/dist/_chunks/calendar-appointment-editor-dialog-CXch4Pmu.js.map +1 -0
  11. package/dist/_chunks/{calendar-event-card-DXAYWH6k.js → calendar-event-card-BNEzkjm-.js} +142 -132
  12. package/dist/_chunks/calendar-event-card-BNEzkjm-.js.map +1 -0
  13. package/dist/_chunks/{care-plan-card-bGTIliXc.js → care-plan-card-CwgkImOD.js} +2 -2
  14. package/dist/_chunks/{care-plan-card-bGTIliXc.js.map → care-plan-card-CwgkImOD.js.map} +1 -1
  15. package/dist/_chunks/{care-plan-header-k8FslxsU.js → care-plan-header-Dx5OMkc9.js} +2 -2
  16. package/dist/_chunks/{care-plan-header-k8FslxsU.js.map → care-plan-header-Dx5OMkc9.js.map} +1 -1
  17. package/dist/_chunks/{clinical-note-card-DHn5W_bv.js → clinical-note-card-pPaeWWnu.js} +2 -2
  18. package/dist/_chunks/{clinical-note-card-DHn5W_bv.js.map → clinical-note-card-pPaeWWnu.js.map} +1 -1
  19. package/dist/_chunks/{contact-card-CGpbYuxl.js → contact-card-BSY2YpLZ.js} +2 -2
  20. package/dist/_chunks/{contact-card-CGpbYuxl.js.map → contact-card-BSY2YpLZ.js.map} +1 -1
  21. package/dist/_chunks/{contact-profile-card-CCgf0Ntt.js → contact-profile-card-CsZNMlws.js} +2 -2
  22. package/dist/_chunks/{contact-profile-card-CCgf0Ntt.js.map → contact-profile-card-CsZNMlws.js.map} +1 -1
  23. package/dist/_chunks/contact-round-DiSvB3LP.js +18 -0
  24. package/dist/_chunks/contact-round-DiSvB3LP.js.map +1 -0
  25. package/dist/_chunks/{default-tabs-DOuHEKI5.js → default-tabs-BnB6FUEW.js} +2 -2
  26. package/dist/_chunks/{default-tabs-DOuHEKI5.js.map → default-tabs-BnB6FUEW.js.map} +1 -1
  27. package/dist/_chunks/{entity-summary-BanguTa6.js → entity-summary-KHM0PnSI.js} +56 -68
  28. package/dist/_chunks/entity-summary-KHM0PnSI.js.map +1 -0
  29. package/dist/_chunks/file-pen-line-k4uMBM3h.js +29 -0
  30. package/dist/_chunks/file-pen-line-k4uMBM3h.js.map +1 -0
  31. package/dist/_chunks/{header-settings-DsvheAOt.js → header-settings-ZGvYAuKF.js} +101 -97
  32. package/dist/_chunks/header-settings-ZGvYAuKF.js.map +1 -0
  33. package/dist/_chunks/{info-tip-C-MPkShR.js → info-tip-B3cn3fY2.js} +2 -2
  34. package/dist/_chunks/{info-tip-C-MPkShR.js.map → info-tip-B3cn3fY2.js.map} +1 -1
  35. package/dist/_chunks/{link-DtCfnLnF.js → link-CeV7FoI6.js} +2 -2
  36. package/dist/_chunks/{link-DtCfnLnF.js.map → link-CeV7FoI6.js.map} +1 -1
  37. package/dist/_chunks/{marketplace-app-shell-BOBWmzoT.js → marketplace-app-shell-D_HA8CKx.js} +2 -2
  38. package/dist/_chunks/{marketplace-app-shell-BOBWmzoT.js.map → marketplace-app-shell-D_HA8CKx.js.map} +1 -1
  39. package/dist/_chunks/{nav-grid-D2xVcHTO.js → nav-grid-dEgDAri3.js} +2 -2
  40. package/dist/_chunks/{nav-grid-D2xVcHTO.js.map → nav-grid-dEgDAri3.js.map} +1 -1
  41. package/dist/_chunks/{note-attachment-cnj2JRrg.js → note-attachment-MNTIqdSz.js} +2 -2
  42. package/dist/_chunks/{note-attachment-cnj2JRrg.js.map → note-attachment-MNTIqdSz.js.map} +1 -1
  43. package/dist/_chunks/{note-timeline-BrjHBQfx.js → note-timeline-BQeW0VZY.js} +2 -2
  44. package/dist/_chunks/{note-timeline-BrjHBQfx.js.map → note-timeline-BQeW0VZY.js.map} +1 -1
  45. package/dist/_chunks/{notes-panel-n1JFNQ5u.js → notes-panel-DIY7eNsq.js} +2 -2
  46. package/dist/_chunks/{notes-panel-n1JFNQ5u.js.map → notes-panel-DIY7eNsq.js.map} +1 -1
  47. package/dist/_chunks/{patient-details-Cba9HQj_.js → patient-details-DBtEITfE.js} +2 -2
  48. package/dist/_chunks/{patient-details-Cba9HQj_.js.map → patient-details-DBtEITfE.js.map} +1 -1
  49. package/dist/_chunks/{patient-field-row-CtDihADs.js → patient-field-row-a5d4QijH.js} +2 -2
  50. package/dist/_chunks/{patient-field-row-CtDihADs.js.map → patient-field-row-a5d4QijH.js.map} +1 -1
  51. package/dist/_chunks/{patient-search-D_S7joff.js → patient-search-OAwFgOW3.js} +2 -2
  52. package/dist/_chunks/{patient-search-D_S7joff.js.map → patient-search-OAwFgOW3.js.map} +1 -1
  53. package/dist/_chunks/{patient-summary-card-DnLdbtsw.js → patient-summary-card-BUcZ-gaL.js} +3 -3
  54. package/dist/_chunks/{patient-summary-card-DnLdbtsw.js.map → patient-summary-card-BUcZ-gaL.js.map} +1 -1
  55. package/dist/_chunks/{payment-request-card-CEIalOtr.js → payment-request-card-Dv4WbRBe.js} +2 -2
  56. package/dist/_chunks/{payment-request-card-CEIalOtr.js.map → payment-request-card-Dv4WbRBe.js.map} +1 -1
  57. package/dist/_chunks/{product-hub-panel-CqRJlmb7.js → product-hub-panel-a8wdVOUt.js} +2 -2
  58. package/dist/_chunks/{product-hub-panel-CqRJlmb7.js.map → product-hub-panel-a8wdVOUt.js.map} +1 -1
  59. package/dist/_chunks/{public-footer-C8UIzqLJ.js → public-footer-D0cqScpz.js} +2 -2
  60. package/dist/_chunks/{public-footer-C8UIzqLJ.js.map → public-footer-D0cqScpz.js.map} +1 -1
  61. package/dist/_chunks/{signature-request-Dzs0jZsd.js → signature-request-DW2PSp66.js} +3 -3
  62. package/dist/_chunks/{signature-request-Dzs0jZsd.js.map → signature-request-DW2PSp66.js.map} +1 -1
  63. package/dist/_chunks/{signed-out-frame-fUf7tqs3.js → signed-out-frame-Oa2e1yps.js} +2 -2
  64. package/dist/_chunks/{signed-out-frame-fUf7tqs3.js.map → signed-out-frame-Oa2e1yps.js.map} +1 -1
  65. package/dist/_chunks/task-editor-CVRrDqpe.js +1256 -0
  66. package/dist/_chunks/task-editor-CVRrDqpe.js.map +1 -0
  67. package/dist/_chunks/{toast-BNoN8Qjh.js → toast-DQ1Zu1kk.js} +264 -251
  68. package/dist/_chunks/{toast-BNoN8Qjh.js.map → toast-DQ1Zu1kk.js.map} +1 -1
  69. package/dist/_chunks/{treatment-receipt-1VnuinhY.js → treatment-receipt-BZzwvsnY.js} +73 -56
  70. package/dist/_chunks/treatment-receipt-BZzwvsnY.js.map +1 -0
  71. package/dist/_chunks/use-appointment-details-read-BrykoTOR.js +2475 -0
  72. package/dist/_chunks/use-appointment-details-read-BrykoTOR.js.map +1 -0
  73. package/dist/_chunks/{whatsapp-button-DV9JFmtq.js → whatsapp-button-XbozeDl_.js} +32 -25
  74. package/dist/_chunks/whatsapp-button-XbozeDl_.js.map +1 -0
  75. package/dist/agent-catalog.json +49 -16
  76. package/dist/agent-i18n/en.json +5 -5
  77. package/dist/browser-support.js +1 -1
  78. package/dist/components/_shared/patient-picker.d.ts +10 -0
  79. package/dist/components/_shared/patient-picker.d.ts.map +1 -1
  80. package/dist/components/appointment-card/index.js +2 -2
  81. package/dist/components/appointment-details-panel/appointment-details-panel.d.ts +30 -1
  82. package/dist/components/appointment-details-panel/appointment-details-panel.d.ts.map +1 -1
  83. package/dist/components/appointment-details-panel/appointment-details-panel.links.d.ts +15 -0
  84. package/dist/components/appointment-details-panel/appointment-details-panel.links.d.ts.map +1 -0
  85. package/dist/components/appointment-details-panel/appointment-details-panel.recurrence.d.ts +9 -0
  86. package/dist/components/appointment-details-panel/appointment-details-panel.recurrence.d.ts.map +1 -0
  87. package/dist/components/appointment-details-panel/appointment-details-panel.sections.d.ts +12 -3
  88. package/dist/components/appointment-details-panel/appointment-details-panel.sections.d.ts.map +1 -1
  89. package/dist/components/appointment-details-panel/appointment-details-panel.types.d.ts +63 -1
  90. package/dist/components/appointment-details-panel/appointment-details-panel.types.d.ts.map +1 -1
  91. package/dist/components/appointment-details-panel/index.d.ts +2 -1
  92. package/dist/components/appointment-details-panel/index.d.ts.map +1 -1
  93. package/dist/components/appointment-details-panel/index.js +5 -4
  94. package/dist/components/appointment-timeline/index.js +1 -1
  95. package/dist/components/bill-table/index.js +1 -1
  96. package/dist/components/calendar/calendar.d.ts +22 -0
  97. package/dist/components/calendar/calendar.d.ts.map +1 -1
  98. package/dist/components/calendar/index.js +1 -1
  99. package/dist/components/calendar-event-card/calendar-event-card.d.ts +8 -0
  100. package/dist/components/calendar-event-card/calendar-event-card.d.ts.map +1 -1
  101. package/dist/components/calendar-event-card/index.js +1 -1
  102. package/dist/components/care-plan-card/index.js +1 -1
  103. package/dist/components/care-plan-header/index.js +1 -1
  104. package/dist/components/clinical-note-card/index.js +1 -1
  105. package/dist/components/contact-card/index.js +1 -1
  106. package/dist/components/contact-profile-card/index.js +1 -1
  107. package/dist/components/entity-summary/index.js +1 -1
  108. package/dist/components/header-settings/header-settings.d.ts.map +1 -1
  109. package/dist/components/header-settings/index.js +1 -1
  110. package/dist/components/info-tip/index.js +1 -1
  111. package/dist/components/link/index.js +1 -1
  112. package/dist/components/nav-grid/index.js +1 -1
  113. package/dist/components/note-timeline/index.js +1 -1
  114. package/dist/components/notes-panel/index.js +1 -1
  115. package/dist/components/patient-details/index.js +1 -1
  116. package/dist/components/patient-search/index.js +1 -1
  117. package/dist/components/patient-summary-card/index.js +1 -1
  118. package/dist/components/payment-card/index.js +1 -1
  119. package/dist/components/product-hub-tray/index.js +1 -1
  120. package/dist/components/public-footer/index.js +1 -1
  121. package/dist/components/task-editor/index.js +1 -1
  122. package/dist/components/toast/index.js +1 -1
  123. package/dist/components/toast/toast.d.ts.map +1 -1
  124. package/dist/components/treatment-receipt/index.d.ts +2 -2
  125. package/dist/components/treatment-receipt/index.d.ts.map +1 -1
  126. package/dist/components/treatment-receipt/index.js +2 -1
  127. package/dist/components/treatment-receipt/treatment-receipt.d.ts +11 -1
  128. package/dist/components/treatment-receipt/treatment-receipt.d.ts.map +1 -1
  129. package/dist/components/whatsapp-button/index.js +1 -1
  130. package/dist/components/whatsapp-button/whatsapp-button.d.ts.map +1 -1
  131. package/dist/core.css +1 -1
  132. package/dist/fullcalendar.css +5 -1
  133. package/dist/host-compat.css +4 -1
  134. package/dist/i18n/locales/ar.d.ts +119 -4
  135. package/dist/i18n/locales/ar.d.ts.map +1 -1
  136. package/dist/i18n/locales/ar.js +130 -15
  137. package/dist/i18n/locales/ar.js.map +1 -1
  138. package/dist/i18n/locales/de.d.ts +119 -4
  139. package/dist/i18n/locales/de.d.ts.map +1 -1
  140. package/dist/i18n/locales/de.js +130 -15
  141. package/dist/i18n/locales/de.js.map +1 -1
  142. package/dist/i18n/locales/el.d.ts +119 -4
  143. package/dist/i18n/locales/el.d.ts.map +1 -1
  144. package/dist/i18n/locales/el.js +130 -15
  145. package/dist/i18n/locales/el.js.map +1 -1
  146. package/dist/i18n/locales/en.d.ts +119 -4
  147. package/dist/i18n/locales/en.d.ts.map +1 -1
  148. package/dist/i18n/locales/en.js +122 -10
  149. package/dist/i18n/locales/en.js.map +1 -1
  150. package/dist/i18n/locales/es.d.ts +119 -4
  151. package/dist/i18n/locales/es.d.ts.map +1 -1
  152. package/dist/i18n/locales/es.js +130 -15
  153. package/dist/i18n/locales/es.js.map +1 -1
  154. package/dist/i18n/locales/fr.d.ts +119 -4
  155. package/dist/i18n/locales/fr.d.ts.map +1 -1
  156. package/dist/i18n/locales/fr.js +130 -15
  157. package/dist/i18n/locales/fr.js.map +1 -1
  158. package/dist/i18n/locales/hi.d.ts +119 -4
  159. package/dist/i18n/locales/hi.d.ts.map +1 -1
  160. package/dist/i18n/locales/hi.js +130 -15
  161. package/dist/i18n/locales/hi.js.map +1 -1
  162. package/dist/i18n/locales/it.d.ts +119 -4
  163. package/dist/i18n/locales/it.d.ts.map +1 -1
  164. package/dist/i18n/locales/it.js +130 -15
  165. package/dist/i18n/locales/it.js.map +1 -1
  166. package/dist/i18n/locales/ja.d.ts +119 -4
  167. package/dist/i18n/locales/ja.d.ts.map +1 -1
  168. package/dist/i18n/locales/ja.js +130 -15
  169. package/dist/i18n/locales/ja.js.map +1 -1
  170. package/dist/i18n/locales/nl.d.ts +119 -4
  171. package/dist/i18n/locales/nl.d.ts.map +1 -1
  172. package/dist/i18n/locales/nl.js +130 -15
  173. package/dist/i18n/locales/nl.js.map +1 -1
  174. package/dist/i18n/locales/pl.d.ts +119 -4
  175. package/dist/i18n/locales/pl.d.ts.map +1 -1
  176. package/dist/i18n/locales/pl.js +130 -15
  177. package/dist/i18n/locales/pl.js.map +1 -1
  178. package/dist/i18n/locales/pt.d.ts +119 -4
  179. package/dist/i18n/locales/pt.d.ts.map +1 -1
  180. package/dist/i18n/locales/pt.js +130 -15
  181. package/dist/i18n/locales/pt.js.map +1 -1
  182. package/dist/i18n/locales/ro.d.ts +119 -4
  183. package/dist/i18n/locales/ro.d.ts.map +1 -1
  184. package/dist/i18n/locales/ro.js +130 -15
  185. package/dist/i18n/locales/ro.js.map +1 -1
  186. package/dist/i18n/locales/ru.d.ts +119 -4
  187. package/dist/i18n/locales/ru.d.ts.map +1 -1
  188. package/dist/i18n/locales/ru.js +130 -15
  189. package/dist/i18n/locales/ru.js.map +1 -1
  190. package/dist/i18n/locales/sq.d.ts +119 -4
  191. package/dist/i18n/locales/sq.d.ts.map +1 -1
  192. package/dist/i18n/locales/sq.js +130 -15
  193. package/dist/i18n/locales/sq.js.map +1 -1
  194. package/dist/i18n/locales/sv.d.ts +119 -4
  195. package/dist/i18n/locales/sv.d.ts.map +1 -1
  196. package/dist/i18n/locales/sv.js +130 -15
  197. package/dist/i18n/locales/sv.js.map +1 -1
  198. package/dist/i18n/locales/tr.d.ts +119 -4
  199. package/dist/i18n/locales/tr.d.ts.map +1 -1
  200. package/dist/i18n/locales/tr.js +130 -15
  201. package/dist/i18n/locales/tr.js.map +1 -1
  202. package/dist/i18n/locales/zh.d.ts +119 -4
  203. package/dist/i18n/locales/zh.d.ts.map +1 -1
  204. package/dist/i18n/locales/zh.js +130 -15
  205. package/dist/i18n/locales/zh.js.map +1 -1
  206. package/dist/index.js +1112 -1107
  207. package/dist/locales/ar.json +130 -15
  208. package/dist/locales/de.json +130 -15
  209. package/dist/locales/el.json +130 -15
  210. package/dist/locales/en.json +122 -7
  211. package/dist/locales/es.json +130 -15
  212. package/dist/locales/fr.json +130 -15
  213. package/dist/locales/hi.json +130 -15
  214. package/dist/locales/it.json +130 -15
  215. package/dist/locales/ja.json +130 -15
  216. package/dist/locales/nl.json +130 -15
  217. package/dist/locales/pl.json +130 -15
  218. package/dist/locales/pt.json +130 -15
  219. package/dist/locales/ro.json +130 -15
  220. package/dist/locales/ru.json +130 -15
  221. package/dist/locales/sq.json +130 -15
  222. package/dist/locales/sv.json +130 -15
  223. package/dist/locales/tr.json +130 -15
  224. package/dist/locales/zh.json +130 -15
  225. package/dist/patterns/calendar/calendar-appointment-details.d.ts +83 -2
  226. package/dist/patterns/calendar/calendar-appointment-details.d.ts.map +1 -1
  227. package/dist/patterns/calendar/calendar-appointment-editor-dialog.d.ts.map +1 -1
  228. package/dist/patterns/calendar/calendar-archive.d.ts +12 -0
  229. package/dist/patterns/calendar/calendar-archive.d.ts.map +1 -0
  230. package/dist/patterns/calendar/calendar-bookings-panel.d.ts.map +1 -1
  231. package/dist/patterns/calendar/calendar-care-rules.d.ts +19 -23
  232. package/dist/patterns/calendar/calendar-care-rules.d.ts.map +1 -1
  233. package/dist/patterns/calendar/calendar-delete-confirm.d.ts +18 -0
  234. package/dist/patterns/calendar/calendar-delete-confirm.d.ts.map +1 -0
  235. package/dist/patterns/calendar/calendar-document-scope-confirm.d.ts +12 -0
  236. package/dist/patterns/calendar/calendar-document-scope-confirm.d.ts.map +1 -0
  237. package/dist/patterns/calendar/calendar-editor-guard.d.ts +12 -0
  238. package/dist/patterns/calendar/calendar-editor-guard.d.ts.map +1 -0
  239. package/dist/patterns/calendar/calendar-editor-hydration.d.ts +13 -2
  240. package/dist/patterns/calendar/calendar-editor-hydration.d.ts.map +1 -1
  241. package/dist/patterns/calendar/calendar-load-error.d.ts +11 -0
  242. package/dist/patterns/calendar/calendar-load-error.d.ts.map +1 -0
  243. package/dist/patterns/calendar/calendar-patient-locked.d.ts +13 -0
  244. package/dist/patterns/calendar/calendar-patient-locked.d.ts.map +1 -0
  245. package/dist/patterns/calendar/calendar-patient-picker.d.ts +6 -1
  246. package/dist/patterns/calendar/calendar-patient-picker.d.ts.map +1 -1
  247. package/dist/patterns/calendar/calendar-prompts.d.ts +11 -0
  248. package/dist/patterns/calendar/calendar-prompts.d.ts.map +1 -0
  249. package/dist/patterns/calendar/calendar-settings-ical.d.ts +11 -0
  250. package/dist/patterns/calendar/calendar-settings-ical.d.ts.map +1 -0
  251. package/dist/patterns/calendar/calendar-settings-overlay.d.ts +73 -0
  252. package/dist/patterns/calendar/calendar-settings-overlay.d.ts.map +1 -0
  253. package/dist/patterns/calendar/calendar-settings-panel.d.ts +62 -0
  254. package/dist/patterns/calendar/calendar-settings-panel.d.ts.map +1 -0
  255. package/dist/patterns/calendar/calendar-settings-practice.d.ts +20 -0
  256. package/dist/patterns/calendar/calendar-settings-practice.d.ts.map +1 -0
  257. package/dist/patterns/calendar/calendar-status-colours.d.ts +18 -0
  258. package/dist/patterns/calendar/calendar-status-colours.d.ts.map +1 -0
  259. package/dist/patterns/calendar/calendar-upcoming-panel.d.ts.map +1 -1
  260. package/dist/patterns/calendar/calendar-waiting-list-panel.d.ts +17 -2
  261. package/dist/patterns/calendar/calendar-waiting-list-panel.d.ts.map +1 -1
  262. package/dist/patterns/calendar/calendar-workspace.d.ts +285 -6
  263. package/dist/patterns/calendar/calendar-workspace.d.ts.map +1 -1
  264. package/dist/patterns/calendar/calendar-workspace.model.d.ts +103 -17
  265. package/dist/patterns/calendar/calendar-workspace.model.d.ts.map +1 -1
  266. package/dist/patterns/calendar/calendar.data.d.ts +9 -3
  267. package/dist/patterns/calendar/calendar.data.d.ts.map +1 -1
  268. package/dist/patterns/calendar/calendar.journey.d.ts +69 -5
  269. package/dist/patterns/calendar/calendar.journey.d.ts.map +1 -1
  270. package/dist/patterns/calendar/calendar.model.d.ts +129 -22
  271. package/dist/patterns/calendar/calendar.model.d.ts.map +1 -1
  272. package/dist/patterns/calendar/calendar.preferences.d.ts +4 -0
  273. package/dist/patterns/calendar/calendar.preferences.d.ts.map +1 -1
  274. package/dist/patterns/calendar/calendar.sheets.d.ts +129 -18
  275. package/dist/patterns/calendar/calendar.sheets.d.ts.map +1 -1
  276. package/dist/patterns/calendar/calendar.surface.d.ts +64 -6
  277. package/dist/patterns/calendar/calendar.surface.d.ts.map +1 -1
  278. package/dist/patterns/calendar/calendar.types.d.ts +231 -6
  279. package/dist/patterns/calendar/calendar.types.d.ts.map +1 -1
  280. package/dist/patterns/calendar/index.d.ts +9 -6
  281. package/dist/patterns/calendar/index.d.ts.map +1 -1
  282. package/dist/patterns/calendar/index.js +18 -15
  283. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  284. package/dist/patterns/signature-request/index.js +1 -1
  285. package/dist/patterns/signed-out-frame/index.js +1 -1
  286. package/dist/tokens.css +5 -1
  287. package/package.json +1 -1
  288. package/dist/_chunks/appointment-card-0PebvrOS.js.map +0 -1
  289. package/dist/_chunks/calendar-_sgjuH3L.js.map +0 -1
  290. package/dist/_chunks/calendar-appointment-editor-dialog-CGDDGMdo.js +0 -10974
  291. package/dist/_chunks/calendar-appointment-editor-dialog-CGDDGMdo.js.map +0 -1
  292. package/dist/_chunks/calendar-event-card-DXAYWH6k.js.map +0 -1
  293. package/dist/_chunks/entity-summary-BanguTa6.js.map +0 -1
  294. package/dist/_chunks/header-settings-DsvheAOt.js.map +0 -1
  295. package/dist/_chunks/task-editor-C05yx7JJ.js +0 -1218
  296. package/dist/_chunks/task-editor-C05yx7JJ.js.map +0 -1
  297. package/dist/_chunks/treatment-receipt-1VnuinhY.js.map +0 -1
  298. package/dist/_chunks/use-appointment-details-read-Bm408XzX.js +0 -2198
  299. package/dist/_chunks/use-appointment-details-read-Bm408XzX.js.map +0 -1
  300. package/dist/_chunks/whatsapp-button-DV9JFmtq.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-appointment-details-read-Bm408XzX.js","sources":["../../node_modules/lucide-react/dist/esm/icons/cake.mjs","../../node_modules/lucide-react/dist/esm/icons/clipboard-paste.mjs","../../node_modules/lucide-react/dist/esm/icons/id-card.mjs","../../node_modules/lucide-react/dist/esm/icons/move.mjs","../../src/components/appointment-details-panel/appointment-details-panel.agent.ts","../../src/components/appointment-details-panel/appointment-details-panel.focus.ts","../../src/components/_shared/appointment-format.ts","../../src/components/appointment-details-panel/appointment-details-panel.history.tsx","../../src/components/appointment-details-panel/appointment-details-panel.identity.tsx","../../src/components/appointment-details-panel/appointment-details-panel.info-hover.tsx","../../src/components/appointment-details-panel/appointment-details-panel.sections.tsx","../../src/components/appointment-details-panel/appointment-details-panel.tsx","../../src/components/appointment-details-panel/use-appointment-details-read.ts"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M20 21v-8a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8\", key: \"1w3rig\" }],\n [\"path\", { d: \"M4 16s.5-1 2-1 2.5 2 4 2 2.5-2 4-2 2.5 2 4 2 2-1 2-1\", key: \"n2jgmb\" }],\n [\"path\", { d: \"M2 21h20\", key: \"1nyx9w\" }],\n [\"path\", { d: \"M7 8v3\", key: \"1qtyvj\" }],\n [\"path\", { d: \"M12 8v3\", key: \"hwp4zt\" }],\n [\"path\", { d: \"M17 8v3\", key: \"1i6e5u\" }],\n [\"path\", { d: \"M7 4h.01\", key: \"1bh4kh\" }],\n [\"path\", { d: \"M12 4h.01\", key: \"1ujb9j\" }],\n [\"path\", { d: \"M17 4h.01\", key: \"1upcoc\" }]\n];\nconst Cake = createLucideIcon(\"cake\", __iconNode);\n\nexport { __iconNode, Cake as default };\n//# sourceMappingURL=cake.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M11 14h10\", key: \"1w8e9d\" }],\n [\"path\", { d: \"M16 4h2a2 2 0 0 1 2 2v1.344\", key: \"1e62lh\" }],\n [\"path\", { d: \"m17 18 4-4-4-4\", key: \"z2g111\" }],\n [\"path\", { d: \"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 1.793-1.113\", key: \"bjbb7m\" }],\n [\"rect\", { x: \"8\", y: \"2\", width: \"8\", height: \"4\", rx: \"1\", key: \"ublpy\" }]\n];\nconst ClipboardPaste = createLucideIcon(\"clipboard-paste\", __iconNode);\n\nexport { __iconNode, ClipboardPaste as default };\n//# sourceMappingURL=clipboard-paste.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M16 10h2\", key: \"8sgtl7\" }],\n [\"path\", { d: \"M16 14h2\", key: \"epxaof\" }],\n [\"path\", { d: \"M6.17 15a3 3 0 0 1 5.66 0\", key: \"n6f512\" }],\n [\"circle\", { cx: \"9\", cy: \"11\", r: \"2\", key: \"yxgjnd\" }],\n [\"rect\", { x: \"2\", y: \"5\", width: \"20\", height: \"14\", rx: \"2\", key: \"qneu4z\" }]\n];\nconst IdCard = createLucideIcon(\"id-card\", __iconNode);\n\nexport { __iconNode, IdCard as default };\n//# sourceMappingURL=id-card.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 2v20\", key: \"t6zp3m\" }],\n [\"path\", { d: \"m15 19-3 3-3-3\", key: \"11eu04\" }],\n [\"path\", { d: \"m19 9 3 3-3 3\", key: \"1mg7y2\" }],\n [\"path\", { d: \"M2 12h20\", key: \"9i4pu4\" }],\n [\"path\", { d: \"m5 9-3 3 3 3\", key: \"j64kie\" }],\n [\"path\", { d: \"m9 5 3-3 3 3\", key: \"l8vdw6\" }]\n];\nconst Move = createLucideIcon(\"move\", __iconNode);\n\nexport { __iconNode, Move as default };\n//# sourceMappingURL=move.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter: AppointmentDetailsPanel. */\n/* */\n/* Reads ids and enums only: the occurrence id, the load status, the */\n/* appointment status, the footer actions on offer, whether History is */\n/* open and whether privacy mode is on. Never a patient name, a phone */\n/* number or a note. */\n/* */\n/* set_status goes through the footer's own WorkflowStatusControl, so the */\n/* panel shows the saving state and any refusal exactly as for a click; */\n/* it is `phi` + openWorld: the status is a named patient's attendance. */\n/* The footer actions (Edit, Move, Copy, Delete, WhatsApp …) are the */\n/* host's and are reached through their data-action hooks: the host's own */\n/* confirmation guards Delete. An offered action with no hook in the */\n/* footer strip is folded into More: open More (MORE_TRIGGER below), and */\n/* its menu item carries the same data-action. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AppointmentDetailsPanelHandle } from './appointment-details-panel';\n\n/* The footer's More trigger, found without its translated label: the one\n menu-opening icon button in the actions group. */\nconst MORE_TRIGGER =\n '[data-component=\"button-group\"] [data-component=\"icon-button\"][aria-haspopup=\"menu\"]';\n\nexport const appointmentDetailsPanelAgent: AgentAdapter<AppointmentDetailsPanelHandle> =\n {\n id: 'appointment-details-panel',\n // open and close back open_history and close_history; set_value backs\n // set_status.\n capabilities: ['open', 'close', 'set_value'],\n state: {\n eventId: {\n type: 'string | null',\n descriptionKey: 'ui.agent.appointmentDetailsPanel.state.eventId',\n description:\n 'The occurrence on screen or being read, as the host identifies it. After a failed or refused read, the occurrence it was for when the host says so. Null when there is none, or the host did not say.',\n read: (handle) => handle.getEventId(),\n },\n loadStatus: {\n type: \"'loading' | 'ready' | 'error' | 'refused'\",\n descriptionKey: 'ui.agent.appointmentDetailsPanel.state.loadStatus',\n description:\n 'Where the read is: loading, ready, failed (with Retry) or refused. Actions need ready.',\n read: (handle) => handle.getLoadStatus(),\n },\n appointmentStatus: {\n type: \"'confirmed' | 'waiting' | 'in_care' | 'done' | 'cancelled' | 'absent' | null\",\n descriptionKey:\n 'ui.agent.appointmentDetailsPanel.state.appointmentStatus',\n description:\n 'The appointment status as last saved here or read. Null when none is recorded or nothing is on screen.',\n read: (handle) => handle.getAppointmentStatus(),\n },\n allowedStatuses: {\n type: 'string[]',\n descriptionKey:\n 'ui.agent.appointmentDetailsPanel.state.allowedStatuses',\n description:\n 'The statuses set_status accepts now, in menu order. Empty when the status is read-only.',\n read: (handle) => handle.getAllowedStatuses(),\n },\n offeredActions: {\n type: 'string[]',\n descriptionKey: 'ui.agent.appointmentDetailsPanel.state.offeredActions',\n description:\n 'The footer actions on offer, as their data-action values (for example edit-appointment, delete-appointment), in footer order, including any folded into More.',\n read: (handle) => handle.getOfferedActions(),\n },\n historyOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.appointmentDetailsPanel.state.historyOpen',\n description: 'Whether the History sub-view covers the details.',\n read: (handle) => handle.isHistoryOpen(),\n },\n privacy: {\n type: 'boolean',\n descriptionKey: 'ui.agent.appointmentDetailsPanel.state.privacy',\n description:\n 'Whether privacy mode is on. The patient identity and personal fields are then masked on screen.',\n read: (handle) => handle.isPrivacy(),\n },\n },\n actions: {\n open_history: {\n safety: 'read',\n openWorld: true,\n idempotent: true,\n errors: ['No appointment is on screen, or History is not offered.'],\n descriptionKey: 'ui.agent.appointmentDetailsPanel.actions.openHistory',\n description:\n \"Slide the appointment's history over the details, as its header button does; the host reads it then if it did not send it with the details. It lists who changed what, and when.\",\n invoke: (handle) => handle.openHistory(),\n },\n close_history: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.appointmentDetailsPanel.actions.closeHistory',\n description: 'Return from History to the details.',\n invoke: (handle) => handle.closeHistory(),\n },\n set_status: {\n safety: 'phi',\n openWorld: true,\n idempotent: true,\n argsType: '{ status: string }',\n argsSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n enum: [\n 'confirmed',\n 'waiting',\n 'in_care',\n 'done',\n 'cancelled',\n 'absent',\n ],\n },\n },\n required: ['status'],\n },\n errors: [\n 'The status is read-only: no appointment on screen, no host save, readOnly, or no allowed statuses.',\n 'The status is not in allowedStatuses.',\n 'A status save is already in flight.',\n 'The host refused the change. The previous status stays and the panel shows the message.',\n ],\n examples: [{ args: { status: 'waiting' } }],\n descriptionKey: 'ui.agent.appointmentDetailsPanel.actions.setStatus',\n description:\n 'Save a new appointment status through the host, as the footer control does. Resolves once the host has saved it.',\n invoke: (handle, args: { status: string }) =>\n handle.setAppointmentStatus(\n args.status as Parameters<\n AppointmentDetailsPanelHandle['setAppointmentStatus']\n >[0],\n ),\n },\n retry: {\n safety: 'read',\n openWorld: true,\n errors: [\n 'Retry is not offered: the read has not failed or been refused as retryable, or the host offers no Retry.',\n ],\n descriptionKey: 'ui.agent.appointmentDetailsPanel.actions.retry',\n description:\n 'Ask the host to read the appointment again, after a failed read or a refusal it marked retryable.',\n invoke: (handle) => handle.retry(),\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'appointment-details-panel',\n description: `Marks the panel. It also carries data-event-id and data-status. Inside, cards carry data-card (patient, appointment, notes, treatments), footer actions data-action, and the History and description sub-views data-details-subview. An action in offeredActions with no data-action in the footer strip is folded into More: click the panel's ${MORE_TRIGGER}, and its menu item carries the same data-action.`,\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop, or generated.',\n },\n },\n };\n","/* Where focus goes when the control that held it leaves the details\n panel: the panel's own parts share these, so every rescue behaves the\n same way. */\n\n/** Hands focus to `target` only when focus fell to the page: a control that\n * held it was removed. Focus the user put elsewhere stays there. */\nexport function rescueFocus(target: HTMLElement | null | undefined): void {\n const active = document.activeElement;\n if (active && active !== document.body) return;\n target?.focus({ preventScroll: true });\n}\n\n/** A heading, made focusable on demand: where focus goes when the control\n * that held it leaves the panel or one of its cards. */\nexport function focusHeading(headingId: string): void {\n const heading = document.getElementById(headingId);\n if (heading && !heading.hasAttribute('tabindex')) heading.tabIndex = -1;\n rescueFocus(heading);\n}\n","/* Pure helpers for reading one appointment: dates, the patient's age,\n phones, address and the history order. No React and no i18n lookups.\n Shared by AppointmentDetailsPanel and the calendar pattern, which\n re-exports them under their old names. */\nimport type {\n AppointmentPhoneNumber,\n AppointmentRecurrenceFrequency,\n} from '../appointment-details-panel/appointment-details-panel.types';\n\n/** A date-only value (a birthday, an all-day start) is already a local day;\n * anything else parses as the wall clock it carries. */\nexport function parseEventDate(value: string | Date): Date {\n return typeof value === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(value)\n ? new Date(`${value}T00:00:00`)\n : new Date(value);\n}\n\n/** \"Wednesday, 24 June 2026\" in the reader's locale; '' when unreadable. */\nexport function formatDay(locale: string, value: Date | string): string {\n try {\n return new Intl.DateTimeFormat(locale, {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }).format(parseEventDate(value));\n } catch {\n return '';\n }\n}\n\n/** \"09:00–09:45\" in the reader's locale, 24-hour; '' when unreadable. */\nexport function formatTimeRange(\n locale: string,\n start: Date | string,\n end?: Date | string,\n): string {\n const s = new Date(start);\n const e = end ? new Date(end) : s;\n try {\n const fmt = new Intl.DateTimeFormat(locale, {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n });\n return typeof fmt.formatRange === 'function'\n ? fmt.formatRange(s, e)\n : `${fmt.format(s)} – ${fmt.format(e)}`;\n } catch {\n return '';\n }\n}\n\n/** Absolute stamp for booked-at and history lines: day and time. */\nexport const DETAIL_STAMP_FORMAT: Intl.DateTimeFormatOptions = {\n weekday: 'short',\n day: 'numeric',\n month: 'short',\n hour: '2-digit',\n minute: '2-digit',\n};\n\n/** Completed years between a birth date and `on`, the practice's clock\n * rather than the real one, so the figure never drifts under a test. */\nexport function ageInYears(dobIso: string, on: Date | string): number {\n const dob = parseEventDate(dobIso);\n const at = parseEventDate(on);\n let age = at.getFullYear() - dob.getFullYear();\n const monthDelta = at.getMonth() - dob.getMonth();\n if (monthDelta < 0 || (monthDelta === 0 && at.getDate() < dob.getDate())) {\n age -= 1;\n }\n return Math.max(0, age);\n}\n\nconst START_ISO = /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})$/;\n\n/** The host's zone-less wall clock as a local Date, or undefined when it is\n * not a real 'YYYY-MM-DDTHH:mm:ss' reading. Ranges are checked rather than\n * round-tripped, so a time inside a daylight-saving gap still parses. */\nexport function parseAppointmentStartIso(\n startIso: string | undefined,\n): Date | undefined {\n const match = typeof startIso === 'string' ? START_ISO.exec(startIso) : null;\n if (!match) return undefined;\n const [year, month, day, hours, minutes, seconds] = match\n .slice(1)\n .map(Number);\n const monthEnd = new Date(0);\n monthEnd.setFullYear(year, month, 0);\n if (\n month < 1 ||\n month > 12 ||\n day < 1 ||\n day > monthEnd.getDate() ||\n hours > 23 ||\n minutes > 59 ||\n seconds > 59\n )\n return undefined;\n const start = new Date(0);\n start.setFullYear(year, month - 1, day);\n start.setHours(hours, minutes, seconds, 0);\n return start;\n}\n\n/** A Timeline set to 'newest-first' is a plain column, so the DOM order\n * must already be newest first. Unreadable dates stay last, in input\n * order; equal instants keep theirs. The input is not changed. */\nexport function sortHistoryNewestFirst<T extends { atIso: string }>(\n entries: readonly T[],\n): T[] {\n return entries\n .map((entry) => {\n const parsed = Date.parse(entry.atIso);\n return { entry, time: Number.isFinite(parsed) ? parsed : -Infinity };\n })\n .sort((a, b) => (a.time === b.time ? 0 : b.time - a.time))\n .map(({ entry }) => entry);\n}\n\n/** The editor's label key for each frequency, under\n * `calendarWorkspace.editor.*`. A literal map, so key extractors see\n * every key. */\nexport const RECURRENCE_LABEL_KEY: Record<\n AppointmentRecurrenceFrequency,\n string\n> = {\n daily: 'recurrenceDaily',\n weekly: 'recurrenceWeekly',\n monthly: 'recurrenceMonthly',\n quarterly: 'recurrenceQuarterly',\n semiannual: 'recurrenceSemiannual',\n yearly: 'recurrenceYearly',\n};\n\n/** What a patient record needs for its phones. */\nexport interface PhonesSource {\n phone?: string;\n phones?: AppointmentPhoneNumber[];\n}\n\n/** Every labelled phone number. The single `phone` is the mobile when the\n * record carries no list. A record with neither has no numbers, which is\n * not the same as one labelled blank: the list comes back empty and the\n * caller omits the rows. */\nexport function patientPhones(patient: PhonesSource): AppointmentPhoneNumber[] {\n if (patient.phones) return patient.phones;\n return patient.phone ? [{ label: 'mobile', number: patient.phone }] : [];\n}\n\n/** What a patient record needs for its address. */\nexport interface AddressSource {\n address?: string;\n postalCode?: string;\n city?: string;\n}\n\n/** The address as one line, the map search's text. Empty when the host\n * sent no address at all: the caller then offers no search. */\nexport function patientAddressLine(patient: AddressSource): string {\n return [patient.address, patient.postalCode, patient.city]\n .filter((part): part is string => Boolean(part))\n .join(', ');\n}\n\n/** The map link's visible label: street and city, as the platform popover\n * prints them. The postcode belongs in the search, not in the label. */\nexport function patientAddressLabel(patient: AddressSource): string {\n return [patient.address, patient.city]\n .filter((part): part is string => Boolean(part))\n .join(', ');\n}\n\n/** Google Maps search for the patient's address: the popover's map link. */\nexport function patientMapsUrl(patient: AddressSource): string {\n const query = patientAddressLine(patient);\n return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(query)}`;\n}\n","/* The appointment's history as a kit Timeline, newest first. Shared by the\n details panel's History sub-view and the calendar editor's. Internal to\n this directory: the calendar pattern imports it by path. */\nimport {\n ArrowRight,\n CalendarClock,\n CalendarPlus,\n Clock,\n Move,\n Pencil,\n Trash2,\n} from 'lucide-react';\nimport type { CSSProperties, ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { APPOINTMENT_STATE_WORKFLOW } from '../_shared/entity-card';\nimport {\n DETAIL_STAMP_FORMAT,\n sortHistoryNewestFirst,\n} from '../_shared/appointment-format';\nimport { EmptyState } from '../empty-state';\nimport { Timeline } from '../timeline';\nimport {\n useAppointmentWorkflowStatus,\n WorkflowStatusDisplay,\n} from '../workflow-status';\nimport type {\n AppointmentHistoryChange,\n AppointmentHistoryEntry,\n AppointmentHistoryField,\n} from './appointment-details-panel.types';\n\nconst detailKey = (suffix: string): string =>\n `calendarWorkspace.details.${suffix}`;\n\nexport interface AppointmentHistoryTimelineProps {\n /** In any order: the timeline sorts a copy, newest first. */\n history: readonly AppointmentHistoryEntry[];\n /** Locale for the stamps. Defaults to the active i18n language. */\n locale?: string;\n /** Say \"What changed was not recorded.\" under an edit that carries no\n * fields and no changes. Off by default: such an edit shows only its\n * title, as before. Turn it on once the host records changes, so the\n * older entries read as incomplete rather than empty. */\n noteUnrecordedEdits?: boolean;\n /** Privacy mode, as on the details cards: a patient or care change\n * names the field but not its values. */\n privacy?: boolean;\n}\n\n/* Fields whose values name the patient or describe their care: kept out\n of view in privacy mode. */\nconst PRIVATE_FIELDS: ReadonlySet<string> = new Set(['patient', 'care']);\n\n/* The platform keeps a colour as hex only (DoctorColor), with no name:\n such a value shows as a swatch. */\nconst HEX_COLOUR = /^#?(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i;\n\n/* A change with neither side says nothing: it is dropped. */\nconst hasASide = (change: AppointmentHistoryChange): boolean => {\n switch (change.field) {\n case 'time':\n return Boolean(change.fromIso || change.toIso);\n case 'duration':\n return change.fromMin !== undefined || change.toMin !== undefined;\n default:\n return Boolean(change.from || change.to);\n }\n};\n\n/** Every change an entry carries: the kind's own (a move's time, a\n * resize's duration, a status) first, then any further changes from the\n * same save, each field once. */\nexport function historyChanges(\n entry: AppointmentHistoryEntry,\n): AppointmentHistoryChange[] {\n const own: AppointmentHistoryChange[] =\n entry.kind === 'moved'\n ? [{ field: 'time', fromIso: entry.fromIso, toIso: entry.toIso }]\n : entry.kind === 'resized'\n ? [{ field: 'duration', fromMin: entry.fromMin, toMin: entry.toMin }]\n : entry.kind === 'status'\n ? [{ field: 'status', from: entry.from, to: entry.to }]\n : [];\n const further = ('changes' in entry ? (entry.changes ?? []) : []).filter(\n hasASide,\n );\n const seen = new Set<string>(own.map((change) => change.field));\n return [\n ...own,\n ...further.filter((change) => {\n if (seen.has(change.field)) return false;\n seen.add(change.field);\n return true;\n }),\n ];\n}\n\nconst sameDay = (a: Date, b: Date): boolean =>\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\n\n/** One row per history entry, reading what happened as exactly as the host\n * recorded it: a title naming the change, then each value before and\n * after (a status as two read-only pills). An edit recorded without\n * detail can say so (`noteUnrecordedEdits`); an empty history shows \"No\n * changes recorded\". */\nexport function AppointmentHistoryTimeline({\n history,\n locale,\n noteUnrecordedEdits = false,\n privacy = false,\n}: AppointmentHistoryTimelineProps) {\n const { t, i18n: runtimeI18n } = useTranslation('ui');\n const { optionFor } = useAppointmentWorkflowStatus(null);\n const shownLocale = locale ?? runtimeI18n.language;\n const formatWith = (\n iso: string,\n options: Intl.DateTimeFormatOptions,\n ): string => {\n try {\n return new Intl.DateTimeFormat(shownLocale, options).format(\n new Date(iso),\n );\n } catch {\n return iso;\n }\n };\n const formatStamp = (iso: string): string =>\n formatWith(iso, DETAIL_STAMP_FORMAT);\n const notSet = t(detailKey('history.notSet'));\n\n /* A change's two sides as text: for the sentence a screen reader hears,\n and for every field but status, what is shown. A move within one day\n names the day once. */\n const sidesOf = (\n change: AppointmentHistoryChange,\n ): { from?: string; to?: string } => {\n switch (change.field) {\n case 'status':\n return {\n from: change.from && optionFor(change.from).label,\n to: change.to && optionFor(change.to).label,\n };\n case 'time': {\n const from = change.fromIso && new Date(change.fromIso);\n const to = change.toIso && new Date(change.toIso);\n const toOnly =\n from && to && sameDay(from, to)\n ? formatWith(change.toIso as string, {\n hour: '2-digit',\n minute: '2-digit',\n })\n : undefined;\n return {\n from: change.fromIso && formatStamp(change.fromIso),\n to: toOnly ?? (change.toIso && formatStamp(change.toIso)),\n };\n }\n case 'duration':\n return {\n from:\n change.fromMin === undefined\n ? undefined\n : t(detailKey('history.minutes'), { n: change.fromMin }),\n to:\n change.toMin === undefined\n ? undefined\n : t(detailKey('history.minutes'), { n: change.toMin }),\n };\n default:\n return { from: change.from || undefined, to: change.to || undefined };\n }\n };\n\n const sentenceOf = (change: AppointmentHistoryChange): string => {\n const field = t(detailKey(`history.fields.${change.field}`));\n const { from, to } = sidesOf(change);\n /* A hex code means nothing read aloud: say what changed. */\n if (\n change.field === 'colour' &&\n [from, to].some((value) => value && HEX_COLOUR.test(value))\n )\n return t(detailKey('history.changed.colour'));\n if (from && !to)\n return t(detailKey('history.changeCleared'), { field, from });\n if (!from && to) return t(detailKey('history.changeSet'), { field, to });\n return t(detailKey('history.changeFromTo'), {\n field,\n from: from ?? notSet,\n to: to ?? notSet,\n });\n };\n\n /* Before → after, as seen. The sentence above is what is heard. */\n const valueOf = (change: AppointmentHistoryChange): ReactNode => {\n /* min-w-0 lets a long unbroken value (a care name, a compound word)\n wrap inside the card instead of pushing past it. */\n const side = (text: string | undefined, isAfter: boolean): ReactNode =>\n text && change.field === 'colour' && HEX_COLOUR.test(text) ? (\n <span\n className=\"ds:inline-block ds:size-4 ds:shrink-0 ds:rounded-[var(--radius-full)] ds:border ds:border-[color:var(--border)] ds:[background-color:var(--history-swatch)] ds:forced-colors:[forced-color-adjust:none]\"\n // eslint-disable-next-line react/forbid-dom-props -- a host colour, set through a CSS custom property (23-constraints §inline-style exception)\n style={\n {\n '--history-swatch': text.startsWith('#') ? text : `#${text}`,\n } as CSSProperties\n }\n />\n ) : text ? (\n <span\n className={\n isAfter\n ? 'ds:min-w-0 ds:font-[var(--font-weight-medium)] ds:text-[color:var(--foreground)]'\n : 'ds:min-w-0 ds:text-[color:var(--muted-foreground)]'\n }\n >\n {text}\n </span>\n ) : (\n <span className=\"ds:min-w-0 ds:text-[color:var(--muted-foreground)]\">\n {notSet}\n </span>\n );\n const pill = (\n value: Extract<AppointmentHistoryChange, { field: 'status' }>['from'],\n ): ReactNode =>\n value ? (\n <WorkflowStatusDisplay\n value={value}\n option={optionFor(value)}\n size=\"sm\"\n />\n ) : (\n side(undefined, false)\n );\n const { from, to } = sidesOf(change);\n /* Heard as one sentence in every screen reader, browse mode included;\n the arrow row is for the eye. */\n return (\n <div className=\"ds:min-w-0\" data-history-change={change.field}>\n <span className=\"ds:sr-only\">{sentenceOf(change)}</span>\n <div\n aria-hidden=\"true\"\n className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {change.field === 'status' ? pill(change.from) : side(from, false)}\n <ArrowRight\n className=\"ds:size-4 ds:shrink-0 ds:text-[color:var(--muted-foreground)] ds:rtl:rotate-180\"\n aria-hidden=\"true\"\n />\n {change.field === 'status' ? pill(change.to) : side(to, true)}\n </div>\n </div>\n );\n };\n\n /* History line → title, tone, dot glyph and what changed. */\n const describe = (\n entry: AppointmentHistoryEntry,\n ): {\n title: string;\n type: 'info' | 'success' | 'warning' | 'error' | 'neutral';\n icon: ReactNode;\n detail?: ReactNode;\n } => {\n switch (entry.kind) {\n case 'created':\n return {\n title: t(detailKey('history.created')),\n type: 'success',\n icon: <CalendarPlus size={16} aria-hidden=\"true\" />,\n };\n case 'confirmedByPatient': {\n const ConfirmedGlyph = APPOINTMENT_STATE_WORKFLOW.confirmed.Icon;\n return {\n title: t(detailKey('history.confirmedByPatient')),\n type: 'success',\n icon: <ConfirmedGlyph size={16} aria-hidden=\"true\" />,\n };\n }\n case 'deleted':\n return {\n title: t(detailKey('history.deleted')),\n type: 'error',\n icon: <Trash2 size={16} aria-hidden=\"true\" />,\n };\n default:\n break;\n }\n const all = historyChanges(entry);\n /* Privacy keeps a patient or care change to its field name. */\n const changes = privacy\n ? all.filter((change) => !PRIVATE_FIELDS.has(change.field))\n : all;\n /* Fields the host names without values, or privacy withholds: listed\n as \"Changed: …\" so nothing that changed goes unmentioned. */\n const valued = new Set<string>(changes.map((change) => change.field));\n const uncovered = [\n ...(entry.kind === 'edited' ? entry.fields : []),\n ...all\n .filter((change) => !valued.has(change.field))\n .map((change) => change.field),\n ].filter(\n (field, index, list): field is AppointmentHistoryField =>\n field !== 'status' &&\n !valued.has(field) &&\n list.indexOf(field) === index,\n );\n const alsoChanged =\n uncovered.length > 0\n ? t(detailKey('history.editedDetail'), {\n fields: uncovered\n .map((field) => t(detailKey(`history.fields.${field}`)))\n .join(', '),\n })\n : undefined;\n const [only] = changes;\n if (changes.length === 1 && only && !alsoChanged) {\n /* One change: the title names it, the line shows before → after. */\n switch (only.field) {\n case 'status': {\n const { to } = only;\n const StatusGlyph = to ? APPOINTMENT_STATE_WORKFLOW[to].Icon : Pencil;\n return {\n title: t(detailKey('history.status')),\n type: to === 'cancelled' || to === 'absent' ? 'warning' : 'neutral',\n icon: <StatusGlyph size={16} aria-hidden=\"true\" />,\n detail: valueOf(only),\n };\n }\n case 'time':\n return {\n title: t(detailKey('history.moved')),\n type: 'info',\n icon: <Move size={16} aria-hidden=\"true\" />,\n detail: valueOf(only),\n };\n case 'duration':\n return {\n title: t(detailKey('history.resized')),\n type: 'info',\n icon: <Clock size={16} aria-hidden=\"true\" />,\n detail: valueOf(only),\n };\n default:\n return {\n title: t(detailKey(`history.changed.${only.field}`)),\n type: 'neutral',\n icon: <Pencil size={16} aria-hidden=\"true\" />,\n detail: valueOf(only),\n };\n }\n }\n if (changes.length > 0) {\n /* Several changes in one save: each on its own labelled line, under\n the kind's own title (a move that also changed the chair is still\n a move), then any field named without values. */\n const lead =\n entry.kind === 'moved'\n ? {\n title: 'history.moved',\n icon: <Move size={16} aria-hidden=\"true\" />,\n }\n : entry.kind === 'resized'\n ? {\n title: 'history.resized',\n icon: <Clock size={16} aria-hidden=\"true\" />,\n }\n : entry.kind === 'status'\n ? {\n title: 'history.status',\n icon: (() => {\n const StatusGlyph =\n APPOINTMENT_STATE_WORKFLOW[entry.to].Icon;\n return <StatusGlyph size={16} aria-hidden=\"true\" />;\n })(),\n }\n : {\n title: 'history.edited',\n icon: <Pencil size={16} aria-hidden=\"true\" />,\n };\n return {\n title: t(detailKey(lead.title)),\n type:\n entry.kind === 'moved' || entry.kind === 'resized'\n ? 'info'\n : entry.kind === 'status' &&\n (entry.to === 'cancelled' || entry.to === 'absent')\n ? 'warning'\n : 'neutral',\n icon: lead.icon,\n detail: (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <dl\n aria-label={t(detailKey('history.changesLabel'))}\n className=\"ds:m-0 ds:grid ds:grid-cols-[auto_minmax(0,1fr)] ds:items-baseline ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-xs)]\"\n >\n {changes.map((change) => (\n <div key={change.field} className=\"ds:contents\">\n <dt className=\"type-label ds:text-[color:var(--muted-foreground)]\">\n {t(detailKey(`history.fields.${change.field}`))}\n </dt>\n <dd className=\"ds:m-0 ds:min-w-0\">{valueOf(change)}</dd>\n </div>\n ))}\n </dl>\n {alsoChanged ? <p className=\"ds:m-0\">{alsoChanged}</p> : null}\n </div>\n ),\n };\n }\n /* An edit recorded without its values: name the fields when known,\n else, when the host asks, say plainly that the detail was not\n recorded. */\n return {\n title: t(detailKey('history.edited')),\n type: 'neutral',\n icon: <Pencil size={16} aria-hidden=\"true\" />,\n detail: alsoChanged ? (\n alsoChanged\n ) : noteUnrecordedEdits ? (\n <span className=\"ds:text-[color:var(--muted-foreground)]\">\n {t(detailKey('history.notRecorded'))}\n </span>\n ) : undefined,\n };\n };\n if (history.length === 0) {\n return (\n <EmptyState\n variant=\"first-use\"\n size=\"sm\"\n title={t(detailKey('historyEmpty'))}\n />\n );\n }\n return (\n <Timeline order=\"newest-first\" aria-label={t(detailKey('historyTitle'))}>\n {sortHistoryNewestFirst(history).map((entry) => {\n const shape = describe(entry);\n return (\n <Timeline.Event\n key={entry.id}\n eventId={entry.id}\n type={shape.type}\n className=\"ds:[column-gap:var(--spacing-sm)] ds:[padding-block-end:var(--spacing-lg)] ds:before:bg-[var(--primary)]\"\n >\n <Timeline.Dot icon={shape.icon} />\n <Timeline.Content\n title={shape.title}\n description={shape.detail}\n className=\"ds:[padding-block-end:0] ds:[&>[data-component=card]]:border-[color:var(--card-border)] ds:[&>[data-component=card]]:shadow-[var(--shadow-card)]\"\n /* No author (a patient confirming by link): no blank avatar. */\n actor={entry.actor.trim() ? { name: entry.actor } : undefined}\n >\n <span className=\"ds:mt-[var(--spacing-sm)] ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <CalendarClock\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-[color:var(--muted-foreground)]\"\n />\n <Timeline.Timestamp\n date={entry.atIso}\n relative={false}\n locale={shownLocale}\n />\n </span>\n </Timeline.Content>\n </Timeline.Event>\n );\n })}\n </Timeline>\n );\n}\n","/* The identity strip: avatar, name, status badge and the labelled\n indicator chips, with the anamnesis warnings below. Shown by the details\n panel when there is no patient card, and by the calendar editor above its\n form. Data-free: the caller resolves the name, the age and the status.\n Internal to this directory: the calendar pattern imports it by path. */\nimport {\n Euro,\n Globe,\n HeartPulse,\n Repeat,\n TriangleAlert,\n Video,\n} from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { formatDay } from '../_shared/appointment-format';\nimport { Alert } from '../alert';\nimport { Avatar } from '../avatar';\nimport { Badge } from '../badge';\nimport { Button } from '../button';\nimport type { CalendarEvent, CalendarEventStatus } from '../calendar';\nimport { useAppointmentWorkflowStatus } from '../workflow-status';\nimport type { AppointmentAnamnesisAnswer } from './appointment-details-panel.types';\n\ntype StatusBadgeVariant =\n | 'success'\n | 'info'\n | 'warning'\n | 'error'\n | 'accentSoft';\n\n/** The Badge variant a status wears as a chip, beside the grid card's disc.\n * The glyph and the label come from the shared workflow status options. */\nexport const APPOINTMENT_STATUS_BADGE_VARIANT: Record<\n CalendarEventStatus,\n StatusBadgeVariant\n> = {\n confirmed: 'success',\n waiting: 'info',\n in_care: 'accentSoft',\n done: 'success',\n cancelled: 'error',\n absent: 'warning',\n};\n\n/** The card flags the chips spell out. */\nexport type IndicatorFlags = Pick<\n CalendarEvent,\n | 'isBookedOnline'\n | 'hasUnassignedPatient'\n | 'hasHighlightedAnamnesis'\n | 'hasBillableAmount'\n | 'isTelehealth'\n | 'isRecurring'\n>;\n\n/** Wherever a grid card carries the disc symbols, the peek and the details\n * panel spell them out: a glyph and the full label in a semantic Badge,\n * in the same tones as the discs. */\nexport function IndicatorChips({ event }: { event: IndicatorFlags }) {\n const { t } = useTranslation('ui');\n const key = (suffix: string): string =>\n `calendarWorkspace.details.indicators.${suffix}`;\n const chips: Array<{\n id: string;\n icon: ReactNode;\n label: string;\n variant: 'info' | 'warning' | 'accentSoft';\n }> = [];\n if (event.isBookedOnline) {\n chips.push({\n id: 'online',\n icon: <Globe aria-hidden=\"true\" />,\n label: t(key('bookedOnline')),\n variant: 'info',\n });\n }\n if (event.hasUnassignedPatient) {\n chips.push({\n id: 'unassigned',\n icon: <TriangleAlert aria-hidden=\"true\" />,\n label: t(key('unassignedPatient')),\n variant: 'warning',\n });\n }\n if (event.hasHighlightedAnamnesis) {\n chips.push({\n id: 'anamnesis',\n icon: <HeartPulse aria-hidden=\"true\" />,\n label: t(key('anamnesis')),\n variant: 'accentSoft',\n });\n }\n if (event.hasBillableAmount) {\n chips.push({\n id: 'billable',\n icon: <Euro aria-hidden=\"true\" />,\n label: t(key('billable')),\n variant: 'warning',\n });\n }\n if (event.isTelehealth) {\n chips.push({\n id: 'telehealth',\n icon: <Video aria-hidden=\"true\" />,\n label: t(key('telehealth')),\n variant: 'info',\n });\n }\n if (event.isRecurring) {\n chips.push({\n id: 'recurring',\n icon: <Repeat aria-hidden=\"true\" />,\n label: t(key('recurring')),\n variant: 'info',\n });\n }\n if (chips.length === 0) return null;\n return (\n <span className=\"ds:flex ds:flex-wrap ds:gap-[var(--spacing-2xs)]\">\n {chips.map((chip) => (\n <Badge\n key={chip.id}\n variant={chip.variant}\n size=\"sm\"\n leading={chip.icon}\n >\n {chip.label}\n </Badge>\n ))}\n </span>\n );\n}\n\nexport interface AppointmentIdentityStripProps {\n /** The name to show, never blank: the record's, else the appointment's\n * title, else \"Patient record not loaded\". */\n name: string;\n avatarSrc?: string;\n /** Someone is booked but their record did not load: says so once, beside\n * the name, so it never reads as \"no patient\". */\n unresolved?: boolean;\n status?: CalendarEventStatus;\n /** The flags the indicator chips spell out. */\n flags: IndicatorFlags;\n /** Completed years, printed beside the name. Absent = no age. */\n age?: number;\n /** Set = the name becomes a link-styled button to the patient folder. */\n onOpenPatient?: () => void;\n highlightedAnamnesisCount?: number;\n expiredAnamnesisCount?: number;\n /** The highlighted answers themselves, listed under the warning. */\n anamnesisAnswers?: readonly AppointmentAnamnesisAnswer[];\n /** Locale for the interview dates. Defaults to the active language. */\n locale?: string;\n}\n\n/** Identity strip above the details or the editor: avatar, name, status\n * badge and chips, the read-at-a-glance layer. */\nexport function AppointmentIdentityStrip({\n name,\n avatarSrc,\n unresolved = false,\n status,\n flags,\n age,\n onOpenPatient,\n highlightedAnamnesisCount = 0,\n expiredAnamnesisCount = 0,\n anamnesisAnswers = [],\n locale,\n}: AppointmentIdentityStripProps) {\n const { t, i18n: runtimeI18n } = useTranslation('ui');\n const key = (suffix: string): string => `calendarWorkspace.details.${suffix}`;\n const { optionFor } = useAppointmentWorkflowStatus(status);\n const statusOption = status ? optionFor(status) : undefined;\n const highlighted = highlightedAnamnesisCount;\n const expired = expiredAnamnesisCount;\n return (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-md)] ds:pb-0\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Avatar name={name} src={avatarSrc} />\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)] ds:[min-inline-size:0]\">\n {/* The platform pop-over links the name to the patient folder\n and prints the age beside it. */}\n <span className=\"ds:flex ds:flex-wrap ds:items-baseline ds:gap-[var(--spacing-2xs)] ds:text-start\">\n {onOpenPatient ? (\n <Button size=\"sm\" intent=\"link\" onClick={() => onOpenPatient()}>\n {name}\n </Button>\n ) : (\n <span className=\"ds:font-[var(--font-weight-semibold)] ds:truncate\">\n {name}\n </span>\n )}\n {age !== undefined ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t(key('patientAge'), { n: age })}\n </span>\n ) : null}\n </span>\n {/* Said once, next to the name it qualifies. Without it \"we could\n not load this patient\" and \"this patient has nothing recorded\"\n would look the same. */}\n {unresolved ? (\n <span className=\"type-body-sm ds:text-start ds:text-[color:var(--muted-foreground)]\">\n {t(key('patientNotLoaded'))}\n </span>\n ) : null}\n {status && statusOption ? (\n <span>\n <Badge\n variant={APPOINTMENT_STATUS_BADGE_VARIANT[status]}\n size=\"sm\"\n leading={statusOption.icon}\n >\n {statusOption.label}\n </Badge>\n </span>\n ) : null}\n <IndicatorChips event={flags} />\n </div>\n </div>\n {/* The pop-over's anamnesis warnings: the two counts and the\n highlighted answers. Present from mount, so announce=\"off\"; the\n title is a <p> so the panel's heading stays alone. */}\n {highlighted + expired > 0 ? (\n <Alert\n variant=\"warning\"\n announce=\"off\"\n icon={<HeartPulse aria-hidden=\"true\" />}\n >\n <Alert.Title as=\"p\">{t(key('anamnesisTitle'))}</Alert.Title>\n <Alert.Description>\n {[\n highlighted > 0\n ? t(key('anamnesisHighlighted'), { n: highlighted })\n : null,\n expired > 0 ? t(key('anamnesisExpired'), { n: expired }) : null,\n ]\n .filter((line): line is string => line !== null)\n .join(' · ')}\n </Alert.Description>\n {anamnesisAnswers.length > 0 ? (\n /* Question · yes or no · answer · interview date, as the\n platform's details dialog lists them. A list, not a\n Description, which renders a <p>. */\n <ul className=\"type-body-sm ds:m-0 ds:mt-[var(--spacing-xs)] ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-2xs)] ds:p-0\">\n {anamnesisAnswers.map((answer) => (\n <li key={answer.question} className=\"ds:text-start\">\n <span className=\"ds:font-[var(--font-weight-semibold)]\">\n {answer.question}\n </span>\n {` · ${t(key(answer.yes ? 'anamnesisYes' : 'anamnesisNo'))}`}\n {answer.answer ? ` · ${answer.answer}` : ''}\n {` · ${formatDay(locale ?? runtimeI18n.language, answer.interviewIso)}`}\n </li>\n ))}\n </ul>\n ) : null}\n {/* No Renew action: re-issuing the anamnesis is a platform flow\n the kit cannot start. The expired count stays: it is a\n clinical fact, not an offer. */}\n </Alert>\n ) : null}\n </div>\n );\n}\n","/**\n * The hover card body the details panel's chips share: an eyebrow naming\n * the kind of thing, a heading restating the chip in words, and the facts\n * the chip could not fit. Ported from the calendar-rail demo's hover\n * grammar; `PatientSummaryCard.flagHover` renders it around its own chip,\n * and `InfoHover` wraps the chips the panel renders itself.\n */\nimport type { ReactNode } from 'react';\nimport { HoverCard } from '../hover-card';\n\nexport interface InfoHoverFact {\n text: ReactNode;\n /** A caveat or provenance note, quieter than the rest. */\n muted?: boolean;\n}\n\nexport function InfoHoverBody({\n eyebrow,\n heading,\n facts,\n}: {\n eyebrow: string;\n heading: string;\n facts?: readonly InfoHoverFact[];\n}): ReactNode {\n return (\n <>\n <HoverCard.Eyebrow>{eyebrow}</HoverCard.Eyebrow>\n <HoverCard.Heading>{heading}</HoverCard.Heading>\n {facts && facts.length > 0 ? (\n <HoverCard.Body>\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-2xs)] ds:p-0 type-body-sm\">\n {facts.map((fact, index) => (\n <li\n key={index}\n className={\n fact.muted\n ? 'ds:text-[color:var(--muted-foreground)]'\n : undefined\n }\n >\n {fact.text}\n </li>\n ))}\n </ul>\n </HoverCard.Body>\n ) : null}\n </>\n );\n}\n\nconst TRIGGER =\n 'ds:inline-flex ds:cursor-pointer ds:rounded-[var(--radius-full)] ds:p-0 ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]';\n\n/**\n * Wraps a chip the panel renders itself in the same card. It carries no\n * open button: the pattern has no seam to open invoicing or the anamnesis.\n */\nexport function InfoHover({\n id,\n eyebrow,\n heading,\n facts,\n children,\n}: {\n /** Stamped as `data-chip-hover`, the trigger's DOM hook. */\n id: string;\n eyebrow: string;\n heading: string;\n facts?: readonly InfoHoverFact[];\n /** The chip; its visible text is the trigger's accessible name. */\n children: ReactNode;\n}): ReactNode {\n return (\n <HoverCard>\n {/* A real button: `asChild` onto a bare span stamps `aria-haspopup`\n on something a keyboard can never reach. */}\n <HoverCard.Trigger asChild>\n <button type=\"button\" data-chip-hover={id} className={TRIGGER}>\n {children}\n </button>\n </HoverCard.Trigger>\n <HoverCard.Content side=\"bottom\" align=\"start\" size=\"sm\">\n <InfoHoverBody eyebrow={eyebrow} heading={heading} facts={facts} />\n </HoverCard.Content>\n </HoverCard>\n );\n}\n","/* The cards of AppointmentDetailsPanel, laid out as the calendar-rail demo\n lays them out and built on the kit's primitives. Each prints one row per\n member the host sent: an absent member renders nothing, and a card with\n nothing to show renders no card. Contact is printed as read; masking is\n the host's. The operator and chair labels, the currency and the clock are\n the caller's: nothing here reads a calendar context. */\nimport {\n Armchair,\n Building2,\n Cake,\n CalendarDays,\n ClipboardList,\n Clock,\n HeartPulse,\n Hourglass,\n Mail,\n MapPin,\n NotebookPen,\n Phone,\n Repeat,\n Smartphone,\n Video,\n} from 'lucide-react';\nimport { useId, useRef, type ReactElement, type ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport {\n ageInYears,\n DETAIL_STAMP_FORMAT,\n formatDay,\n formatTimeRange,\n patientAddressLabel,\n patientAddressLine,\n patientMapsUrl,\n patientPhones,\n RECURRENCE_LABEL_KEY,\n} from '../_shared/appointment-format';\nimport type { PatientField } from '../_shared/patient-fields';\nimport { Alert } from '../alert';\nimport { Avatar } from '../avatar';\nimport { Badge } from '../badge';\nimport { Button, IconButton } from '../button';\nimport { Counter } from '../counter';\nimport { DescriptionList } from '../description-list';\nimport { NoteTimeline } from '../note-timeline';\nimport { PatientSummaryCard } from '../patient-summary-card';\nimport { SectionCard } from '../section-card';\nimport { Timestamp } from '../timestamp';\nimport { TransactionChip } from '../transaction-chip';\nimport { TreatmentReceipt } from '../treatment-receipt';\nimport { focusHeading } from './appointment-details-panel.focus';\nimport {\n InfoHover,\n InfoHoverBody,\n type InfoHoverFact,\n} from './appointment-details-panel.info-hover';\nimport type {\n AppointmentDetailsChairLabel,\n AppointmentDetailsNotesPreview,\n AppointmentDetailsOperatorLabel,\n AppointmentDetailsRead,\n AppointmentHistoryEntry,\n} from './appointment-details-panel.types';\n\ninterface CardProps {\n details: AppointmentDetailsRead;\n locale: string;\n /** ISO 4217 code for every amount. */\n currency: string;\n}\n\ninterface Row {\n id: string;\n label: string;\n icon?: ReactElement;\n value: ReactNode;\n}\n\nconst key = (suffix: string): string => `calendarWorkspace.details.${suffix}`;\nconst MUTED = 'type-body-sm ds:text-[color:var(--muted-foreground)]';\n// `dir=\"ltr\"` isolates the number/address from the surrounding paragraph's\n// bidi context: a phone number or email is an LTR datum even in an RTL\n// (Arabic) rendering, and without it the digits/punctuation can reorder.\nconst telLink = (number: string) => (\n <a href={`tel:${number.replace(/\\s/g, '')}`} dir=\"ltr\">\n {number}\n </a>\n);\nconst mailLink = (email: string) => (\n <a href={`mailto:${email}`} dir=\"ltr\">\n {email}\n </a>\n);\nconst formatMoney = (\n locale: string,\n amount: number,\n currency: string,\n): string =>\n new Intl.NumberFormat(locale, { style: 'currency', currency }).format(amount);\n\n/** Term and detail pairs; nothing at all without a row. */\nfunction Rows({ rows }: { rows: Array<Row | false | null | undefined | ''> }) {\n const shown = rows.filter((entry): entry is Row => !!entry);\n if (shown.length === 0) return null;\n return (\n <DescriptionList layout=\"inline\" density=\"compact\">\n {shown.map((entry) => (\n <DescriptionList.Row\n key={entry.id}\n data-row={entry.id}\n icon={entry.icon}\n >\n <DescriptionList.Term>{entry.label}</DescriptionList.Term>\n <DescriptionList.Detail>{entry.value}</DescriptionList.Detail>\n </DescriptionList.Row>\n ))}\n </DescriptionList>\n );\n}\n\n/**\n * The kit's PatientSummaryCard: identity, the attention chips, the money\n * chips and the contact fields. Every chip explains itself in a hover\n * card; money reads worst first (owed, to invoice, paid online), labelled\n * and without glyphs.\n */\nexport function DetailsPatientCard({\n details,\n locale,\n currency,\n now,\n mapsLink = false,\n}: CardProps & {\n /** The practice clock the age is computed against. */\n now: Date | string;\n /** The user's map-link setting (platform `showPatientAddressMapLink`). */\n mapsLink?: boolean;\n}) {\n const { t } = useTranslation('ui');\n const { patient, signing, money, booking } = details;\n if (!patient) return null;\n const signingShown = signing && signing.required > 0 ? signing : undefined;\n const pending = (signingShown?.toComplete ?? 0) > 0;\n const signingFacts: InfoHoverFact[] = signingShown\n ? [\n {\n text: !pending\n ? t(key('signingAllSigned'))\n : signingShown.requestedVia === 'sms'\n ? t(key('signingRequestedSms'))\n : signingShown.requestedVia === 'email'\n ? t(key('signingRequestedEmail'))\n : t(key('signingNotRequested')),\n },\n ...(signingShown.aesSetUp\n ? []\n : [{ text: t(key('aesMissing')), muted: true }]),\n ]\n : [];\n const highlighted = patient.highlightedAnamnesisCount ?? 0;\n const expired = patient.expiredAnamnesisCount ?? 0;\n const answerFacts: InfoHoverFact[] = (\n patient.highlightedAnamnesisAnswers ?? []\n ).map((answer) => ({\n text: [\n answer.question,\n t(key(answer.yes ? 'anamnesisYes' : 'anamnesisNo')),\n answer.answer,\n formatDay(locale, answer.interviewIso),\n ]\n .filter(Boolean)\n .join(' · '),\n }));\n const query = patientAddressLine(patient);\n const addressLabel = patientAddressLabel(patient) || query;\n const fields: PatientField[] = [\n ...(patient.dobIso\n ? [\n {\n id: 'dob',\n label: t(key('dob')),\n icon: <Cake />,\n value: `${formatDay(locale, patient.dobIso)} ${t(\n key('patientAge'),\n {\n n: ageInYears(patient.dobIso, now),\n },\n )}`,\n },\n ]\n : []),\n ...patientPhones(patient).map((phone, index) => {\n const hasLabel =\n phone.label === 'mobile' ||\n phone.label === 'home' ||\n phone.label === 'work';\n return {\n id: `phone-${index}`,\n label: hasLabel\n ? t(`calendarWorkspace.print.phoneLabels.${phone.label}`)\n : t(key('phone')),\n icon: phone.label === 'mobile' ? <Smartphone /> : <Phone />,\n value: telLink(phone.number),\n };\n }),\n ...(patient.email\n ? [\n {\n id: 'email',\n label: t(key('email')),\n icon: <Mail />,\n value: mailLink(patient.email),\n },\n ]\n : []),\n ...(mapsLink\n ? [\n {\n id: 'address',\n label: t(key('address')),\n icon: <MapPin />,\n value: query ? (\n <a\n href={patientMapsUrl(patient)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`${t(key('mapsLink'))}: ${addressLabel}`}\n >\n {addressLabel}\n </a>\n ) : (\n <span className={MUTED}>{t(key('noAddress'))}</span>\n ),\n },\n ]\n : []),\n ];\n const unpaid = money?.unpaidAmount ?? 0;\n const billable = money?.billableAmount ?? 0;\n const paidOnline = booking?.paidOnlineAmount ?? 0;\n /* A money chip under its hover card: the amount again, and whose it is. */\n const chip = (\n state: 'debt' | 'to-invoice' | 'settled',\n amount: number,\n id: string,\n headingKey: string,\n factKey: string,\n /** The money's own name, where the state's word would mislead. */\n label?: string,\n ) => (\n <InfoHover\n id={id}\n eyebrow={t(key('hoverBilling'))}\n heading={t(key(headingKey), {\n amount: formatMoney(locale, amount, currency),\n })}\n facts={[{ text: t(key(factKey)) }]}\n >\n <TransactionChip\n data-chip={id}\n state={state}\n amount={amount}\n currency={currency}\n locale={locale}\n size=\"md\"\n showLabel\n label={label}\n showIcon={false}\n />\n </InfoHover>\n );\n return (\n <PatientSummaryCard\n data-card=\"patient\"\n name={patient.name}\n avatarUrl={patient.avatarSrc}\n locale={locale}\n surface=\"elevated\"\n density=\"compact\"\n flags={{\n unsignedDocumentsCount: signingShown?.toComplete ?? 0,\n highlightedAnamnesisCount: highlighted,\n }}\n flagHover={{\n ...(signingShown\n ? {\n unsignedDocuments: (\n <InfoHoverBody\n eyebrow={t(key('sectionSigning'))}\n heading={\n signingShown.toComplete === 1\n ? t(key('signingToSignOne'))\n : t(key('signingToSignMany'), {\n n: signingShown.toComplete,\n })\n }\n facts={signingFacts}\n />\n ),\n }\n : {}),\n highlightedAnamnesis: (\n <InfoHoverBody\n eyebrow={t(key('anamnesisTitle'))}\n heading={t(key('anamnesisHighlighted'), { n: highlighted })}\n facts={answerFacts}\n />\n ),\n }}\n extraChips={\n unpaid > 0 || billable > 0 || paidOnline > 0 || expired > 0 ? (\n <>\n {/* One group, so no other chip lands between the money chips. */}\n <span className=\"ds:inline-flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\">\n {unpaid > 0\n ? chip(\n 'debt',\n unpaid,\n 'unpaid',\n 'hoverUnpaidHeading',\n 'hoverUnpaidFact',\n )\n : null}\n {billable > 0\n ? chip(\n 'to-invoice',\n billable,\n 'billable',\n 'hoverBillableHeading',\n 'hoverBillableFact',\n )\n : null}\n {paidOnline > 0\n ? chip(\n 'settled',\n paidOnline,\n 'paidOnline',\n 'hoverPaidOnlineHeading',\n 'hoverPaidOnlineFact',\n /* A deposit is settled money, but \"Settled\" hides where\n it came from: the chip says what its hover card says. */\n t(key('paidOnline')),\n )\n : null}\n </span>\n {expired > 0 ? (\n <InfoHover\n id=\"anamnesisExpired\"\n eyebrow={t(key('anamnesisTitle'))}\n heading={t(key('anamnesisExpired'), { n: expired })}\n facts={[{ text: t(key('hoverAnamnesisExpiredFact')) }]}\n >\n <Badge\n data-chip=\"anamnesisExpired\"\n variant=\"warning\"\n size=\"md\"\n leading={<HeartPulse />}\n >\n {t(key('anamnesisExpired'), { n: expired })}\n </Badge>\n </InfoHover>\n ) : null}\n </>\n ) : undefined\n }\n /* Controlled, so a field this patient has and the last one did not (a\n third phone, the address once the map link is on) is shown too. */\n visibleFieldOrder={fields.map((field) => field.id)}\n sections={\n fields.length > 0\n ? [{ id: 'contact', heading: t(key('sectionPatient')), fields }]\n : undefined\n }\n />\n );\n}\n\n/**\n * When, how long, who and where, the series rule, and what the booking\n * site recorded. Operator and chair names are the caller's labels, so an\n * id without one prints no row. `description` is the caller's slot for the\n * description, above the facts.\n */\nexport function DetailsAppointmentCard({\n details,\n locale,\n currency,\n operator,\n chair,\n description,\n privacy = false,\n history,\n}: CardProps & {\n operator?: AppointmentDetailsOperatorLabel;\n chair?: AppointmentDetailsChairLabel;\n description?: ReactNode;\n /** Privacy mode: what the booker typed is dropped; when they booked stays. */\n privacy?: boolean;\n /** The history the user may see, as the panel resolved it (the host's\n * own read, else the read's). Absent while withheld or not yet read:\n * then no \"Created by\" row. */\n history?: readonly AppointmentHistoryEntry[];\n}) {\n const { t } = useTranslation('ui');\n const { appointment, booking, patient } = details;\n const editor = (suffix: string) => t(`calendarWorkspace.editor.${suffix}`);\n /* A zone-less wall clock parses as local time. */\n const start = new Date(appointment.startIso);\n const end = new Date(start.getTime() + appointment.durationMin * 60_000);\n const timed = Number.isFinite(start.getTime());\n const { recurrence } = appointment;\n const frequencyKey = recurrence && RECURRENCE_LABEL_KEY[recurrence.frequency];\n const frequency = frequencyKey\n ? t(`calendarWorkspace.editor.${frequencyKey}`)\n : undefined;\n const bookingRows: Array<Row | false | undefined | ''> = booking\n ? [\n booking.bookedAtIso && {\n id: 'bookedAt',\n label: t(key('bookedAt')),\n value: (\n <Timestamp\n value={booking.bookedAtIso}\n format=\"absolute\"\n shape=\"bare\"\n locale={locale}\n absoluteFormat={DETAIL_STAMP_FORMAT}\n />\n ),\n },\n booking.typedName && {\n id: 'bookingName',\n label: t(key('bookingName')),\n value: booking.typedName,\n },\n booking.phone && {\n id: 'bookingPhone',\n label: t(key('bookingPhone')),\n value: telLink(booking.phone),\n },\n booking.email && {\n id: 'bookingEmail',\n label: t(key('bookingEmail')),\n value: mailLink(booking.email),\n },\n booking.note && {\n id: 'bookingNote',\n label: t(key('bookingNote')),\n value: booking.note,\n },\n /* With a patient the amount is a chip on the patient card. */\n !patient &&\n booking.paidOnlineAmount !== undefined && {\n id: 'paidOnline',\n label: t(key('paidOnline')),\n value: formatMoney(locale, booking.paidOnlineAmount, currency),\n },\n ]\n : [];\n /* Privacy keeps the one booking fact that names nobody: when. */\n const shownBookingRows = privacy\n ? bookingRows.filter((row) => row && row.id === 'bookedAt')\n : bookingRows;\n const hasBooking = shownBookingRows.some(Boolean);\n /* Who put the appointment in, from the history's creation line. An\n online booking has no such line (the booking block says when), and a\n line with no author (a patient) names nobody. */\n const creation =\n booking || appointment.bookedOnline\n ? undefined\n : history\n ?.filter(\n (entry) => entry.kind === 'created' && entry.actor.trim() !== '',\n )\n .sort((a, b) => Date.parse(a.atIso) - Date.parse(b.atIso))[0];\n return (\n <SectionCard\n data-card=\"appointment\"\n title={t(key('sectionAppointment'))}\n headingLevel={3}\n >\n {description}\n <Rows\n rows={[\n timed && {\n id: 'date',\n label: editor('date'),\n icon: <CalendarDays />,\n value: formatDay(locale, start),\n },\n timed && {\n id: 'time',\n label: t(key('time')),\n icon: <Clock />,\n value: appointment.allDay\n ? editor('allDay')\n : formatTimeRange(locale, start, end),\n },\n !appointment.allDay && {\n id: 'duration',\n label: editor('duration'),\n icon: <Hourglass />,\n value: `${appointment.durationMin} ${editor('durationUnit')}`,\n },\n appointment.isTelehealth && {\n id: 'type',\n label: editor('type'),\n icon: <Video />,\n value: editor('typeTelehealth'),\n },\n operator && {\n id: 'operator',\n label: t(key('operator')),\n /* A person, as on the grid: the avatar fills the icon slot. */\n icon: (\n <Avatar name={operator.name} src={operator.avatarSrc} size=\"xs\" />\n ),\n value: operator.name,\n },\n chair && {\n id: 'chair',\n label: t(key('chair')),\n icon: <Armchair />,\n value: (\n <Badge variant=\"neutral\" size=\"sm\" leading={<Armchair />}>\n {chair.name}\n </Badge>\n ),\n },\n appointment.branchLabel && {\n id: 'branch',\n label: editor('branch'),\n icon: <Building2 />,\n value: appointment.branchLabel,\n },\n creation && {\n id: 'createdBy',\n label: t(key('createdBy')),\n icon: <Avatar name={creation.actor} size=\"xs\" />,\n value: (\n <span className=\"ds:inline-flex ds:flex-wrap ds:items-baseline ds:gap-x-[var(--spacing-xs)]\">\n <span>{creation.actor}</span>{' '}\n <span className=\"ds:text-[color:var(--muted-foreground)]\">\n <Timestamp\n value={creation.atIso}\n format=\"absolute\"\n shape=\"bare\"\n locale={locale}\n absoluteFormat={DETAIL_STAMP_FORMAT}\n />\n </span>\n </span>\n ),\n },\n frequency &&\n recurrence && {\n id: 'series',\n label: t(key('seriesLabel')),\n icon: <Repeat />,\n value:\n recurrence.count === undefined\n ? frequency\n : t(key('seriesRule'), {\n frequency,\n count: recurrence.count,\n }),\n },\n ]}\n />\n {hasBooking ? (\n <div\n data-block=\"booking\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <h4 className=\"ds:m-0 type-label ds:text-[color:var(--muted-foreground)]\">\n {t(key('sectionBooking'))}\n </h4>\n <Rows rows={shownBookingRows} />\n </div>\n ) : null}\n </SectionCard>\n );\n}\n\n/** The linked plan, by number when the host has one, and the kit's\n * TreatmentReceipt: one line per treatment, a price only when the host\n * sends one (the editor's price gate), and a total only when every line\n * is priced. */\nexport function DetailsTreatmentsCard({\n details,\n locale,\n currency,\n privacy = false,\n}: CardProps & {\n /** Privacy mode: the plan's free-text name goes, as on the hover peek. */\n privacy?: boolean;\n}) {\n const { t } = useTranslation('ui');\n const { care } = details;\n const plan = privacy ? undefined : care?.plan;\n if (!care || (!plan && care.lines.length === 0)) return null;\n return (\n <SectionCard\n data-card=\"treatments\"\n title={t(key('sectionTreatments'))}\n headingLevel={3}\n >\n {plan ? (\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)] type-title-item\">\n <ClipboardList\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-[color:var(--muted-foreground)]\"\n />\n {plan.number\n ? t(key('planLine'), { number: plan.number, name: plan.name })\n : plan.name}\n </span>\n ) : null}\n {care.lines.length > 0 ? (\n <TreatmentReceipt\n lines={care.lines.map(({ entryId, careId: _careId, ...line }) => ({\n id: entryId,\n ...line,\n }))}\n locale={locale}\n currency={currency}\n />\n ) : null}\n </SectionCard>\n );\n}\n\nconst NOTES_PREVIEWED = 3;\n\n/** The patient's latest notes, pinned first, as the host holds them. A\n * click on a note opens the Notes tool at it; the header button opens the\n * tool from the keyboard. */\nexport function DetailsNotesCard({\n preview,\n onOpenNotes,\n locale,\n}: {\n preview: AppointmentDetailsNotesPreview;\n onOpenNotes?: (noteId?: string) => void;\n locale?: string;\n}) {\n const { t } = useTranslation('ui');\n const headingId = useId();\n const status = preview.status ?? 'ready';\n /* Retry leaves with the error it answered: the card's heading keeps the\n focus until the read settles. */\n const retried = useRef(false);\n useIsomorphicLayoutEffect(() => {\n if (!retried.current) return;\n if (status !== 'loading') retried.current = false;\n focusHeading(headingId);\n }, [status, headingId]);\n const count =\n preview.total ?? (status === 'ready' ? preview.notes.length : null);\n const more = Math.max(0, (count ?? 0) - NOTES_PREVIEWED);\n const openLabel =\n more > 0 ? t(key('notesMore'), { n: more }) : t(key('notesPreviewOpen'));\n return (\n <SectionCard\n /* `data-card`, not `data-component`: SectionCard's own marker must\n survive, or the kit's cascade reset loses this element. */\n data-card=\"notes\"\n headingId={headingId}\n headingLevel={3}\n title={\n count === null\n ? t('notesPanel.title')\n : t(key('notesPreviewTitle'), { count })\n }\n headerAction={\n onOpenNotes && (count ?? 0) > 0 ? (\n <span className=\"ds:relative ds:inline-flex\">\n <IconButton\n icon={<NotebookPen aria-hidden=\"true\" />}\n intent=\"outline\"\n size=\"sm\"\n data-action=\"open-patient-notes\"\n aria-label={openLabel}\n tooltip={openLabel}\n onClick={() => onOpenNotes()}\n />\n {more > 0 ? (\n /* Decorative: the button's name already says the count. */\n <Counter\n variant=\"outline\"\n size=\"sm\"\n background=\"surface\"\n count={more}\n aria-hidden=\"true\"\n className=\"ds:pointer-events-none ds:absolute ds:-top-[var(--spacing-2xs)] ds:-end-[var(--spacing-2xs)]\"\n />\n ) : null}\n </span>\n ) : undefined\n }\n >\n {status === 'error' ? (\n <Alert variant=\"error\">\n <Alert.Description>{t('notesPanel.loadError')}</Alert.Description>\n {preview.onRetry ? (\n <Alert.Action>\n <Button\n intent=\"secondary\"\n size=\"sm\"\n onClick={() => {\n retried.current = true;\n preview.onRetry?.();\n }}\n >\n {t('notesPanel.retry')}\n </Button>\n </Alert.Action>\n ) : null}\n </Alert>\n ) : null}\n {preview.notes.length === 0 && status === 'loading' ? (\n <>\n <span role=\"status\" className=\"ds:sr-only\">\n {t('notesPanel.loading')}\n </span>\n <NoteTimeline notes={[]} loading loadingRows={2} />\n </>\n ) : status !== 'error' || preview.notes.length > 0 ? (\n /* A note click, or Enter or Space on it, goes straight to that note\n in the Notes tool; the header button opens the tool at the top. */\n <NoteTimeline\n notes={preview.notes}\n maxItems={NOTES_PREVIEWED}\n locale={locale}\n aria-labelledby={headingId}\n onNoteActivate={onOpenNotes}\n emptyState={\n <p className=\"ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t(key('notesPreviewEmpty'))}\n </p>\n }\n />\n ) : null}\n </SectionCard>\n );\n}\n","/* -------------------------------------------------------------------- */\n/* AppointmentDetailsPanel */\n/* */\n/* One appointment occurrence, read-only apart from its status and its */\n/* description: a header with History, the patient, appointment, notes */\n/* and treatments cards, and a pinned footer with the status control and */\n/* the host's actions. History and the description editor slide over the */\n/* body as PanelSubviews. While there is no read it shows a skeleton, an */\n/* error with Retry, or a refusal. */\n/* */\n/* Everything comes from props: the read, the operator and chair labels, */\n/* the currency, the practice clock and one handler per action. An absent */\n/* handler withholds its control, and each handler receives the event id */\n/* of the read it acted on. The calendar pattern's details panel is an */\n/* adapter over this component. */\n/* */\n/* DOM hooks: the root carries data-component=\"appointment-details-panel\" */\n/* with data-component-id, data-event-id and data-status; cards carry */\n/* data-card, footer actions data-action, sub-views data-details-subview. */\n/* -------------------------------------------------------------------- */\nimport { cva } from 'class-variance-authority';\nimport {\n CalendarClock,\n Camera,\n ChevronDown,\n ClipboardList,\n ClipboardPaste,\n Copy,\n File,\n FileText,\n Folder,\n History as HistoryIcon,\n IdCard,\n Move,\n Pencil,\n Plus,\n ReceiptEuro,\n SquareCheckBig,\n Trash2,\n Video,\n} from 'lucide-react';\nimport {\n forwardRef,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type MutableRefObject,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { getErrorMessage } from '../_shared/get-error-message';\nimport { handledRejection } from '../_shared/handled-rejection';\nimport {\n PrivacyHiddenLine,\n PrivacyIdentityCard,\n} from '../_shared/privacy-mask';\nimport { Alert } from '../alert';\nimport { Button, IconButton } from '../button';\nimport { ButtonGroup, type ButtonGroupOverflowItem } from '../button-group';\nimport type { CalendarEventStatus } from '../calendar';\nimport { DropdownMenu } from '../dropdown-menu';\nimport { EditableDescription } from '../editable-description';\nimport { NoteTimeline } from '../note-timeline';\nimport { PanelHeader } from '../panel-header';\nimport { PanelSubview } from '../panel-subview';\nimport { PatientSummaryCard } from '../patient-summary-card';\nimport { SectionCard } from '../section-card';\nimport { CONTENT_ENTER_CLASS, Skeleton } from '../skeleton';\nimport { TextArea } from '../text-area';\nimport { Tooltip } from '../tooltip';\nimport { TreatmentReceipt } from '../treatment-receipt';\nimport { WhatsAppGlyph } from '../whatsapp-button';\nimport {\n APPOINTMENT_WORKFLOW_STATUSES,\n isCalendarEventStatus,\n useAppointmentWorkflowStatus,\n WorkflowStatusControl,\n WorkflowStatusDisplay,\n type WorkflowStatusControlHandle,\n} from '../workflow-status';\nimport { appointmentDetailsPanelAgent } from './appointment-details-panel.agent';\nimport { focusHeading, rescueFocus } from './appointment-details-panel.focus';\nimport { AppointmentHistoryTimeline } from './appointment-details-panel.history';\nimport { AppointmentIdentityStrip } from './appointment-details-panel.identity';\nimport {\n DetailsAppointmentCard,\n DetailsNotesCard,\n DetailsPatientCard,\n DetailsTreatmentsCard,\n} from './appointment-details-panel.sections';\nimport type {\n AppointmentDetailsChairLabel,\n AppointmentDetailsHistory,\n AppointmentDetailsNotesPreview,\n AppointmentDetailsOperatorLabel,\n AppointmentDetailsRead,\n AppointmentDetailsState,\n AppointmentDocumentKind,\n} from './appointment-details-panel.types';\n\n/* -------------------------------------------------------------------- */\n/* Public API */\n/* -------------------------------------------------------------------- */\n\nexport interface AppointmentDetailsPanelProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'children' | 'title' | 'onCopy'\n> {\n /** The read, or the shell state while there is none. Pair it with\n * `useAppointmentDetailsRead`, which keeps the latest selection. */\n state: AppointmentDetailsState;\n /** Retry from the error shell and from a retryable refusal. Without it,\n * no Retry button. */\n onRetry?: () => void;\n /** The appointment's patient id when the read carries no record: an id\n * without a record reads \"Patient record not loaded\", never \"no\n * patient\". Default `read.patient?.id`. */\n patientId?: string;\n /** The operator's label, resolved by the host from\n * `appointment.operatorId`. Absent = no operator row. */\n operator?: AppointmentDetailsOperatorLabel;\n /** The chair's label. Absent = no chair row. */\n chair?: AppointmentDetailsChairLabel;\n /** ISO 4217 code for the money chips, the paid-online row and the\n * treatment prices. Default 'EUR'. */\n currency?: string;\n /** The practice clock the patient's age is computed against. Default:\n * the real clock. */\n now?: Date | string;\n /** Locale for dates, times and amounts. Default: the active language. */\n locale?: string;\n /** Header title. Default \"Appointment details\". Ignored under `privacy`,\n * so a patient name can never reach the header. */\n title?: string;\n /** Privacy mode: the identity is masked; the photo, contact fields,\n * chips, description, notes, the booker's contact, the plan name and\n * `whatsappUrl` are withheld. Time, operator, chair, status, treatments\n * and History stay. A display mask on top of the host's server-side\n * masking, never instead of it. */\n privacy?: boolean;\n /** The grid's mask for this appointment; bullets without one. Read only\n * under `privacy`. */\n privacyTitle?: string;\n /** The user's map-link setting (platform `showPatientAddressMapLink`). */\n mapsLink?: boolean;\n /** The latest notes of this appointment's patient, and only theirs: set\n * `patientId` and notes for another patient show as loading. Without\n * it, no notes card. Pass it only when the appointment has a patient. */\n notesPreview?: AppointmentDetailsNotesPreview;\n /** Open the host's Notes tool, at one note when a note was clicked.\n * Without it, the preview opens nothing. */\n onOpenNotes?: (noteId?: string) => void;\n /** The appointment's history, read by the host once History opens.\n * Present = the user may read it, so the header offers History. Set its\n * `eventId`: entries for another occurrence show as loading. Wins over\n * `read.history`, the shortcut for a history sent with the read. */\n history?: AppointmentDetailsHistory;\n /** History opened, from its button or the agent: start the host's read.\n * Called on every opening. */\n onOpenHistory?: (eventId: string) => void;\n /** In History, say \"What changed was not recorded.\" under an edit that\n * carries no detail. Off by default. */\n noteUnrecordedEdits?: boolean;\n /** Withholds Edit, Move, Copy, Delete, the status change and the\n * description edit. Join, WhatsApp, Create task and the documents menu\n * are the host's to withhold. */\n readOnly?: boolean;\n /** Save a new status. Reject with a translated Error: the control keeps\n * the old status and shows the message. Absent = status read-only.\n * Every handler's last argument is the event id of the read it acted\n * on: write to that appointment, never to \"the current selection\". */\n onStatusChange?: (\n status: CalendarEventStatus,\n eventId: string,\n ) => Promise<void>;\n /** The statuses this user may set, in any order; the menu keeps the\n * platform's. Default: all six. The current status is always shown, and\n * disabled when not allowed. With no status to move to (an empty list,\n * or the current one alone) the status is shown read-only. */\n allowedStatuses?: readonly CalendarEventStatus[];\n /** Save a new description from the pencil's sub-view. Reject with a\n * translated Error: the sub-view stays open and shows it. Absent = the\n * description is read-only. */\n onDescriptionChange?: (description: string, eventId: string) => Promise<void>;\n /** Hand over to the host's editor. */\n onEdit?: (eventId: string) => void;\n /** Arm the host's move placement. */\n onMove?: (eventId: string) => void;\n /** Start the host's copy. With treatments on the read, a menu asks for\n * the appointment alone or with its treatments. */\n onCopy?: (withTreatments: boolean, eventId: string) => void;\n /** Start the host's delete. The host owns the confirmation, the series\n * scope and any care-plan clean-up. */\n onDelete?: (eventId: string) => void;\n /** Join the video visit. The host keeps the session code. */\n onJoinTelehealth?: (eventId: string) => void;\n /** The host's WhatsApp bridge. Wins over `whatsappUrl` as the one\n * button. Withhold it yourself where the user may not message the\n * patient. */\n onWhatsApp?: (eventId: string) => void;\n /** A host-composed WhatsApp link, opened in a new tab. Withheld under\n * `privacy`, because it carries the patient's number. */\n whatsappUrl?: string;\n /** Server-built link to the task page, opened in the same tab. */\n createTaskUrl?: string;\n /** The create-document kinds the user may use, and what each does. The\n * menu keeps the platform's order. */\n documents?: {\n kinds: readonly AppointmentDocumentKind[];\n onCreate: (kind: AppointmentDocumentKind, eventId: string) => void;\n };\n}\n\n/** Curated agent handle: ids and enums only, never patient data. */\nexport interface AppointmentDetailsPanelHandle {\n /** The occurrence on screen or being read, or the one a failed or\n * refused read was for when the state says; null otherwise. */\n getEventId: () => string | null;\n getLoadStatus: () => AppointmentDetailsState['status'];\n /** The status as last saved here or read; null for none, or no read. */\n getAppointmentStatus: () => CalendarEventStatus | null;\n /** The statuses `setAppointmentStatus` accepts now; [] when the status\n * cannot be changed. */\n getAllowedStatuses: () => CalendarEventStatus[];\n /** The footer's `data-action` values, in footer order. */\n getOfferedActions: () => string[];\n isHistoryOpen: () => boolean;\n isPrivacy: () => boolean;\n /** Throws when History is not offered. */\n openHistory: () => void;\n closeHistory: () => void;\n /** The footer control's own path: it shows the saving state and any\n * refusal. Rejects when the change is not offered, not allowed, or a\n * save is in flight, including one started in the same tick. */\n setAppointmentStatus: (status: CalendarEventStatus) => Promise<void>;\n /** Throws when no Retry is offered. */\n retry: () => void;\n}\n\n/* -------------------------------------------------------------------- */\n/* Styles */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:flex ds:h-full ds:min-h-0 ds:flex-col');\n\nconst footerVariants = cva(\n 'ds:flex ds:shrink-0 ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:border-t ds:border-[color:var(--border)] ds:p-[var(--spacing-sm)]',\n);\n\n/* The read-only status takes focus only when the control it replaced\n held it, so it shows the kit's ring then. */\nconst statusShownVariants = cva(\n 'ds:shrink-0 ds:rounded-[var(--radius-md)] ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n);\n\n/* Accessible themes keep the kit's raised target; default themes match\n the 32px status control through Button size=\"sm\". Below `sm` a small\n Button already floors at --min-target-size; from `sm` up it drops that\n floor, so the raise is needed there only (--accessible-target-floor is\n unset outside the accessible themes, so the fallback keeps the drop). */\nconst ACCESSIBLE_TARGET =\n 'ds:sm:[min-block-size:var(--accessible-target-floor,0px)]';\n/* The status control's className lands on its root div, not the trigger\n inside it, so target the direct child. */\nconst ACCESSIBLE_TARGET_STATUS_CONTROL =\n 'ds:sm:[&>button]:[min-block-size:var(--accessible-target-floor,0px)]';\n/* ButtonGroup owns its More trigger and no prop reaches it. Reach it from\n outside by the Ellipsis glyph it renders, which does not translate. */\nconst ACCESSIBLE_TARGET_OVERFLOW_TRIGGER = [\n 'ds:sm:[&_button:has(svg.lucide-ellipsis)]:[min-block-size:var(--accessible-target-floor,0px)]',\n 'ds:[&_button:has(svg.lucide-ellipsis)]:[min-inline-size:var(--accessible-target-floor,auto)]',\n].join(' ');\n\n/* How many term and detail rows the Appointment card shows while it loads:\n date, time, operator, chair. Uneven widths, so they read as facts. */\nconst SKELETON_FACT_WIDTHS = ['40%', '33%', '50%', '25%'] as const;\n\n/* The platform's create-menu order; the host's order and duplicate kinds\n do not change it. */\nconst DOCUMENT_KINDS: readonly AppointmentDocumentKind[] = [\n 'bill',\n 'folder',\n 'template',\n 'empty',\n 'identification',\n 'webcam',\n];\n\n/** Each create-menu item's glyph, per the icon map's duty for that kind. */\nconst DOCUMENT_ICON: Record<AppointmentDocumentKind, ReactNode> = {\n bill: <ReceiptEuro aria-hidden=\"true\" />,\n folder: <Folder aria-hidden=\"true\" />,\n template: <FileText aria-hidden=\"true\" />,\n empty: <File aria-hidden=\"true\" />,\n identification: <IdCard aria-hidden=\"true\" />,\n webcam: <Camera aria-hidden=\"true\" />,\n};\n\nconst key = (suffix: string): string => `calendarWorkspace.details.${suffix}`;\n\n/* -------------------------------------------------------------------- */\n/* Parts */\n/* -------------------------------------------------------------------- */\n\n/** One entry of a footer menu. A menu carries an icon on every item or on\n * none, so the icon is required. */\ntype MenuOption = ButtonGroupOverflowItem & { icon: ReactNode };\n\n/** A footer action that opens a menu. The label is `children` because\n * ButtonGroup keys its collapse stage off a string child, and the options\n * are `overflowItems` too, so More repeats them in a submenu when the\n * action folds away. */\nfunction MenuAction({\n children: label,\n startIcon,\n overflowItems: options,\n 'data-action': action,\n intent,\n background,\n size,\n hideLabel,\n}: {\n children: string;\n startIcon: ReactNode;\n overflowItems: readonly MenuOption[];\n /** On the trigger. ButtonGroup clears it on its measuring copies. */\n 'data-action'?: string;\n /** ButtonGroup: this action shows its own tooltip. */\n 'data-overflow-tip'?: false;\n intent?: 'outline' | 'primary';\n background?: 'transparent' | 'surface';\n size?: 'sm' | 'md' | 'lg';\n hideLabel?: boolean;\n}) {\n return (\n <DropdownMenu.Root>\n <Tooltip label={label} side=\"top\">\n <DropdownMenu.Trigger asChild>\n <Button\n intent={intent}\n background={background}\n size={size}\n data-action={action}\n className={ACCESSIBLE_TARGET}\n startIcon={startIcon}\n aria-haspopup=\"menu\"\n /* The chevron stays when the label folds: it says this opens a\n menu rather than acting. */\n endIcon={<ChevronDown aria-hidden=\"true\" />}\n >\n {hideLabel ? <span className=\"ds:sr-only\">{label}</span> : label}\n </Button>\n </DropdownMenu.Trigger>\n </Tooltip>\n <DropdownMenu.Content align=\"end\">\n {options.map((option) => (\n <DropdownMenu.Item\n key={option.label}\n data-action={option.action}\n startIcon={option.icon}\n onSelect={option.onSelect}\n >\n {option.label}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\n/** The body while the read is in flight: every card already in place,\n * holding a placeholder in the shape of what will land there, so nothing\n * jumps when the answer arrives. */\nfunction DetailsSkeleton() {\n const { t } = useTranslation('ui');\n return (\n <>\n <span role=\"status\" className=\"ds:sr-only\">\n {t('common.loading')}\n </span>\n <div\n aria-hidden=\"true\"\n /* Cards keep their natural height; the column clips at the panel's\n edge, as the scrolling body it stands in for would. */\n className=\"ds:flex ds:min-h-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-sm)] ds:overflow-hidden ds:p-[var(--spacing-md)] ds:[&>*]:shrink-0\"\n >\n <PatientSummaryCard\n name=\"\"\n loading\n surface=\"elevated\"\n density=\"compact\"\n />\n <SectionCard title={t(key('sectionAppointment'))} headingLevel={3}>\n <EditableDescription loading maxLines={2} />\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {SKELETON_FACT_WIDTHS.map((width, index) => (\n <div\n key={width}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\"\n >\n <Skeleton\n variant=\"rounded\"\n stagger={index + 2}\n width=\"var(--spacing-md)\"\n height=\"var(--spacing-md)\"\n className=\"ds:shrink-0\"\n />\n <Skeleton\n variant=\"text\"\n size=\"sm\"\n stagger={index + 2}\n width={width}\n />\n </div>\n ))}\n </div>\n </SectionCard>\n <SectionCard title={t('notesPanel.title')} headingLevel={3}>\n <NoteTimeline notes={[]} loading loadingRows={2} />\n </SectionCard>\n <SectionCard title={t(key('sectionTreatments'))} headingLevel={3}>\n <TreatmentReceipt lines={[]} loading />\n </SectionCard>\n </div>\n <div\n aria-hidden=\"true\"\n className=\"ds:flex ds:shrink-0 ds:items-center ds:gap-[var(--spacing-sm)] ds:border-t ds:border-[color:var(--border)] ds:p-[var(--spacing-md)]\"\n >\n <Skeleton variant=\"rounded\" width=\"33%\" height=\"var(--spacing-xl)\" />\n <Skeleton\n variant=\"rounded\"\n stagger={1}\n height=\"var(--spacing-xl)\"\n className=\"ds:flex-1\"\n />\n </div>\n </>\n );\n}\n\n/** The History sub-view's body: a skeleton while the host reads, an error\n * with Retry, or the timeline. */\nfunction HistoryBody({\n history,\n locale,\n onRetry,\n noteUnrecordedEdits,\n privacy,\n}: {\n history: AppointmentDetailsHistory;\n locale: string;\n onRetry?: () => void;\n noteUnrecordedEdits?: boolean;\n privacy?: boolean;\n}) {\n const { t } = useTranslation('ui');\n const status = history.status ?? (history.entries ? 'ready' : 'loading');\n const entries = status === 'error' ? undefined : history.entries;\n const loading = status === 'loading' || (status !== 'error' && !entries);\n /* One polite line for the life of the sub-view, outside any busy part:\n it says the read is under way, then how it settled. It starts empty,\n so its first words are announced too. An error has its own alert. */\n const [speaking, setSpeaking] = useState(false);\n useEffect(() => setSpeaking(true), []);\n let settled = '';\n if (loading) settled = t('common.loading');\n else if (entries)\n settled =\n entries.length === 0\n ? t(key('historyEmpty'))\n : t(key('historyLoaded'), { n: entries.length });\n let body: ReactNode;\n if (status === 'error')\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <Alert variant=\"error\">\n <Alert.Description>\n {history.message?.trim() || t('emptyState.error.description')}\n </Alert.Description>\n </Alert>\n {onRetry ? (\n <Button\n intent=\"outline\"\n data-action=\"retry-history\"\n onClick={() => onRetry()}\n >\n {t('emptyState.error.cta')}\n </Button>\n ) : null}\n </div>\n );\n else if (loading || !entries)\n body = (\n <div\n aria-hidden=\"true\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n {SKELETON_FACT_WIDTHS.slice(0, 3).map((width, index) => (\n <div\n key={width}\n className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)]\"\n >\n <Skeleton\n variant=\"circular\"\n stagger={index}\n width=\"var(--spacing-xl)\"\n height=\"var(--spacing-xl)\"\n className=\"ds:shrink-0\"\n />\n <Skeleton\n variant=\"rounded\"\n stagger={index}\n width={width}\n height=\"var(--spacing-2xl)\"\n />\n </div>\n ))}\n </div>\n );\n else\n body = (\n <AppointmentHistoryTimeline\n history={entries}\n locale={locale}\n noteUnrecordedEdits={noteUnrecordedEdits}\n privacy={privacy}\n />\n );\n return (\n <>\n <span role=\"status\" className=\"ds:sr-only\">\n {speaking ? settled : ''}\n </span>\n {body}\n </>\n );\n}\n\n/** What the agent handle reads from the appointment on screen. */\ninterface LiveDetails {\n status: CalendarEventStatus | null;\n allowed: CalendarEventStatus[];\n offered: string[];\n historyAvailable: boolean;\n historyOpen: boolean;\n openHistory: () => void;\n closeHistory: () => void;\n}\n\ninterface DetailsContentProps extends Omit<\n AppointmentDetailsPanelProps,\n 'state' | 'onRetry' | 'currency' | 'now' | 'locale' | 'title'\n> {\n read: AppointmentDetailsRead;\n refreshing: boolean;\n currency: string;\n now: Date | string;\n locale: string;\n shownTitle: string;\n /** The panel heading's id, for putting focus back in the panel. */\n headingId: string;\n /** Fade in: the read arrived where the skeleton or an error stood. */\n enter: boolean;\n live: MutableRefObject<LiveDetails | null>;\n statusControl: MutableRefObject<WorkflowStatusControlHandle | null>;\n}\n\n/** One appointment. Keyed by its event id, so the sub-views, the draft and\n * what was saved here reset for the next appointment. */\nfunction DetailsContent({\n read,\n refreshing,\n currency,\n now,\n locale,\n shownTitle,\n headingId,\n enter,\n live,\n statusControl,\n patientId = read.patient?.id,\n operator,\n chair,\n privacy = false,\n privacyTitle,\n mapsLink,\n notesPreview,\n onOpenNotes,\n history: hostHistory,\n onOpenHistory,\n noteUnrecordedEdits = false,\n readOnly = false,\n onStatusChange,\n allowedStatuses = APPOINTMENT_WORKFLOW_STATUSES,\n onDescriptionChange,\n onEdit,\n onMove,\n onCopy,\n onDelete,\n onJoinTelehealth,\n onWhatsApp,\n whatsappUrl: hostWhatsappUrl,\n createTaskUrl,\n documents,\n}: DetailsContentProps) {\n const { t } = useTranslation('ui');\n const { eventId } = read;\n /* Decided once: a later render must not cut the fade short. */\n const [entering] = useState(enter);\n const card = { details: read, locale, currency };\n /* The host's own read wins; a history sent with the read is the\n shortcut. Either one offers History. A late answer for an earlier\n appointment shows as loading, never under this one. */\n const history: AppointmentDetailsHistory | undefined = hostHistory\n ? hostHistory.eventId !== undefined && hostHistory.eventId !== eventId\n ? { status: 'loading' }\n : hostHistory\n : read.history\n ? { entries: read.history }\n : undefined;\n /* Notes for another patient never show under this appointment: they\n read as loading until the host catches up, and without a patient\n there is no card. */\n const notesForPatient =\n notesPreview?.patientId === undefined ||\n notesPreview.patientId === patientId;\n const notes: AppointmentDetailsNotesPreview | undefined = !notesPreview\n ? undefined\n : notesForPatient\n ? notesPreview\n : patientId\n ? { notes: [], status: 'loading', total: null }\n : undefined;\n const editorOffered = Boolean(onDescriptionChange) && !readOnly && !privacy;\n /* Both sub-views stay mounted and slide over the body; PanelSubview owns\n the focus in and back. A sub-view whose seam is withdrawn is shown\n closed at once, and its state is reset below. */\n const [historyOpen, setHistoryOpen] = useState(false);\n const [editingDescription, setEditingDescription] = useState(false);\n const historyShown = historyOpen && history !== undefined;\n const editorShown = editingDescription && editorOffered;\n const openHistory = () => {\n if (historyShown || !history) return;\n setHistoryOpen(true);\n onOpenHistory?.(eventId);\n };\n /* A refresh or a prop change can withdraw a sub-view while it is open:\n close it for good, so it never slides back by itself, and put focus\n back in the panel rather than on the page. */\n const shownBefore = useRef({ history: false, editor: false });\n useIsomorphicLayoutEffect(() => {\n const before = shownBefore.current;\n shownBefore.current = { history: historyShown, editor: editorShown };\n const lostHistory = before.history && history === undefined;\n const lostEditor = before.editor && !editorOffered;\n if (lostHistory) setHistoryOpen(false);\n if (lostEditor) setEditingDescription(false);\n if (lostHistory || lostEditor) focusHeading(headingId);\n });\n /* Retry in the History sub-view leaves with the error: the sub-view keeps\n the focus until the read settles. */\n const historyRef = useRef<HTMLElement>(null);\n const historyRetried = useRef(false);\n const historyStatus =\n history?.status ?? (history?.entries ? 'ready' : 'loading');\n useIsomorphicLayoutEffect(() => {\n if (!historyRetried.current) return;\n if (historyStatus !== 'loading') historyRetried.current = false;\n rescueFocus(historyRef.current);\n }, [historyStatus]);\n /* The description as last saved here; the read is the starting point. */\n const [description, setDescription] = useState(read.appointment.name ?? '');\n /* A fresh read from the host wins over what was saved here. */\n useEffect(() => {\n setDescription(read.appointment.name ?? '');\n }, [read.appointment.name]);\n const [descriptionDraft, setDescriptionDraft] = useState('');\n const [descriptionSaving, setDescriptionSaving] = useState(false);\n const [descriptionError, setDescriptionError] = useState<string>();\n const descriptionFieldRef = useRef<HTMLTextAreaElement>(null);\n /* Filled when the sub-view opens, never by remounting it open. */\n useEffect(() => {\n if (!editingDescription) return;\n setDescriptionDraft(description);\n setDescriptionError(undefined);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- seed once per opening\n }, [editingDescription]);\n const saveDescription = async (): Promise<void> => {\n if (!onDescriptionChange) return;\n const next = descriptionDraft.trim();\n setDescriptionSaving(true);\n setDescriptionError(undefined);\n try {\n await onDescriptionChange(next, eventId);\n setDescription(next);\n setEditingDescription(false);\n } catch (error) {\n setDescriptionError(\n getErrorMessage(error, t(key('descriptionSaveFailed'))),\n );\n } finally {\n setDescriptionSaving(false);\n }\n };\n\n /* The status as last saved here; the read is the starting point. */\n const [status, setStatus] = useState(read.appointment.status);\n useEffect(() => {\n setStatus(read.appointment.status);\n }, [read.appointment.status]);\n /* A re-read that lands wins too, even when it repeats what the panel\n read before the save: someone may have changed it back. */\n const wasRefreshing = useRef(refreshing);\n useIsomorphicLayoutEffect(() => {\n const landed = wasRefreshing.current && !refreshing;\n wasRefreshing.current = refreshing;\n if (!landed) return;\n setStatus(read.appointment.status);\n setDescription(read.appointment.name ?? '');\n }, [refreshing]);\n /* In the platform's order, whatever the host's; unknowns dropped. */\n const permitted = APPOINTMENT_WORKFLOW_STATUSES.filter((option) =>\n allowedStatuses.includes(option),\n );\n const appointmentStatus = useAppointmentWorkflowStatus(status, {\n statuses: permitted,\n /* Shown so the control can say it, but not a choice. */\n disabledStatuses: status && !permitted.includes(status) ? [status] : [],\n });\n /* A control with nothing to move to would only refuse: show the status. */\n const statusEditable =\n Boolean(onStatusChange) &&\n !readOnly &&\n permitted.some((option) => option !== status);\n /* WorkflowStatusControl shows the saving state and the refusal. A\n refusal without a message keeps the panel's own wording. */\n const changeStatus = async (next: string): Promise<void> => {\n if (!onStatusChange || !isCalendarEventStatus(next)) return;\n try {\n await onStatusChange(next, eventId);\n } catch (error) {\n throw new Error(getErrorMessage(error, t(key('statusSaveFailed'))));\n }\n setStatus(next);\n };\n\n /* The composed link carries the patient's number: withheld under\n privacy. */\n const whatsappUrl = privacy ? undefined : hostWhatsappUrl;\n const documentKinds = DOCUMENT_KINDS.filter((kind) =>\n documents?.kinds.includes(kind),\n );\n const copyMenu = (read.care?.lines.length ?? 0) > 0;\n const assigned = patientId !== undefined && patientId !== '';\n\n const statusLabel = t(key('status'));\n const statusName = `${statusLabel}: ${appointmentStatus.option.label}`;\n const statusShownRef = useRef<HTMLDivElement>(null);\n /* A save or a re-read can leave nothing to move to: the control gives\n way to the read-only status, which takes the focus the control held\n and says the outcome. */\n const statusWasEditable = useRef(statusEditable);\n useIsomorphicLayoutEffect(() => {\n const lost = statusWasEditable.current && !statusEditable;\n statusWasEditable.current = statusEditable;\n if (!lost) return;\n if (statusShownRef.current) rescueFocus(statusShownRef.current);\n else focusHeading(headingId);\n });\n const statusNode = statusEditable ? (\n <WorkflowStatusControl\n ref={statusControl}\n value={appointmentStatus.value}\n options={appointmentStatus.options}\n size=\"sm\"\n workflowLabel={statusLabel}\n /* The trigger carries the actions' painted surface and, in the\n accessible themes, their raised target too. */\n className={`ds:[&>button]:bg-[color:var(--background)] ${ACCESSIBLE_TARGET_STATUS_CONTROL}`}\n aria-label={statusName}\n onValueChange={changeStatus}\n />\n ) : status ? (\n /* Named as the control is, \"Status: Confirmed\": the small display\n prints the value alone. */\n <div\n ref={statusShownRef}\n role=\"group\"\n aria-label={statusName}\n tabIndex={-1}\n data-status-display=\"\"\n className={statusShownVariants()}\n >\n <WorkflowStatusDisplay\n value={appointmentStatus.value}\n size=\"sm\"\n workflowLabel={statusLabel}\n option={appointmentStatus.option}\n />\n </div>\n ) : null;\n\n /* The footer's actions, in order, each under its data-action. */\n const entries: Array<[string, ReactNode]> = [];\n if (onJoinTelehealth)\n entries.push([\n 'join-telehealth',\n <Button\n key=\"join\"\n intent=\"primary\"\n data-action=\"join-telehealth\"\n className={ACCESSIBLE_TARGET}\n startIcon={<Video aria-hidden=\"true\" />}\n onClick={() => onJoinTelehealth(eventId)}\n >\n {t(key('joinTelehealth'))}\n </Button>,\n ]);\n if (!readOnly && onEdit)\n entries.push([\n 'edit-appointment',\n <Button\n key=\"edit\"\n data-action=\"edit-appointment\"\n className={ACCESSIBLE_TARGET}\n startIcon={<Pencil aria-hidden=\"true\" />}\n onClick={() => onEdit(eventId)}\n >\n {t('calendarWorkspace.editor.editTitle')}\n </Button>,\n ]);\n if (!readOnly && onMove)\n entries.push([\n 'move-appointment',\n <Button\n key=\"move\"\n data-action=\"move-appointment\"\n className={ACCESSIBLE_TARGET}\n startIcon={<Move aria-hidden=\"true\" />}\n onClick={() => onMove(eventId)}\n >\n {t(key('move'))}\n </Button>,\n ]);\n if (!readOnly && onCopy)\n entries.push([\n 'copy-appointment',\n copyMenu ? (\n <MenuAction\n key=\"copy\"\n data-action=\"copy-appointment\"\n data-overflow-tip={false}\n startIcon={<ClipboardPaste aria-hidden=\"true\" />}\n overflowItems={[\n {\n label: t('calendarWorkspace.editor.duplicateAppointmentOnly'),\n icon: <Copy aria-hidden=\"true\" />,\n action: 'copy-appointment-only',\n onSelect: () => onCopy(false, eventId),\n },\n {\n label: t('calendarWorkspace.editor.duplicateWithTreatments'),\n icon: <ClipboardList aria-hidden=\"true\" />,\n action: 'copy-appointment-with-treatments',\n onSelect: () => onCopy(true, eventId),\n },\n ]}\n >\n {t(key('copy'))}\n </MenuAction>\n ) : (\n <Button\n key=\"copy\"\n data-action=\"copy-appointment\"\n className={ACCESSIBLE_TARGET}\n startIcon={<ClipboardPaste aria-hidden=\"true\" />}\n onClick={() => onCopy(false, eventId)}\n >\n {t(key('copy'))}\n </Button>\n ),\n ]);\n if (documents && documentKinds.length > 0)\n entries.push([\n 'open-create-document',\n <MenuAction\n key=\"documents\"\n data-action=\"open-create-document\"\n data-overflow-tip={false}\n startIcon={<Plus aria-hidden=\"true\" />}\n overflowItems={documentKinds.map((kind) => ({\n label: t(key(`documents.${kind}`)),\n icon: DOCUMENT_ICON[kind],\n action: `create-document-${kind}`,\n onSelect: () => documents.onCreate(kind, eventId),\n }))}\n >\n {t(key('documents.label'))}\n </MenuAction>,\n ]);\n if (onWhatsApp)\n entries.push([\n 'open-whatsapp',\n <Button\n key=\"whatsapp\"\n data-action=\"open-whatsapp\"\n className={ACCESSIBLE_TARGET}\n startIcon={<WhatsAppGlyph aria-hidden=\"true\" />}\n onClick={() => onWhatsApp(eventId)}\n >\n {t(key('remindWhatsApp'))}\n </Button>,\n ]);\n else if (whatsappUrl)\n entries.push([\n 'open-whatsapp',\n <Button\n key=\"whatsapp\"\n asChild\n /* A link folds to its icon, then into More, which follows it. */\n data-action=\"open-whatsapp\"\n className={ACCESSIBLE_TARGET}\n startIcon={<WhatsAppGlyph aria-hidden=\"true\" />}\n >\n <a href={whatsappUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n {t(key('remindWhatsApp'))}\n </a>\n </Button>,\n ]);\n if (createTaskUrl)\n entries.push([\n 'create-task',\n <Button\n key=\"task\"\n asChild\n data-action=\"create-task\"\n className={ACCESSIBLE_TARGET}\n startIcon={<SquareCheckBig aria-hidden=\"true\" />}\n >\n <a href={createTaskUrl}>{t(key('createTask'))}</a>\n </Button>,\n ]);\n /* Last, so it is the first to fold into More at a narrow width. */\n if (!readOnly && onDelete)\n entries.push([\n 'delete-appointment',\n <Button\n key=\"delete\"\n intent=\"destructiveOutline\"\n data-action=\"delete-appointment\"\n className={ACCESSIBLE_TARGET}\n startIcon={<Trash2 aria-hidden=\"true\" />}\n onClick={() => onDelete(eventId)}\n >\n {t('calendarWorkspace.editor.delete')}\n </Button>,\n ]);\n const actions = entries.map(([, node]) => node);\n\n live.current = {\n status: status ?? null,\n allowed: statusEditable ? permitted : [],\n offered: entries.map(([id]) => id),\n historyAvailable: history !== undefined,\n historyOpen: historyShown,\n openHistory,\n closeHistory: () => setHistoryOpen(false),\n };\n\n const backLabel = t(key('historyBack'));\n return (\n <div\n className={`ds:flex ds:min-h-0 ds:flex-1 ds:flex-col ${entering ? CONTENT_ENTER_CLASS : ''}`}\n >\n <PanelSubview.Host>\n <PanelHeader\n title={shownTitle}\n headingId={headingId}\n icon={<CalendarClock aria-hidden=\"true\" />}\n sticky\n divider\n actions={\n history ? (\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<HistoryIcon aria-hidden=\"true\" />}\n aria-label={t(key('historyAction'))}\n tooltip={t(key('historyAction'))}\n data-action=\"open-history\"\n onClick={openHistory}\n />\n ) : undefined\n }\n />\n <div\n /* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- the body scrolls inside the rail; axe scrollable-region-focusable needs the tab stop */\n tabIndex={0}\n aria-busy={refreshing || undefined}\n className=\"ds:[min-block-size:0] ds:flex-1 ds:overflow-y-auto\"\n >\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-md)]\">\n {privacy ? (\n <PrivacyIdentityCard mask={privacyTitle} />\n ) : read.patient ? (\n <DetailsPatientCard {...card} now={now} mapsLink={mapsLink} />\n ) : (\n /* No patient card to carry the identity: a patient-less, an\n unassigned or an unresolved booking keeps the strip. */\n <AppointmentIdentityStrip\n name={\n read.appointment.title.trim()\n ? read.appointment.title\n : t(key('patientNotLoaded'))\n }\n unresolved={assigned}\n status={status}\n flags={{\n isTelehealth: read.appointment.isTelehealth,\n isBookedOnline: read.appointment.bookedOnline,\n isRecurring: read.appointment.recurrence !== undefined,\n hasUnassignedPatient:\n read.appointment.bookedOnline && !assigned,\n hasHighlightedAnamnesis: false,\n hasBillableAmount: (read.money?.billableAmount ?? 0) > 0,\n }}\n locale={locale}\n />\n )}\n <DetailsAppointmentCard\n {...card}\n operator={operator}\n chair={chair}\n privacy={privacy}\n /* The creator comes from the history the user may see, as\n History resolves it: withheld history names nobody. */\n history={\n history?.status === 'error' ? undefined : history?.entries\n }\n description={\n /* Not keyed on the text: the pencil must survive a save,\n so the sub-view can hand focus back to it. An empty\n read-only description prints nothing. Privacy hides the\n text and the pencil. */\n privacy ? (\n description ? (\n <PrivacyHiddenLine block=\"description\" />\n ) : undefined\n ) : description || (onDescriptionChange && !readOnly) ? (\n <EditableDescription\n data-block=\"description\"\n role=\"group\"\n aria-label={t('calendarWorkspace.editor.description')}\n value={description}\n editLabel={t(key('editDescription'))}\n onEdit={\n onDescriptionChange && !readOnly\n ? () => setEditingDescription(true)\n : undefined\n }\n />\n ) : undefined\n }\n />\n {notes && privacy ? (\n <SectionCard\n data-card=\"notes\"\n title={t('notesPanel.title')}\n headingLevel={3}\n >\n <PrivacyHiddenLine />\n </SectionCard>\n ) : notes ? (\n <DetailsNotesCard\n preview={notes}\n onOpenNotes={notesForPatient ? onOpenNotes : undefined}\n locale={locale}\n />\n ) : null}\n <DetailsTreatmentsCard {...card} privacy={privacy} />\n </div>\n </div>\n {statusNode || actions.length > 0 ? (\n /* The body scrolls; the status and the actions stay put. The\n status keeps its own segment and never folds. The actions fold\n to icons, then into More, never onto a second line. */\n <div className={footerVariants()}>\n {statusNode}\n {actions.length > 0 ? (\n <ButtonGroup\n label={t(key('actionsLabel'))}\n overflow=\"menu\"\n collapseToIcons\n background=\"surface\"\n size=\"sm\"\n className={`ds:min-w-0 ds:flex-1 ds:text-end ${ACCESSIBLE_TARGET_OVERFLOW_TRIGGER}`}\n >\n {actions}\n </ButtonGroup>\n ) : null}\n </div>\n ) : null}\n {history ? (\n <PanelSubview\n ref={historyRef}\n open={historyShown}\n icon={<HistoryIcon aria-hidden=\"true\" />}\n title={t(key('historyTitle'))}\n backLabel={backLabel}\n headingLevel={3}\n onBack={() => setHistoryOpen(false)}\n data-details-subview=\"history\"\n >\n <div className=\"ds:-m-[var(--panel-subview-inset)] ds:p-[var(--spacing-md)]\">\n <HistoryBody\n history={history}\n locale={locale}\n noteUnrecordedEdits={noteUnrecordedEdits}\n privacy={privacy}\n onRetry={\n history.onRetry\n ? () => {\n historyRetried.current = true;\n history.onRetry?.();\n }\n : undefined\n }\n />\n </div>\n </PanelSubview>\n ) : null}\n {editorOffered ? (\n <PanelSubview\n open={editorShown}\n icon={<Pencil aria-hidden=\"true\" />}\n title={t(key('editDescription'))}\n backLabel={backLabel}\n headingLevel={3}\n initialFocusRef={descriptionFieldRef}\n /* Back and Escape wait for a save in flight, as Cancel does: a\n late answer must not close an editor the user reopened. */\n onBack={() => {\n if (!descriptionSaving) setEditingDescription(false);\n }}\n data-details-subview=\"description\"\n footer={\n <>\n <Button\n intent=\"secondary\"\n disabled={descriptionSaving}\n onClick={() => setEditingDescription(false)}\n >\n {t(key('noteCancel'))}\n </Button>\n <Button\n intent=\"primary\"\n data-action=\"save-description\"\n loading={descriptionSaving}\n onClick={() => void saveDescription()}\n >\n {t(key('descriptionSave'))}\n </Button>\n </>\n }\n >\n <div className=\"ds:-m-[var(--panel-subview-inset)] ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-md)]\">\n {descriptionError ? (\n <Alert variant=\"error\">\n <Alert.Description>{descriptionError}</Alert.Description>\n </Alert>\n ) : null}\n <TextArea\n ref={descriptionFieldRef}\n value={descriptionDraft}\n minRows={6}\n autoResize\n aria-label={t('calendarWorkspace.editor.description')}\n onChange={(event) => setDescriptionDraft(event.target.value)}\n />\n </div>\n </PanelSubview>\n ) : null}\n </PanelSubview.Host>\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\n/**\n * The appointment details panel: a props-driven rail panel for one\n * occurrence. Mount it as a `fill` tool in ControlRoomRail, which adds its\n * favourite and close controls to the panel's own header.\n */\nexport const AppointmentDetailsPanel = forwardRef<\n HTMLDivElement,\n AppointmentDetailsPanelProps\n>(function AppointmentDetailsPanel(\n {\n state,\n onRetry,\n patientId,\n operator,\n chair,\n currency = 'EUR',\n now,\n locale,\n title,\n privacy = false,\n privacyTitle,\n mapsLink,\n notesPreview,\n onOpenNotes,\n history,\n onOpenHistory,\n noteUnrecordedEdits,\n readOnly = false,\n onStatusChange,\n allowedStatuses,\n onDescriptionChange,\n onEdit,\n onMove,\n onCopy,\n onDelete,\n onJoinTelehealth,\n onWhatsApp,\n whatsappUrl,\n createTaskUrl,\n documents,\n id,\n className,\n ...rest\n },\n ref,\n) {\n const { t, i18n: runtimeI18n } = useTranslation('ui');\n const reactId = useId();\n const instanceId = id ?? reactId;\n const headingId = useId();\n const shownLocale = locale ?? runtimeI18n.language;\n /* A host title never reaches the header under privacy: it may be a\n patient's name. */\n const shownTitle = !privacy && title?.trim() ? title : t(key('region'));\n const read = state.status === 'ready' ? state.read : undefined;\n /* An error or a refusal names the occurrence it answers when it can. */\n const eventId = state.status === 'ready' ? state.read.eventId : state.eventId;\n /* The read fades in only where this panel showed a shell before it. A\n panel mounted with its read, or re-reading one, does not flash. */\n const previousStatus = useRef<AppointmentDetailsState['status'] | undefined>(\n undefined,\n );\n const enter =\n previousStatus.current !== undefined && previousStatus.current !== 'ready';\n useEffect(() => {\n previousStatus.current = state.status;\n }, [state.status]);\n const retryOffered =\n Boolean(onRetry) &&\n (state.status === 'error' ||\n (state.status === 'refused' && state.retryable === true));\n /* A swap between the read and the skeleton, the error or the refusal\n mounts a new tree, and whatever held focus leaves with the old one.\n Whether the panel held it is read now, while that node is still here. */\n const rootRef = useRef<HTMLDivElement>(null);\n const setRoot = useMemo(() => composeRefs(ref, rootRef), [ref]);\n const heldFocus = useRef(false);\n if (typeof document !== 'undefined')\n heldFocus.current =\n rootRef.current?.contains(document.activeElement) ?? false;\n const shape = read ? `ready:${read.eventId}` : state.status;\n /* After Retry, and after any swap while the panel held focus, the\n heading takes it: the new tree has no control where focus was. After\n Retry it keeps it until the read settles. */\n const retried = useRef(false);\n useIsomorphicLayoutEffect(() => {\n if (retried.current) {\n if (state.status !== 'loading') retried.current = false;\n focusHeading(headingId);\n } else if (heldFocus.current) focusHeading(headingId);\n }, [shape, headingId]);\n\n /* ---- Agent handle ------------------------------------------------ */\n const live = useRef<LiveDetails | null>(null);\n if (!read) live.current = null;\n const statusControl = useRef<WorkflowStatusControlHandle | null>(null);\n const snapshot = useRef({ state, eventId, privacy, retryOffered, onRetry });\n snapshot.current = { state, eventId, privacy, retryOffered, onRetry };\n const handle = useMemo<AppointmentDetailsPanelHandle>(\n () => ({\n getEventId: () => snapshot.current.eventId ?? null,\n getLoadStatus: () => snapshot.current.state.status,\n getAppointmentStatus: () => live.current?.status ?? null,\n getAllowedStatuses: () => [...(live.current?.allowed ?? [])],\n getOfferedActions: () => [...(live.current?.offered ?? [])],\n isHistoryOpen: () => live.current?.historyOpen ?? false,\n isPrivacy: () => snapshot.current.privacy,\n openHistory: () => {\n if (!live.current?.historyAvailable)\n throw new Error('AppointmentDetailsPanel: History is not offered.');\n live.current.openHistory();\n },\n closeHistory: () => {\n live.current?.closeHistory();\n },\n setAppointmentStatus: (next) => {\n const details = live.current;\n const control = statusControl.current;\n if (!details || !control || details.allowed.length === 0)\n return handledRejection(\n new Error('AppointmentDetailsPanel: the status is read-only.'),\n );\n if (next === details.status) return Promise.resolve();\n if (!details.allowed.includes(next))\n return handledRejection(\n new Error(`AppointmentDetailsPanel: \"${next}\" is not allowed.`),\n );\n const inFlight = () =>\n handledRejection(\n new Error('AppointmentDetailsPanel: a status save is in flight.'),\n );\n if (control.getIsSaving()) return inFlight();\n /* The control declines a change while a save is in flight, even\n one started in this same tick, before its handle re-renders. */\n const saved = control.setValue(next);\n return saved === undefined ? inFlight() : saved;\n },\n retry: () => {\n const { retryOffered: offered, onRetry: host } = snapshot.current;\n if (!offered || !host)\n throw new Error('AppointmentDetailsPanel: Retry is not offered.');\n host();\n },\n }),\n [],\n );\n useAgentRegistration(appointmentDetailsPanelAgent, handle, instanceId);\n\n const header = (\n <PanelHeader\n title={shownTitle}\n headingId={headingId}\n icon={<CalendarClock aria-hidden=\"true\" />}\n sticky\n divider\n />\n );\n let body: ReactNode;\n if (state.status === 'ready') {\n body = (\n <DetailsContent\n key={state.read.eventId}\n read={state.read}\n refreshing={state.refreshing === true}\n currency={currency}\n now={now ?? new Date()}\n locale={shownLocale}\n shownTitle={shownTitle}\n headingId={headingId}\n enter={enter}\n live={live}\n statusControl={statusControl}\n patientId={patientId}\n operator={operator}\n chair={chair}\n privacy={privacy}\n privacyTitle={privacyTitle}\n mapsLink={mapsLink}\n notesPreview={notesPreview}\n onOpenNotes={onOpenNotes}\n history={history}\n onOpenHistory={onOpenHistory}\n noteUnrecordedEdits={noteUnrecordedEdits}\n readOnly={readOnly}\n onStatusChange={onStatusChange}\n allowedStatuses={allowedStatuses}\n onDescriptionChange={onDescriptionChange}\n onEdit={onEdit}\n onMove={onMove}\n onCopy={onCopy}\n onDelete={onDelete}\n onJoinTelehealth={onJoinTelehealth}\n onWhatsApp={onWhatsApp}\n whatsappUrl={whatsappUrl}\n createTaskUrl={createTaskUrl}\n documents={documents}\n />\n );\n } else if (state.status === 'loading') {\n body = (\n <>\n {header}\n <DetailsSkeleton />\n </>\n );\n } else {\n body = (\n <>\n {header}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-md)]\">\n <Alert variant={state.status === 'error' ? 'error' : 'warning'}>\n <Alert.Description>\n {state.status === 'error'\n ? state.message?.trim() || t('emptyState.error.description')\n : state.reason}\n </Alert.Description>\n </Alert>\n {retryOffered ? (\n <Button\n intent=\"outline\"\n data-action=\"retry-load\"\n onClick={() => {\n retried.current = true;\n onRetry?.();\n }}\n >\n {t('emptyState.error.cta')}\n </Button>\n ) : null}\n </div>\n </>\n );\n }\n\n return (\n <div\n ref={setRoot}\n id={id}\n data-component=\"appointment-details-panel\"\n data-component-id={instanceId}\n data-event-id={eventId}\n data-status={state.status}\n aria-busy={state.status === 'loading' || undefined}\n className={rootVariants({ className })}\n {...rest}\n >\n {body}\n </div>\n );\n});\nAppointmentDetailsPanel.displayName = 'AppointmentDetailsPanel';\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport { getErrorMessage } from '../_shared/get-error-message';\nimport { parseAppointmentStartIso } from '../_shared/appointment-format';\nimport type {\n AppointmentDetailsRead,\n AppointmentDetailsState,\n UseAppointmentDetailsReadOptions,\n} from './appointment-details-panel.types';\n\ntype Settled<T extends AppointmentDetailsRead> = Exclude<\n AppointmentDetailsState<T>,\n { status: 'loading' }\n>;\n\n/** The last answer, and the request it answered. */\ninterface Answer<T extends AppointmentDetailsRead> {\n eventId: string;\n /** Which selection of `eventId` asked: coming back to an id is a new one. */\n selection: number;\n request: string;\n value: Settled<T>;\n}\n\nexport interface AppointmentDetailsReadResult<\n T extends AppointmentDetailsRead = AppointmentDetailsRead,\n> {\n /** Pass as AppointmentDetailsPanel `state`. Null while `eventId` is null:\n * there is no selection, so render no panel. */\n state: AppointmentDetailsState<T> | null;\n /** Pass as AppointmentDetailsPanel `onRetry`: reads the same occurrence\n * again. */\n retry: () => void;\n}\n\n/**\n * Reads one occurrence so that the latest selection always wins. A new\n * `eventId` aborts the read in flight and shows the skeleton, even for an\n * id shown before; a late answer for an earlier request is dropped. The\n * error and refused states carry the `eventId` they answer. An answer for\n * another appointment, or with an unreadable `startIso`, becomes an error,\n * so the panel never shows one patient's name with another's appointment.\n * A new `reloadKey` reads\n * the same occurrence again while the current read stays on screen\n * (`refreshing`); if that read fails, the panel shows the error rather than\n * going back to the older read. A null `eventId` reads nothing and returns\n * a null `state`.\n *\n * The latest `load` is the one called, so an inline loader never loops:\n * only `eventId`, `reloadKey` and `retry` start a read.\n */\nexport function useAppointmentDetailsRead<\n T extends AppointmentDetailsRead = AppointmentDetailsRead,\n>(\n options: UseAppointmentDetailsReadOptions<T> & { eventId: string },\n): AppointmentDetailsReadResult<T> & { state: AppointmentDetailsState<T> };\nexport function useAppointmentDetailsRead<\n T extends AppointmentDetailsRead = AppointmentDetailsRead,\n>(\n options: UseAppointmentDetailsReadOptions<T>,\n): AppointmentDetailsReadResult<T>;\nexport function useAppointmentDetailsRead<\n T extends AppointmentDetailsRead = AppointmentDetailsRead,\n>({\n eventId,\n load,\n reloadKey,\n}: UseAppointmentDetailsReadOptions<T>): AppointmentDetailsReadResult<T> {\n const { t } = useTranslation('ui');\n const failure = useRef('');\n failure.current = t('emptyState.error.description');\n /* Held, not a dependency: a host's inline loader must not read again on\n every render. */\n const loadRef = useRef(load);\n useIsomorphicLayoutEffect(() => {\n loadRef.current = load;\n });\n const [retries, setRetries] = useState(0);\n const [answer, setAnswer] = useState<Answer<T>>();\n const request = JSON.stringify([reloadKey ?? null, retries]);\n /* Counts selections: going to B and back to A before B answers reads A\n afresh behind the skeleton, never A's older answer as final. */\n const [selection, setSelection] = useState({ eventId, count: 0 });\n const selectionCount =\n selection.eventId === eventId ? selection.count : selection.count + 1;\n if (selection.eventId !== eventId)\n setSelection({ eventId, count: selectionCount });\n\n useEffect(() => {\n if (eventId === null) {\n /* A cleared selection forgets its answer: selecting the same\n appointment again starts from the skeleton. */\n setAnswer(undefined);\n return undefined;\n }\n const controller = new AbortController();\n const settle = (value: Settled<T>) => {\n if (!controller.signal.aborted)\n setAnswer({ eventId, selection: selectionCount, request, value });\n };\n Promise.resolve()\n .then(() => loadRef.current(eventId, { signal: controller.signal }))\n .then((value) => {\n if (value.status !== 'ready') {\n settle({\n status: 'refused',\n eventId,\n reason: value.reason,\n retryable: value.retryable,\n });\n return;\n }\n /* Never another appointment, and never a start the panel cannot\n place in the day. */\n if (\n value.details?.eventId !== eventId ||\n !parseAppointmentStartIso(value.details.appointment?.startIso)\n )\n throw new Error(failure.current);\n settle({ status: 'ready', read: value.details });\n })\n .catch((error: unknown) => {\n settle({\n status: 'error',\n eventId,\n message: getErrorMessage(error, failure.current),\n });\n });\n return () => controller.abort();\n }, [eventId, selectionCount, request]);\n\n const retry = useCallback(() => setRetries((previous) => previous + 1), []);\n\n if (eventId === null) return { state: null, retry };\n const current =\n answer?.eventId === eventId && answer.selection === selectionCount\n ? answer\n : undefined;\n let state: AppointmentDetailsState<T> = { status: 'loading', eventId };\n if (current?.request === request) state = current.value;\n else if (current?.value.status === 'ready')\n /* A re-read of the same occurrence keeps what is on screen. */\n state = { status: 'ready', read: current.value.read, refreshing: true };\n return { state, retry };\n}\n"],"names":["__iconNode","Cake","createLucideIcon","ClipboardPaste","IdCard","Move","MORE_TRIGGER","appointmentDetailsPanelAgent","handle","args","rescueFocus","target","active","focusHeading","headingId","heading","parseEventDate","value","formatDay","locale","formatTimeRange","start","end","s","e","fmt","DETAIL_STAMP_FORMAT","ageInYears","dobIso","on","dob","at","age","monthDelta","START_ISO","parseAppointmentStartIso","startIso","match","year","month","day","hours","minutes","seconds","monthEnd","sortHistoryNewestFirst","entries","entry","parsed","a","b","RECURRENCE_LABEL_KEY","patientPhones","patient","patientAddressLine","part","patientAddressLabel","patientMapsUrl","query","detailKey","suffix","PRIVATE_FIELDS","HEX_COLOUR","hasASide","change","historyChanges","own","further","seen","sameDay","AppointmentHistoryTimeline","history","noteUnrecordedEdits","privacy","t","runtimeI18n","useTranslation","optionFor","useAppointmentWorkflowStatus","shownLocale","formatWith","iso","options","formatStamp","notSet","sidesOf","from","to","toOnly","sentenceOf","field","valueOf","side","text","isAfter","jsx","pill","WorkflowStatusDisplay","jsxs","ArrowRight","describe","CalendarPlus","ConfirmedGlyph","APPOINTMENT_STATE_WORKFLOW","Trash2","all","changes","valued","uncovered","index","list","alsoChanged","only","StatusGlyph","Pencil","Clock","lead","EmptyState","Timeline","shape","CalendarClock","APPOINTMENT_STATUS_BADGE_VARIANT","IndicatorChips","event","key","chips","Globe","TriangleAlert","HeartPulse","Euro","Video","Repeat","chip","Badge","AppointmentIdentityStrip","name","avatarSrc","unresolved","status","flags","onOpenPatient","highlightedAnamnesisCount","expiredAnamnesisCount","anamnesisAnswers","statusOption","highlighted","expired","Avatar","Button","Alert","line","answer","InfoHoverBody","eyebrow","facts","Fragment","HoverCard","fact","TRIGGER","InfoHover","id","children","MUTED","telLink","number","mailLink","email","formatMoney","amount","currency","Rows","rows","shown","DescriptionList","DetailsPatientCard","details","now","mapsLink","signing","money","booking","signingShown","pending","signingFacts","answerFacts","addressLabel","fields","phone","hasLabel","Smartphone","Phone","Mail","MapPin","unpaid","billable","paidOnline","state","headingKey","factKey","label","TransactionChip","PatientSummaryCard","DetailsAppointmentCard","operator","chair","description","appointment","editor","timed","recurrence","frequencyKey","frequency","bookingRows","Timestamp","shownBookingRows","row","hasBooking","creation","SectionCard","CalendarDays","Hourglass","Armchair","Building2","DetailsTreatmentsCard","care","plan","ClipboardList","TreatmentReceipt","entryId","_careId","NOTES_PREVIEWED","DetailsNotesCard","preview","onOpenNotes","useId","retried","useRef","useIsomorphicLayoutEffect","count","more","openLabel","IconButton","NotebookPen","Counter","_a","NoteTimeline","rootVariants","cva","footerVariants","statusShownVariants","ACCESSIBLE_TARGET","ACCESSIBLE_TARGET_STATUS_CONTROL","ACCESSIBLE_TARGET_OVERFLOW_TRIGGER","SKELETON_FACT_WIDTHS","DOCUMENT_KINDS","DOCUMENT_ICON","ReceiptEuro","Folder","FileText","File","Camera","MenuAction","startIcon","action","intent","background","size","hideLabel","DropdownMenu","Tooltip","ChevronDown","option","DetailsSkeleton","EditableDescription","width","Skeleton","HistoryBody","onRetry","loading","speaking","setSpeaking","useState","useEffect","settled","body","DetailsContent","read","refreshing","shownTitle","enter","live","statusControl","patientId","privacyTitle","notesPreview","hostHistory","onOpenHistory","readOnly","onStatusChange","allowedStatuses","APPOINTMENT_WORKFLOW_STATUSES","onDescriptionChange","onEdit","onMove","onCopy","onDelete","onJoinTelehealth","onWhatsApp","hostWhatsappUrl","createTaskUrl","documents","eventId","entering","card","notesForPatient","notes","editorOffered","historyOpen","setHistoryOpen","editingDescription","setEditingDescription","historyShown","editorShown","openHistory","shownBefore","before","lostHistory","lostEditor","historyRef","historyRetried","historyStatus","setDescription","descriptionDraft","setDescriptionDraft","descriptionSaving","setDescriptionSaving","descriptionError","setDescriptionError","descriptionFieldRef","saveDescription","next","error","getErrorMessage","setStatus","wasRefreshing","landed","permitted","appointmentStatus","statusEditable","changeStatus","isCalendarEventStatus","whatsappUrl","documentKinds","kind","copyMenu","assigned","statusLabel","statusName","statusShownRef","statusWasEditable","lost","statusNode","WorkflowStatusControl","Copy","Plus","WhatsAppGlyph","SquareCheckBig","actions","node","backLabel","CONTENT_ENTER_CLASS","PanelSubview","PanelHeader","HistoryIcon","PrivacyIdentityCard","_b","PrivacyHiddenLine","ButtonGroup","TextArea","AppointmentDetailsPanel","forwardRef","title","className","rest","ref","reactId","instanceId","previousStatus","retryOffered","rootRef","setRoot","useMemo","composeRefs","heldFocus","snapshot","control","handledRejection","inFlight","saved","offered","host","useAgentRegistration","header","useAppointmentDetailsRead","load","reloadKey","failure","loadRef","retries","setRetries","setAnswer","request","selection","setSelection","selectionCount","controller","settle","retry","useCallback","previous","current"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"whatsapp-button-DV9JFmtq.js","sources":["../../src/components/whatsapp-button/whatsapp-button.tsx"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* WhatsAppButton — kit-tokened Click-to-Chat affordance. */\n/* */\n/* Replaces the booking website's loose green-circle-with-caption */\n/* combo (see HTP screenshot in the rebrand discussion) with a single */\n/* well-anchored affordance. Two variants: */\n/* */\n/* - `pill` — inline rounded button, brand green + white glyph + */\n/* label. Drops anywhere in card / header chrome. */\n/* - `fab` — circular floating action button, glyph only, */\n/* persistently anchored in the page corner. Carries an */\n/* `aria-label` so the SR announcement is \"Open WhatsApp */\n/* chat\" without rendering a loose visible caption. */\n/* */\n/* WhatsApp brand guidance requires the canonical #25D366 surface and */\n/* the official phone-bubble glyph — those live in `--brand-whatsapp` */\n/* tokens (added under `src/tokens/index.css`) so all four themes can */\n/* shift the green for accessible contrast without bleeding the brand */\n/* requirement into component code. */\n/* ------------------------------------------------------------------ */\n\nimport {\n forwardRef,\n useMemo,\n type AnchorHTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\n\n/* ------------------------------------------------------------------ */\n/* WhatsApp glyph */\n/* */\n/* Inlined SVG — no external icon dep. The path matches WhatsApp's */\n/* official brand mark (speech bubble + phone). `currentColor` lets */\n/* the kit's `--brand-whatsapp-foreground` paint the glyph from a */\n/* single CVA class, so accessible-theme shifts apply without code. */\n/* ------------------------------------------------------------------ */\n\nexport function WhatsAppGlyph({\n className,\n}: {\n className?: string;\n}): ReactNode {\n return (\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <path d=\"M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.149-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.71.306 1.263.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413Z\" />\n </svg>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst rootVariants = cva(\n [\n // `position` is provided by `positionVariants` below — `static`\n // sets `ds:relative` (so the pseudo-element touch-target anchors),\n // `bottom-end` / `bottom-start` set `ds:fixed`. Keeping `relative`\n // off the base avoids the cascade conflict that made `position:\n // relative` win against `position: fixed` in the compiled CSS\n // (booking-website was patching with `style={{position:'fixed'}}`).\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:font-medium',\n // The pill can shrink, so an unpinned glyph would squash horizontally\n // while its height held, distorting the brand mark.\n 'ds:[&_svg]:shrink-0',\n 'ds:bg-[var(--brand-whatsapp)] ds:text-[var(--brand-whatsapp-foreground)]',\n 'ds:hover:bg-[var(--brand-whatsapp-hover)]',\n 'ds:active:opacity-90',\n 'ds:transition-[background-color,box-shadow,opacity]',\n 'ds:duration-[var(--animation-duration)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n // Focus ring colour is `var(--ring)` (= `--primary` in light, ditto\n // through theme cascade) — NOT `--brand-whatsapp`. Painting the\n // ring brand-green on a brand-green surface makes it invisible.\n 'ds:focus-visible:outline-[var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n // Under Windows High Contrast Mode the bg + shadow are stripped;\n // repaint a solid border + swap the focus ring to CanvasText so\n // the affordance stays identifiable.\n 'ds:forced-colors:border ds:forced-colors:border-[ButtonBorder]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n 'ds:disabled:opacity-50 ds:disabled:cursor-not-allowed',\n 'ds:motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n variant: {\n // Pill — inline rounded button. Visible label is the brand\n // affordance text; glyph sits leading.\n //\n // No `whitespace-nowrap`: with it the pill's min-content width was\n // the whole label on one line, so a long label outgrew the viewport\n // and spilled off screen. Wrapping lets shrink-to-fit cap the pill.\n // `text-center` centres the wrapped line, the block padding keeps it\n // off the rounded edges, and `overflow-wrap` breaks a compound word\n // (German especially) that would otherwise still be too wide.\n pill: [\n 'ds:rounded-[var(--radius-full)] ds:gap-[var(--spacing-xs)]',\n 'ds:text-center ds:py-[var(--spacing-2xs)]',\n 'ds:[overflow-wrap:anywhere]',\n ].join(' '),\n // FAB — circular floating action button. Glyph only; the\n // label resolves into `aria-label`.\n fab: [\n 'ds:rounded-full ds:shadow-[var(--shadow-lg)]',\n 'ds:hover:shadow-[var(--shadow-xl)] ds:active:shadow-[var(--shadow-md)]',\n ].join(' '),\n },\n size: {\n sm: '',\n md: '',\n lg: '',\n },\n },\n compoundVariants: [\n {\n variant: 'pill',\n size: 'sm',\n class:\n 'ds:ps-3 ds:pe-3.5 ds:text-[length:var(--font-size-sm)] ds:[&_svg]:size-4 ds:min-h-[var(--min-target-size)] ds:sm:min-h-9 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:hidden',\n },\n {\n variant: 'pill',\n size: 'md',\n class:\n 'ds:min-h-10 ds:ps-4 ds:pe-5 ds:text-[length:var(--font-size-base)] ds:[&_svg]:size-5',\n },\n {\n variant: 'pill',\n size: 'lg',\n class:\n 'ds:min-h-12 ds:ps-5 ds:pe-6 ds:text-[length:var(--font-size-lg)] ds:[&_svg]:size-6',\n },\n // FAB — fixed square dimensions; the `sm` case mirrors the\n // FloatingActionButton's pseudo-target expansion below the\n // `sm:` breakpoint so a 40px circle still hits 44/48 px on\n // mobile.\n {\n variant: 'fab',\n size: 'sm',\n class:\n 'ds:h-10 ds:w-10 ds:[&_svg]:size-5 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:hidden',\n },\n {\n variant: 'fab',\n size: 'md',\n class: 'ds:h-14 ds:w-14 ds:[&_svg]:size-7',\n },\n {\n variant: 'fab',\n size: 'lg',\n class: 'ds:h-16 ds:w-16 ds:[&_svg]:size-8',\n },\n ],\n defaultVariants: {\n variant: 'pill',\n size: 'md',\n },\n },\n);\n\nconst positionVariants = cva('', {\n variants: {\n position: {\n // `relative` so the `::before` pseudo touch-target (defined in\n // the `pill sm` / `fab sm` compound variants) anchors to the\n // button's box. The fixed-positioning variants below don't need\n // this — `position: fixed` is itself a positioning context for\n // descendants and pseudo-elements.\n static: 'ds:relative',\n // Only ONE inset is set, so the cap must reserve the opposite gutter\n // itself — otherwise a long label pins to its inset edge and spills\n // off the other one. The arbitrary-PROPERTY form is load-bearing:\n // `max-inline-size-[…]` is not a utility and emits nothing.\n 'bottom-end':\n 'ds:fixed ds:z-[var(--z-fixed)] ds:bottom-[calc(var(--spacing-lg)+env(safe-area-inset-bottom,0px))] ds:end-[var(--spacing-lg)] ds:[max-inline-size:calc(100%_-_(var(--spacing-lg)_*_2))]',\n 'bottom-start':\n 'ds:fixed ds:z-[var(--z-fixed)] ds:bottom-[calc(var(--spacing-lg)+env(safe-area-inset-bottom,0px))] ds:start-[var(--spacing-lg)] ds:[max-inline-size:calc(100%_-_(var(--spacing-lg)_*_2))]',\n },\n },\n defaultVariants: { position: 'static' },\n});\n\n/* ------------------------------------------------------------------ */\n/* Collapse — pill on wide viewports, glyph-only circle on narrow ones */\n/* */\n/* The booking site wants the pill with its question copy on desktop */\n/* and just the glyph on a phone. Doing it in CSS (`max-sm:` / */\n/* `max-md:`) instead of a JS media query means the server render and */\n/* the first paint already agree, so there is no flash of the wrong */\n/* shape. Below the breakpoint the root takes the `fab` chrome of the */\n/* same size and the label drops to `sr-only`, so the accessible name */\n/* is unchanged. Tailwind needs literal class strings, hence one entry */\n/* per breakpoint × size rather than a template. */\n/* ------------------------------------------------------------------ */\n\nconst collapseVariants = cva('', {\n variants: {\n collapseLabelBelow: {\n sm: 'ds:max-sm:gap-0 ds:max-sm:p-0 ds:max-sm:min-h-0 ds:max-sm:rounded-full ds:max-sm:shadow-[var(--shadow-lg)]',\n md: 'ds:max-md:gap-0 ds:max-md:p-0 ds:max-md:min-h-0 ds:max-md:rounded-full ds:max-md:shadow-[var(--shadow-lg)]',\n },\n size: {\n sm: '',\n md: '',\n lg: '',\n },\n },\n compoundVariants: [\n // Mirrors the `fab` size ladder above. The `sm` circle keeps the\n // pseudo touch-target the `pill sm` compound already paints below\n // the `sm:` breakpoint, so 40px still hits 44/48px on a phone.\n {\n collapseLabelBelow: 'sm',\n size: 'sm',\n class: 'ds:max-sm:h-10 ds:max-sm:w-10 ds:max-sm:[&_svg]:size-5',\n },\n {\n collapseLabelBelow: 'sm',\n size: 'md',\n class: 'ds:max-sm:h-14 ds:max-sm:w-14 ds:max-sm:[&_svg]:size-7',\n },\n {\n collapseLabelBelow: 'sm',\n size: 'lg',\n class: 'ds:max-sm:h-16 ds:max-sm:w-16 ds:max-sm:[&_svg]:size-8',\n },\n // The `pill sm` pseudo touch-target only paints below `sm:`, so a\n // 40px circle collapsed at `md` would sit under the target minimum\n // between the two breakpoints. Size that one circle to the minimum\n // itself (44px, 48px in the accessible themes) instead.\n {\n collapseLabelBelow: 'md',\n size: 'sm',\n class:\n 'ds:max-md:h-[var(--min-target-size)] ds:max-md:w-[var(--min-target-size)] ds:max-md:[&_svg]:size-5',\n },\n {\n collapseLabelBelow: 'md',\n size: 'md',\n class: 'ds:max-md:h-14 ds:max-md:w-14 ds:max-md:[&_svg]:size-7',\n },\n {\n collapseLabelBelow: 'md',\n size: 'lg',\n class: 'ds:max-md:h-16 ds:max-md:w-16 ds:max-md:[&_svg]:size-8',\n },\n ],\n});\n\nconst collapsedLabelClass = {\n sm: 'ds:max-sm:sr-only',\n md: 'ds:max-md:sr-only',\n} as const;\n\n/* ------------------------------------------------------------------ */\n/* URL builder */\n/* ------------------------------------------------------------------ */\n\n/**\n * Build a `wa.me` deep-link from an E.164 phone number and an\n * optional prefilled message. The number is stripped to digits — the\n * `wa.me` host requires digits only (no `+`, no separators).\n *\n * Returns `null` (not an empty `wa.me/` URL) when the input contains\n * no digits — the caller is then responsible for rendering a disabled\n * affordance rather than shipping a broken link. In dev a `console.warn`\n * fires so the typo is visible during development.\n */\nfunction buildWaMeUrl(phoneNumber: string, message?: string): string | null {\n const digits = phoneNumber.replace(/\\D/g, '');\n if (digits.length === 0) {\n if (\n typeof import.meta !== 'undefined' &&\n typeof import.meta.env !== 'undefined' &&\n import.meta.env.DEV === true\n ) {\n console.warn(\n `[WhatsAppButton] phoneNumber \"${phoneNumber}\" contains no digits — ` +\n `the affordance will render disabled. Pass an E.164 number ` +\n `(e.g. \"+393331234567\") to fix.`,\n );\n }\n return null;\n }\n const base = `https://wa.me/${digits}`;\n if (!message) return base;\n return `${base}?text=${encodeURIComponent(message)}`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Props */\n/* ------------------------------------------------------------------ */\n\nexport interface WhatsAppButtonProps\n extends\n Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'children'>,\n VariantProps<typeof rootVariants>,\n VariantProps<typeof positionVariants> {\n /**\n * Phone number to chat to. E.164 format is recommended\n * (e.g. `+393331234567`). Any non-digit characters are stripped\n * before the URL is built — `wa.me` requires digits only.\n */\n phoneNumber: string;\n /**\n * Optional prefilled message. The receiver sees this in their\n * compose box. Keep it short and human — long pasted text is the\n * single most common reason consumers drop the affordance.\n */\n message?: string;\n /**\n * Override the visible / accessible label. Defaults to\n * `t('whatsApp.label')` (or `t('whatsApp.questionPrompt')` when\n * `tone=\"question\"`) for the pill variant, and\n * `t('whatsApp.fabLabel')` for the FAB.\n */\n label?: ReactNode;\n /**\n * Copy tone for the pill variant.\n * - `standard` (default) — brief \"Chat on WhatsApp\" affordance.\n * - `question` — invitational \"Have questions? Chat on WhatsApp\"\n * copy. Routes through `t('whatsApp.questionPrompt')`. Use on\n * public-facing surfaces (booking pages, marketing) where the\n * button is the only prompt encouraging engagement.\n *\n * Ignored for `variant=\"fab\"` — the floating action button is\n * glyph-only and its `aria-label` stays concise via `fabLabel`.\n */\n tone?: 'standard' | 'question';\n /**\n * Pill only. Below the named Tailwind breakpoint the pill becomes a\n * glyph-only circle (the `fab` chrome of the same `size`) and the\n * label moves to screen-reader-only text, so the accessible name is\n * unchanged. Pure CSS, so server render and first paint agree.\n * Use it where the pill's copy earns its space on desktop but would\n * crowd a phone: the booking site's practice page passes `\"sm\"`.\n *\n * Ignored for `variant=\"fab\"`, which is glyph-only already.\n */\n collapseLabelBelow?: 'sm' | 'md';\n}\n\n/* ------------------------------------------------------------------ */\n/* WhatsAppButton */\n/* ------------------------------------------------------------------ */\n\nexport const WhatsAppButton = forwardRef<\n HTMLAnchorElement,\n WhatsAppButtonProps\n>(\n (\n {\n phoneNumber,\n message,\n variant = 'pill',\n size = 'md',\n position,\n label,\n tone = 'standard',\n collapseLabelBelow,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const href = useMemo(\n () => buildWaMeUrl(phoneNumber, message),\n [phoneNumber, message],\n );\n // Default-label cascade:\n // FAB → `whatsApp.fabLabel` (always concise)\n // pill, tone=question → `whatsApp.questionPrompt` (invitational)\n // pill, tone=standard → `whatsApp.label` (default)\n // Consumer's `label` prop overrides any of the above.\n const defaultLabelKey =\n variant === 'fab'\n ? 'whatsApp.fabLabel'\n : tone === 'question'\n ? 'whatsApp.questionPrompt'\n : 'whatsApp.label';\n const resolvedLabel = label ?? t(defaultLabelKey);\n\n const collapse = variant === 'pill' ? collapseLabelBelow : undefined;\n const composedClassName = [\n rootVariants({ variant, size }),\n positionVariants({ position }),\n collapse ? collapseVariants({ collapseLabelBelow: collapse, size }) : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n // When the input has no digits, render an `aria-disabled` anchor\n // with the same chrome but no `href` — assistive tech announces the\n // disabled state and click does nothing. `buildWaMeUrl` already\n // emitted a dev-mode warning above. `target` / `rel` are stripped\n // too because they're meaningless without `href`.\n const isDisabled = href === null;\n const commonAnchorProps = {\n ref,\n ...(isDisabled\n ? {}\n : {\n href: href as string,\n target: '_blank' as const,\n rel: 'noopener noreferrer' as const,\n }),\n /* An <a> without href has NO implicit role, and `aria-disabled` is\n prohibited on a roleless element (axe aria-prohibited-attr). Give\n the disabled anchor an explicit link role so the state is legal\n and assistive tech still announces it. */\n /* `tabIndex` too: an <a> without href is not focusable, and\n `aria-disabled` presupposes something focus CAN reach — otherwise\n the reason the control is disabled never reaches a keyboard. */\n ...(isDisabled ? { role: 'link' as const, tabIndex: 0 } : {}),\n 'aria-disabled': isDisabled ? true : undefined,\n 'data-component': 'whatsapp-button' as const,\n 'data-variant': variant,\n 'data-collapse-label-below': collapse,\n onClick: (event: React.MouseEvent<HTMLAnchorElement>) => {\n if (isDisabled) event.preventDefault();\n rest.onClick?.(event);\n },\n className: composedClassName,\n };\n\n // Screen-reader cue for the new-tab behaviour. WCAG 3.2.5 / G201:\n // user-initiated link openings to a new context should be\n // announced. Reused `link.opensInNewTab` from the kit's `ui` ns —\n // single source of truth across every external-link affordance.\n const opensInNewTabSrText = isDisabled\n ? null\n : t('link.opensInNewTab', 'Opens in a new tab');\n\n if (variant === 'fab') {\n // FAB — circular, glyph-only. The accessible name lives on the\n // anchor's `aria-label` (resolved label). No visible caption,\n // which is exactly what the redesign fixes vs. the legacy\n // green-circle-with-loose-text affordance.\n const fabAriaLabel =\n typeof resolvedLabel === 'string'\n ? opensInNewTabSrText\n ? `${resolvedLabel} — ${opensInNewTabSrText}`\n : resolvedLabel\n : undefined;\n return (\n <a {...rest} {...commonAnchorProps} aria-label={fabAriaLabel}>\n <WhatsAppGlyph />\n {typeof resolvedLabel !== 'string' ? (\n <span className=\"ds:sr-only\">\n {resolvedLabel}\n {opensInNewTabSrText ? ` — ${opensInNewTabSrText}` : null}\n </span>\n ) : null}\n </a>\n );\n }\n\n return (\n <a {...rest} {...commonAnchorProps}>\n <WhatsAppGlyph />\n <span className={collapse ? collapsedLabelClass[collapse] : undefined}>\n {resolvedLabel}\n </span>\n {opensInNewTabSrText ? (\n <span className=\"ds:sr-only\"> — {opensInNewTabSrText}</span>\n ) : null}\n </a>\n );\n },\n);\nWhatsAppButton.displayName = 'WhatsAppButton';\n"],"names":["WhatsAppGlyph","className","jsx","rootVariants","cva","positionVariants","collapseVariants","collapsedLabelClass","buildWaMeUrl","phoneNumber","message","digits","base","WhatsAppButton","forwardRef","variant","size","position","label","tone","collapseLabelBelow","rest","ref","t","useTranslation","href","useMemo","resolvedLabel","collapse","composedClassName","isDisabled","commonAnchorProps","event","_a","opensInNewTabSrText","fabAriaLabel","jsxs"],"mappings":"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"}