@alfadocs/ui-kit-debug 1.35.0 → 1.36.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 (582) hide show
  1. package/dist/_chunks/{actions-cell-renderer-yy03OgRL.js → actions-cell-renderer-CUn1pqEq.js} +3 -3
  2. package/dist/_chunks/{actions-cell-renderer-yy03OgRL.js.map → actions-cell-renderer-CUn1pqEq.js.map} +1 -1
  3. package/dist/_chunks/{agenda-card-DVz3jwTf.js → agenda-card-DyQtHb9z.js} +2 -2
  4. package/dist/_chunks/{agenda-card-DVz3jwTf.js.map → agenda-card-DyQtHb9z.js.map} +1 -1
  5. package/dist/_chunks/{agenda-tray-1oDWCJdB.js → agenda-tray-DYGCTIWB.js} +3 -3
  6. package/dist/_chunks/{agenda-tray-1oDWCJdB.js.map → agenda-tray-DYGCTIWB.js.map} +1 -1
  7. package/dist/_chunks/{ai-consent-banner-OggpS5hW.js → ai-consent-banner-De4gzSBZ.js} +4 -4
  8. package/dist/_chunks/{ai-consent-banner-OggpS5hW.js.map → ai-consent-banner-De4gzSBZ.js.map} +1 -1
  9. package/dist/_chunks/{ai-prompt-input-Dt7tpCBh.js → ai-prompt-input-DdxlaI7q.js} +2 -2
  10. package/dist/_chunks/{ai-prompt-input-Dt7tpCBh.js.map → ai-prompt-input-DdxlaI7q.js.map} +1 -1
  11. package/dist/_chunks/{alert-CiJT540z.js → alert-CiQ5Pa3Q.js} +2 -2
  12. package/dist/_chunks/{alert-CiJT540z.js.map → alert-CiQ5Pa3Q.js.map} +1 -1
  13. package/dist/_chunks/{alia-sidebar-D18kp3p9.js → alia-sidebar-B6bXlZZk.js} +6 -6
  14. package/dist/_chunks/{alia-sidebar-D18kp3p9.js.map → alia-sidebar-B6bXlZZk.js.map} +1 -1
  15. package/dist/_chunks/{anamnesis-card-NTi4LLzI.js → anamnesis-card-DGwINeNn.js} +3 -3
  16. package/dist/_chunks/{anamnesis-card-NTi4LLzI.js.map → anamnesis-card-DGwINeNn.js.map} +1 -1
  17. package/dist/_chunks/{anamnesis-summary-card-DGVKBQoq.js → anamnesis-summary-card-GYHa7VGp.js} +3 -3
  18. package/dist/_chunks/{anamnesis-summary-card-DGVKBQoq.js.map → anamnesis-summary-card-GYHa7VGp.js.map} +1 -1
  19. package/dist/_chunks/{anamnesis-summary-rows-BYgyp_i2.js → anamnesis-summary-rows-Cxtgo2ok.js} +12 -12
  20. package/dist/_chunks/{anamnesis-summary-rows-BYgyp_i2.js.map → anamnesis-summary-rows-Cxtgo2ok.js.map} +1 -1
  21. package/dist/_chunks/{antenatal-schedule-timeline-sXfIp5lp.js → antenatal-schedule-timeline-CXk_tzWG.js} +2 -2
  22. package/dist/_chunks/{antenatal-schedule-timeline-sXfIp5lp.js.map → antenatal-schedule-timeline-CXk_tzWG.js.map} +1 -1
  23. package/dist/_chunks/{appointment-card-Bh_CIlc6.js → appointment-card-WsDGBBut.js} +120 -126
  24. package/dist/_chunks/appointment-card-WsDGBBut.js.map +1 -0
  25. package/dist/_chunks/{appointment-timeline-De-Wqdkw.js → appointment-timeline-ByfovxqR.js} +5 -5
  26. package/dist/_chunks/{appointment-timeline-De-Wqdkw.js.map → appointment-timeline-ByfovxqR.js.map} +1 -1
  27. package/dist/_chunks/{appointment-tray-4I9wTAi4.js → appointment-tray-D6UyJHej.js} +3 -3
  28. package/dist/_chunks/{appointment-tray-4I9wTAi4.js.map → appointment-tray-D6UyJHej.js.map} +1 -1
  29. package/dist/_chunks/arrow-right-KsIrLdt0.js +15 -0
  30. package/dist/_chunks/arrow-right-KsIrLdt0.js.map +1 -0
  31. package/dist/_chunks/{audio-recorder-11wClczr.js → audio-recorder-BlQBC7N_.js} +3 -3
  32. package/dist/_chunks/{audio-recorder-11wClczr.js.map → audio-recorder-BlQBC7N_.js.map} +1 -1
  33. package/dist/_chunks/{badge-sTusUqZD.js → badge-BudgzTe_.js} +2 -2
  34. package/dist/_chunks/{badge-sTusUqZD.js.map → badge-BudgzTe_.js.map} +1 -1
  35. package/dist/_chunks/{balance-badge-cell-DhBtFRoW.js → balance-badge-cell-B0Z8Dwn8.js} +6 -6
  36. package/dist/_chunks/{balance-badge-cell-DhBtFRoW.js.map → balance-badge-cell-B0Z8Dwn8.js.map} +1 -1
  37. package/dist/_chunks/{bishop-score-CAl7C5hm.js → bishop-score-D5b8tktp.js} +2 -2
  38. package/dist/_chunks/{bishop-score-CAl7C5hm.js.map → bishop-score-D5b8tktp.js.map} +1 -1
  39. package/dist/_chunks/{bmi-calculator-Dwkih9a4.js → bmi-calculator-dOKP-vW4.js} +4 -4
  40. package/dist/_chunks/{bmi-calculator-Dwkih9a4.js.map → bmi-calculator-dOKP-vW4.js.map} +1 -1
  41. package/dist/_chunks/{booking-BqkEtsKx.js → booking-Dp-9qR6F.js} +9 -9
  42. package/dist/_chunks/{booking-BqkEtsKx.js.map → booking-Dp-9qR6F.js.map} +1 -1
  43. package/dist/_chunks/button-group-QmN1VdUW.js +307 -0
  44. package/dist/_chunks/button-group-QmN1VdUW.js.map +1 -0
  45. package/dist/_chunks/{calendar-Dgvl5L4T.js → calendar-7GAUlsNO.js} +3 -3
  46. package/dist/_chunks/{calendar-Dgvl5L4T.js.map → calendar-7GAUlsNO.js.map} +1 -1
  47. package/dist/_chunks/{calendar-event-card-DSh-69HT.js → calendar-event-card-DKUnT9Be.js} +91 -134
  48. package/dist/_chunks/calendar-event-card-DKUnT9Be.js.map +1 -0
  49. package/dist/_chunks/{calendar-workspace-UywR5gUl.js → calendar-workspace-Duv_5B4j.js} +2494 -2415
  50. package/dist/_chunks/calendar-workspace-Duv_5B4j.js.map +1 -0
  51. package/dist/_chunks/{care-plan-card-DHVhBcvs.js → care-plan-card-COFOI-fI.js} +5 -5
  52. package/dist/_chunks/{care-plan-card-DHVhBcvs.js.map → care-plan-card-COFOI-fI.js.map} +1 -1
  53. package/dist/_chunks/{care-plan-entry-card-Dx6IdTcR.js → care-plan-entry-card-BOKn0KW-.js} +6 -6
  54. package/dist/_chunks/{care-plan-entry-card-Dx6IdTcR.js.map → care-plan-entry-card-BOKn0KW-.js.map} +1 -1
  55. package/dist/_chunks/{care-plan-header-UTX5ZD74.js → care-plan-header-CbuOuVBw.js} +4 -4
  56. package/dist/_chunks/{care-plan-header-UTX5ZD74.js.map → care-plan-header-CbuOuVBw.js.map} +1 -1
  57. package/dist/_chunks/{carousel.agent-CLxdHEBP.js → carousel.agent-Dv4a4M8L.js} +2 -2
  58. package/dist/_chunks/{carousel.agent-CLxdHEBP.js.map → carousel.agent-Dv4a4M8L.js.map} +1 -1
  59. package/dist/_chunks/{chart-C6eHTxkO.js → chart-iWl76PXv.js} +3 -3
  60. package/dist/_chunks/{chart-C6eHTxkO.js.map → chart-iWl76PXv.js.map} +1 -1
  61. package/dist/_chunks/{chat-input-BsB5Umpj.js → chat-input-qM5QpUSq.js} +2 -2
  62. package/dist/_chunks/{chat-input-BsB5Umpj.js.map → chat-input-qM5QpUSq.js.map} +1 -1
  63. package/dist/_chunks/{chat-message-C-8UU2av.js → chat-message-RniXtrCH.js} +2 -2
  64. package/dist/_chunks/{chat-message-C-8UU2av.js.map → chat-message-RniXtrCH.js.map} +1 -1
  65. package/dist/_chunks/{checkbox-BuZ1u__2.js → checkbox-CZkipDn7.js} +2 -2
  66. package/dist/_chunks/{checkbox-BuZ1u__2.js.map → checkbox-CZkipDn7.js.map} +1 -1
  67. package/dist/_chunks/{checkbox-group-CfqMv57d.js → checkbox-group-DomUzpkF.js} +2 -2
  68. package/dist/_chunks/{checkbox-group-CfqMv57d.js.map → checkbox-group-DomUzpkF.js.map} +1 -1
  69. package/dist/_chunks/clinical-note-card-DdsGYMmI.js +325 -0
  70. package/dist/_chunks/clinical-note-card-DdsGYMmI.js.map +1 -0
  71. package/dist/_chunks/{code-block-BIkpRLkl.js → code-block-uVjNSI9g.js} +2 -2
  72. package/dist/_chunks/{code-block-BIkpRLkl.js.map → code-block-uVjNSI9g.js.map} +1 -1
  73. package/dist/_chunks/{connection-status-DRZIcMqM.js → connection-status-OEsWjmRk.js} +3 -3
  74. package/dist/_chunks/{connection-status-DRZIcMqM.js.map → connection-status-OEsWjmRk.js.map} +1 -1
  75. package/dist/_chunks/{contact-profile-card-DSI9uumA.js → contact-profile-card--My1H2UD.js} +3 -3
  76. package/dist/_chunks/{contact-profile-card-DSI9uumA.js.map → contact-profile-card--My1H2UD.js.map} +1 -1
  77. package/dist/_chunks/{control-room-rail-5MbhjsxN.js → control-room-rail-Ds45_g4f.js} +4 -4
  78. package/dist/_chunks/{control-room-rail-5MbhjsxN.js.map → control-room-rail-Ds45_g4f.js.map} +1 -1
  79. package/dist/_chunks/{counter-dRlTNC_y.js → counter-WsvRuum1.js} +50 -15
  80. package/dist/_chunks/counter-WsvRuum1.js.map +1 -0
  81. package/dist/_chunks/{cycle-calculator-DVgxBfP0.js → cycle-calculator-BJeaXiZv.js} +3 -3
  82. package/dist/_chunks/{cycle-calculator-DVgxBfP0.js.map → cycle-calculator-BJeaXiZv.js.map} +1 -1
  83. package/dist/_chunks/{dashboard-grid-BFtdHqfn.js → dashboard-grid-B23BFzRl.js} +2 -2
  84. package/dist/_chunks/{dashboard-grid-BFtdHqfn.js.map → dashboard-grid-B23BFzRl.js.map} +1 -1
  85. package/dist/_chunks/{data-table-DC96JJIq.js → data-table-BYGK-gUJ.js} +6 -6
  86. package/dist/_chunks/{data-table-DC96JJIq.js.map → data-table-BYGK-gUJ.js.map} +1 -1
  87. package/dist/_chunks/{data-table-tabs-DVIFkqx_.js → data-table-tabs-BMR0zsVQ.js} +3 -3
  88. package/dist/_chunks/{data-table-tabs-DVIFkqx_.js.map → data-table-tabs-BMR0zsVQ.js.map} +1 -1
  89. package/dist/_chunks/{date-picker-B6NW_PS5.js → date-picker-6tFnKFty.js} +14 -14
  90. package/dist/_chunks/{date-picker-B6NW_PS5.js.map → date-picker-6tFnKFty.js.map} +1 -1
  91. package/dist/_chunks/{dependent-selector-yTKKsuc9.js → dependent-selector-BHDP0nBB.js} +3 -3
  92. package/dist/_chunks/{dependent-selector-yTKKsuc9.js.map → dependent-selector-BHDP0nBB.js.map} +1 -1
  93. package/dist/_chunks/{description-list-CjJqR8WK.js → description-list-C1RXMDZ_.js} +2 -2
  94. package/dist/_chunks/{description-list-CjJqR8WK.js.map → description-list-C1RXMDZ_.js.map} +1 -1
  95. package/dist/_chunks/{document-preview-BrhMHNh8.js → document-preview-DsEyRcNd.js} +4 -4
  96. package/dist/_chunks/{document-preview-BrhMHNh8.js.map → document-preview-DsEyRcNd.js.map} +1 -1
  97. package/dist/_chunks/{document-scanner-C5Vrbu21.js → document-scanner-CbWVtm7u.js} +53 -52
  98. package/dist/_chunks/{document-scanner-C5Vrbu21.js.map → document-scanner-CbWVtm7u.js.map} +1 -1
  99. package/dist/_chunks/{due-date-calculator-CxgK8vzt.js → due-date-calculator-Dhc9Ljkb.js} +6 -6
  100. package/dist/_chunks/{due-date-calculator-CxgK8vzt.js.map → due-date-calculator-Dhc9Ljkb.js.map} +1 -1
  101. package/dist/_chunks/{editable-currency-cell-renderer-B7TVZ5ZJ.js → editable-currency-cell-renderer-D7blbDFY.js} +4 -4
  102. package/dist/_chunks/{editable-currency-cell-renderer-B7TVZ5ZJ.js.map → editable-currency-cell-renderer-D7blbDFY.js.map} +1 -1
  103. package/dist/_chunks/{editor-overlay-DEc5yYwo.js → editor-overlay-8fKAcRsm.js} +2 -2
  104. package/dist/_chunks/{editor-overlay-DEc5yYwo.js.map → editor-overlay-8fKAcRsm.js.map} +1 -1
  105. package/dist/_chunks/{entity-card-9_62gY7l.js → entity-card-I-Gio5wo.js} +36 -32
  106. package/dist/_chunks/entity-card-I-Gio5wo.js.map +1 -0
  107. package/dist/_chunks/{entity-summary-5o768XLU.js → entity-summary-BbW0mIzU.js} +4 -4
  108. package/dist/_chunks/{entity-summary-5o768XLU.js.map → entity-summary-BbW0mIzU.js.map} +1 -1
  109. package/dist/_chunks/{face-scheme-l-CQyLs-.js → face-scheme-uFvhqz6h.js} +4 -4
  110. package/dist/_chunks/{face-scheme-l-CQyLs-.js.map → face-scheme-uFvhqz6h.js.map} +1 -1
  111. package/dist/_chunks/{fetal-weight-Dqy0T1fP.js → fetal-weight-C6SxchOv.js} +2 -2
  112. package/dist/_chunks/{fetal-weight-Dqy0T1fP.js.map → fetal-weight-C6SxchOv.js.map} +1 -1
  113. package/dist/_chunks/{field-array-BjkXZzSr.js → field-array-C9dmRaIM.js} +2 -2
  114. package/dist/_chunks/{field-array-BjkXZzSr.js.map → field-array-C9dmRaIM.js.map} +1 -1
  115. package/dist/_chunks/{file-manager-CI2Qn8qW.js → file-manager-DvkFgj7d.js} +7 -7
  116. package/dist/_chunks/{file-manager-CI2Qn8qW.js.map → file-manager-DvkFgj7d.js.map} +1 -1
  117. package/dist/_chunks/{file-upload-CwxdqkMK.js → file-upload-BDpb08GM.js} +71 -78
  118. package/dist/_chunks/file-upload-BDpb08GM.js.map +1 -0
  119. package/dist/_chunks/{fiscal-code-input-B_nYMSEM.js → fiscal-code-input-CkwIdB1y.js} +2 -2
  120. package/dist/_chunks/{fiscal-code-input-B_nYMSEM.js.map → fiscal-code-input-CkwIdB1y.js.map} +1 -1
  121. package/dist/_chunks/{freemium-paywall-DrXzYfv-.js → freemium-paywall-BqGk_SBU.js} +2 -2
  122. package/dist/_chunks/{freemium-paywall-DrXzYfv-.js.map → freemium-paywall-BqGk_SBU.js.map} +1 -1
  123. package/dist/_chunks/{gestational-age-calculator-CZHVrERT.js → gestational-age-calculator-DDOGaPvg.js} +6 -6
  124. package/dist/_chunks/{gestational-age-calculator-CZHVrERT.js.map → gestational-age-calculator-DDOGaPvg.js.map} +1 -1
  125. package/dist/_chunks/{hcg-doubling-C2fQxfXd.js → hcg-doubling-Bb_n6tEa.js} +2 -2
  126. package/dist/_chunks/{hcg-doubling-C2fQxfXd.js.map → hcg-doubling-Bb_n6tEa.js.map} +1 -1
  127. package/dist/_chunks/{header-DUXRIPyM.js → header-BZ4pZlJV.js} +2 -2
  128. package/dist/_chunks/{header-DUXRIPyM.js.map → header-BZ4pZlJV.js.map} +1 -1
  129. package/dist/_chunks/{header-settings-DvjZNMhD.js → header-settings-B8mLc03Q.js} +4 -4
  130. package/dist/_chunks/{header-settings-DvjZNMhD.js.map → header-settings-B8mLc03Q.js.map} +1 -1
  131. package/dist/_chunks/hover-card-Bcku1GQu.js +511 -0
  132. package/dist/_chunks/hover-card-Bcku1GQu.js.map +1 -0
  133. package/dist/_chunks/{icon-button-DA2CAGHZ.js → icon-button-8xqRnkdG.js} +2 -2
  134. package/dist/_chunks/{icon-button-DA2CAGHZ.js.map → icon-button-8xqRnkdG.js.map} +1 -1
  135. package/dist/_chunks/{icon-button-group-VCCod3Hz.js → icon-button-group-Dj6CRoYR.js} +2 -2
  136. package/dist/_chunks/{icon-button-group-VCCod3Hz.js.map → icon-button-group-Dj6CRoYR.js.map} +1 -1
  137. package/dist/_chunks/{icon-picker-DOa89vn3.js → icon-picker-CTWzlHJr.js} +2 -2
  138. package/dist/_chunks/{icon-picker-DOa89vn3.js.map → icon-picker-CTWzlHJr.js.map} +1 -1
  139. package/dist/_chunks/{info-tip-CADik6WN.js → info-tip-ey_Pon2y.js} +2 -2
  140. package/dist/_chunks/{info-tip-CADik6WN.js.map → info-tip-ey_Pon2y.js.map} +1 -1
  141. package/dist/_chunks/{key-value-pair-BIBdZBLg.js → key-value-pair-DczGb4yz.js} +42 -41
  142. package/dist/_chunks/key-value-pair-DczGb4yz.js.map +1 -0
  143. package/dist/_chunks/{link-cell-renderer-BEpMNtAa.js → link-cell-renderer-BNa8x6oJ.js} +6 -6
  144. package/dist/_chunks/{link-cell-renderer-BEpMNtAa.js.map → link-cell-renderer-BNa8x6oJ.js.map} +1 -1
  145. package/dist/_chunks/loader-circle-BECIU_8N.js +12 -0
  146. package/dist/_chunks/loader-circle-BECIU_8N.js.map +1 -0
  147. package/dist/_chunks/{locale-picker-CwFtqSkt.js → locale-picker-BLeHbFSc.js} +3 -3
  148. package/dist/_chunks/{locale-picker-CwFtqSkt.js.map → locale-picker-BLeHbFSc.js.map} +1 -1
  149. package/dist/_chunks/{marketplace-app-shell-CK_ND8Tr.js → marketplace-app-shell-BwH6Aruw.js} +6 -6
  150. package/dist/_chunks/{marketplace-app-shell-CK_ND8Tr.js.map → marketplace-app-shell-BwH6Aruw.js.map} +1 -1
  151. package/dist/_chunks/{message-card-BUMv16un.js → message-card-Dm5Xshup.js} +2 -2
  152. package/dist/_chunks/{message-card-BUMv16un.js.map → message-card-Dm5Xshup.js.map} +1 -1
  153. package/dist/_chunks/{message-tray-0zsv27xX.js → message-tray-BcLyaO-G.js} +3 -3
  154. package/dist/_chunks/{message-tray-0zsv27xX.js.map → message-tray-BcLyaO-G.js.map} +1 -1
  155. package/dist/_chunks/{multi-select-DYOvx2SJ.js → multi-select-CtPd7g4x.js} +15 -15
  156. package/dist/_chunks/{multi-select-DYOvx2SJ.js.map → multi-select-CtPd7g4x.js.map} +1 -1
  157. package/dist/_chunks/note-attachment-CwDir3kK.js +124 -0
  158. package/dist/_chunks/note-attachment-CwDir3kK.js.map +1 -0
  159. package/dist/_chunks/note-timeline-CXfSV3yX.js +231 -0
  160. package/dist/_chunks/note-timeline-CXfSV3yX.js.map +1 -0
  161. package/dist/_chunks/{notes-panel-BjLt-kiP.js → notes-panel-Co8D3uDd.js} +7 -7
  162. package/dist/_chunks/{notes-panel-BjLt-kiP.js.map → notes-panel-Co8D3uDd.js.map} +1 -1
  163. package/dist/_chunks/{notification-card-CtrzoTUO.js → notification-card-ChcK9Wat.js} +2 -2
  164. package/dist/_chunks/{notification-card-CtrzoTUO.js.map → notification-card-ChcK9Wat.js.map} +1 -1
  165. package/dist/_chunks/{notification-tray-BiRzXHDf.js → notification-tray-CJ8jOe-U.js} +4 -4
  166. package/dist/_chunks/{notification-tray-BiRzXHDf.js.map → notification-tray-CJ8jOe-U.js.map} +1 -1
  167. package/dist/_chunks/{operator-hero-aG_qyn6g.js → operator-hero-XIdwDmN2.js} +3 -3
  168. package/dist/_chunks/{operator-hero-aG_qyn6g.js.map → operator-hero-XIdwDmN2.js.map} +1 -1
  169. package/dist/_chunks/{optical-prescription-DUJOhKz_.js → optical-prescription-cphK41eP.js} +2 -2
  170. package/dist/_chunks/{optical-prescription-DUJOhKz_.js.map → optical-prescription-cphK41eP.js.map} +1 -1
  171. package/dist/_chunks/panel-header-D_mTdhUp.js +128 -0
  172. package/dist/_chunks/panel-header-D_mTdhUp.js.map +1 -0
  173. package/dist/_chunks/patient-details-f7SSXkTJ.js +371 -0
  174. package/dist/_chunks/patient-details-f7SSXkTJ.js.map +1 -0
  175. package/dist/_chunks/patient-field-row-BQZoP4m2.js +787 -0
  176. package/dist/_chunks/patient-field-row-BQZoP4m2.js.map +1 -0
  177. package/dist/_chunks/{patient-search-HeEUB-_X.js → patient-search-D08b6jgj.js} +2 -2
  178. package/dist/_chunks/{patient-search-HeEUB-_X.js.map → patient-search-D08b6jgj.js.map} +1 -1
  179. package/dist/_chunks/patient-summary-card-Bz7KdUin.js +533 -0
  180. package/dist/_chunks/patient-summary-card-Bz7KdUin.js.map +1 -0
  181. package/dist/_chunks/{payment-automation-upsell-DwQW2fRp.js → payment-automation-upsell-BLTdE2em.js} +50 -59
  182. package/dist/_chunks/payment-automation-upsell-BLTdE2em.js.map +1 -0
  183. package/dist/_chunks/{payment-form-Ds1I9KqB.js → payment-form-BHMDqW9C.js} +2 -2
  184. package/dist/_chunks/{payment-form-Ds1I9KqB.js.map → payment-form-BHMDqW9C.js.map} +1 -1
  185. package/dist/_chunks/{payment-request-card-DvEsWEkC.js → payment-request-card-BxcdvxKR.js} +6 -6
  186. package/dist/_chunks/{payment-request-card-DvEsWEkC.js.map → payment-request-card-BxcdvxKR.js.map} +1 -1
  187. package/dist/_chunks/{pdf-viewer-DUIsV9s5.js → pdf-viewer-DUKdn5iq.js} +2 -2
  188. package/dist/_chunks/{pdf-viewer-DUIsV9s5.js.map → pdf-viewer-DUKdn5iq.js.map} +1 -1
  189. package/dist/_chunks/{periodontal-chart-B9fphroR.js → periodontal-chart-BF_e3wZp.js} +2 -2
  190. package/dist/_chunks/{periodontal-chart-B9fphroR.js.map → periodontal-chart-BF_e3wZp.js.map} +1 -1
  191. package/dist/_chunks/{periodontal-chart-card-qEZPXj83.js → periodontal-chart-card-BJEuJuzh.js} +3 -3
  192. package/dist/_chunks/{periodontal-chart-card-qEZPXj83.js.map → periodontal-chart-card-BJEuJuzh.js.map} +1 -1
  193. package/dist/_chunks/{periodontal-diagnosis-lEwA8wqX.js → periodontal-diagnosis-C7pfPOct.js} +5 -5
  194. package/dist/_chunks/{periodontal-diagnosis-lEwA8wqX.js.map → periodontal-diagnosis-C7pfPOct.js.map} +1 -1
  195. package/dist/_chunks/{periodontal-risk-chart-0x7KVZjL.js → periodontal-risk-chart-B2tNFa15.js} +2 -2
  196. package/dist/_chunks/{periodontal-risk-chart-0x7KVZjL.js.map → periodontal-risk-chart-B2tNFa15.js.map} +1 -1
  197. package/dist/_chunks/{permission-matrix-BIJrGEmz.js → permission-matrix-VdAXjjHU.js} +3 -3
  198. package/dist/_chunks/{permission-matrix-BIJrGEmz.js.map → permission-matrix-VdAXjjHU.js.map} +1 -1
  199. package/dist/_chunks/{popover-DP6WCVwm.js → popover-DzR5QYxp.js} +24 -24
  200. package/dist/_chunks/{popover-DP6WCVwm.js.map → popover-DzR5QYxp.js.map} +1 -1
  201. package/dist/_chunks/{practice-profile-hero-DQyDvpJL.js → practice-profile-hero-DxoLlQr5.js} +2 -2
  202. package/dist/_chunks/{practice-profile-hero-DQyDvpJL.js.map → practice-profile-hero-DxoLlQr5.js.map} +1 -1
  203. package/dist/_chunks/{practice-results-kayDEorM.js → practice-results-DOcORTkP.js} +4 -4
  204. package/dist/_chunks/{practice-results-kayDEorM.js.map → practice-results-DOcORTkP.js.map} +1 -1
  205. package/dist/_chunks/{pregnancy-dating-n5j5dAKy.js → pregnancy-dating-nV1_S6w0.js} +6 -6
  206. package/dist/_chunks/{pregnancy-dating-n5j5dAKy.js.map → pregnancy-dating-nV1_S6w0.js.map} +1 -1
  207. package/dist/_chunks/{pregnancy-weight-gain-D5A8vPjj.js → pregnancy-weight-gain-tRecShAD.js} +4 -4
  208. package/dist/_chunks/{pregnancy-weight-gain-D5A8vPjj.js.map → pregnancy-weight-gain-tRecShAD.js.map} +1 -1
  209. package/dist/_chunks/{privacy-lock-CkAUo6Dz.js → privacy-lock-Be39vQUN.js} +2 -2
  210. package/dist/_chunks/{privacy-lock-CkAUo6Dz.js.map → privacy-lock-Be39vQUN.js.map} +1 -1
  211. package/dist/_chunks/{product-hub-panel-BScCotGD.js → product-hub-panel-C0TO69P7.js} +2 -2
  212. package/dist/_chunks/{product-hub-panel-BScCotGD.js.map → product-hub-panel-C0TO69P7.js.map} +1 -1
  213. package/dist/_chunks/{public-header.agent-kth2SdXn.js → public-header.agent-Bl1KFwSE.js} +3 -3
  214. package/dist/_chunks/{public-header.agent-kth2SdXn.js.map → public-header.agent-Bl1KFwSE.js.map} +1 -1
  215. package/dist/_chunks/{radio-DNRe6H_8.js → radio-6fml-pWk.js} +2 -2
  216. package/dist/_chunks/{radio-DNRe6H_8.js.map → radio-6fml-pWk.js.map} +1 -1
  217. package/dist/_chunks/{radio-group-DyVBgnA3.js → radio-group-CIjmyioi.js} +3 -3
  218. package/dist/_chunks/{radio-group-DyVBgnA3.js.map → radio-group-CIjmyioi.js.map} +1 -1
  219. package/dist/_chunks/{radiograph-panel.agent-o4jwEJPC.js → radiograph-panel.agent-k0G7JuoM.js} +6 -6
  220. package/dist/_chunks/{radiograph-panel.agent-o4jwEJPC.js.map → radiograph-panel.agent-k0G7JuoM.js.map} +1 -1
  221. package/dist/_chunks/{reviews-panel-BKHEfqVQ.js → reviews-panel-BaHZb_ai.js} +3 -3
  222. package/dist/_chunks/{reviews-panel-BKHEfqVQ.js.map → reviews-panel-BaHZb_ai.js.map} +1 -1
  223. package/dist/_chunks/{rich-text-editor-CCI-Y3DN.js → rich-text-editor-BTXlorm5.js} +7 -7
  224. package/dist/_chunks/{rich-text-editor-CCI-Y3DN.js.map → rich-text-editor-BTXlorm5.js.map} +1 -1
  225. package/dist/_chunks/{search-bar-CJj6sI9m.js → search-bar-CCmViqaa.js} +46 -46
  226. package/dist/_chunks/{search-bar-CJj6sI9m.js.map → search-bar-CCmViqaa.js.map} +1 -1
  227. package/dist/_chunks/section-card.agent-W18CHEgX.js +74 -0
  228. package/dist/_chunks/section-card.agent-W18CHEgX.js.map +1 -0
  229. package/dist/_chunks/{sheet-BSznOyJs.js → sheet-hm04DGFd.js} +2 -2
  230. package/dist/_chunks/{sheet-BSznOyJs.js.map → sheet-hm04DGFd.js.map} +1 -1
  231. package/dist/_chunks/{sign-document-jF4fZDJ5.js → sign-document-CRQuAn4W.js} +2 -2
  232. package/dist/_chunks/{sign-document-jF4fZDJ5.js.map → sign-document-CRQuAn4W.js.map} +1 -1
  233. package/dist/_chunks/{signature-request-vihDT8On.js → signature-request-Dej2g86d.js} +5 -5
  234. package/dist/_chunks/{signature-request-vihDT8On.js.map → signature-request-Dej2g86d.js.map} +1 -1
  235. package/dist/_chunks/{signature-status-chip-T5fyS-k9.js → signature-status-chip-D4NsrdeI.js} +3 -3
  236. package/dist/_chunks/{signature-status-chip-T5fyS-k9.js.map → signature-status-chip-D4NsrdeI.js.map} +1 -1
  237. package/dist/_chunks/{slot-grid-BuZOKfcd.js → slot-grid-8Ko6thzz.js} +2 -2
  238. package/dist/_chunks/{slot-grid-BuZOKfcd.js.map → slot-grid-8Ko6thzz.js.map} +1 -1
  239. package/dist/_chunks/{streaming-text-CvsjIQ7S.js → streaming-text-DjFqLSt_.js} +2 -2
  240. package/dist/_chunks/{streaming-text-CvsjIQ7S.js.map → streaming-text-DjFqLSt_.js.map} +1 -1
  241. package/dist/_chunks/{tab-bar-DvFJIQfL.js → tab-bar-rDkLiaA6.js} +2 -2
  242. package/dist/_chunks/{tab-bar-DvFJIQfL.js.map → tab-bar-rDkLiaA6.js.map} +1 -1
  243. package/dist/_chunks/{tag-3wgkwwDB.js → tag-Ci3xJPcH.js} +2 -2
  244. package/dist/_chunks/{tag-3wgkwwDB.js.map → tag-Ci3xJPcH.js.map} +1 -1
  245. package/dist/_chunks/{task-tray-COo-RlDv.js → task-tray-wl9eti6J.js} +2 -2
  246. package/dist/_chunks/{task-tray-COo-RlDv.js.map → task-tray-wl9eti6J.js.map} +1 -1
  247. package/dist/_chunks/{tasks-panel-DLKpSNoE.js → tasks-panel-BDNB7hsZ.js} +5 -5
  248. package/dist/_chunks/{tasks-panel-DLKpSNoE.js.map → tasks-panel-BDNB7hsZ.js.map} +1 -1
  249. package/dist/_chunks/{theme-toggle-uEwoKjl3.js → theme-toggle-CMz8YfC1.js} +3 -3
  250. package/dist/_chunks/{theme-toggle-uEwoKjl3.js.map → theme-toggle-CMz8YfC1.js.map} +1 -1
  251. package/dist/_chunks/{timeline-Bs9Erxlo.js → timeline-61AihzYz.js} +47 -47
  252. package/dist/_chunks/timeline-61AihzYz.js.map +1 -0
  253. package/dist/_chunks/{toast-YZz2sBzB.js → toast-8jqtbfAB.js} +2 -2
  254. package/dist/_chunks/{toast-YZz2sBzB.js.map → toast-8jqtbfAB.js.map} +1 -1
  255. package/dist/_chunks/{tool-rail-ONaV-Nzz.js → tool-rail-Bq5eiFMG.js} +3 -3
  256. package/dist/_chunks/{tool-rail-ONaV-Nzz.js.map → tool-rail-Bq5eiFMG.js.map} +1 -1
  257. package/dist/_chunks/{tooltip-DvmfrNvB.js → tooltip-Cp-PLePW.js} +41 -41
  258. package/dist/_chunks/tooltip-Cp-PLePW.js.map +1 -0
  259. package/dist/_chunks/{tooth-scheme-Qe7LO5Di.js → tooth-scheme-BWkYxxjR.js} +3 -3
  260. package/dist/_chunks/{tooth-scheme-Qe7LO5Di.js.map → tooth-scheme-BWkYxxjR.js.map} +1 -1
  261. package/dist/_chunks/{transaction-chip-DJCstquX.js → transaction-chip-Dth1nThY.js} +49 -48
  262. package/dist/_chunks/{transaction-chip-DJCstquX.js.map → transaction-chip-Dth1nThY.js.map} +1 -1
  263. package/dist/_chunks/{transcript-panel-BGkEhvHO.js → transcript-panel-u2HHxZB6.js} +2 -2
  264. package/dist/_chunks/{transcript-panel-BGkEhvHO.js.map → transcript-panel-u2HHxZB6.js.map} +1 -1
  265. package/dist/_chunks/user-x-DYszNtIg.js +45 -0
  266. package/dist/_chunks/user-x-DYszNtIg.js.map +1 -0
  267. package/dist/_chunks/{warning-stack-DQz0Jyir.js → warning-stack-BW5Dwb3z.js} +3 -3
  268. package/dist/_chunks/{warning-stack-DQz0Jyir.js.map → warning-stack-BW5Dwb3z.js.map} +1 -1
  269. package/dist/_chunks/{widget-picker-DvUkBemi.js → widget-picker-B1sj6uyf.js} +2 -2
  270. package/dist/_chunks/{widget-picker-DvUkBemi.js.map → widget-picker-B1sj6uyf.js.map} +1 -1
  271. package/dist/_chunks/{workflow-map-dNzJjBWG.js → workflow-map-D-LEni11.js} +5 -5
  272. package/dist/_chunks/{workflow-map-dNzJjBWG.js.map → workflow-map-D-LEni11.js.map} +1 -1
  273. package/dist/_chunks/workflow-status-xeaJTzD3.js +476 -0
  274. package/dist/_chunks/workflow-status-xeaJTzD3.js.map +1 -0
  275. package/dist/agent-catalog.json +185 -1
  276. package/dist/agent-i18n/en.json +27 -0
  277. package/dist/components/_shared/entity-card/entity-card.d.ts +44 -0
  278. package/dist/components/_shared/entity-card/entity-card.d.ts.map +1 -1
  279. package/dist/components/_shared/entity-card/index.d.ts +1 -1
  280. package/dist/components/_shared/entity-card/index.d.ts.map +1 -1
  281. package/dist/components/_shared/note-attachment.d.ts +41 -0
  282. package/dist/components/_shared/note-attachment.d.ts.map +1 -0
  283. package/dist/components/_shared/note-markdown.d.ts +3 -0
  284. package/dist/components/_shared/note-markdown.d.ts.map +1 -0
  285. package/dist/components/_shared/patient-field-row.d.ts +40 -0
  286. package/dist/components/_shared/patient-field-row.d.ts.map +1 -0
  287. package/dist/components/agenda-card/index.js +1 -1
  288. package/dist/components/agenda-tray/index.js +1 -1
  289. package/dist/components/ai-consent-banner/index.js +1 -1
  290. package/dist/components/ai-prompt-input/index.js +1 -1
  291. package/dist/components/alert/index.js +1 -1
  292. package/dist/components/anamnesis-card/index.js +1 -1
  293. package/dist/components/anamnesis-summary-card/index.js +1 -1
  294. package/dist/components/appointment-card/appointment-card.d.ts.map +1 -1
  295. package/dist/components/appointment-card/index.js +2 -2
  296. package/dist/components/appointment-timeline/index.js +1 -1
  297. package/dist/components/audio-recorder/index.js +1 -1
  298. package/dist/components/badge/index.js +1 -1
  299. package/dist/components/bishop-score/index.js +1 -1
  300. package/dist/components/bmi-calculator/index.js +1 -1
  301. package/dist/components/booking/index.js +1 -1
  302. package/dist/components/button/index.js +1 -1
  303. package/dist/components/button-group/button-group.d.ts +20 -0
  304. package/dist/components/button-group/button-group.d.ts.map +1 -1
  305. package/dist/components/button-group/index.js +1 -1
  306. package/dist/components/calendar/index.js +1 -1
  307. package/dist/components/calendar-event-card/index.js +1 -1
  308. package/dist/components/care-plan-card/index.js +1 -1
  309. package/dist/components/care-plan-entry-card/index.js +1 -1
  310. package/dist/components/care-plan-header/index.js +1 -1
  311. package/dist/components/carousel/index.js +1 -1
  312. package/dist/components/chart/index.js +1 -1
  313. package/dist/components/chat-input/index.js +1 -1
  314. package/dist/components/chat-message/index.js +1 -1
  315. package/dist/components/checkbox/index.js +1 -1
  316. package/dist/components/checkbox-group/index.js +1 -1
  317. package/dist/components/clinical-note-card/clinical-note-card.d.ts +2 -34
  318. package/dist/components/clinical-note-card/clinical-note-card.d.ts.map +1 -1
  319. package/dist/components/clinical-note-card/index.js +1 -1
  320. package/dist/components/connection-status/index.js +1 -1
  321. package/dist/components/contact-profile-card/index.js +1 -1
  322. package/dist/components/control-room-rail/index.js +1 -1
  323. package/dist/components/counter/counter.d.ts +6 -0
  324. package/dist/components/counter/counter.d.ts.map +1 -1
  325. package/dist/components/counter/index.js +1 -1
  326. package/dist/components/cycle-calculator/index.js +1 -1
  327. package/dist/components/dashboard-grid/index.js +1 -1
  328. package/dist/components/data-table/index.js +4 -4
  329. package/dist/components/data-table-tabs/index.js +1 -1
  330. package/dist/components/date-picker/index.js +1 -1
  331. package/dist/components/dependent-selector/index.js +1 -1
  332. package/dist/components/description-list/index.js +1 -1
  333. package/dist/components/document-preview/index.js +1 -1
  334. package/dist/components/document-scanner/index.js +1 -1
  335. package/dist/components/due-date-calculator/index.js +2 -2
  336. package/dist/components/editor-overlay/index.js +1 -1
  337. package/dist/components/entity-summary/index.js +1 -1
  338. package/dist/components/face-scheme/index.js +1 -1
  339. package/dist/components/fetal-weight/index.js +1 -1
  340. package/dist/components/field-array/index.js +1 -1
  341. package/dist/components/file-manager/index.js +1 -1
  342. package/dist/components/file-upload/index.js +1 -1
  343. package/dist/components/fiscal-code-input/index.js +1 -1
  344. package/dist/components/freemium-paywall/index.js +1 -1
  345. package/dist/components/gestational-age-calculator/index.js +1 -1
  346. package/dist/components/hcg-doubling/index.js +1 -1
  347. package/dist/components/header/index.js +1 -1
  348. package/dist/components/header-settings/index.js +1 -1
  349. package/dist/components/hover-card/hover-card.agent.d.ts +4 -0
  350. package/dist/components/hover-card/hover-card.agent.d.ts.map +1 -0
  351. package/dist/components/hover-card/hover-card.d.ts +80 -0
  352. package/dist/components/hover-card/hover-card.d.ts.map +1 -0
  353. package/dist/components/hover-card/index.d.ts +4 -0
  354. package/dist/components/hover-card/index.d.ts.map +1 -0
  355. package/dist/components/hover-card/index.js +6 -0
  356. package/dist/components/hover-card/index.js.map +1 -0
  357. package/dist/components/icon-button/index.js +1 -1
  358. package/dist/components/icon-button-group/index.js +1 -1
  359. package/dist/components/icon-picker/index.js +1 -1
  360. package/dist/components/index.d.ts +4 -0
  361. package/dist/components/index.d.ts.map +1 -1
  362. package/dist/components/info-tip/index.js +1 -1
  363. package/dist/components/key-value-pair/index.js +1 -1
  364. package/dist/components/key-value-pair/key-value-pair.d.ts +8 -1
  365. package/dist/components/key-value-pair/key-value-pair.d.ts.map +1 -1
  366. package/dist/components/locale-picker/index.js +1 -1
  367. package/dist/components/message-card/index.js +1 -1
  368. package/dist/components/message-tray/index.js +1 -1
  369. package/dist/components/multi-select/index.js +1 -1
  370. package/dist/components/note-timeline/index.d.ts +4 -0
  371. package/dist/components/note-timeline/index.d.ts.map +1 -0
  372. package/dist/components/note-timeline/index.js +6 -0
  373. package/dist/components/note-timeline/index.js.map +1 -0
  374. package/dist/components/note-timeline/note-timeline.agent.d.ts +4 -0
  375. package/dist/components/note-timeline/note-timeline.agent.d.ts.map +1 -0
  376. package/dist/components/note-timeline/note-timeline.d.ts +77 -0
  377. package/dist/components/note-timeline/note-timeline.d.ts.map +1 -0
  378. package/dist/components/notes-panel/index.js +1 -1
  379. package/dist/components/notification-card/index.js +1 -1
  380. package/dist/components/notification-tray/index.js +1 -1
  381. package/dist/components/operator-hero/index.js +1 -1
  382. package/dist/components/optical-prescription/index.js +1 -1
  383. package/dist/components/panel-header/index.js +1 -1
  384. package/dist/components/panel-header/panel-header.d.ts +7 -0
  385. package/dist/components/panel-header/panel-header.d.ts.map +1 -1
  386. package/dist/components/patient-details/index.js +1 -1
  387. package/dist/components/patient-details/patient-details.d.ts.map +1 -1
  388. package/dist/components/patient-search/index.js +1 -1
  389. package/dist/components/patient-summary-card/index.js +1 -1
  390. package/dist/components/patient-summary-card/patient-summary-card.d.ts +54 -0
  391. package/dist/components/patient-summary-card/patient-summary-card.d.ts.map +1 -1
  392. package/dist/components/patient-table/index.js +1 -1
  393. package/dist/components/payment-card/index.js +1 -1
  394. package/dist/components/payment-form/index.js +1 -1
  395. package/dist/components/pdf-viewer/index.js +1 -1
  396. package/dist/components/periodontal-chart/index.js +1 -1
  397. package/dist/components/periodontal-chart-card/index.js +1 -1
  398. package/dist/components/periodontal-diagnosis/index.js +1 -1
  399. package/dist/components/periodontal-risk-chart/index.js +1 -1
  400. package/dist/components/permission-matrix/index.js +1 -1
  401. package/dist/components/popover/index.js +1 -1
  402. package/dist/components/practice-profile-hero/index.js +1 -1
  403. package/dist/components/practice-results/index.js +1 -1
  404. package/dist/components/pregnancy-dating/index.js +1 -1
  405. package/dist/components/pregnancy-weight-gain/index.js +1 -1
  406. package/dist/components/privacy-lock/index.js +1 -1
  407. package/dist/components/product-hub-tray/index.js +1 -1
  408. package/dist/components/public-header/index.js +1 -1
  409. package/dist/components/radio/index.js +1 -1
  410. package/dist/components/radio-group/index.js +2 -2
  411. package/dist/components/radiograph-panel/index.js +1 -1
  412. package/dist/components/reviews-panel/index.js +1 -1
  413. package/dist/components/rich-text-editor/index.js +1 -1
  414. package/dist/components/search-bar/index.js +1 -1
  415. package/dist/components/section-card/index.d.ts +4 -0
  416. package/dist/components/section-card/index.d.ts.map +1 -0
  417. package/dist/components/section-card/index.js +6 -0
  418. package/dist/components/section-card/index.js.map +1 -0
  419. package/dist/components/section-card/section-card.agent.d.ts +3 -0
  420. package/dist/components/section-card/section-card.agent.d.ts.map +1 -0
  421. package/dist/components/section-card/section-card.d.ts +30 -0
  422. package/dist/components/section-card/section-card.d.ts.map +1 -0
  423. package/dist/components/sheet/index.js +1 -1
  424. package/dist/components/sign-document/index.js +1 -1
  425. package/dist/components/signature-status-chip/index.js +1 -1
  426. package/dist/components/slot-grid/index.js +1 -1
  427. package/dist/components/streaming-text/index.js +1 -1
  428. package/dist/components/tab-bar/index.js +1 -1
  429. package/dist/components/tag/index.js +1 -1
  430. package/dist/components/task-tray/index.js +1 -1
  431. package/dist/components/tasks-panel/index.js +1 -1
  432. package/dist/components/theme-toggle/index.js +1 -1
  433. package/dist/components/timeline/index.js +1 -1
  434. package/dist/components/timeline/timeline.d.ts +1 -1
  435. package/dist/components/timeline/timeline.d.ts.map +1 -1
  436. package/dist/components/toast/index.js +1 -1
  437. package/dist/components/tool-rail/index.js +1 -1
  438. package/dist/components/tooltip/index.js +1 -1
  439. package/dist/components/tooltip/tooltip.d.ts.map +1 -1
  440. package/dist/components/tooth-scheme/index.js +1 -1
  441. package/dist/components/transaction-chip/index.js +1 -1
  442. package/dist/components/transaction-chip/transaction-chip.d.ts +11 -0
  443. package/dist/components/transaction-chip/transaction-chip.d.ts.map +1 -1
  444. package/dist/components/transcript-panel/index.js +1 -1
  445. package/dist/components/warning-stack/index.js +1 -1
  446. package/dist/components/widget-picker/index.js +1 -1
  447. package/dist/components/workflow/index.js +1 -1
  448. package/dist/components/workflow-status/index.d.ts +4 -0
  449. package/dist/components/workflow-status/index.d.ts.map +1 -0
  450. package/dist/components/workflow-status/index.js +7 -0
  451. package/dist/components/workflow-status/index.js.map +1 -0
  452. package/dist/components/workflow-status/workflow-status.agent.d.ts +4 -0
  453. package/dist/components/workflow-status/workflow-status.agent.d.ts.map +1 -0
  454. package/dist/components/workflow-status/workflow-status.d.ts +52 -0
  455. package/dist/components/workflow-status/workflow-status.d.ts.map +1 -0
  456. package/dist/host-compat.css +4 -1
  457. package/dist/i18n/locales/ar.d.ts +12 -0
  458. package/dist/i18n/locales/ar.d.ts.map +1 -1
  459. package/dist/i18n/locales/ar.js +12 -0
  460. package/dist/i18n/locales/ar.js.map +1 -1
  461. package/dist/i18n/locales/de.d.ts +12 -0
  462. package/dist/i18n/locales/de.d.ts.map +1 -1
  463. package/dist/i18n/locales/de.js +12 -0
  464. package/dist/i18n/locales/de.js.map +1 -1
  465. package/dist/i18n/locales/el.d.ts +12 -0
  466. package/dist/i18n/locales/el.d.ts.map +1 -1
  467. package/dist/i18n/locales/el.js +12 -0
  468. package/dist/i18n/locales/el.js.map +1 -1
  469. package/dist/i18n/locales/en.d.ts +12 -0
  470. package/dist/i18n/locales/en.d.ts.map +1 -1
  471. package/dist/i18n/locales/en.js +12 -0
  472. package/dist/i18n/locales/en.js.map +1 -1
  473. package/dist/i18n/locales/es.d.ts +12 -0
  474. package/dist/i18n/locales/es.d.ts.map +1 -1
  475. package/dist/i18n/locales/es.js +12 -0
  476. package/dist/i18n/locales/es.js.map +1 -1
  477. package/dist/i18n/locales/fr.d.ts +12 -0
  478. package/dist/i18n/locales/fr.d.ts.map +1 -1
  479. package/dist/i18n/locales/fr.js +12 -0
  480. package/dist/i18n/locales/fr.js.map +1 -1
  481. package/dist/i18n/locales/hi.d.ts +12 -0
  482. package/dist/i18n/locales/hi.d.ts.map +1 -1
  483. package/dist/i18n/locales/hi.js +12 -0
  484. package/dist/i18n/locales/hi.js.map +1 -1
  485. package/dist/i18n/locales/it.d.ts +12 -0
  486. package/dist/i18n/locales/it.d.ts.map +1 -1
  487. package/dist/i18n/locales/it.js +12 -0
  488. package/dist/i18n/locales/it.js.map +1 -1
  489. package/dist/i18n/locales/ja.d.ts +12 -0
  490. package/dist/i18n/locales/ja.d.ts.map +1 -1
  491. package/dist/i18n/locales/ja.js +12 -0
  492. package/dist/i18n/locales/ja.js.map +1 -1
  493. package/dist/i18n/locales/nl.d.ts +12 -0
  494. package/dist/i18n/locales/nl.d.ts.map +1 -1
  495. package/dist/i18n/locales/nl.js +12 -0
  496. package/dist/i18n/locales/nl.js.map +1 -1
  497. package/dist/i18n/locales/pl.d.ts +12 -0
  498. package/dist/i18n/locales/pl.d.ts.map +1 -1
  499. package/dist/i18n/locales/pl.js +12 -0
  500. package/dist/i18n/locales/pl.js.map +1 -1
  501. package/dist/i18n/locales/pt.d.ts +12 -0
  502. package/dist/i18n/locales/pt.d.ts.map +1 -1
  503. package/dist/i18n/locales/pt.js +12 -0
  504. package/dist/i18n/locales/pt.js.map +1 -1
  505. package/dist/i18n/locales/ro.d.ts +12 -0
  506. package/dist/i18n/locales/ro.d.ts.map +1 -1
  507. package/dist/i18n/locales/ro.js +12 -0
  508. package/dist/i18n/locales/ro.js.map +1 -1
  509. package/dist/i18n/locales/ru.d.ts +12 -0
  510. package/dist/i18n/locales/ru.d.ts.map +1 -1
  511. package/dist/i18n/locales/ru.js +12 -0
  512. package/dist/i18n/locales/ru.js.map +1 -1
  513. package/dist/i18n/locales/sq.d.ts +12 -0
  514. package/dist/i18n/locales/sq.d.ts.map +1 -1
  515. package/dist/i18n/locales/sq.js +12 -0
  516. package/dist/i18n/locales/sq.js.map +1 -1
  517. package/dist/i18n/locales/sv.d.ts +12 -0
  518. package/dist/i18n/locales/sv.d.ts.map +1 -1
  519. package/dist/i18n/locales/sv.js +12 -0
  520. package/dist/i18n/locales/sv.js.map +1 -1
  521. package/dist/i18n/locales/tr.d.ts +12 -0
  522. package/dist/i18n/locales/tr.d.ts.map +1 -1
  523. package/dist/i18n/locales/tr.js +12 -0
  524. package/dist/i18n/locales/tr.js.map +1 -1
  525. package/dist/i18n/locales/zh.d.ts +12 -0
  526. package/dist/i18n/locales/zh.d.ts.map +1 -1
  527. package/dist/i18n/locales/zh.js +12 -0
  528. package/dist/i18n/locales/zh.js.map +1 -1
  529. package/dist/index.js +929 -916
  530. package/dist/index.js.map +1 -1
  531. package/dist/locales/ar.json +12 -0
  532. package/dist/locales/de.json +12 -0
  533. package/dist/locales/el.json +12 -0
  534. package/dist/locales/en.json +12 -0
  535. package/dist/locales/es.json +12 -0
  536. package/dist/locales/fr.json +12 -0
  537. package/dist/locales/hi.json +12 -0
  538. package/dist/locales/it.json +12 -0
  539. package/dist/locales/ja.json +12 -0
  540. package/dist/locales/nl.json +12 -0
  541. package/dist/locales/pl.json +12 -0
  542. package/dist/locales/pt.json +12 -0
  543. package/dist/locales/ro.json +12 -0
  544. package/dist/locales/ru.json +12 -0
  545. package/dist/locales/sq.json +12 -0
  546. package/dist/locales/sv.json +12 -0
  547. package/dist/locales/tr.json +12 -0
  548. package/dist/locales/zh.json +12 -0
  549. package/dist/patterns/alia-assistant/index.js +1 -1
  550. package/dist/patterns/anamnesis/index.js +1 -1
  551. package/dist/patterns/calendar/calendar.model.d.ts +2 -0
  552. package/dist/patterns/calendar/calendar.model.d.ts.map +1 -1
  553. package/dist/patterns/calendar/calendar.sheets.d.ts.map +1 -1
  554. package/dist/patterns/calendar/calendar.surface.d.ts.map +1 -1
  555. package/dist/patterns/calendar/index.js +1 -1
  556. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  557. package/dist/patterns/payment-automation-upsell/index.js +1 -1
  558. package/dist/patterns/signature-request/index.js +1 -1
  559. package/dist/tokens.css +1 -1
  560. package/package.json +17 -1
  561. package/dist/_chunks/appointment-card-Bh_CIlc6.js.map +0 -1
  562. package/dist/_chunks/button-group-CaxRJsNG.js +0 -289
  563. package/dist/_chunks/button-group-CaxRJsNG.js.map +0 -1
  564. package/dist/_chunks/calendar-event-card-DSh-69HT.js.map +0 -1
  565. package/dist/_chunks/calendar-workspace-UywR5gUl.js.map +0 -1
  566. package/dist/_chunks/clinical-note-card-CTRzmqvv.js +0 -438
  567. package/dist/_chunks/clinical-note-card-CTRzmqvv.js.map +0 -1
  568. package/dist/_chunks/counter-dRlTNC_y.js.map +0 -1
  569. package/dist/_chunks/entity-card-9_62gY7l.js.map +0 -1
  570. package/dist/_chunks/field-value-BetdWMA2.js +0 -384
  571. package/dist/_chunks/field-value-BetdWMA2.js.map +0 -1
  572. package/dist/_chunks/file-upload-CwxdqkMK.js.map +0 -1
  573. package/dist/_chunks/key-value-pair-BIBdZBLg.js.map +0 -1
  574. package/dist/_chunks/panel-header-D313n_9-.js +0 -105
  575. package/dist/_chunks/panel-header-D313n_9-.js.map +0 -1
  576. package/dist/_chunks/patient-details-BGiawUHd.js +0 -760
  577. package/dist/_chunks/patient-details-BGiawUHd.js.map +0 -1
  578. package/dist/_chunks/patient-summary-card--CT_gbaQ.js +0 -454
  579. package/dist/_chunks/patient-summary-card--CT_gbaQ.js.map +0 -1
  580. package/dist/_chunks/payment-automation-upsell-DwQW2fRp.js.map +0 -1
  581. package/dist/_chunks/timeline-Bs9Erxlo.js.map +0 -1
  582. package/dist/_chunks/tooltip-DvmfrNvB.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"radiograph-panel.agent-o4jwEJPC.js","sources":["../../node_modules/lucide-react/dist/esm/icons/git-compare-arrows.mjs","../../node_modules/lucide-react/dist/esm/icons/images.mjs","../../src/components/radiograph-panel/radiograph-panel.tsx","../../src/components/radiograph-panel/radiograph-panel.agent.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 [\"circle\", { cx: \"5\", cy: \"6\", r: \"3\", key: \"1qnov2\" }],\n [\"path\", { d: \"M12 6h5a2 2 0 0 1 2 2v7\", key: \"1yj91y\" }],\n [\"path\", { d: \"m15 9-3-3 3-3\", key: \"1lwv8l\" }],\n [\"circle\", { cx: \"19\", cy: \"18\", r: \"3\", key: \"1qljk2\" }],\n [\"path\", { d: \"M12 18H7a2 2 0 0 1-2-2V9\", key: \"16sdep\" }],\n [\"path\", { d: \"m9 15 3 3-3 3\", key: \"1m3kbl\" }]\n];\nconst GitCompareArrows = createLucideIcon(\"git-compare-arrows\", __iconNode);\n\nexport { __iconNode, GitCompareArrows as default };\n//# sourceMappingURL=git-compare-arrows.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: \"m22 11-1.296-1.296a2.4 2.4 0 0 0-3.408 0L11 16\", key: \"9kzy35\" }],\n [\"path\", { d: \"M4 8a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2\", key: \"1t0f0t\" }],\n [\"circle\", { cx: \"13\", cy: \"7\", r: \"1\", fill: \"currentColor\", key: \"1obus6\" }],\n [\"rect\", { x: \"8\", y: \"2\", width: \"14\", height: \"14\", rx: \"2\", key: \"1gvhby\" }]\n];\nconst Images = createLucideIcon(\"images\", __iconNode);\n\nexport { __iconNode, Images as default };\n//# sourceMappingURL=images.mjs.map\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactElement,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Upload,\n ZoomIn,\n ZoomOut,\n ChevronLeft,\n ChevronRight,\n Trash2,\n Eye,\n GitCompareArrows,\n Images,\n} from 'lucide-react';\nimport type { FdiId, Radiograph, RadiographKind } from '../tooth-scheme';\nimport { Dialog } from '../dialog';\nimport { Button } from '../button';\nimport { IconButton } from '../icon-button';\nimport { Badge } from '../badge';\nimport { FormField } from '../form-field';\nimport { TextArea } from '../text-area';\nimport { FileUpload } from '../file-upload';\nimport { DatePicker } from '../date-picker';\nimport { DateRangePicker, type DateRangeValue } from '../date-range-picker';\nimport { EmptyState } from '../empty-state';\nimport { PanelHeader } from '../panel-header';\n\n/* ------------------------------------------------------------------ */\n/* RadiographPanel — the Imaging tool for the Control Room rail. */\n/* */\n/* Shows one tooth's radiographs (x-rays / endorali): an upload */\n/* composer, a sortable + date-filtered history, and a fullscreen */\n/* viewer that zooms / steps / compares films. Drops into a */\n/* `ControlRoomRail` tool `panel`, the patient profile, or a care-plan */\n/* editor — anywhere a selected tooth's imaging belongs. The host owns */\n/* the films (`radiographs`) and persistence (`onAddRadiograph` / */\n/* `onDeleteRadiograph`); the panel owns only view state. The chart */\n/* drives selection via `ToothScheme.onOpenRadiographs(toothId)`. */\n/* */\n/* Image urls are opaque / consumer-hosted — never bundled. Real */\n/* radiographs are PHI; stories use synthetic placeholders only. */\n/* ------------------------------------------------------------------ */\n\nconst ZOOM_CLASS = ['ds:scale-100', 'ds:scale-150', 'ds:scale-200'] as const;\n\n/** Sort films newest-first (or oldest-first); undated films sink to the end in\n * BOTH directions — mirrors `ToothScheme.sortByDateDesc`. */\nfunction sortByDate(films: Radiograph[], desc: boolean): Radiograph[] {\n return [...films].sort((a, b) => {\n if (a.date === b.date) return 0;\n if (!a.date) return 1;\n if (!b.date) return -1;\n return (a.date < b.date ? -1 : 1) * (desc ? -1 : 1);\n });\n}\n\n/** Date-range membership. ISO `YYYY-MM-DD` is parsed at LOCAL midnight (the\n * `+'T00:00:00'`) so the filter agrees with the local-midnight `Date` objects\n * the DateRangePicker emits — without it, films are off-by-one west of UTC. */\nfunction inRange(film: Radiograph, range: DateRangeValue): boolean {\n if (!film.date) return !range.from && !range.to;\n const d = new Date(`${film.date}T00:00:00`);\n if (range.from && d < range.from) return false;\n if (range.to && d > range.to) return false;\n return true;\n}\n\n/** Local `YYYY-MM-DD` — avoids the UTC shift `Date.toISOString()` introduces\n * west of UTC for the local-midnight Date the DatePicker emits. */\nfunction toLocalIsoDate(d: Date): string {\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n}\n\nexport interface RadiographPanelHandle {\n /** Read the films currently shown (after the host's `radiographs` prop). */\n getRadiographs: () => Radiograph[];\n /** Open the fullscreen viewer on a film by id. */\n openViewer: (id: string) => void;\n /** Close the fullscreen viewer. */\n closeViewer: () => void;\n}\n\nexport interface RadiographPanelProps extends Omit<\n HTMLAttributes<HTMLElement>,\n 'title' | 'children'\n> {\n /** Instance id — emitted as `data-component-id` for the agent registry. */\n id?: string;\n /** The tooth whose films are shown (FDI id). Null → a \"select a tooth\" prompt. */\n toothId?: FdiId | null;\n /** Display label for the selected tooth. Defaults to the localised \"Tooth {{id}}\". */\n toothLabel?: string;\n /** The selected tooth's films. The panel sorts + filters; order in is irrelevant. */\n radiographs?: Radiograph[];\n /** Commit a new film (the host persists it). Omit to hide the upload composer. */\n onAddRadiograph?: (draft: {\n fileName: string;\n date?: string;\n note?: string;\n }) => void;\n /** Remove a film by id. Omit to hide the delete affordance. */\n onDeleteRadiograph?: (id: string) => void;\n /** Panel heading. Defaults to the localised \"Imaging\". */\n title?: string;\n /** Accessible name for the panel region (defaults to `title`). */\n 'aria-label'?: string;\n}\n\nfunction KindBadge({ kind }: { kind: RadiographKind }): ReactElement {\n const { t } = useTranslation();\n const label = t(`radiographPanel.kind.${kind}`, {\n defaultValue: {\n periapical: 'Periapical',\n bitewing: 'Bitewing',\n panoramic: 'Panoramic',\n other: 'Other',\n }[kind],\n });\n return (\n <Badge variant=\"neutral\" size=\"sm\">\n {label}\n </Badge>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Fullscreen viewer — lightbox + compare */\n/* ------------------------------------------------------------------ */\n\ninterface ViewerState {\n films: Radiograph[];\n index: number;\n compare: boolean;\n}\n\nfunction RadiographViewer({\n state,\n toothLabel,\n onClose,\n onIndexChange,\n}: {\n state: ViewerState | null;\n toothLabel: string;\n onClose: () => void;\n onIndexChange: (index: number) => void;\n}): ReactElement {\n const { t } = useTranslation();\n const [zoom, setZoom] = useState(0);\n // Reset zoom when the viewed film changes (prev/next) or the mode flips, so a\n // user doesn't carry one film's zoom into the next.\n useEffect(() => {\n setZoom(0);\n }, [state?.index, state?.compare]);\n const films = state?.films ?? [];\n const current = state ? films[state.index] : undefined;\n\n return (\n <Dialog.Root\n open={state !== null}\n onOpenChange={(next) => {\n if (!next) {\n setZoom(0);\n onClose();\n }\n }}\n >\n <Dialog.Content size=\"fullscreen\" aria-describedby={undefined}>\n <Dialog.Header>\n <Dialog.Title>\n {state?.compare\n ? t('radiographPanel.viewer.compareTitle', {\n defaultValue: '{{tooth}} — comparison',\n tooth: toothLabel,\n })\n : t('radiographPanel.viewer.title', {\n defaultValue: '{{tooth}} — radiograph',\n tooth: toothLabel,\n })}\n </Dialog.Title>\n </Dialog.Header>\n <Dialog.Body>\n {state?.compare ? (\n <div className=\"ds:grid ds:grid-cols-2 ds:gap-[var(--spacing-md)]\">\n {films.slice(0, 2).map((film) => (\n <figure\n key={film.id}\n className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n <div className=\"ds:flex ds:items-center ds:justify-center ds:overflow-hidden ds:rounded-[var(--radius-md)] ds:bg-[var(--muted)] ds:p-[var(--spacing-xs)]\">\n <img\n src={film.thumbnailUrl ?? film.url}\n alt={film.alt ?? toothLabel}\n className=\"ds:max-h-full ds:max-w-full ds:object-contain\"\n />\n </div>\n <figcaption className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {film.date}\n </figcaption>\n </figure>\n ))}\n </div>\n ) : (\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:max-h-full ds:items-center ds:justify-center ds:overflow-hidden ds:rounded-[var(--radius-md)] ds:bg-[var(--muted)] ds:p-[var(--spacing-sm)]\">\n <img\n src={current?.thumbnailUrl ?? current?.url}\n alt={current?.alt ?? toothLabel}\n className={[\n 'ds:max-h-full ds:max-w-full ds:object-contain',\n 'ds:origin-center ds:transition-transform ds:motion-reduce:transition-none',\n ZOOM_CLASS[zoom],\n ].join(' ')}\n />\n </div>\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <IconButton\n icon={<ChevronLeft aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.viewer.prev', {\n defaultValue: 'Previous radiograph',\n })}\n size=\"sm\"\n flipIconInRtl\n disabled={!state || state.index === 0}\n onClick={() =>\n state && onIndexChange(Math.max(0, state.index - 1))\n }\n />\n <span\n aria-live=\"polite\"\n className=\"type-meta ds:text-[color:var(--muted-foreground)]\"\n >\n {t('radiographPanel.viewer.position', {\n defaultValue: '{{current}} / {{total}}',\n current: (state?.index ?? 0) + 1,\n total: films.length,\n })}\n </span>\n <IconButton\n icon={<ChevronRight aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.viewer.next', {\n defaultValue: 'Next radiograph',\n })}\n size=\"sm\"\n flipIconInRtl\n disabled={!state || state.index >= films.length - 1}\n onClick={() =>\n state &&\n onIndexChange(Math.min(films.length - 1, state.index + 1))\n }\n />\n <span\n aria-hidden=\"true\"\n className=\"ds:ms-[var(--spacing-xs)] ds:me-[var(--spacing-xs)] ds:h-[var(--spacing-md)] ds:w-px ds:bg-[var(--border)]\"\n />\n <IconButton\n icon={<ZoomOut aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.viewer.zoomOut', {\n defaultValue: 'Zoom out',\n })}\n size=\"sm\"\n disabled={zoom === 0}\n onClick={() => setZoom((z) => Math.max(0, z - 1))}\n />\n <IconButton\n icon={<ZoomIn aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.viewer.zoomIn', {\n defaultValue: 'Zoom in',\n })}\n size=\"sm\"\n disabled={zoom === ZOOM_CLASS.length - 1}\n onClick={() =>\n setZoom((z) => Math.min(ZOOM_CLASS.length - 1, z + 1))\n }\n />\n </div>\n {current?.note ? (\n <p className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {current.note}\n </p>\n ) : null}\n </div>\n )}\n </Dialog.Body>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* RadiographPanel */\n/* ------------------------------------------------------------------ */\n\nexport const RadiographPanel = forwardRef<\n RadiographPanelHandle,\n RadiographPanelProps\n>(function RadiographPanel(\n {\n id,\n toothId,\n toothLabel: toothLabelProp,\n radiographs = [],\n onAddRadiograph,\n onDeleteRadiograph,\n title,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n) {\n const { t } = useTranslation();\n\n const [viewer, setViewer] = useState<ViewerState | null>(null);\n const [compareIds, setCompareIds] = useState<string[]>([]);\n const [sortDesc, setSortDesc] = useState(true);\n const [range, setRange] = useState<DateRangeValue>({});\n const [pendingFile, setPendingFile] = useState<string | null>(null);\n const [date, setDate] = useState<Date | undefined>(undefined);\n const [note, setNote] = useState('');\n\n // Stable, current snapshot for the imperative handle.\n const filmsRef = useRef<Radiograph[]>(radiographs);\n filmsRef.current = radiographs;\n\n useImperativeHandle(\n ref,\n () => ({\n getRadiographs: () => filmsRef.current,\n openViewer: (filmId) => {\n const index = filmsRef.current.findIndex((f) => f.id === filmId);\n if (index >= 0) {\n setViewer({ films: filmsRef.current, index, compare: false });\n }\n },\n closeViewer: () => setViewer(null),\n }),\n [],\n );\n\n const heading =\n title ?? t('radiographPanel.title', { defaultValue: 'Imaging' });\n const toothLabel =\n toothLabelProp ??\n (toothId\n ? t('radiographPanel.toothLabel', {\n defaultValue: 'Tooth {{id}}',\n id: toothId,\n })\n : '');\n\n const visible = useMemo(\n () =>\n sortByDate(\n radiographs.filter((f) => inRange(f, range)),\n sortDesc,\n ),\n [radiographs, range, sortDesc],\n );\n\n const toggleCompare = useCallback((filmId: string) => {\n setCompareIds((ids) =>\n ids.includes(filmId)\n ? ids.filter((x) => x !== filmId)\n : [...ids, filmId].slice(-2),\n );\n }, []);\n\n const handleUpload = useCallback(() => {\n if (!pendingFile || !onAddRadiograph) return;\n onAddRadiograph({\n fileName: pendingFile,\n date: date ? toLocalIsoDate(date) : undefined,\n note: note || undefined,\n });\n setPendingFile(null);\n setNote('');\n setDate(undefined);\n }, [pendingFile, date, note, onAddRadiograph]);\n\n // History filter controls — pinned in the PanelHeader's filters row (only\n // meaningful once a tooth is selected) so they stay put as the list scrolls.\n const historyFilters = toothId ? (\n <>\n <FormField\n label={t('radiographPanel.history.range', {\n defaultValue: 'Date range',\n })}\n >\n <DateRangePicker value={range} onChange={setRange} />\n </FormField>\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={() => setSortDesc((s) => !s)}>\n {sortDesc\n ? t('radiographPanel.history.sortNewest', {\n defaultValue: 'Newest first',\n })\n : t('radiographPanel.history.sortOldest', {\n defaultValue: 'Oldest first',\n })}\n </Button>\n <Button\n intent=\"ghost\"\n size=\"sm\"\n startIcon={<GitCompareArrows aria-hidden=\"true\" />}\n disabled={compareIds.length !== 2}\n onClick={() => {\n const films = radiographs.filter((f) => compareIds.includes(f.id));\n if (films.length === 2) {\n setViewer({ films, index: 0, compare: true });\n }\n }}\n >\n {t('radiographPanel.history.compare', {\n defaultValue: 'Compare',\n })}\n </Button>\n </div>\n </>\n ) : undefined;\n\n return (\n <section\n data-component=\"radiograph-panel\"\n data-component-id={id}\n data-tooth={toothId ?? undefined}\n aria-label={ariaLabel ?? heading}\n className={['ds:flex ds:flex-col', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {/* Shared rail-panel header: title + film-count badge, history filters\n pinned beneath, divider, sticky so it stays visible as the list\n scrolls. The rail injects favourite/close into the action cluster. */}\n <PanelHeader\n sticky\n icon={<Images aria-hidden=\"true\" />}\n title={\n <>\n {toothId ? toothLabel : heading}\n {toothId ? (\n <Badge variant=\"info\" size=\"sm\">\n {radiographs.length}\n </Badge>\n ) : null}\n </>\n }\n filters={historyFilters}\n />\n\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:p-[var(--spacing-md)]\">\n {!toothId ? (\n <EmptyState\n variant=\"first-use\"\n title={t('radiographPanel.noTooth.title', {\n defaultValue: 'No tooth selected',\n })}\n description={t('radiographPanel.noTooth.body', {\n defaultValue:\n 'Select a tooth on the chart to view its radiographs.',\n })}\n />\n ) : (\n <>\n {/* Upload */}\n {onAddRadiograph ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <FormField\n label={t('radiographPanel.upload.file', {\n defaultValue: 'Image file',\n })}\n >\n <FileUpload\n accept={{ 'image/*': ['.png', '.jpg', '.jpeg', '.webp'] }}\n variant=\"both\"\n showPreview\n onDrop={(accepted) =>\n setPendingFile(accepted[0]?.name ?? null)\n }\n />\n </FormField>\n <FormField\n label={t('radiographPanel.upload.date', {\n defaultValue: 'Acquisition date',\n })}\n >\n <DatePicker value={date} onChange={(d) => setDate(d)} />\n </FormField>\n <FormField\n label={t('radiographPanel.upload.note', {\n defaultValue: 'Note (optional)',\n })}\n >\n <TextArea\n rows={2}\n value={note}\n onChange={(e) => setNote(e.target.value)}\n placeholder={t('radiographPanel.upload.notePlaceholder', {\n defaultValue: 'E.g. routine check, apical lesion…',\n })}\n />\n </FormField>\n <Button\n intent=\"primary\"\n size=\"sm\"\n startIcon={<Upload aria-hidden=\"true\" />}\n disabled={!pendingFile}\n onClick={handleUpload}\n className=\"ds:self-start\"\n >\n {t('radiographPanel.upload.submit', {\n defaultValue: 'Upload',\n })}\n </Button>\n </div>\n ) : null}\n\n {/* History */}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {visible.length === 0 ? (\n <EmptyState\n variant=\"first-use\"\n title={t('radiographPanel.history.emptyTitle', {\n defaultValue: 'No radiographs yet',\n })}\n description={t('radiographPanel.history.emptyBody', {\n defaultValue: 'Upload the first film for this tooth.',\n })}\n />\n ) : (\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-xs)] ds:p-0\">\n {visible.map((film, visibleIndex) => {\n const selected = compareIds.includes(film.id);\n // Disambiguate the repeated row actions for screen readers by\n // the film's date (falls back to its 1-based position).\n const filmLabel = film.date ?? String(visibleIndex + 1);\n return (\n <li\n key={film.id}\n data-radiograph-id={film.id}\n data-selected={selected}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)] ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--card-border)] ds:bg-[var(--card)] ds:p-[var(--spacing-xs)] ds:data-[selected=true]:border-[color:var(--info-foreground)]\"\n >\n <img\n src={film.thumbnailUrl ?? film.url}\n alt={film.alt ?? ''}\n className=\"ds:h-16 ds:w-12 ds:shrink-0 ds:rounded-[var(--radius-sm)] ds:object-cover\"\n />\n <div className=\"ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-body-sm ds:text-[color:var(--foreground)]\">\n {film.date}\n </span>\n <KindBadge kind={film.kind ?? 'periapical'} />\n </div>\n <IconButton\n icon={<Eye aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.history.view', {\n defaultValue: 'View radiograph {{film}}',\n film: filmLabel,\n })}\n size=\"sm\"\n intent=\"ghost\"\n // Step the viewer through the FILTERED + sorted list the\n // user is looking at, not every film on the tooth.\n onClick={() =>\n setViewer({\n films: visible,\n index: visibleIndex,\n compare: false,\n })\n }\n />\n <IconButton\n icon={<GitCompareArrows aria-hidden=\"true\" />}\n aria-label={\n selected\n ? t('radiographPanel.history.compareRemove', {\n defaultValue:\n 'Remove {{film}} from comparison',\n film: filmLabel,\n })\n : t('radiographPanel.history.compareAdd', {\n defaultValue:\n 'Select {{film}} for comparison',\n film: filmLabel,\n })\n }\n aria-pressed={selected}\n size=\"sm\"\n intent={selected ? 'secondary' : 'ghost'}\n onClick={() => toggleCompare(film.id)}\n />\n {onDeleteRadiograph ? (\n <IconButton\n icon={<Trash2 aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.history.delete', {\n defaultValue: 'Delete radiograph {{film}}',\n film: filmLabel,\n })}\n size=\"sm\"\n intent=\"ghost\"\n onClick={() => onDeleteRadiograph(film.id)}\n />\n ) : null}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n </>\n )}\n </div>\n\n <RadiographViewer\n state={viewer}\n toothLabel={toothLabel}\n onClose={() => setViewer(null)}\n onIndexChange={(index) => setViewer((v) => (v ? { ...v, index } : v))}\n />\n </section>\n );\n});\n\n// `Images` is the panel's imaging glyph (a films archive, not a radiation\n// hazard) — re-exported so a host registering the Control Room tool can use\n// the same icon as the panel.\nexport { Images as RadiographPanelIcon };\n","import type { AgentAdapter } from '../../agent/types';\nimport type { RadiographPanelHandle } from './radiograph-panel';\nimport type { Radiograph } from '../tooth-scheme';\n\n/**\n * The Imaging panel for the Control Room rail. It DISPLAYS the selected tooth's\n * radiographs and drives the fullscreen viewer; uploads and deletes are the\n * host's responsibility (the `onAddRadiograph` / `onDeleteRadiograph` props),\n * so they are not exposed here — the consuming pattern/app owns those `write` /\n * `destructive` workflows and their `radiograph.*` API contracts.\n */\nexport const radiographPanelAgent: AgentAdapter<RadiographPanelHandle> = {\n id: 'radiograph-panel',\n // pick — open a specific film in the viewer; view_change — the viewer is a\n // view surface over the host-owned films.\n capabilities: ['pick', 'view_change'],\n state: {\n radiographs: {\n // A9: structural refs only (id + kind) — never the free-text `note`,\n // service dates, or consumer-hosted image URLs in the always-on snapshot.\n type: 'Array<{ id: string; kind?: string }>',\n descriptionKey: 'ui.agent.radiographPanel.state.radiographs',\n description:\n 'Structural references (id + kind) to the films shown for the selected tooth.',\n read: (handle) =>\n handle\n .getRadiographs()\n .map((film) => ({ id: film.id, kind: film.kind ?? 'periapical' })),\n },\n },\n actions: {\n view_radiograph: {\n safety: 'read',\n argsType: '{ id: string }',\n argsSchema: {\n type: 'object',\n properties: { id: { type: 'string' } },\n required: ['id'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.radiographPanel.actions.viewRadiograph',\n description: 'Open a film in the fullscreen viewer by id.',\n invoke: (handle, args: { id: string }) => {\n handle.openViewer(args.id);\n },\n },\n close_viewer: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.radiographPanel.actions.closeViewer',\n description: 'Close the fullscreen radiograph viewer.',\n invoke: (handle) => {\n handle.closeViewer();\n },\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'radiograph-panel' },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n item: {\n attr: 'data-radiograph-id',\n description:\n \"Each film row (`<li>`) carries its radiograph id as `data-radiograph-id`. The panel root additionally carries the selected tooth's FDI id as `data-tooth`.\",\n },\n },\n};\n\n// Re-exported for callers building typed reads against the adapter.\nexport type { Radiograph };\n"],"names":["__iconNode","GitCompareArrows","createLucideIcon","Images","ZOOM_CLASS","sortByDate","films","desc","a","b","inRange","film","range","d","toLocalIsoDate","pad","n","KindBadge","kind","t","useTranslation","label","Badge","RadiographViewer","state","toothLabel","onClose","onIndexChange","zoom","setZoom","useState","useEffect","current","jsx","Dialog","next","jsxs","IconButton","ChevronLeft","ChevronRight","ZoomOut","z","ZoomIn","RadiographPanel","forwardRef","id","toothId","toothLabelProp","radiographs","onAddRadiograph","onDeleteRadiograph","title","ariaLabel","className","rest","ref","viewer","setViewer","compareIds","setCompareIds","sortDesc","setSortDesc","setRange","pendingFile","setPendingFile","date","setDate","note","setNote","filmsRef","useRef","useImperativeHandle","filmId","index","f","heading","visible","useMemo","toggleCompare","useCallback","ids","x","handleUpload","historyFilters","Fragment","FormField","DateRangePicker","Button","s","PanelHeader","FileUpload","accepted","_a","DatePicker","TextArea","e","Upload","EmptyState","visibleIndex","selected","filmLabel","Eye","Trash2","v","radiographPanelAgent","handle","args"],"mappings":"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","x_google_ignoreList":[0,1]}
1
+ {"version":3,"file":"radiograph-panel.agent-k0G7JuoM.js","sources":["../../node_modules/lucide-react/dist/esm/icons/git-compare-arrows.mjs","../../node_modules/lucide-react/dist/esm/icons/images.mjs","../../src/components/radiograph-panel/radiograph-panel.tsx","../../src/components/radiograph-panel/radiograph-panel.agent.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 [\"circle\", { cx: \"5\", cy: \"6\", r: \"3\", key: \"1qnov2\" }],\n [\"path\", { d: \"M12 6h5a2 2 0 0 1 2 2v7\", key: \"1yj91y\" }],\n [\"path\", { d: \"m15 9-3-3 3-3\", key: \"1lwv8l\" }],\n [\"circle\", { cx: \"19\", cy: \"18\", r: \"3\", key: \"1qljk2\" }],\n [\"path\", { d: \"M12 18H7a2 2 0 0 1-2-2V9\", key: \"16sdep\" }],\n [\"path\", { d: \"m9 15 3 3-3 3\", key: \"1m3kbl\" }]\n];\nconst GitCompareArrows = createLucideIcon(\"git-compare-arrows\", __iconNode);\n\nexport { __iconNode, GitCompareArrows as default };\n//# sourceMappingURL=git-compare-arrows.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: \"m22 11-1.296-1.296a2.4 2.4 0 0 0-3.408 0L11 16\", key: \"9kzy35\" }],\n [\"path\", { d: \"M4 8a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2\", key: \"1t0f0t\" }],\n [\"circle\", { cx: \"13\", cy: \"7\", r: \"1\", fill: \"currentColor\", key: \"1obus6\" }],\n [\"rect\", { x: \"8\", y: \"2\", width: \"14\", height: \"14\", rx: \"2\", key: \"1gvhby\" }]\n];\nconst Images = createLucideIcon(\"images\", __iconNode);\n\nexport { __iconNode, Images as default };\n//# sourceMappingURL=images.mjs.map\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactElement,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Upload,\n ZoomIn,\n ZoomOut,\n ChevronLeft,\n ChevronRight,\n Trash2,\n Eye,\n GitCompareArrows,\n Images,\n} from 'lucide-react';\nimport type { FdiId, Radiograph, RadiographKind } from '../tooth-scheme';\nimport { Dialog } from '../dialog';\nimport { Button } from '../button';\nimport { IconButton } from '../icon-button';\nimport { Badge } from '../badge';\nimport { FormField } from '../form-field';\nimport { TextArea } from '../text-area';\nimport { FileUpload } from '../file-upload';\nimport { DatePicker } from '../date-picker';\nimport { DateRangePicker, type DateRangeValue } from '../date-range-picker';\nimport { EmptyState } from '../empty-state';\nimport { PanelHeader } from '../panel-header';\n\n/* ------------------------------------------------------------------ */\n/* RadiographPanel — the Imaging tool for the Control Room rail. */\n/* */\n/* Shows one tooth's radiographs (x-rays / endorali): an upload */\n/* composer, a sortable + date-filtered history, and a fullscreen */\n/* viewer that zooms / steps / compares films. Drops into a */\n/* `ControlRoomRail` tool `panel`, the patient profile, or a care-plan */\n/* editor — anywhere a selected tooth's imaging belongs. The host owns */\n/* the films (`radiographs`) and persistence (`onAddRadiograph` / */\n/* `onDeleteRadiograph`); the panel owns only view state. The chart */\n/* drives selection via `ToothScheme.onOpenRadiographs(toothId)`. */\n/* */\n/* Image urls are opaque / consumer-hosted — never bundled. Real */\n/* radiographs are PHI; stories use synthetic placeholders only. */\n/* ------------------------------------------------------------------ */\n\nconst ZOOM_CLASS = ['ds:scale-100', 'ds:scale-150', 'ds:scale-200'] as const;\n\n/** Sort films newest-first (or oldest-first); undated films sink to the end in\n * BOTH directions — mirrors `ToothScheme.sortByDateDesc`. */\nfunction sortByDate(films: Radiograph[], desc: boolean): Radiograph[] {\n return [...films].sort((a, b) => {\n if (a.date === b.date) return 0;\n if (!a.date) return 1;\n if (!b.date) return -1;\n return (a.date < b.date ? -1 : 1) * (desc ? -1 : 1);\n });\n}\n\n/** Date-range membership. ISO `YYYY-MM-DD` is parsed at LOCAL midnight (the\n * `+'T00:00:00'`) so the filter agrees with the local-midnight `Date` objects\n * the DateRangePicker emits — without it, films are off-by-one west of UTC. */\nfunction inRange(film: Radiograph, range: DateRangeValue): boolean {\n if (!film.date) return !range.from && !range.to;\n const d = new Date(`${film.date}T00:00:00`);\n if (range.from && d < range.from) return false;\n if (range.to && d > range.to) return false;\n return true;\n}\n\n/** Local `YYYY-MM-DD` — avoids the UTC shift `Date.toISOString()` introduces\n * west of UTC for the local-midnight Date the DatePicker emits. */\nfunction toLocalIsoDate(d: Date): string {\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n}\n\nexport interface RadiographPanelHandle {\n /** Read the films currently shown (after the host's `radiographs` prop). */\n getRadiographs: () => Radiograph[];\n /** Open the fullscreen viewer on a film by id. */\n openViewer: (id: string) => void;\n /** Close the fullscreen viewer. */\n closeViewer: () => void;\n}\n\nexport interface RadiographPanelProps extends Omit<\n HTMLAttributes<HTMLElement>,\n 'title' | 'children'\n> {\n /** Instance id — emitted as `data-component-id` for the agent registry. */\n id?: string;\n /** The tooth whose films are shown (FDI id). Null → a \"select a tooth\" prompt. */\n toothId?: FdiId | null;\n /** Display label for the selected tooth. Defaults to the localised \"Tooth {{id}}\". */\n toothLabel?: string;\n /** The selected tooth's films. The panel sorts + filters; order in is irrelevant. */\n radiographs?: Radiograph[];\n /** Commit a new film (the host persists it). Omit to hide the upload composer. */\n onAddRadiograph?: (draft: {\n fileName: string;\n date?: string;\n note?: string;\n }) => void;\n /** Remove a film by id. Omit to hide the delete affordance. */\n onDeleteRadiograph?: (id: string) => void;\n /** Panel heading. Defaults to the localised \"Imaging\". */\n title?: string;\n /** Accessible name for the panel region (defaults to `title`). */\n 'aria-label'?: string;\n}\n\nfunction KindBadge({ kind }: { kind: RadiographKind }): ReactElement {\n const { t } = useTranslation();\n const label = t(`radiographPanel.kind.${kind}`, {\n defaultValue: {\n periapical: 'Periapical',\n bitewing: 'Bitewing',\n panoramic: 'Panoramic',\n other: 'Other',\n }[kind],\n });\n return (\n <Badge variant=\"neutral\" size=\"sm\">\n {label}\n </Badge>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Fullscreen viewer — lightbox + compare */\n/* ------------------------------------------------------------------ */\n\ninterface ViewerState {\n films: Radiograph[];\n index: number;\n compare: boolean;\n}\n\nfunction RadiographViewer({\n state,\n toothLabel,\n onClose,\n onIndexChange,\n}: {\n state: ViewerState | null;\n toothLabel: string;\n onClose: () => void;\n onIndexChange: (index: number) => void;\n}): ReactElement {\n const { t } = useTranslation();\n const [zoom, setZoom] = useState(0);\n // Reset zoom when the viewed film changes (prev/next) or the mode flips, so a\n // user doesn't carry one film's zoom into the next.\n useEffect(() => {\n setZoom(0);\n }, [state?.index, state?.compare]);\n const films = state?.films ?? [];\n const current = state ? films[state.index] : undefined;\n\n return (\n <Dialog.Root\n open={state !== null}\n onOpenChange={(next) => {\n if (!next) {\n setZoom(0);\n onClose();\n }\n }}\n >\n <Dialog.Content size=\"fullscreen\" aria-describedby={undefined}>\n <Dialog.Header>\n <Dialog.Title>\n {state?.compare\n ? t('radiographPanel.viewer.compareTitle', {\n defaultValue: '{{tooth}} — comparison',\n tooth: toothLabel,\n })\n : t('radiographPanel.viewer.title', {\n defaultValue: '{{tooth}} — radiograph',\n tooth: toothLabel,\n })}\n </Dialog.Title>\n </Dialog.Header>\n <Dialog.Body>\n {state?.compare ? (\n <div className=\"ds:grid ds:grid-cols-2 ds:gap-[var(--spacing-md)]\">\n {films.slice(0, 2).map((film) => (\n <figure\n key={film.id}\n className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n <div className=\"ds:flex ds:items-center ds:justify-center ds:overflow-hidden ds:rounded-[var(--radius-md)] ds:bg-[var(--muted)] ds:p-[var(--spacing-xs)]\">\n <img\n src={film.thumbnailUrl ?? film.url}\n alt={film.alt ?? toothLabel}\n className=\"ds:max-h-full ds:max-w-full ds:object-contain\"\n />\n </div>\n <figcaption className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {film.date}\n </figcaption>\n </figure>\n ))}\n </div>\n ) : (\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:max-h-full ds:items-center ds:justify-center ds:overflow-hidden ds:rounded-[var(--radius-md)] ds:bg-[var(--muted)] ds:p-[var(--spacing-sm)]\">\n <img\n src={current?.thumbnailUrl ?? current?.url}\n alt={current?.alt ?? toothLabel}\n className={[\n 'ds:max-h-full ds:max-w-full ds:object-contain',\n 'ds:origin-center ds:transition-transform ds:motion-reduce:transition-none',\n ZOOM_CLASS[zoom],\n ].join(' ')}\n />\n </div>\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <IconButton\n icon={<ChevronLeft aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.viewer.prev', {\n defaultValue: 'Previous radiograph',\n })}\n size=\"sm\"\n flipIconInRtl\n disabled={!state || state.index === 0}\n onClick={() =>\n state && onIndexChange(Math.max(0, state.index - 1))\n }\n />\n <span\n aria-live=\"polite\"\n className=\"type-meta ds:text-[color:var(--muted-foreground)]\"\n >\n {t('radiographPanel.viewer.position', {\n defaultValue: '{{current}} / {{total}}',\n current: (state?.index ?? 0) + 1,\n total: films.length,\n })}\n </span>\n <IconButton\n icon={<ChevronRight aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.viewer.next', {\n defaultValue: 'Next radiograph',\n })}\n size=\"sm\"\n flipIconInRtl\n disabled={!state || state.index >= films.length - 1}\n onClick={() =>\n state &&\n onIndexChange(Math.min(films.length - 1, state.index + 1))\n }\n />\n <span\n aria-hidden=\"true\"\n className=\"ds:ms-[var(--spacing-xs)] ds:me-[var(--spacing-xs)] ds:h-[var(--spacing-md)] ds:w-px ds:bg-[var(--border)]\"\n />\n <IconButton\n icon={<ZoomOut aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.viewer.zoomOut', {\n defaultValue: 'Zoom out',\n })}\n size=\"sm\"\n disabled={zoom === 0}\n onClick={() => setZoom((z) => Math.max(0, z - 1))}\n />\n <IconButton\n icon={<ZoomIn aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.viewer.zoomIn', {\n defaultValue: 'Zoom in',\n })}\n size=\"sm\"\n disabled={zoom === ZOOM_CLASS.length - 1}\n onClick={() =>\n setZoom((z) => Math.min(ZOOM_CLASS.length - 1, z + 1))\n }\n />\n </div>\n {current?.note ? (\n <p className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {current.note}\n </p>\n ) : null}\n </div>\n )}\n </Dialog.Body>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* RadiographPanel */\n/* ------------------------------------------------------------------ */\n\nexport const RadiographPanel = forwardRef<\n RadiographPanelHandle,\n RadiographPanelProps\n>(function RadiographPanel(\n {\n id,\n toothId,\n toothLabel: toothLabelProp,\n radiographs = [],\n onAddRadiograph,\n onDeleteRadiograph,\n title,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n) {\n const { t } = useTranslation();\n\n const [viewer, setViewer] = useState<ViewerState | null>(null);\n const [compareIds, setCompareIds] = useState<string[]>([]);\n const [sortDesc, setSortDesc] = useState(true);\n const [range, setRange] = useState<DateRangeValue>({});\n const [pendingFile, setPendingFile] = useState<string | null>(null);\n const [date, setDate] = useState<Date | undefined>(undefined);\n const [note, setNote] = useState('');\n\n // Stable, current snapshot for the imperative handle.\n const filmsRef = useRef<Radiograph[]>(radiographs);\n filmsRef.current = radiographs;\n\n useImperativeHandle(\n ref,\n () => ({\n getRadiographs: () => filmsRef.current,\n openViewer: (filmId) => {\n const index = filmsRef.current.findIndex((f) => f.id === filmId);\n if (index >= 0) {\n setViewer({ films: filmsRef.current, index, compare: false });\n }\n },\n closeViewer: () => setViewer(null),\n }),\n [],\n );\n\n const heading =\n title ?? t('radiographPanel.title', { defaultValue: 'Imaging' });\n const toothLabel =\n toothLabelProp ??\n (toothId\n ? t('radiographPanel.toothLabel', {\n defaultValue: 'Tooth {{id}}',\n id: toothId,\n })\n : '');\n\n const visible = useMemo(\n () =>\n sortByDate(\n radiographs.filter((f) => inRange(f, range)),\n sortDesc,\n ),\n [radiographs, range, sortDesc],\n );\n\n const toggleCompare = useCallback((filmId: string) => {\n setCompareIds((ids) =>\n ids.includes(filmId)\n ? ids.filter((x) => x !== filmId)\n : [...ids, filmId].slice(-2),\n );\n }, []);\n\n const handleUpload = useCallback(() => {\n if (!pendingFile || !onAddRadiograph) return;\n onAddRadiograph({\n fileName: pendingFile,\n date: date ? toLocalIsoDate(date) : undefined,\n note: note || undefined,\n });\n setPendingFile(null);\n setNote('');\n setDate(undefined);\n }, [pendingFile, date, note, onAddRadiograph]);\n\n // History filter controls — pinned in the PanelHeader's filters row (only\n // meaningful once a tooth is selected) so they stay put as the list scrolls.\n const historyFilters = toothId ? (\n <>\n <FormField\n label={t('radiographPanel.history.range', {\n defaultValue: 'Date range',\n })}\n >\n <DateRangePicker value={range} onChange={setRange} />\n </FormField>\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={() => setSortDesc((s) => !s)}>\n {sortDesc\n ? t('radiographPanel.history.sortNewest', {\n defaultValue: 'Newest first',\n })\n : t('radiographPanel.history.sortOldest', {\n defaultValue: 'Oldest first',\n })}\n </Button>\n <Button\n intent=\"ghost\"\n size=\"sm\"\n startIcon={<GitCompareArrows aria-hidden=\"true\" />}\n disabled={compareIds.length !== 2}\n onClick={() => {\n const films = radiographs.filter((f) => compareIds.includes(f.id));\n if (films.length === 2) {\n setViewer({ films, index: 0, compare: true });\n }\n }}\n >\n {t('radiographPanel.history.compare', {\n defaultValue: 'Compare',\n })}\n </Button>\n </div>\n </>\n ) : undefined;\n\n return (\n <section\n data-component=\"radiograph-panel\"\n data-component-id={id}\n data-tooth={toothId ?? undefined}\n aria-label={ariaLabel ?? heading}\n className={['ds:flex ds:flex-col', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {/* Shared rail-panel header: title + film-count badge, history filters\n pinned beneath, divider, sticky so it stays visible as the list\n scrolls. The rail injects favourite/close into the action cluster. */}\n <PanelHeader\n sticky\n icon={<Images aria-hidden=\"true\" />}\n title={\n <>\n {toothId ? toothLabel : heading}\n {toothId ? (\n <Badge variant=\"info\" size=\"sm\">\n {radiographs.length}\n </Badge>\n ) : null}\n </>\n }\n filters={historyFilters}\n />\n\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:p-[var(--spacing-md)]\">\n {!toothId ? (\n <EmptyState\n variant=\"first-use\"\n title={t('radiographPanel.noTooth.title', {\n defaultValue: 'No tooth selected',\n })}\n description={t('radiographPanel.noTooth.body', {\n defaultValue:\n 'Select a tooth on the chart to view its radiographs.',\n })}\n />\n ) : (\n <>\n {/* Upload */}\n {onAddRadiograph ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <FormField\n label={t('radiographPanel.upload.file', {\n defaultValue: 'Image file',\n })}\n >\n <FileUpload\n accept={{ 'image/*': ['.png', '.jpg', '.jpeg', '.webp'] }}\n variant=\"both\"\n showPreview\n onDrop={(accepted) =>\n setPendingFile(accepted[0]?.name ?? null)\n }\n />\n </FormField>\n <FormField\n label={t('radiographPanel.upload.date', {\n defaultValue: 'Acquisition date',\n })}\n >\n <DatePicker value={date} onChange={(d) => setDate(d)} />\n </FormField>\n <FormField\n label={t('radiographPanel.upload.note', {\n defaultValue: 'Note (optional)',\n })}\n >\n <TextArea\n rows={2}\n value={note}\n onChange={(e) => setNote(e.target.value)}\n placeholder={t('radiographPanel.upload.notePlaceholder', {\n defaultValue: 'E.g. routine check, apical lesion…',\n })}\n />\n </FormField>\n <Button\n intent=\"primary\"\n size=\"sm\"\n startIcon={<Upload aria-hidden=\"true\" />}\n disabled={!pendingFile}\n onClick={handleUpload}\n className=\"ds:self-start\"\n >\n {t('radiographPanel.upload.submit', {\n defaultValue: 'Upload',\n })}\n </Button>\n </div>\n ) : null}\n\n {/* History */}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {visible.length === 0 ? (\n <EmptyState\n variant=\"first-use\"\n title={t('radiographPanel.history.emptyTitle', {\n defaultValue: 'No radiographs yet',\n })}\n description={t('radiographPanel.history.emptyBody', {\n defaultValue: 'Upload the first film for this tooth.',\n })}\n />\n ) : (\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-xs)] ds:p-0\">\n {visible.map((film, visibleIndex) => {\n const selected = compareIds.includes(film.id);\n // Disambiguate the repeated row actions for screen readers by\n // the film's date (falls back to its 1-based position).\n const filmLabel = film.date ?? String(visibleIndex + 1);\n return (\n <li\n key={film.id}\n data-radiograph-id={film.id}\n data-selected={selected}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)] ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--card-border)] ds:bg-[var(--card)] ds:p-[var(--spacing-xs)] ds:data-[selected=true]:border-[color:var(--info-foreground)]\"\n >\n <img\n src={film.thumbnailUrl ?? film.url}\n alt={film.alt ?? ''}\n className=\"ds:h-16 ds:w-12 ds:shrink-0 ds:rounded-[var(--radius-sm)] ds:object-cover\"\n />\n <div className=\"ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-body-sm ds:text-[color:var(--foreground)]\">\n {film.date}\n </span>\n <KindBadge kind={film.kind ?? 'periapical'} />\n </div>\n <IconButton\n icon={<Eye aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.history.view', {\n defaultValue: 'View radiograph {{film}}',\n film: filmLabel,\n })}\n size=\"sm\"\n intent=\"ghost\"\n // Step the viewer through the FILTERED + sorted list the\n // user is looking at, not every film on the tooth.\n onClick={() =>\n setViewer({\n films: visible,\n index: visibleIndex,\n compare: false,\n })\n }\n />\n <IconButton\n icon={<GitCompareArrows aria-hidden=\"true\" />}\n aria-label={\n selected\n ? t('radiographPanel.history.compareRemove', {\n defaultValue:\n 'Remove {{film}} from comparison',\n film: filmLabel,\n })\n : t('radiographPanel.history.compareAdd', {\n defaultValue:\n 'Select {{film}} for comparison',\n film: filmLabel,\n })\n }\n aria-pressed={selected}\n size=\"sm\"\n intent={selected ? 'secondary' : 'ghost'}\n onClick={() => toggleCompare(film.id)}\n />\n {onDeleteRadiograph ? (\n <IconButton\n icon={<Trash2 aria-hidden=\"true\" />}\n aria-label={t('radiographPanel.history.delete', {\n defaultValue: 'Delete radiograph {{film}}',\n film: filmLabel,\n })}\n size=\"sm\"\n intent=\"ghost\"\n onClick={() => onDeleteRadiograph(film.id)}\n />\n ) : null}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n </>\n )}\n </div>\n\n <RadiographViewer\n state={viewer}\n toothLabel={toothLabel}\n onClose={() => setViewer(null)}\n onIndexChange={(index) => setViewer((v) => (v ? { ...v, index } : v))}\n />\n </section>\n );\n});\n\n// `Images` is the panel's imaging glyph (a films archive, not a radiation\n// hazard) — re-exported so a host registering the Control Room tool can use\n// the same icon as the panel.\nexport { Images as RadiographPanelIcon };\n","import type { AgentAdapter } from '../../agent/types';\nimport type { RadiographPanelHandle } from './radiograph-panel';\nimport type { Radiograph } from '../tooth-scheme';\n\n/**\n * The Imaging panel for the Control Room rail. It DISPLAYS the selected tooth's\n * radiographs and drives the fullscreen viewer; uploads and deletes are the\n * host's responsibility (the `onAddRadiograph` / `onDeleteRadiograph` props),\n * so they are not exposed here — the consuming pattern/app owns those `write` /\n * `destructive` workflows and their `radiograph.*` API contracts.\n */\nexport const radiographPanelAgent: AgentAdapter<RadiographPanelHandle> = {\n id: 'radiograph-panel',\n // pick — open a specific film in the viewer; view_change — the viewer is a\n // view surface over the host-owned films.\n capabilities: ['pick', 'view_change'],\n state: {\n radiographs: {\n // A9: structural refs only (id + kind) — never the free-text `note`,\n // service dates, or consumer-hosted image URLs in the always-on snapshot.\n type: 'Array<{ id: string; kind?: string }>',\n descriptionKey: 'ui.agent.radiographPanel.state.radiographs',\n description:\n 'Structural references (id + kind) to the films shown for the selected tooth.',\n read: (handle) =>\n handle\n .getRadiographs()\n .map((film) => ({ id: film.id, kind: film.kind ?? 'periapical' })),\n },\n },\n actions: {\n view_radiograph: {\n safety: 'read',\n argsType: '{ id: string }',\n argsSchema: {\n type: 'object',\n properties: { id: { type: 'string' } },\n required: ['id'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.radiographPanel.actions.viewRadiograph',\n description: 'Open a film in the fullscreen viewer by id.',\n invoke: (handle, args: { id: string }) => {\n handle.openViewer(args.id);\n },\n },\n close_viewer: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.radiographPanel.actions.closeViewer',\n description: 'Close the fullscreen radiograph viewer.',\n invoke: (handle) => {\n handle.closeViewer();\n },\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'radiograph-panel' },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n item: {\n attr: 'data-radiograph-id',\n description:\n \"Each film row (`<li>`) carries its radiograph id as `data-radiograph-id`. The panel root additionally carries the selected tooth's FDI id as `data-tooth`.\",\n },\n },\n};\n\n// Re-exported for callers building typed reads against the adapter.\nexport type { Radiograph };\n"],"names":["__iconNode","GitCompareArrows","createLucideIcon","Images","ZOOM_CLASS","sortByDate","films","desc","a","b","inRange","film","range","d","toLocalIsoDate","pad","n","KindBadge","kind","t","useTranslation","label","Badge","RadiographViewer","state","toothLabel","onClose","onIndexChange","zoom","setZoom","useState","useEffect","current","jsx","Dialog","next","jsxs","IconButton","ChevronLeft","ChevronRight","ZoomOut","z","ZoomIn","RadiographPanel","forwardRef","id","toothId","toothLabelProp","radiographs","onAddRadiograph","onDeleteRadiograph","title","ariaLabel","className","rest","ref","viewer","setViewer","compareIds","setCompareIds","sortDesc","setSortDesc","setRange","pendingFile","setPendingFile","date","setDate","note","setNote","filmsRef","useRef","useImperativeHandle","filmId","index","f","heading","visible","useMemo","toggleCompare","useCallback","ids","x","handleUpload","historyFilters","Fragment","FormField","DateRangePicker","Button","s","PanelHeader","FileUpload","accepted","_a","DatePicker","TextArea","e","Upload","EmptyState","visibleIndex","selected","filmLabel","Eye","Trash2","v","radiographPanelAgent","handle","args"],"mappings":"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","x_google_ignoreList":[0,1]}
@@ -6,11 +6,11 @@ import { u as X } from "./registry-DvAUVLHh.js";
6
6
  import { R as k } from "./rating-BYbUowdK.js";
7
7
  import { C as A } from "./card-DPmk26CL.js";
8
8
  import { C as Y, b as Z, a as ee } from "./collapsible-CTjxzGuF.js";
9
- import { D as l } from "./description-list-CjJqR8WK.js";
9
+ import { D as l } from "./description-list-C1RXMDZ_.js";
10
10
  import { E as te } from "./empty-state-X0sVPfVo.js";
11
11
  import { S as T } from "./skeleton-CZbwyJAA.js";
12
12
  import { B as se } from "./button-nJaPh_HC.js";
13
- import { P as re } from "./panel-header-D313n_9-.js";
13
+ import { P as re } from "./panel-header-D_mTdhUp.js";
14
14
  import { S as ae } from "./star-Bf9L2Uot.js";
15
15
  import { C as ne } from "./chevron-down-DWE7GSq9.js";
16
16
  const ie = {
@@ -556,4 +556,4 @@ export {
556
556
  me as R,
557
557
  ie as r
558
558
  };
559
- //# sourceMappingURL=reviews-panel-BKHEfqVQ.js.map
559
+ //# sourceMappingURL=reviews-panel-BaHZb_ai.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reviews-panel-BKHEfqVQ.js","sources":["../../src/components/reviews-panel/reviews-panel.agent.ts","../../src/components/reviews-panel/reviews-panel.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — ReviewsPanel. */\n/* */\n/* Replaces the legacy patient-reviews Carousel with a single panel that */\n/* surfaces an aggregate score, a star-bucket filter, and a vertical list */\n/* of compact review cards. The adapter exposes the active filter and the */\n/* visible review count so a host agent can drive the panel and observe */\n/* what the user actually sees after the filter is applied. The reviews */\n/* themselves remain owned by the consumer — they never flow through the */\n/* adapter (PHI: pseudonyms + free-text comments stay on the page). */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { ReviewFilter, ReviewsPanelHandle } from './reviews-panel';\n\nexport const reviewsPanelAgent: AgentAdapter<ReviewsPanelHandle> = {\n id: 'reviews-panel',\n capabilities: ['filter'],\n state: {\n filter: {\n type: 'string',\n descriptionKey: 'ui.agent.reviewsPanel.state.filter',\n description:\n 'Active star-bucket filter — `\"all\"` or an integer 1..5. Reads the controlled `filter` prop.',\n read: (handle) => handle.getFilter(),\n },\n visibleCount: {\n type: 'number',\n descriptionKey: 'ui.agent.reviewsPanel.state.visibleCount',\n description:\n 'Number of reviews currently rendered after the filter is applied.',\n read: (handle) => handle.getVisibleCount(),\n },\n },\n actions: {\n set_filter: {\n // Pure ephemeral narrowing of the visible list — no data loss.\n safety: 'read',\n argsType: '{ filter: \"all\" | 1 | 2 | 3 | 4 | 5 }',\n argsSchema: {\n type: 'object',\n properties: {\n filter: {\n description: 'Star bucket to show, or \"all\" to clear the filter.',\n oneOf: [\n { type: 'string', enum: ['all'] },\n { type: 'integer', enum: [1, 2, 3, 4, 5] },\n ],\n },\n },\n required: ['filter'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.reviewsPanel.actions.setFilter',\n description:\n 'Narrow the visible review list to a star bucket, or `\"all\"` to clear the filter.',\n examples: [\n { args: { filter: 5 }, note: 'Show only 5-star reviews.' },\n { args: { filter: 'all' }, note: 'Clear the star filter.' },\n ],\n invoke: (handle, args: { filter: ReviewFilter }) => {\n handle.setFilter(args.filter);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'reviews-panel',\n description: 'Marks the ReviewsPanel root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { ChevronDown, Star } from 'lucide-react';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { reviewsPanelAgent } from './reviews-panel.agent';\nimport { Rating } from '../rating/rating';\nimport { Card } from '../card/card';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from '../collapsible/collapsible';\nimport { DescriptionList } from '../description-list/description-list';\nimport { EmptyState } from '../empty-state/empty-state';\nimport { Skeleton } from '../skeleton/skeleton';\nimport { Button } from '../button/button';\nimport { PanelHeader } from '../panel-header';\n\n/* -------------------------------------------------------------------- */\n/* ReviewsPanel */\n/* */\n/* Replaces the legacy patient-reviews Carousel with a two-column panel */\n/* — a star-bucket filter sidebar + a vertical list of compact review */\n/* cards — that surfaces the aggregate score, the volume, and (via a */\n/* per-card Collapsible) the rich per-axis breakdown alfaDocs already */\n/* collects but the carousel buried. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\nexport interface ReviewItem {\n id: string;\n /** When the review was authored (ISO 8601). */\n authoredAt: string;\n /** Anonymised author display (\"Marco T.\", \"Anna_M\"). Falls back to a localised \"Anonymous\". */\n pseudonym?: string;\n /** 0..max — drives the visible star summary on the compact card. */\n overallScore: number;\n /** Short free-text comment shown on the compact card. */\n comment?: string;\n /** Practice reply (revealed in the expanded panel only). */\n reply?: string;\n /** Optional per-axis breakdown — when present, the card grows an\n * \"Expand\" affordance that reveals these in a DescriptionList. */\n breakdown?: {\n appointmentScore?: number;\n communicationScore?: number;\n staffScore?: number;\n overallScore?: number;\n };\n /** Optional categorical follow-ups, surfaced inside the breakdown. */\n futureVisit?: 'yes' | 'no' | 'unsure';\n recommendation?: 'yes' | 'no' | 'unsure';\n}\n\nexport interface ReviewsAggregate {\n /** Total review count across all star buckets (may exceed the loaded set when paginated). */\n count: number;\n /** Average score across the full population (drives the header `Rating`). */\n averageScore: number;\n /**\n * Optional histogram — per-bucket count keyed by integer star value 1..5.\n * When omitted, the panel derives buckets from the loaded `reviews` array\n * (best-effort: paginated consumers SHOULD provide this explicitly).\n */\n histogram?: Record<1 | 2 | 3 | 4 | 5, number>;\n}\n\nexport type ReviewFilter = 'all' | 1 | 2 | 3 | 4 | 5;\n\nexport interface ReviewsPanelHandle {\n getFilter: () => ReviewFilter;\n setFilter: (next: ReviewFilter) => void;\n /** Total visible after filter is applied. */\n getVisibleCount: () => number;\n}\n\nexport interface ReviewsPanelProps extends Omit<\n ComponentPropsWithoutRef<'section'>,\n 'aria-label' | 'children'\n> {\n reviews: ReviewItem[];\n aggregate: ReviewsAggregate;\n\n /**\n * Active star filter. Controlled — consumer owns it for shareability via\n * URL query strings. Omit for uncontrolled (panel-managed) filtering.\n */\n filter?: ReviewFilter;\n onFilterChange?: (next: ReviewFilter) => void;\n\n /**\n * Optional intro callout shown above the list (e.g. \"Riepilogo delle\n * opinioni — i pazienti raccontano…\"). Render-prop slot so the consumer\n * can drop in `<Alert>` / `<Callout>` / plain `<p>`.\n */\n introSlot?: ReactNode;\n\n /** Optional header right-end action (e.g. a \"Leave a review\" button). */\n headerActionSlot?: ReactNode;\n\n /** Override the default region aria-label. */\n 'aria-label'?: string;\n\n /** Agent-readiness id. */\n id?: string;\n\n className?: string;\n\n /**\n * Hide the filter sidebar — useful when the panel mounts under ~640px\n * width or inside a narrow column. Defaults to false.\n */\n hideFilter?: boolean;\n\n /**\n * @default 'flat'\n * `'elevated'` wraps the panel in the equivalent of `Card variant=\"elevated\"`\n * — same tokens (`--card`, `--card-border`, `--shadow-card`,\n * `--radius-lg`), same padding. Use to drop the consumer-side\n * `<Card><Card.Body>` wrap.\n */\n surface?: 'flat' | 'elevated';\n\n /** Render skeletons for the header and the list. */\n loading?: boolean;\n}\n\n/* -------------------------------------------------------------------- */\n/* Constants & helpers */\n/* -------------------------------------------------------------------- */\n\nconst FILTER_VALUES: readonly ReviewFilter[] = ['all', 5, 4, 3, 2, 1] as const;\n\nfunction bucketOf(score: number): 1 | 2 | 3 | 4 | 5 {\n const n = Math.min(5, Math.max(1, Math.floor(score)));\n return n as 1 | 2 | 3 | 4 | 5;\n}\n\nfunction deriveHistogram(\n reviews: ReviewItem[],\n): Record<1 | 2 | 3 | 4 | 5, number> {\n const out: Record<1 | 2 | 3 | 4 | 5, number> = {\n 1: 0,\n 2: 0,\n 3: 0,\n 4: 0,\n 5: 0,\n };\n for (const r of reviews) out[bucketOf(r.overallScore)] += 1;\n return out;\n}\n\n/* -------------------------------------------------------------------- */\n/* FilterBar — hand-rolled radiogroup with roving tabindex */\n/* */\n/* Lives in the shared `PanelHeader` filters row, so it lays out */\n/* HORIZONTALLY (a wrapping bar of star-bucket chips) rather than the */\n/* legacy vertical sidebar column. Still the WAI-ARIA RadioGroup pattern */\n/* — each chip is a full click target with a non-text leading glyph (the */\n/* star ramp) and a trailing count. NOT Radix `RadioGroup` because we */\n/* need that glyph-plus-count chip shape. */\n/* */\n/* Activation is automatic — Arrow keys move BOTH focus and selection, */\n/* so a keyboard user feels the same responsiveness as a mouse user. */\n/* That's the right call here because filter activation is cheap (re- */\n/* renders the visible list); contrast with the booking ServiceGrid */\n/* where activation cascades through downstream selection state. */\n/* -------------------------------------------------------------------- */\n\nconst filterRowVariants = cva(\n [\n 'ds:relative ds:inline-flex ds:items-center ds:justify-center',\n 'ds:gap-[var(--spacing-xs)]',\n 'ds:min-h-[var(--min-target-size)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)]',\n 'ds:pt-[var(--spacing-2xs)] ds:pb-[var(--spacing-2xs)]',\n 'ds:text-start',\n 'ds:transition-[background-color,color]',\n 'ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n 'ds:cursor-pointer',\n ].join(' '),\n {\n variants: {\n state: {\n idle: 'ds:hover:bg-[var(--muted)]/30 ds:text-[var(--foreground)]',\n selected: [\n 'ds:bg-[var(--primary)]',\n 'ds:text-[var(--primary-foreground)]',\n 'ds:font-[var(--font-weight-semibold)]',\n ].join(' '),\n },\n },\n defaultVariants: { state: 'idle' },\n },\n);\n\ninterface FilterBarProps {\n filter: ReviewFilter;\n histogram: Record<1 | 2 | 3 | 4 | 5, number>;\n totalCount: number;\n onChange: (next: ReviewFilter) => void;\n}\n\nfunction FilterBar({\n filter,\n histogram,\n totalCount,\n onChange,\n}: FilterBarProps) {\n const { t } = useTranslation();\n const labelId = useId();\n\n // Roving tabindex tracks where keyboard focus is. We use AUTOMATIC\n // activation: arrow keys move focus AND fire onChange (see the rationale\n // above the component). To keep the visible aria-checked row and the\n // tab-stop aligned when the parent changes `filter` externally (e.g.\n // from a `?filter=4` URL parameter on page load), sync focusIndex to\n // the current filter via the effect below — without it, the tab stop\n // could land on `All` while the highlight shows `4`.\n const [focusIndex, setFocusIndex] = useState<number>(() =>\n Math.max(0, FILTER_VALUES.indexOf(filter)),\n );\n useEffect(() => {\n const i = FILTER_VALUES.indexOf(filter);\n if (i >= 0) setFocusIndex(i);\n }, [filter]);\n\n const rowRefs = useRef<Map<number, HTMLButtonElement>>(new Map());\n const focusAt = useCallback((index: number) => {\n rowRefs.current.get(index)?.focus();\n }, []);\n\n const total = FILTER_VALUES.length;\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLButtonElement>, index: number) => {\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowRight': {\n event.preventDefault();\n const next = (index + 1) % total;\n setFocusIndex(next);\n focusAt(next);\n onChange(FILTER_VALUES[next]);\n break;\n }\n case 'ArrowUp':\n case 'ArrowLeft': {\n event.preventDefault();\n const prev = (index - 1 + total) % total;\n setFocusIndex(prev);\n focusAt(prev);\n onChange(FILTER_VALUES[prev]);\n break;\n }\n case 'Home': {\n event.preventDefault();\n setFocusIndex(0);\n focusAt(0);\n onChange(FILTER_VALUES[0]);\n break;\n }\n case 'End': {\n event.preventDefault();\n const last = total - 1;\n setFocusIndex(last);\n focusAt(last);\n onChange(FILTER_VALUES[last]);\n break;\n }\n case 'Enter':\n case ' ': {\n event.preventDefault();\n onChange(FILTER_VALUES[index]);\n break;\n }\n default:\n break;\n }\n },\n [total, focusAt, onChange],\n );\n\n return (\n <>\n <h3\n id={labelId}\n className=\"type-label ds:font-[var(--font-weight-semibold)] ds:text-[var(--foreground)] ds:m-0\"\n >\n {t('reviewsPanel.filterTitle')}\n </h3>\n <div\n role=\"radiogroup\"\n aria-labelledby={labelId}\n className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-2xs)]\"\n >\n {FILTER_VALUES.map((val, index) => {\n const isAll = val === 'all';\n const stars = isAll ? 0 : (val as 1 | 2 | 3 | 4 | 5);\n const count = isAll\n ? totalCount\n : histogram[stars as 1 | 2 | 3 | 4 | 5];\n const isSelected = val === filter;\n const isFocused = focusIndex === index;\n const ariaLabel = isAll\n ? t('reviewsPanel.filter.allLabel', { count })\n : t('reviewsPanel.filter.starsLabel', { stars, count });\n\n return (\n <button\n key={String(val)}\n ref={(node) => {\n if (node) rowRefs.current.set(index, node);\n else rowRefs.current.delete(index);\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n aria-label={ariaLabel}\n tabIndex={isFocused ? 0 : -1}\n onClick={() => {\n setFocusIndex(index);\n onChange(val);\n }}\n onFocus={() => setFocusIndex(index)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n data-filter-bucket={String(val)}\n className={filterRowVariants({\n state: isSelected ? 'selected' : 'idle',\n })}\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {isAll ? (\n <span className=\"type-label\">\n {t('reviewsPanel.filter.allShort')}\n </span>\n ) : (\n <Rating value={stars} size=\"sm\" decorative />\n )}\n </span>\n <span\n aria-hidden=\"true\"\n className={[\n 'type-meta',\n // Idle row: count is dimmed (--muted-foreground over\n // --background ≈ 4.5:1, AA passes). Selected row\n // paints violet bg + white text on the BUTTON, but\n // the count's own explicit color override would\n // otherwise win the cascade and leave dark navy-grey\n // text on the violet pill (~3:1, AA-fail). Match the\n // row's foreground when selected; slight opacity\n // keeps the count secondary to the label.\n isSelected\n ? 'ds:text-[color:var(--primary-foreground)]'\n : 'ds:text-[var(--muted-foreground)]',\n ].join(' ')}\n >\n {count}\n </span>\n </button>\n );\n })}\n </div>\n </>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* ReviewCard — compact card with optional Collapsible breakdown */\n/* -------------------------------------------------------------------- */\n\ninterface ReviewCardProps {\n review: ReviewItem;\n locale: string;\n}\n\nfunction ReviewCard({ review, locale }: ReviewCardProps) {\n const { t } = useTranslation();\n const triggerId = useId();\n const contentId = useId();\n const [open, setOpen] = useState(false);\n\n const breakdownHasValues = Boolean(\n review.breakdown && Object.values(review.breakdown).some((v) => v != null),\n );\n const hasDetails =\n Boolean(review.reply) ||\n breakdownHasValues ||\n Boolean(review.futureVisit) ||\n Boolean(review.recommendation);\n\n const formattedDate = useMemo(() => {\n if (!review.authoredAt) return '';\n try {\n const parsed = new Date(review.authoredAt);\n if (Number.isNaN(parsed.getTime())) return review.authoredAt;\n return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(\n parsed,\n );\n } catch {\n return review.authoredAt;\n }\n }, [review.authoredAt, locale]);\n\n const pseudonym = review.pseudonym ?? t('reviewsPanel.anonymous');\n\n // Compose the full Card body. The Collapsible wraps the footer + the\n // hidden content so both share the same Radix Root and the Trigger's\n // `data-state` reaches the Content automatically (used for the height\n // animation). The Footer + Content are direct Card children so the\n // Card root's flex-col places them in order.\n const footerAndDetails = (\n <Collapsible\n open={hasDetails ? open : false}\n onOpenChange={hasDetails ? setOpen : undefined}\n >\n <Card.Footer>\n <span className=\"type-meta ds:text-[var(--muted-foreground)]\">\n {formattedDate}\n </span>\n {hasDetails ? (\n <CollapsibleTrigger asChild>\n <button\n id={triggerId}\n type=\"button\"\n data-review-trigger\n className=\"ds:ms-auto ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)] ds:rounded-[var(--radius-sm)] ds:ps-[var(--spacing-2xs)] ds:pe-[var(--spacing-2xs)] ds:pt-[var(--spacing-2xs)] ds:pb-[var(--spacing-2xs)] ds:bg-transparent ds:border-0 ds:text-[length:var(--font-size-sm)] ds:text-[var(--primary)] ds:hover:underline ds:cursor-pointer ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)] ds:forced-colors:focus-visible:outline-[CanvasText]\"\n >\n {open\n ? t('reviewsPanel.card.collapse')\n : t('reviewsPanel.card.expand')}\n <ChevronDown\n aria-hidden=\"true\"\n className={[\n 'ds:size-4 ds:transition-transform ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n open ? 'ds:rotate-180' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n />\n </button>\n </CollapsibleTrigger>\n ) : null}\n </Card.Footer>\n {hasDetails ? (\n <CollapsibleContent id={contentId} aria-labelledby={triggerId}>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pb-[var(--spacing-md)]\">\n {breakdownHasValues ||\n review.futureVisit ||\n review.recommendation ? (\n <DescriptionList layout=\"inline\" density=\"compact\">\n {review.breakdown?.appointmentScore != null ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.appointment')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n <Rating\n value={review.breakdown.appointmentScore}\n size=\"sm\"\n />\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.breakdown?.communicationScore != null ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.communication')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n <Rating\n value={review.breakdown.communicationScore}\n size=\"sm\"\n />\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.breakdown?.staffScore != null ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.staff')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n <Rating value={review.breakdown.staffScore} size=\"sm\" />\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.breakdown?.overallScore != null ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.overall')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n <Rating value={review.breakdown.overallScore} size=\"sm\" />\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.futureVisit ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.futureVisit')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n {t(`reviewsPanel.answer.${review.futureVisit}`)}\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.recommendation ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.recommendation')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n {t(`reviewsPanel.answer.${review.recommendation}`)}\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n </DescriptionList>\n ) : null}\n {review.reply ? (\n <div className=\"ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)]/40 ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:pt-[var(--spacing-sm)] ds:pb-[var(--spacing-sm)]\">\n <p className=\"type-label ds:m-0 ds:mb-[var(--spacing-2xs)] ds:text-[var(--muted-foreground)] ds:font-[var(--font-weight-semibold)]\">\n {t('reviewsPanel.replyTitle')}\n </p>\n <p className=\"type-body-sm ds:m-0 ds:text-[var(--foreground)] ds:[white-space:pre-line]\">\n {review.reply}\n </p>\n </div>\n ) : null}\n </div>\n </CollapsibleContent>\n ) : null}\n </Collapsible>\n );\n\n return (\n <Card variant=\"default\" className=\"ds:shadow-[var(--shadow-sm)]\">\n <Card.Header>\n <div className=\"ds:flex ds:items-start ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <h4 className=\"type-title-item ds:m-0 ds:text-[var(--foreground)]\">\n {pseudonym}\n </h4>\n <Rating value={review.overallScore} size=\"sm\" />\n </div>\n </Card.Header>\n {review.comment ? (\n <Card.Body>\n <p className=\"type-body ds:m-0 ds:text-[var(--foreground)] ds:line-clamp-2\">\n {review.comment}\n </p>\n </Card.Body>\n ) : null}\n {footerAndDetails}\n </Card>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* PanelSkeleton — loading state */\n/* -------------------------------------------------------------------- */\n\nfunction PanelSkeleton({ hideFilter }: { hideFilter: boolean }) {\n // The parent <section> already carries `aria-busy=\"true\"`, which is the\n // canonical SR signal for \"this region is loading\". Don't add `role=status`\n // + `aria-live=polite` here too — pairing both would double-announce on\n // mount. Skeleton itself is `aria-hidden`.\n return (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <Skeleton variant=\"text\" width=\"40%\" />\n <Skeleton variant=\"text\" width=\"20%\" />\n </div>\n {!hideFilter ? (\n <div className=\"ds:flex ds:flex-wrap ds:gap-[var(--spacing-xs)]\">\n {Array.from({ length: 6 }, (_, i) => (\n <Skeleton\n key={`rp-fs-${i}`}\n variant=\"rounded\"\n width=\"4rem\"\n height=\"2.5rem\"\n />\n ))}\n </div>\n ) : null}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {Array.from({ length: 3 }, (_, i) => (\n <Skeleton key={`rp-rs-${i}`} variant=\"rounded\" height=\"6rem\" />\n ))}\n </div>\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Root variants */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva(\n // No root padding: the shared `PanelHeader` owns the header's edge\n // padding (px/pt/pb) and the body wrapper below owns the content\n // padding, so the header divider can span flush to the panel edge.\n 'ds:flex ds:w-full ds:flex-col ds:text-[var(--foreground)]',\n {\n variants: {\n // `surface=\"elevated\"` matches `Card variant=\"elevated\"` — same\n // chrome tokens — so consumers can drop their own Card wraps\n // without producing a double-card look. Padding is supplied by the\n // header + body, not the root, so the header divider reaches the\n // card edge. Default `'flat'` adds no chrome.\n surface: {\n flat: '',\n elevated: [\n 'ds:overflow-hidden',\n 'ds:rounded-[var(--radius-lg)]',\n 'ds:bg-[var(--card)] ds:text-[var(--card-foreground)]',\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:shadow-[var(--shadow-card)]',\n ].join(' '),\n },\n },\n defaultVariants: { surface: 'flat' },\n },\n);\n\n/* -------------------------------------------------------------------- */\n/* ReviewsPanel */\n/* -------------------------------------------------------------------- */\n\nexport const ReviewsPanel = forwardRef<HTMLElement, ReviewsPanelProps>(\n (\n {\n reviews,\n aggregate,\n filter: filterProp,\n onFilterChange,\n introSlot,\n headerActionSlot,\n 'aria-label': ariaLabel,\n id,\n className,\n hideFilter = false,\n surface = 'flat',\n loading = false,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const locale = i18n.language ?? 'en';\n\n // Controlled / uncontrolled filter handling. When `filterProp` is\n // undefined the panel manages the filter internally — the consumer can\n // mount the panel and never wire `filter` / `onFilterChange` for the\n // common case where the URL doesn't carry the filter state. When the\n // prop IS provided, the consumer owns the truth.\n const [internalFilter, setInternalFilter] = useState<ReviewFilter>('all');\n const filter = filterProp ?? internalFilter;\n\n const handleFilterChange = useCallback(\n (next: ReviewFilter) => {\n if (filterProp === undefined) setInternalFilter(next);\n onFilterChange?.(next);\n },\n [filterProp, onFilterChange],\n );\n\n // Prefer the consumer-provided histogram; fall back to deriving from the\n // loaded reviews. Pagination consumers SHOULD pass an explicit histogram\n // so the per-bucket counts reflect server-side totals rather than only\n // what's loaded on this page.\n const histogram = useMemo(\n () => aggregate.histogram ?? deriveHistogram(reviews),\n [aggregate.histogram, reviews],\n );\n\n const visibleReviews = useMemo(() => {\n if (filter === 'all') return reviews;\n return reviews.filter((r) => bucketOf(r.overallScore) === filter);\n }, [reviews, filter]);\n\n /* Agent registration — exposes filter + visible count via refs so the\n imperative handle returns the latest values without re-creating the\n handle on every render. */\n const latestFilterRef = useRef(filter);\n latestFilterRef.current = filter;\n const latestVisibleCountRef = useRef(visibleReviews.length);\n latestVisibleCountRef.current = visibleReviews.length;\n\n const agentHandle = useMemo<ReviewsPanelHandle>(\n () => ({\n getFilter: () => latestFilterRef.current,\n setFilter: (next) => handleFilterChange(next),\n getVisibleCount: () => latestVisibleCountRef.current,\n }),\n [handleFilterChange],\n );\n\n const rootRef = useRef<HTMLElement>(null);\n useImperativeHandle(ref, () => rootRef.current as HTMLElement, []);\n useAgentRegistration(reviewsPanelAgent, agentHandle, id);\n\n const resolvedAriaLabel = ariaLabel ?? t('reviewsPanel.regionLabel');\n const dataFilter = String(filter);\n\n /* ---------------------------- Loading ---------------------------- */\n if (loading) {\n return (\n <section\n ref={rootRef as React.Ref<HTMLElement>}\n aria-label={resolvedAriaLabel}\n aria-busy=\"true\"\n id={id}\n data-component=\"reviews-panel\"\n data-component-id={id}\n data-filter={dataFilter}\n data-state=\"loading\"\n className={rootVariants({ surface, className })}\n {...rest}\n >\n <div className=\"ds:p-[var(--spacing-md)]\">\n <PanelSkeleton hideFilter={hideFilter} />\n </div>\n </section>\n );\n }\n\n /* ----------------------- Zero-total empty ------------------------ */\n // No header, no filter — just the EmptyState. The region landmark is\n // still emitted so an agent can locate the empty panel by its\n // data-component marker.\n if (aggregate.count === 0 && reviews.length === 0) {\n return (\n <section\n ref={rootRef as React.Ref<HTMLElement>}\n aria-label={resolvedAriaLabel}\n id={id}\n data-component=\"reviews-panel\"\n data-component-id={id}\n data-filter={dataFilter}\n data-state=\"empty\"\n className={rootVariants({ surface, className })}\n {...rest}\n >\n <div className=\"ds:p-[var(--spacing-md)]\">\n <EmptyState\n variant=\"no-results\"\n title={t('reviewsPanel.empty.title')}\n description={t('reviewsPanel.empty.description')}\n />\n </div>\n </section>\n );\n }\n\n const showFilter = !hideFilter;\n\n return (\n <section\n ref={rootRef as React.Ref<HTMLElement>}\n aria-label={resolvedAriaLabel}\n id={id}\n data-component=\"reviews-panel\"\n data-component-id={id}\n data-filter={dataFilter}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {/* Shared rail header — the panel root is a region landmark with an\n accessible name, so this nested <header> is a generic element\n (not a banner) and stays within the region. The rail injects the\n favourite / close actions via PanelHeaderActionsProvider; the\n panel's own aggregate Rating + headerActionSlot lead the cluster. */}\n <PanelHeader\n title={t('reviewsPanel.title')}\n icon={<Star aria-hidden=\"true\" />}\n titleScale=\"section\"\n sticky\n actions={\n <>\n {headerActionSlot}\n <Rating\n value={aggregate.averageScore}\n reviews={{ count: aggregate.count }}\n size=\"md\"\n />\n </>\n }\n filters={\n showFilter ? (\n <FilterBar\n filter={filter}\n histogram={histogram}\n totalCount={aggregate.count}\n onChange={handleFilterChange}\n />\n ) : undefined\n }\n />\n\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:min-w-0 ds:p-[var(--spacing-md)]\">\n {introSlot\n ? // Render the slot raw — the consumer's introSlot owns\n // its own visual chrome (Alert, Infotip, plain <p>, …).\n // 0.31.x wrapped the slot in a `bg-info/8` tinted box,\n // but when the consumer passed an Alert with its own\n // tinted surface the visual stack rendered TWO concentric\n // tinted boxes (\"double effect\"). The wrapper added no\n // semantic value either (no role, no aria), so dropping\n // it is purely visual.\n introSlot\n : null}\n\n {visibleReviews.length === 0 ? (\n // `role=\"status\"` already implies `aria-live=\"polite\"` —\n // declaring both would queue two announcements when the\n // filter changes (the radio's aria-checked flip + this\n // container's text). Keeping `role` only.\n <div\n role=\"status\"\n data-state=\"no-match\"\n className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)] ds:rounded-[var(--radius-md)] ds:border ds:border-dashed ds:border-[var(--border)] ds:p-[var(--spacing-lg)] ds:text-center\"\n >\n <p className=\"type-body ds:m-0 ds:text-[var(--muted-foreground)]\">\n {filter === 'all'\n ? t('reviewsPanel.empty.title')\n : t('reviewsPanel.empty.filterDescription', {\n stars: filter,\n })}\n </p>\n {filter !== 'all' ? (\n <Button\n intent=\"secondary\"\n size=\"sm\"\n onClick={() => handleFilterChange('all')}\n >\n {t('reviewsPanel.empty.resetFilter')}\n </Button>\n ) : null}\n </div>\n ) : (\n <ol\n aria-label={t('reviewsPanel.listLabel')}\n className=\"ds:list-none ds:m-0 ds:p-0 ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n {visibleReviews.map((review) => (\n <li key={review.id} data-review-id={review.id}>\n <ReviewCard review={review} locale={locale} />\n </li>\n ))}\n </ol>\n )}\n </div>\n </section>\n );\n },\n);\n\nReviewsPanel.displayName = 'ReviewsPanel';\n"],"names":["reviewsPanelAgent","handle","args","FILTER_VALUES","bucketOf","score","deriveHistogram","reviews","out","r","filterRowVariants","cva","FilterBar","filter","histogram","totalCount","onChange","t","useTranslation","labelId","useId","focusIndex","setFocusIndex","useState","useEffect","i","rowRefs","useRef","focusAt","useCallback","index","_a","total","handleKeyDown","event","next","prev","last","jsxs","Fragment","jsx","val","isAll","stars","count","isSelected","isFocused","ariaLabel","node","e","Rating","ReviewCard","review","locale","triggerId","contentId","open","setOpen","breakdownHasValues","hasDetails","formattedDate","useMemo","parsed","pseudonym","footerAndDetails","Collapsible","Card","CollapsibleTrigger","ChevronDown","CollapsibleContent","DescriptionList","_b","_c","_d","PanelSkeleton","hideFilter","Skeleton","_","rootVariants","ReviewsPanel","forwardRef","aggregate","filterProp","onFilterChange","introSlot","headerActionSlot","id","className","surface","loading","rest","ref","i18n","internalFilter","setInternalFilter","handleFilterChange","visibleReviews","latestFilterRef","latestVisibleCountRef","agentHandle","rootRef","useImperativeHandle","useAgentRegistration","resolvedAriaLabel","dataFilter","EmptyState","showFilter","PanelHeader","Star","Button"],"mappings":"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"}
1
+ {"version":3,"file":"reviews-panel-BaHZb_ai.js","sources":["../../src/components/reviews-panel/reviews-panel.agent.ts","../../src/components/reviews-panel/reviews-panel.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — ReviewsPanel. */\n/* */\n/* Replaces the legacy patient-reviews Carousel with a single panel that */\n/* surfaces an aggregate score, a star-bucket filter, and a vertical list */\n/* of compact review cards. The adapter exposes the active filter and the */\n/* visible review count so a host agent can drive the panel and observe */\n/* what the user actually sees after the filter is applied. The reviews */\n/* themselves remain owned by the consumer — they never flow through the */\n/* adapter (PHI: pseudonyms + free-text comments stay on the page). */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { ReviewFilter, ReviewsPanelHandle } from './reviews-panel';\n\nexport const reviewsPanelAgent: AgentAdapter<ReviewsPanelHandle> = {\n id: 'reviews-panel',\n capabilities: ['filter'],\n state: {\n filter: {\n type: 'string',\n descriptionKey: 'ui.agent.reviewsPanel.state.filter',\n description:\n 'Active star-bucket filter — `\"all\"` or an integer 1..5. Reads the controlled `filter` prop.',\n read: (handle) => handle.getFilter(),\n },\n visibleCount: {\n type: 'number',\n descriptionKey: 'ui.agent.reviewsPanel.state.visibleCount',\n description:\n 'Number of reviews currently rendered after the filter is applied.',\n read: (handle) => handle.getVisibleCount(),\n },\n },\n actions: {\n set_filter: {\n // Pure ephemeral narrowing of the visible list — no data loss.\n safety: 'read',\n argsType: '{ filter: \"all\" | 1 | 2 | 3 | 4 | 5 }',\n argsSchema: {\n type: 'object',\n properties: {\n filter: {\n description: 'Star bucket to show, or \"all\" to clear the filter.',\n oneOf: [\n { type: 'string', enum: ['all'] },\n { type: 'integer', enum: [1, 2, 3, 4, 5] },\n ],\n },\n },\n required: ['filter'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.reviewsPanel.actions.setFilter',\n description:\n 'Narrow the visible review list to a star bucket, or `\"all\"` to clear the filter.',\n examples: [\n { args: { filter: 5 }, note: 'Show only 5-star reviews.' },\n { args: { filter: 'all' }, note: 'Clear the star filter.' },\n ],\n invoke: (handle, args: { filter: ReviewFilter }) => {\n handle.setFilter(args.filter);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'reviews-panel',\n description: 'Marks the ReviewsPanel root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { ChevronDown, Star } from 'lucide-react';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { reviewsPanelAgent } from './reviews-panel.agent';\nimport { Rating } from '../rating/rating';\nimport { Card } from '../card/card';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from '../collapsible/collapsible';\nimport { DescriptionList } from '../description-list/description-list';\nimport { EmptyState } from '../empty-state/empty-state';\nimport { Skeleton } from '../skeleton/skeleton';\nimport { Button } from '../button/button';\nimport { PanelHeader } from '../panel-header';\n\n/* -------------------------------------------------------------------- */\n/* ReviewsPanel */\n/* */\n/* Replaces the legacy patient-reviews Carousel with a two-column panel */\n/* — a star-bucket filter sidebar + a vertical list of compact review */\n/* cards — that surfaces the aggregate score, the volume, and (via a */\n/* per-card Collapsible) the rich per-axis breakdown alfaDocs already */\n/* collects but the carousel buried. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\nexport interface ReviewItem {\n id: string;\n /** When the review was authored (ISO 8601). */\n authoredAt: string;\n /** Anonymised author display (\"Marco T.\", \"Anna_M\"). Falls back to a localised \"Anonymous\". */\n pseudonym?: string;\n /** 0..max — drives the visible star summary on the compact card. */\n overallScore: number;\n /** Short free-text comment shown on the compact card. */\n comment?: string;\n /** Practice reply (revealed in the expanded panel only). */\n reply?: string;\n /** Optional per-axis breakdown — when present, the card grows an\n * \"Expand\" affordance that reveals these in a DescriptionList. */\n breakdown?: {\n appointmentScore?: number;\n communicationScore?: number;\n staffScore?: number;\n overallScore?: number;\n };\n /** Optional categorical follow-ups, surfaced inside the breakdown. */\n futureVisit?: 'yes' | 'no' | 'unsure';\n recommendation?: 'yes' | 'no' | 'unsure';\n}\n\nexport interface ReviewsAggregate {\n /** Total review count across all star buckets (may exceed the loaded set when paginated). */\n count: number;\n /** Average score across the full population (drives the header `Rating`). */\n averageScore: number;\n /**\n * Optional histogram — per-bucket count keyed by integer star value 1..5.\n * When omitted, the panel derives buckets from the loaded `reviews` array\n * (best-effort: paginated consumers SHOULD provide this explicitly).\n */\n histogram?: Record<1 | 2 | 3 | 4 | 5, number>;\n}\n\nexport type ReviewFilter = 'all' | 1 | 2 | 3 | 4 | 5;\n\nexport interface ReviewsPanelHandle {\n getFilter: () => ReviewFilter;\n setFilter: (next: ReviewFilter) => void;\n /** Total visible after filter is applied. */\n getVisibleCount: () => number;\n}\n\nexport interface ReviewsPanelProps extends Omit<\n ComponentPropsWithoutRef<'section'>,\n 'aria-label' | 'children'\n> {\n reviews: ReviewItem[];\n aggregate: ReviewsAggregate;\n\n /**\n * Active star filter. Controlled — consumer owns it for shareability via\n * URL query strings. Omit for uncontrolled (panel-managed) filtering.\n */\n filter?: ReviewFilter;\n onFilterChange?: (next: ReviewFilter) => void;\n\n /**\n * Optional intro callout shown above the list (e.g. \"Riepilogo delle\n * opinioni — i pazienti raccontano…\"). Render-prop slot so the consumer\n * can drop in `<Alert>` / `<Callout>` / plain `<p>`.\n */\n introSlot?: ReactNode;\n\n /** Optional header right-end action (e.g. a \"Leave a review\" button). */\n headerActionSlot?: ReactNode;\n\n /** Override the default region aria-label. */\n 'aria-label'?: string;\n\n /** Agent-readiness id. */\n id?: string;\n\n className?: string;\n\n /**\n * Hide the filter sidebar — useful when the panel mounts under ~640px\n * width or inside a narrow column. Defaults to false.\n */\n hideFilter?: boolean;\n\n /**\n * @default 'flat'\n * `'elevated'` wraps the panel in the equivalent of `Card variant=\"elevated\"`\n * — same tokens (`--card`, `--card-border`, `--shadow-card`,\n * `--radius-lg`), same padding. Use to drop the consumer-side\n * `<Card><Card.Body>` wrap.\n */\n surface?: 'flat' | 'elevated';\n\n /** Render skeletons for the header and the list. */\n loading?: boolean;\n}\n\n/* -------------------------------------------------------------------- */\n/* Constants & helpers */\n/* -------------------------------------------------------------------- */\n\nconst FILTER_VALUES: readonly ReviewFilter[] = ['all', 5, 4, 3, 2, 1] as const;\n\nfunction bucketOf(score: number): 1 | 2 | 3 | 4 | 5 {\n const n = Math.min(5, Math.max(1, Math.floor(score)));\n return n as 1 | 2 | 3 | 4 | 5;\n}\n\nfunction deriveHistogram(\n reviews: ReviewItem[],\n): Record<1 | 2 | 3 | 4 | 5, number> {\n const out: Record<1 | 2 | 3 | 4 | 5, number> = {\n 1: 0,\n 2: 0,\n 3: 0,\n 4: 0,\n 5: 0,\n };\n for (const r of reviews) out[bucketOf(r.overallScore)] += 1;\n return out;\n}\n\n/* -------------------------------------------------------------------- */\n/* FilterBar — hand-rolled radiogroup with roving tabindex */\n/* */\n/* Lives in the shared `PanelHeader` filters row, so it lays out */\n/* HORIZONTALLY (a wrapping bar of star-bucket chips) rather than the */\n/* legacy vertical sidebar column. Still the WAI-ARIA RadioGroup pattern */\n/* — each chip is a full click target with a non-text leading glyph (the */\n/* star ramp) and a trailing count. NOT Radix `RadioGroup` because we */\n/* need that glyph-plus-count chip shape. */\n/* */\n/* Activation is automatic — Arrow keys move BOTH focus and selection, */\n/* so a keyboard user feels the same responsiveness as a mouse user. */\n/* That's the right call here because filter activation is cheap (re- */\n/* renders the visible list); contrast with the booking ServiceGrid */\n/* where activation cascades through downstream selection state. */\n/* -------------------------------------------------------------------- */\n\nconst filterRowVariants = cva(\n [\n 'ds:relative ds:inline-flex ds:items-center ds:justify-center',\n 'ds:gap-[var(--spacing-xs)]',\n 'ds:min-h-[var(--min-target-size)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)]',\n 'ds:pt-[var(--spacing-2xs)] ds:pb-[var(--spacing-2xs)]',\n 'ds:text-start',\n 'ds:transition-[background-color,color]',\n 'ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n 'ds:cursor-pointer',\n ].join(' '),\n {\n variants: {\n state: {\n idle: 'ds:hover:bg-[var(--muted)]/30 ds:text-[var(--foreground)]',\n selected: [\n 'ds:bg-[var(--primary)]',\n 'ds:text-[var(--primary-foreground)]',\n 'ds:font-[var(--font-weight-semibold)]',\n ].join(' '),\n },\n },\n defaultVariants: { state: 'idle' },\n },\n);\n\ninterface FilterBarProps {\n filter: ReviewFilter;\n histogram: Record<1 | 2 | 3 | 4 | 5, number>;\n totalCount: number;\n onChange: (next: ReviewFilter) => void;\n}\n\nfunction FilterBar({\n filter,\n histogram,\n totalCount,\n onChange,\n}: FilterBarProps) {\n const { t } = useTranslation();\n const labelId = useId();\n\n // Roving tabindex tracks where keyboard focus is. We use AUTOMATIC\n // activation: arrow keys move focus AND fire onChange (see the rationale\n // above the component). To keep the visible aria-checked row and the\n // tab-stop aligned when the parent changes `filter` externally (e.g.\n // from a `?filter=4` URL parameter on page load), sync focusIndex to\n // the current filter via the effect below — without it, the tab stop\n // could land on `All` while the highlight shows `4`.\n const [focusIndex, setFocusIndex] = useState<number>(() =>\n Math.max(0, FILTER_VALUES.indexOf(filter)),\n );\n useEffect(() => {\n const i = FILTER_VALUES.indexOf(filter);\n if (i >= 0) setFocusIndex(i);\n }, [filter]);\n\n const rowRefs = useRef<Map<number, HTMLButtonElement>>(new Map());\n const focusAt = useCallback((index: number) => {\n rowRefs.current.get(index)?.focus();\n }, []);\n\n const total = FILTER_VALUES.length;\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLButtonElement>, index: number) => {\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowRight': {\n event.preventDefault();\n const next = (index + 1) % total;\n setFocusIndex(next);\n focusAt(next);\n onChange(FILTER_VALUES[next]);\n break;\n }\n case 'ArrowUp':\n case 'ArrowLeft': {\n event.preventDefault();\n const prev = (index - 1 + total) % total;\n setFocusIndex(prev);\n focusAt(prev);\n onChange(FILTER_VALUES[prev]);\n break;\n }\n case 'Home': {\n event.preventDefault();\n setFocusIndex(0);\n focusAt(0);\n onChange(FILTER_VALUES[0]);\n break;\n }\n case 'End': {\n event.preventDefault();\n const last = total - 1;\n setFocusIndex(last);\n focusAt(last);\n onChange(FILTER_VALUES[last]);\n break;\n }\n case 'Enter':\n case ' ': {\n event.preventDefault();\n onChange(FILTER_VALUES[index]);\n break;\n }\n default:\n break;\n }\n },\n [total, focusAt, onChange],\n );\n\n return (\n <>\n <h3\n id={labelId}\n className=\"type-label ds:font-[var(--font-weight-semibold)] ds:text-[var(--foreground)] ds:m-0\"\n >\n {t('reviewsPanel.filterTitle')}\n </h3>\n <div\n role=\"radiogroup\"\n aria-labelledby={labelId}\n className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-2xs)]\"\n >\n {FILTER_VALUES.map((val, index) => {\n const isAll = val === 'all';\n const stars = isAll ? 0 : (val as 1 | 2 | 3 | 4 | 5);\n const count = isAll\n ? totalCount\n : histogram[stars as 1 | 2 | 3 | 4 | 5];\n const isSelected = val === filter;\n const isFocused = focusIndex === index;\n const ariaLabel = isAll\n ? t('reviewsPanel.filter.allLabel', { count })\n : t('reviewsPanel.filter.starsLabel', { stars, count });\n\n return (\n <button\n key={String(val)}\n ref={(node) => {\n if (node) rowRefs.current.set(index, node);\n else rowRefs.current.delete(index);\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n aria-label={ariaLabel}\n tabIndex={isFocused ? 0 : -1}\n onClick={() => {\n setFocusIndex(index);\n onChange(val);\n }}\n onFocus={() => setFocusIndex(index)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n data-filter-bucket={String(val)}\n className={filterRowVariants({\n state: isSelected ? 'selected' : 'idle',\n })}\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {isAll ? (\n <span className=\"type-label\">\n {t('reviewsPanel.filter.allShort')}\n </span>\n ) : (\n <Rating value={stars} size=\"sm\" decorative />\n )}\n </span>\n <span\n aria-hidden=\"true\"\n className={[\n 'type-meta',\n // Idle row: count is dimmed (--muted-foreground over\n // --background ≈ 4.5:1, AA passes). Selected row\n // paints violet bg + white text on the BUTTON, but\n // the count's own explicit color override would\n // otherwise win the cascade and leave dark navy-grey\n // text on the violet pill (~3:1, AA-fail). Match the\n // row's foreground when selected; slight opacity\n // keeps the count secondary to the label.\n isSelected\n ? 'ds:text-[color:var(--primary-foreground)]'\n : 'ds:text-[var(--muted-foreground)]',\n ].join(' ')}\n >\n {count}\n </span>\n </button>\n );\n })}\n </div>\n </>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* ReviewCard — compact card with optional Collapsible breakdown */\n/* -------------------------------------------------------------------- */\n\ninterface ReviewCardProps {\n review: ReviewItem;\n locale: string;\n}\n\nfunction ReviewCard({ review, locale }: ReviewCardProps) {\n const { t } = useTranslation();\n const triggerId = useId();\n const contentId = useId();\n const [open, setOpen] = useState(false);\n\n const breakdownHasValues = Boolean(\n review.breakdown && Object.values(review.breakdown).some((v) => v != null),\n );\n const hasDetails =\n Boolean(review.reply) ||\n breakdownHasValues ||\n Boolean(review.futureVisit) ||\n Boolean(review.recommendation);\n\n const formattedDate = useMemo(() => {\n if (!review.authoredAt) return '';\n try {\n const parsed = new Date(review.authoredAt);\n if (Number.isNaN(parsed.getTime())) return review.authoredAt;\n return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(\n parsed,\n );\n } catch {\n return review.authoredAt;\n }\n }, [review.authoredAt, locale]);\n\n const pseudonym = review.pseudonym ?? t('reviewsPanel.anonymous');\n\n // Compose the full Card body. The Collapsible wraps the footer + the\n // hidden content so both share the same Radix Root and the Trigger's\n // `data-state` reaches the Content automatically (used for the height\n // animation). The Footer + Content are direct Card children so the\n // Card root's flex-col places them in order.\n const footerAndDetails = (\n <Collapsible\n open={hasDetails ? open : false}\n onOpenChange={hasDetails ? setOpen : undefined}\n >\n <Card.Footer>\n <span className=\"type-meta ds:text-[var(--muted-foreground)]\">\n {formattedDate}\n </span>\n {hasDetails ? (\n <CollapsibleTrigger asChild>\n <button\n id={triggerId}\n type=\"button\"\n data-review-trigger\n className=\"ds:ms-auto ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)] ds:rounded-[var(--radius-sm)] ds:ps-[var(--spacing-2xs)] ds:pe-[var(--spacing-2xs)] ds:pt-[var(--spacing-2xs)] ds:pb-[var(--spacing-2xs)] ds:bg-transparent ds:border-0 ds:text-[length:var(--font-size-sm)] ds:text-[var(--primary)] ds:hover:underline ds:cursor-pointer ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)] ds:forced-colors:focus-visible:outline-[CanvasText]\"\n >\n {open\n ? t('reviewsPanel.card.collapse')\n : t('reviewsPanel.card.expand')}\n <ChevronDown\n aria-hidden=\"true\"\n className={[\n 'ds:size-4 ds:transition-transform ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n open ? 'ds:rotate-180' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n />\n </button>\n </CollapsibleTrigger>\n ) : null}\n </Card.Footer>\n {hasDetails ? (\n <CollapsibleContent id={contentId} aria-labelledby={triggerId}>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pb-[var(--spacing-md)]\">\n {breakdownHasValues ||\n review.futureVisit ||\n review.recommendation ? (\n <DescriptionList layout=\"inline\" density=\"compact\">\n {review.breakdown?.appointmentScore != null ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.appointment')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n <Rating\n value={review.breakdown.appointmentScore}\n size=\"sm\"\n />\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.breakdown?.communicationScore != null ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.communication')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n <Rating\n value={review.breakdown.communicationScore}\n size=\"sm\"\n />\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.breakdown?.staffScore != null ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.staff')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n <Rating value={review.breakdown.staffScore} size=\"sm\" />\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.breakdown?.overallScore != null ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.overall')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n <Rating value={review.breakdown.overallScore} size=\"sm\" />\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.futureVisit ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.futureVisit')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n {t(`reviewsPanel.answer.${review.futureVisit}`)}\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n {review.recommendation ? (\n <DescriptionList.Row>\n <DescriptionList.Term>\n {t('reviewsPanel.breakdown.recommendation')}\n </DescriptionList.Term>\n <DescriptionList.Detail>\n {t(`reviewsPanel.answer.${review.recommendation}`)}\n </DescriptionList.Detail>\n </DescriptionList.Row>\n ) : null}\n </DescriptionList>\n ) : null}\n {review.reply ? (\n <div className=\"ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)]/40 ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:pt-[var(--spacing-sm)] ds:pb-[var(--spacing-sm)]\">\n <p className=\"type-label ds:m-0 ds:mb-[var(--spacing-2xs)] ds:text-[var(--muted-foreground)] ds:font-[var(--font-weight-semibold)]\">\n {t('reviewsPanel.replyTitle')}\n </p>\n <p className=\"type-body-sm ds:m-0 ds:text-[var(--foreground)] ds:[white-space:pre-line]\">\n {review.reply}\n </p>\n </div>\n ) : null}\n </div>\n </CollapsibleContent>\n ) : null}\n </Collapsible>\n );\n\n return (\n <Card variant=\"default\" className=\"ds:shadow-[var(--shadow-sm)]\">\n <Card.Header>\n <div className=\"ds:flex ds:items-start ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <h4 className=\"type-title-item ds:m-0 ds:text-[var(--foreground)]\">\n {pseudonym}\n </h4>\n <Rating value={review.overallScore} size=\"sm\" />\n </div>\n </Card.Header>\n {review.comment ? (\n <Card.Body>\n <p className=\"type-body ds:m-0 ds:text-[var(--foreground)] ds:line-clamp-2\">\n {review.comment}\n </p>\n </Card.Body>\n ) : null}\n {footerAndDetails}\n </Card>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* PanelSkeleton — loading state */\n/* -------------------------------------------------------------------- */\n\nfunction PanelSkeleton({ hideFilter }: { hideFilter: boolean }) {\n // The parent <section> already carries `aria-busy=\"true\"`, which is the\n // canonical SR signal for \"this region is loading\". Don't add `role=status`\n // + `aria-live=polite` here too — pairing both would double-announce on\n // mount. Skeleton itself is `aria-hidden`.\n return (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <Skeleton variant=\"text\" width=\"40%\" />\n <Skeleton variant=\"text\" width=\"20%\" />\n </div>\n {!hideFilter ? (\n <div className=\"ds:flex ds:flex-wrap ds:gap-[var(--spacing-xs)]\">\n {Array.from({ length: 6 }, (_, i) => (\n <Skeleton\n key={`rp-fs-${i}`}\n variant=\"rounded\"\n width=\"4rem\"\n height=\"2.5rem\"\n />\n ))}\n </div>\n ) : null}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {Array.from({ length: 3 }, (_, i) => (\n <Skeleton key={`rp-rs-${i}`} variant=\"rounded\" height=\"6rem\" />\n ))}\n </div>\n </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Root variants */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva(\n // No root padding: the shared `PanelHeader` owns the header's edge\n // padding (px/pt/pb) and the body wrapper below owns the content\n // padding, so the header divider can span flush to the panel edge.\n 'ds:flex ds:w-full ds:flex-col ds:text-[var(--foreground)]',\n {\n variants: {\n // `surface=\"elevated\"` matches `Card variant=\"elevated\"` — same\n // chrome tokens — so consumers can drop their own Card wraps\n // without producing a double-card look. Padding is supplied by the\n // header + body, not the root, so the header divider reaches the\n // card edge. Default `'flat'` adds no chrome.\n surface: {\n flat: '',\n elevated: [\n 'ds:overflow-hidden',\n 'ds:rounded-[var(--radius-lg)]',\n 'ds:bg-[var(--card)] ds:text-[var(--card-foreground)]',\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:shadow-[var(--shadow-card)]',\n ].join(' '),\n },\n },\n defaultVariants: { surface: 'flat' },\n },\n);\n\n/* -------------------------------------------------------------------- */\n/* ReviewsPanel */\n/* -------------------------------------------------------------------- */\n\nexport const ReviewsPanel = forwardRef<HTMLElement, ReviewsPanelProps>(\n (\n {\n reviews,\n aggregate,\n filter: filterProp,\n onFilterChange,\n introSlot,\n headerActionSlot,\n 'aria-label': ariaLabel,\n id,\n className,\n hideFilter = false,\n surface = 'flat',\n loading = false,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const locale = i18n.language ?? 'en';\n\n // Controlled / uncontrolled filter handling. When `filterProp` is\n // undefined the panel manages the filter internally — the consumer can\n // mount the panel and never wire `filter` / `onFilterChange` for the\n // common case where the URL doesn't carry the filter state. When the\n // prop IS provided, the consumer owns the truth.\n const [internalFilter, setInternalFilter] = useState<ReviewFilter>('all');\n const filter = filterProp ?? internalFilter;\n\n const handleFilterChange = useCallback(\n (next: ReviewFilter) => {\n if (filterProp === undefined) setInternalFilter(next);\n onFilterChange?.(next);\n },\n [filterProp, onFilterChange],\n );\n\n // Prefer the consumer-provided histogram; fall back to deriving from the\n // loaded reviews. Pagination consumers SHOULD pass an explicit histogram\n // so the per-bucket counts reflect server-side totals rather than only\n // what's loaded on this page.\n const histogram = useMemo(\n () => aggregate.histogram ?? deriveHistogram(reviews),\n [aggregate.histogram, reviews],\n );\n\n const visibleReviews = useMemo(() => {\n if (filter === 'all') return reviews;\n return reviews.filter((r) => bucketOf(r.overallScore) === filter);\n }, [reviews, filter]);\n\n /* Agent registration — exposes filter + visible count via refs so the\n imperative handle returns the latest values without re-creating the\n handle on every render. */\n const latestFilterRef = useRef(filter);\n latestFilterRef.current = filter;\n const latestVisibleCountRef = useRef(visibleReviews.length);\n latestVisibleCountRef.current = visibleReviews.length;\n\n const agentHandle = useMemo<ReviewsPanelHandle>(\n () => ({\n getFilter: () => latestFilterRef.current,\n setFilter: (next) => handleFilterChange(next),\n getVisibleCount: () => latestVisibleCountRef.current,\n }),\n [handleFilterChange],\n );\n\n const rootRef = useRef<HTMLElement>(null);\n useImperativeHandle(ref, () => rootRef.current as HTMLElement, []);\n useAgentRegistration(reviewsPanelAgent, agentHandle, id);\n\n const resolvedAriaLabel = ariaLabel ?? t('reviewsPanel.regionLabel');\n const dataFilter = String(filter);\n\n /* ---------------------------- Loading ---------------------------- */\n if (loading) {\n return (\n <section\n ref={rootRef as React.Ref<HTMLElement>}\n aria-label={resolvedAriaLabel}\n aria-busy=\"true\"\n id={id}\n data-component=\"reviews-panel\"\n data-component-id={id}\n data-filter={dataFilter}\n data-state=\"loading\"\n className={rootVariants({ surface, className })}\n {...rest}\n >\n <div className=\"ds:p-[var(--spacing-md)]\">\n <PanelSkeleton hideFilter={hideFilter} />\n </div>\n </section>\n );\n }\n\n /* ----------------------- Zero-total empty ------------------------ */\n // No header, no filter — just the EmptyState. The region landmark is\n // still emitted so an agent can locate the empty panel by its\n // data-component marker.\n if (aggregate.count === 0 && reviews.length === 0) {\n return (\n <section\n ref={rootRef as React.Ref<HTMLElement>}\n aria-label={resolvedAriaLabel}\n id={id}\n data-component=\"reviews-panel\"\n data-component-id={id}\n data-filter={dataFilter}\n data-state=\"empty\"\n className={rootVariants({ surface, className })}\n {...rest}\n >\n <div className=\"ds:p-[var(--spacing-md)]\">\n <EmptyState\n variant=\"no-results\"\n title={t('reviewsPanel.empty.title')}\n description={t('reviewsPanel.empty.description')}\n />\n </div>\n </section>\n );\n }\n\n const showFilter = !hideFilter;\n\n return (\n <section\n ref={rootRef as React.Ref<HTMLElement>}\n aria-label={resolvedAriaLabel}\n id={id}\n data-component=\"reviews-panel\"\n data-component-id={id}\n data-filter={dataFilter}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {/* Shared rail header — the panel root is a region landmark with an\n accessible name, so this nested <header> is a generic element\n (not a banner) and stays within the region. The rail injects the\n favourite / close actions via PanelHeaderActionsProvider; the\n panel's own aggregate Rating + headerActionSlot lead the cluster. */}\n <PanelHeader\n title={t('reviewsPanel.title')}\n icon={<Star aria-hidden=\"true\" />}\n titleScale=\"section\"\n sticky\n actions={\n <>\n {headerActionSlot}\n <Rating\n value={aggregate.averageScore}\n reviews={{ count: aggregate.count }}\n size=\"md\"\n />\n </>\n }\n filters={\n showFilter ? (\n <FilterBar\n filter={filter}\n histogram={histogram}\n totalCount={aggregate.count}\n onChange={handleFilterChange}\n />\n ) : undefined\n }\n />\n\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:min-w-0 ds:p-[var(--spacing-md)]\">\n {introSlot\n ? // Render the slot raw — the consumer's introSlot owns\n // its own visual chrome (Alert, Infotip, plain <p>, …).\n // 0.31.x wrapped the slot in a `bg-info/8` tinted box,\n // but when the consumer passed an Alert with its own\n // tinted surface the visual stack rendered TWO concentric\n // tinted boxes (\"double effect\"). The wrapper added no\n // semantic value either (no role, no aria), so dropping\n // it is purely visual.\n introSlot\n : null}\n\n {visibleReviews.length === 0 ? (\n // `role=\"status\"` already implies `aria-live=\"polite\"` —\n // declaring both would queue two announcements when the\n // filter changes (the radio's aria-checked flip + this\n // container's text). Keeping `role` only.\n <div\n role=\"status\"\n data-state=\"no-match\"\n className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)] ds:rounded-[var(--radius-md)] ds:border ds:border-dashed ds:border-[var(--border)] ds:p-[var(--spacing-lg)] ds:text-center\"\n >\n <p className=\"type-body ds:m-0 ds:text-[var(--muted-foreground)]\">\n {filter === 'all'\n ? t('reviewsPanel.empty.title')\n : t('reviewsPanel.empty.filterDescription', {\n stars: filter,\n })}\n </p>\n {filter !== 'all' ? (\n <Button\n intent=\"secondary\"\n size=\"sm\"\n onClick={() => handleFilterChange('all')}\n >\n {t('reviewsPanel.empty.resetFilter')}\n </Button>\n ) : null}\n </div>\n ) : (\n <ol\n aria-label={t('reviewsPanel.listLabel')}\n className=\"ds:list-none ds:m-0 ds:p-0 ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n {visibleReviews.map((review) => (\n <li key={review.id} data-review-id={review.id}>\n <ReviewCard review={review} locale={locale} />\n </li>\n ))}\n </ol>\n )}\n </div>\n </section>\n );\n },\n);\n\nReviewsPanel.displayName = 'ReviewsPanel';\n"],"names":["reviewsPanelAgent","handle","args","FILTER_VALUES","bucketOf","score","deriveHistogram","reviews","out","r","filterRowVariants","cva","FilterBar","filter","histogram","totalCount","onChange","t","useTranslation","labelId","useId","focusIndex","setFocusIndex","useState","useEffect","i","rowRefs","useRef","focusAt","useCallback","index","_a","total","handleKeyDown","event","next","prev","last","jsxs","Fragment","jsx","val","isAll","stars","count","isSelected","isFocused","ariaLabel","node","e","Rating","ReviewCard","review","locale","triggerId","contentId","open","setOpen","breakdownHasValues","hasDetails","formattedDate","useMemo","parsed","pseudonym","footerAndDetails","Collapsible","Card","CollapsibleTrigger","ChevronDown","CollapsibleContent","DescriptionList","_b","_c","_d","PanelSkeleton","hideFilter","Skeleton","_","rootVariants","ReviewsPanel","forwardRef","aggregate","filterProp","onFilterChange","introSlot","headerActionSlot","id","className","surface","loading","rest","ref","i18n","internalFilter","setInternalFilter","handleFilterChange","visibleReviews","latestFilterRef","latestVisibleCountRef","agentHandle","rootRef","useImperativeHandle","useAgentRegistration","resolvedAriaLabel","dataFilter","EmptyState","showFilter","PanelHeader","Star","Button"],"mappings":"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"}
@@ -5,9 +5,9 @@ import { useTranslation as ee } from "react-i18next";
5
5
  import { SafeHtml as qt, sanitiseHtml as jt } from "../safe-html/index.js";
6
6
  import { u as Ft } from "./registry-DvAUVLHh.js";
7
7
  import { S as gt } from "./spinner-hbwuKwMf.js";
8
- import { I as F } from "./icon-button-DA2CAGHZ.js";
8
+ import { I as F } from "./icon-button-8xqRnkdG.js";
9
9
  import { T as Bt } from "./text-area-Bt3p7Pt0.js";
10
- import { E as Kt } from "./editor-overlay-DEc5yYwo.js";
10
+ import { E as Kt } from "./editor-overlay-8fKAcRsm.js";
11
11
  import { X as lt } from "./x-B5YnXwCz.js";
12
12
  import { R as Vt } from "./rotate-ccw-BBQnIVTr.js";
13
13
  import { C as Gt } from "./check-DrFSN__t.js";
@@ -15,14 +15,14 @@ import { S as Se } from "./square-DASBRZ0U.js";
15
15
  import { M as ft } from "./mic-CUklMZGF.js";
16
16
  import { S as Wt } from "./send-C5kDJ-Mz.js";
17
17
  import { B as ie } from "./button-nJaPh_HC.js";
18
- import { a as pt } from "./tooltip-DvmfrNvB.js";
19
- import { P as q } from "./popover-DP6WCVwm.js";
18
+ import { a as pt } from "./tooltip-Cp-PLePW.js";
19
+ import { P as q } from "./popover-DzR5QYxp.js";
20
20
  import { D as Ae } from "./dropdown-menu-DU-Hrf33.js";
21
21
  import { D as B } from "./dialog-BJiLqhx6.js";
22
22
  import { C as We } from "./color-picker-Bl5f0iK1.js";
23
23
  import { T as Ie } from "./text-input-CUvCb6ST.js";
24
- import { C as Xt } from "./checkbox-BuZ1u__2.js";
25
- import { F as Ut } from "./file-upload-CwxdqkMK.js";
24
+ import { C as Xt } from "./checkbox-CZkipDn7.js";
25
+ import { F as Ut } from "./file-upload-BDpb08GM.js";
26
26
  import { c as T } from "./createLucideIcon-DhHxpK9K.js";
27
27
  import { E as Qt } from "./ellipsis-dRo9ouSU.js";
28
28
  import { H as Zt } from "./highlighter-DSkckT2Q.js";
@@ -2624,4 +2624,4 @@ export {
2624
2624
  hn as r,
2625
2625
  Qn as w
2626
2626
  };
2627
- //# sourceMappingURL=rich-text-editor-CCI-Y3DN.js.map
2627
+ //# sourceMappingURL=rich-text-editor-BTXlorm5.js.map