@alfadocs/ui-kit-debug 0.63.0 → 0.65.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 (445) hide show
  1. package/dist/_chunks/{agenda-tray-DA6qj8BL.js → agenda-tray-Bh1KfEOG.js} +2 -2
  2. package/dist/_chunks/{agenda-tray-DA6qj8BL.js.map → agenda-tray-Bh1KfEOG.js.map} +1 -1
  3. package/dist/_chunks/{ai-consent-banner-DBKV27je.js → ai-consent-banner-Btzmk8OH.js} +3 -2
  4. package/dist/_chunks/{ai-consent-banner-DBKV27je.js.map → ai-consent-banner-Btzmk8OH.js.map} +1 -1
  5. package/dist/_chunks/{ai-prompt-input-C6sCr1Vi.js → ai-prompt-input-BwEACCPm.js} +3 -3
  6. package/dist/_chunks/{ai-prompt-input-C6sCr1Vi.js.map → ai-prompt-input-BwEACCPm.js.map} +1 -1
  7. package/dist/_chunks/{ai-tools-rail-7tC3GT4h.js → ai-tools-rail-JnlTqfS4.js} +2 -2
  8. package/dist/_chunks/{ai-tools-rail-7tC3GT4h.js.map → ai-tools-rail-JnlTqfS4.js.map} +1 -1
  9. package/dist/_chunks/{alia-sidebar-DlvyXgVC.js → alia-sidebar-CN8pA6c-.js} +7 -7
  10. package/dist/_chunks/{alia-sidebar-DlvyXgVC.js.map → alia-sidebar-CN8pA6c-.js.map} +1 -1
  11. package/dist/_chunks/{anamnesis-card-CmkBVAln.js → anamnesis-card-qeLYRG79.js} +2 -2
  12. package/dist/_chunks/{anamnesis-card-CmkBVAln.js.map → anamnesis-card-qeLYRG79.js.map} +1 -1
  13. package/dist/_chunks/{antenatal-schedule-timeline-CdiqkF05.js → antenatal-schedule-timeline-BfzFjEyb.js} +3 -3
  14. package/dist/_chunks/{antenatal-schedule-timeline-CdiqkF05.js.map → antenatal-schedule-timeline-BfzFjEyb.js.map} +1 -1
  15. package/dist/_chunks/{appointment-tray-BwDHhWWC.js → appointment-tray-BQnJEora.js} +2 -2
  16. package/dist/_chunks/{appointment-tray-BwDHhWWC.js.map → appointment-tray-BQnJEora.js.map} +1 -1
  17. package/dist/_chunks/{ar-C68WKG5a.js → ar-Cn5Fq48Z.js} +2 -2
  18. package/dist/_chunks/{ar-C68WKG5a.js.map → ar-Cn5Fq48Z.js.map} +1 -1
  19. package/dist/_chunks/{audio-recorder-D6OVfNiZ.js → audio-recorder-DjXLP4aF.js} +3 -3
  20. package/dist/_chunks/{audio-recorder-D6OVfNiZ.js.map → audio-recorder-DjXLP4aF.js.map} +1 -1
  21. package/dist/_chunks/{autocomplete-CDqxB68B.js → autocomplete-CcCFlVf-.js} +4 -4
  22. package/dist/_chunks/{autocomplete-CDqxB68B.js.map → autocomplete-CcCFlVf-.js.map} +1 -1
  23. package/dist/_chunks/{bishop-score-B9tvgoIq.js → bishop-score-x2fNqbuZ.js} +3 -3
  24. package/dist/_chunks/{bishop-score-B9tvgoIq.js.map → bishop-score-x2fNqbuZ.js.map} +1 -1
  25. package/dist/_chunks/{bmi-calculator-DA2NGmVK.js → bmi-calculator-C3roxbqD.js} +2 -2
  26. package/dist/_chunks/{bmi-calculator-DA2NGmVK.js.map → bmi-calculator-C3roxbqD.js.map} +1 -1
  27. package/dist/_chunks/{booking-BUV9fspj.js → booking-L8-YP8BJ.js} +149 -149
  28. package/dist/_chunks/booking-L8-YP8BJ.js.map +1 -0
  29. package/dist/_chunks/calendar-B6soK1Yb.js +17 -0
  30. package/dist/_chunks/calendar-B6soK1Yb.js.map +1 -0
  31. package/dist/_chunks/{calendar-CkuJIg3s.js → calendar-oYWOCrnf.js} +1 -1
  32. package/dist/_chunks/{calendar-CkuJIg3s.js.map → calendar-oYWOCrnf.js.map} +1 -1
  33. package/dist/_chunks/{care-plan-card-QmNpGggC.js → care-plan-card-D42WD4-T.js} +2 -2
  34. package/dist/_chunks/{care-plan-card-QmNpGggC.js.map → care-plan-card-D42WD4-T.js.map} +1 -1
  35. package/dist/_chunks/{care-plan-entry-card-Cnra7vUc.js → care-plan-entry-card-BukNI7Uy.js} +2 -2
  36. package/dist/_chunks/{care-plan-entry-card-Cnra7vUc.js.map → care-plan-entry-card-BukNI7Uy.js.map} +1 -1
  37. package/dist/_chunks/{carousel.agent-DrX96W-1.js → carousel.agent-vt21A_el.js} +2 -2
  38. package/dist/_chunks/{carousel.agent-DrX96W-1.js.map → carousel.agent-vt21A_el.js.map} +1 -1
  39. package/dist/_chunks/{chat-input-CFwc7JxL.js → chat-input-B5zjNEUN.js} +2 -2
  40. package/dist/_chunks/{chat-input-CFwc7JxL.js.map → chat-input-B5zjNEUN.js.map} +1 -1
  41. package/dist/_chunks/{chat-message-Dm8U2RY1.js → chat-message-3V54YipB.js} +2 -2
  42. package/dist/_chunks/{chat-message-Dm8U2RY1.js.map → chat-message-3V54YipB.js.map} +1 -1
  43. package/dist/_chunks/{code-block-HoddNOKJ.js → code-block-BBWHhIc8.js} +2 -2
  44. package/dist/_chunks/{code-block-HoddNOKJ.js.map → code-block-BBWHhIc8.js.map} +1 -1
  45. package/dist/_chunks/{contact-profile-card-DvvVfAA2.js → contact-profile-card-CCeJmjbd.js} +2 -2
  46. package/dist/_chunks/{contact-profile-card-DvvVfAA2.js.map → contact-profile-card-CCeJmjbd.js.map} +1 -1
  47. package/dist/_chunks/{cycle-calculator-C_t1Hs8V.js → cycle-calculator-DrVXbIB4.js} +4 -4
  48. package/dist/_chunks/{cycle-calculator-C_t1Hs8V.js.map → cycle-calculator-DrVXbIB4.js.map} +1 -1
  49. package/dist/_chunks/{date-picker-BfHblqwA.js → date-picker-oGg5BnXL.js} +12 -11
  50. package/dist/_chunks/{date-picker-BfHblqwA.js.map → date-picker-oGg5BnXL.js.map} +1 -1
  51. package/dist/_chunks/{date-picker-variants-CXEAx3O_.js → date-picker-variants-DAcSLTua.js} +358 -372
  52. package/dist/_chunks/date-picker-variants-DAcSLTua.js.map +1 -0
  53. package/dist/_chunks/{date-range-picker-hcAMs1wO.js → date-range-picker-C5BWfH_T.js} +34 -25
  54. package/dist/_chunks/{date-range-picker-hcAMs1wO.js.map → date-range-picker-C5BWfH_T.js.map} +1 -1
  55. package/dist/_chunks/{date-time-picker-H-3Pwqlb.js → date-time-picker-Ze1My59T.js} +18 -17
  56. package/dist/_chunks/{date-time-picker-H-3Pwqlb.js.map → date-time-picker-Ze1My59T.js.map} +1 -1
  57. package/dist/_chunks/{de-DK4A9_a8.js → de-CrJs4ZsX.js} +2 -2
  58. package/dist/_chunks/{de-DK4A9_a8.js.map → de-CrJs4ZsX.js.map} +1 -1
  59. package/dist/_chunks/{description-list-BEbK2g93.js → description-list-gkNGWk5G.js} +2 -2
  60. package/dist/_chunks/{description-list-BEbK2g93.js.map → description-list-gkNGWk5G.js.map} +1 -1
  61. package/dist/_chunks/{due-date-calculator-Q8MIwEVV.js → due-date-calculator-D4K1BnE2.js} +4 -4
  62. package/dist/_chunks/{due-date-calculator-Q8MIwEVV.js.map → due-date-calculator-D4K1BnE2.js.map} +1 -1
  63. package/dist/_chunks/{editable-currency-cell-renderer-D5C5tCfu.js → editable-currency-cell-renderer-CFqQc56y.js} +305 -295
  64. package/dist/_chunks/editable-currency-cell-renderer-CFqQc56y.js.map +1 -0
  65. package/dist/_chunks/editor-overlay-wYm22wZK.js +88 -0
  66. package/dist/_chunks/editor-overlay-wYm22wZK.js.map +1 -0
  67. package/dist/_chunks/{el-B29HXhG5.js → el-DHdMOIhL.js} +6 -6
  68. package/dist/_chunks/{el-B29HXhG5.js.map → el-DHdMOIhL.js.map} +1 -1
  69. package/dist/_chunks/{es-BOwPVwWn.js → es-DCATCfqo.js} +2 -2
  70. package/dist/_chunks/{es-BOwPVwWn.js.map → es-DCATCfqo.js.map} +1 -1
  71. package/dist/_chunks/{fetal-weight-D1a6BmM-.js → fetal-weight-B_pBjlO7.js} +2 -2
  72. package/dist/_chunks/{fetal-weight-D1a6BmM-.js.map → fetal-weight-B_pBjlO7.js.map} +1 -1
  73. package/dist/_chunks/{fiscal-code-input-BZ0FxwUl.js → fiscal-code-input-DPtqluVb.js} +2 -2
  74. package/dist/_chunks/{fiscal-code-input-BZ0FxwUl.js.map → fiscal-code-input-DPtqluVb.js.map} +1 -1
  75. package/dist/_chunks/{fr-DoDBtn0T.js → fr-BfGEMshF.js} +2 -2
  76. package/dist/_chunks/{fr-DoDBtn0T.js.map → fr-BfGEMshF.js.map} +1 -1
  77. package/dist/_chunks/{freemium-paywall-gHGA44dW.js → freemium-paywall-CkWjv3o6.js} +2 -2
  78. package/dist/_chunks/{freemium-paywall-gHGA44dW.js.map → freemium-paywall-CkWjv3o6.js.map} +1 -1
  79. package/dist/_chunks/{gestational-age-calculator-AkNFfZYs.js → gestational-age-calculator-BETQAVkA.js} +7 -7
  80. package/dist/_chunks/{gestational-age-calculator-AkNFfZYs.js.map → gestational-age-calculator-BETQAVkA.js.map} +1 -1
  81. package/dist/_chunks/{hcg-doubling-Dg0Hr7ey.js → hcg-doubling-8zXCJgAQ.js} +3 -3
  82. package/dist/_chunks/{hcg-doubling-Dg0Hr7ey.js.map → hcg-doubling-8zXCJgAQ.js.map} +1 -1
  83. package/dist/_chunks/{header-Ce1Br27u.js → header-CNszv2WQ.js} +2 -2
  84. package/dist/_chunks/{header-Ce1Br27u.js.map → header-CNszv2WQ.js.map} +1 -1
  85. package/dist/_chunks/{header-settings-D5Z2B_Yz.js → header-settings-CNOqIhoW.js} +3 -3
  86. package/dist/_chunks/{header-settings-D5Z2B_Yz.js.map → header-settings-CNOqIhoW.js.map} +1 -1
  87. package/dist/_chunks/{hi-DGByrKby.js → hi-CBFRXEIm.js} +2 -2
  88. package/dist/_chunks/{hi-DGByrKby.js.map → hi-CBFRXEIm.js.map} +1 -1
  89. package/dist/_chunks/icon-button-LqoiKcUN.js +78 -0
  90. package/dist/_chunks/icon-button-LqoiKcUN.js.map +1 -0
  91. package/dist/_chunks/{insert-result-C1SYdueh.js → insert-result-DIAG3ltJ.js} +115 -136
  92. package/dist/_chunks/insert-result-DIAG3ltJ.js.map +1 -0
  93. package/dist/_chunks/{isSameWeek-B1odL2vR.js → isSameWeek-I3DfXUp1.js} +2 -2
  94. package/dist/_chunks/{isSameWeek-B1odL2vR.js.map → isSameWeek-I3DfXUp1.js.map} +1 -1
  95. package/dist/_chunks/{it-B16rEecm.js → it-nz6vAKwG.js} +7 -7
  96. package/dist/_chunks/{it-B16rEecm.js.map → it-nz6vAKwG.js.map} +1 -1
  97. package/dist/_chunks/{ja-B0viOgft.js → ja-DQcqdAEJ.js} +2 -2
  98. package/dist/_chunks/{ja-B0viOgft.js.map → ja-DQcqdAEJ.js.map} +1 -1
  99. package/dist/_chunks/{key-value-pair-CkQIb9EG.js → key-value-pair-BrgbMfbF.js} +2 -2
  100. package/dist/_chunks/{key-value-pair-CkQIb9EG.js.map → key-value-pair-BrgbMfbF.js.map} +1 -1
  101. package/dist/_chunks/{locale-picker-D99UyZVJ.js → locale-picker-C9JmBht3.js} +3 -3
  102. package/dist/_chunks/{locale-picker-D99UyZVJ.js.map → locale-picker-C9JmBht3.js.map} +1 -1
  103. package/dist/_chunks/{marketplace-app-shell-C4OYAC22.js → marketplace-app-shell-BXfRMiRk.js} +4 -4
  104. package/dist/_chunks/{marketplace-app-shell-C4OYAC22.js.map → marketplace-app-shell-BXfRMiRk.js.map} +1 -1
  105. package/dist/_chunks/{message-card-Dvl1TgaN.js → message-card-Bgcvfj6-.js} +2 -2
  106. package/dist/_chunks/{message-card-Dvl1TgaN.js.map → message-card-Bgcvfj6-.js.map} +1 -1
  107. package/dist/_chunks/{message-tray-Dl6GQaaV.js → message-tray-saAVMeHP.js} +3 -3
  108. package/dist/_chunks/{message-tray-Dl6GQaaV.js.map → message-tray-saAVMeHP.js.map} +1 -1
  109. package/dist/_chunks/{multi-select-DOLO3K_z.js → multi-select-BcPylvHR.js} +100 -90
  110. package/dist/_chunks/multi-select-BcPylvHR.js.map +1 -0
  111. package/dist/_chunks/{nl-cBxEX2QU.js → nl-L5SuDjyl.js} +2 -2
  112. package/dist/_chunks/{nl-cBxEX2QU.js.map → nl-L5SuDjyl.js.map} +1 -1
  113. package/dist/_chunks/{notification-card-CObnGdJu.js → notification-card-BiESdm8q.js} +2 -2
  114. package/dist/_chunks/{notification-card-CObnGdJu.js.map → notification-card-BiESdm8q.js.map} +1 -1
  115. package/dist/_chunks/{notification-tray-BWHDIjgd.js → notification-tray-DlgenTEe.js} +3 -3
  116. package/dist/_chunks/{notification-tray-BWHDIjgd.js.map → notification-tray-DlgenTEe.js.map} +1 -1
  117. package/dist/_chunks/{patient-search-CArmRKeg.js → patient-search-Bw9ONucF.js} +2 -2
  118. package/dist/_chunks/{patient-search-CArmRKeg.js.map → patient-search-Bw9ONucF.js.map} +1 -1
  119. package/dist/_chunks/{patient-shell-Coarf346.js → patient-shell-CF_qon7C.js} +3 -3
  120. package/dist/_chunks/{patient-shell-Coarf346.js.map → patient-shell-CF_qon7C.js.map} +1 -1
  121. package/dist/_chunks/{patient-summary-card-BnTqxcTr.js → patient-summary-card-Bgso0p_l.js} +2 -2
  122. package/dist/_chunks/{patient-summary-card-BnTqxcTr.js.map → patient-summary-card-Bgso0p_l.js.map} +1 -1
  123. package/dist/_chunks/{payment-form-DJ9vnzrT.js → payment-form-nXocS_MX.js} +11 -4
  124. package/dist/_chunks/{payment-form-DJ9vnzrT.js.map → payment-form-nXocS_MX.js.map} +1 -1
  125. package/dist/_chunks/{payment-request-card-B_lyobd0.js → payment-request-card-DBz3hVDz.js} +3 -3
  126. package/dist/_chunks/{payment-request-card-B_lyobd0.js.map → payment-request-card-DBz3hVDz.js.map} +1 -1
  127. package/dist/_chunks/{pdf-viewer-chMpwpA4.js → pdf-viewer-GsfNqeeT.js} +3 -3
  128. package/dist/_chunks/pdf-viewer-GsfNqeeT.js.map +1 -0
  129. package/dist/_chunks/{periodontal-chart-card-BYs9hax1.js → periodontal-chart-card-AYyHtU9K.js} +2 -2
  130. package/dist/_chunks/{periodontal-chart-card-BYs9hax1.js.map → periodontal-chart-card-AYyHtU9K.js.map} +1 -1
  131. package/dist/_chunks/phone-input-DVXhNlIl.js +563 -0
  132. package/dist/_chunks/phone-input-DVXhNlIl.js.map +1 -0
  133. package/dist/_chunks/{pl-DtS08ioY.js → pl-YAn5z2wR.js} +3 -3
  134. package/dist/_chunks/{pl-DtS08ioY.js.map → pl-YAn5z2wR.js.map} +1 -1
  135. package/dist/_chunks/{popover-Devce-tT.js → popover-DTbfAuR0.js} +2 -2
  136. package/dist/_chunks/{popover-Devce-tT.js.map → popover-DTbfAuR0.js.map} +1 -1
  137. package/dist/_chunks/{practice-results-CtfciF2v.js → practice-results-CVAgY2RZ.js} +3 -3
  138. package/dist/_chunks/{practice-results-CtfciF2v.js.map → practice-results-CVAgY2RZ.js.map} +1 -1
  139. package/dist/_chunks/{pregnancy-dating-Dg6dTe1p.js → pregnancy-dating-BuzLTwjy.js} +7 -7
  140. package/dist/_chunks/{pregnancy-dating-Dg6dTe1p.js.map → pregnancy-dating-BuzLTwjy.js.map} +1 -1
  141. package/dist/_chunks/{pregnancy-weight-gain-DI7X-0JX.js → pregnancy-weight-gain-aicn7qs7.js} +2 -2
  142. package/dist/_chunks/{pregnancy-weight-gain-DI7X-0JX.js.map → pregnancy-weight-gain-aicn7qs7.js.map} +1 -1
  143. package/dist/_chunks/{privacy-lock-BN3L-alb.js → privacy-lock-C7JyMf0y.js} +2 -2
  144. package/dist/_chunks/{privacy-lock-BN3L-alb.js.map → privacy-lock-C7JyMf0y.js.map} +1 -1
  145. package/dist/_chunks/{product-hub-panel-CkfZBA3t.js → product-hub-panel-CAXDFeGP.js} +2 -2
  146. package/dist/_chunks/{product-hub-panel-CkfZBA3t.js.map → product-hub-panel-CAXDFeGP.js.map} +1 -1
  147. package/dist/_chunks/{pt-yFXs1VvH.js → pt-D9xdT5KQ.js} +6 -6
  148. package/dist/_chunks/{pt-yFXs1VvH.js.map → pt-D9xdT5KQ.js.map} +1 -1
  149. package/dist/_chunks/{public-header.agent-CYQK6T6F.js → public-header.agent-BOhJgZEU.js} +3 -3
  150. package/dist/_chunks/{public-header.agent-CYQK6T6F.js.map → public-header.agent-BOhJgZEU.js.map} +1 -1
  151. package/dist/_chunks/{reviews-panel-CPrXu5TX.js → reviews-panel-DBktKm7i.js} +2 -2
  152. package/dist/_chunks/{reviews-panel-CPrXu5TX.js.map → reviews-panel-DBktKm7i.js.map} +1 -1
  153. package/dist/_chunks/rich-text-editor-u36FqSWz.js +1190 -0
  154. package/dist/_chunks/rich-text-editor-u36FqSWz.js.map +1 -0
  155. package/dist/_chunks/{ro-DsCzSrzR.js → ro-Cp--52bT.js} +2 -2
  156. package/dist/_chunks/{ro-DsCzSrzR.js.map → ro-Cp--52bT.js.map} +1 -1
  157. package/dist/_chunks/{ru-DgDxL0pc.js → ru-BM8eX_Zz.js} +3 -3
  158. package/dist/_chunks/{ru-DgDxL0pc.js.map → ru-BM8eX_Zz.js.map} +1 -1
  159. package/dist/_chunks/{search-bar-CvN_S0jW.js → search-bar-SY2BcV2N.js} +2 -2
  160. package/dist/_chunks/{search-bar-CvN_S0jW.js.map → search-bar-SY2BcV2N.js.map} +1 -1
  161. package/dist/_chunks/{search-input-D3aMvi4l.js → search-input-DbxrnHkW.js} +3 -3
  162. package/dist/_chunks/{search-input-D3aMvi4l.js.map → search-input-DbxrnHkW.js.map} +1 -1
  163. package/dist/_chunks/{select-hsCaJSX3.js → select-CEtRcon5.js} +46 -45
  164. package/dist/_chunks/select-CEtRcon5.js.map +1 -0
  165. package/dist/_chunks/{sheet-xbzu4YiY.js → sheet-taJer-Ha.js} +2 -2
  166. package/dist/_chunks/{sheet-xbzu4YiY.js.map → sheet-taJer-Ha.js.map} +1 -1
  167. package/dist/_chunks/{sign-document--nr5cxsB.js → sign-document-CdAiHiCh.js} +2 -2
  168. package/dist/_chunks/{sign-document--nr5cxsB.js.map → sign-document-CdAiHiCh.js.map} +1 -1
  169. package/dist/_chunks/{sign-in-with-alfadocs-button-BpAjVmsI.js → sign-in-with-alfadocs-button-LppxjlFt.js} +2 -2
  170. package/dist/_chunks/{sign-in-with-alfadocs-button-BpAjVmsI.js.map → sign-in-with-alfadocs-button-LppxjlFt.js.map} +1 -1
  171. package/dist/_chunks/{signature-field-DbhbpLha.js → signature-field-Dy1JRjzE.js} +10 -3
  172. package/dist/_chunks/{signature-field-DbhbpLha.js.map → signature-field-Dy1JRjzE.js.map} +1 -1
  173. package/dist/_chunks/{slot-grid-BlHHP9Qy.js → slot-grid-FsqumOaS.js} +2 -2
  174. package/dist/_chunks/{slot-grid-BlHHP9Qy.js.map → slot-grid-FsqumOaS.js.map} +1 -1
  175. package/dist/_chunks/smart-date-CWikAqZx.js +114 -0
  176. package/dist/_chunks/smart-date-CWikAqZx.js.map +1 -0
  177. package/dist/_chunks/{social-sign-in-button-uJYLM366.js → social-sign-in-button-dlpPI5l7.js} +2 -2
  178. package/dist/_chunks/{social-sign-in-button-uJYLM366.js.map → social-sign-in-button-dlpPI5l7.js.map} +1 -1
  179. package/dist/_chunks/{spinner-OjQNn8oN.js → spinner-hbwuKwMf.js} +10 -10
  180. package/dist/_chunks/{spinner-OjQNn8oN.js.map → spinner-hbwuKwMf.js.map} +1 -1
  181. package/dist/_chunks/{sq-DHlCYN67.js → sq-XRpr0r49.js} +6 -6
  182. package/dist/_chunks/{sq-DHlCYN67.js.map → sq-XRpr0r49.js.map} +1 -1
  183. package/dist/_chunks/{streaming-text-CfhDqtIT.js → streaming-text-BB9mvK4m.js} +2 -2
  184. package/dist/_chunks/{streaming-text-CfhDqtIT.js.map → streaming-text-BB9mvK4m.js.map} +1 -1
  185. package/dist/_chunks/subDays-BcYv1Lxi.js +8 -0
  186. package/dist/_chunks/{subDays-Bs00akhK.js.map → subDays-BcYv1Lxi.js.map} +1 -1
  187. package/dist/_chunks/{sv-O0QaQs_s.js → sv-Z3APomE8.js} +2 -2
  188. package/dist/_chunks/{sv-O0QaQs_s.js.map → sv-Z3APomE8.js.map} +1 -1
  189. package/dist/_chunks/{tabs-BpPYVme_.js → tabs-BIQ0ew1T.js} +2 -2
  190. package/dist/_chunks/{tabs-BpPYVme_.js.map → tabs-BIQ0ew1T.js.map} +1 -1
  191. package/dist/_chunks/{task-tray-Cb_hK4yb.js → task-tray-CAncV-QQ.js} +2 -2
  192. package/dist/_chunks/{task-tray-Cb_hK4yb.js.map → task-tray-CAncV-QQ.js.map} +1 -1
  193. package/dist/_chunks/{theme-toggle-DAW7uC0B.js → theme-toggle-DETmSu_h.js} +2 -2
  194. package/dist/_chunks/{theme-toggle-DAW7uC0B.js.map → theme-toggle-DETmSu_h.js.map} +1 -1
  195. package/dist/_chunks/{toast.agent-B0MCsvdZ.js → toast.agent-vuLRRn2a.js} +2 -2
  196. package/dist/_chunks/{toast.agent-B0MCsvdZ.js.map → toast.agent-vuLRRn2a.js.map} +1 -1
  197. package/dist/_chunks/tooth-scheme-BIx1O2aJ.js +1257 -0
  198. package/dist/_chunks/tooth-scheme-BIx1O2aJ.js.map +1 -0
  199. package/dist/_chunks/{tr-BmNDRuio.js → tr-e0-P4FON.js} +2 -2
  200. package/dist/_chunks/{tr-BmNDRuio.js.map → tr-e0-P4FON.js.map} +1 -1
  201. package/dist/_chunks/{transcript-panel-B4HiC7ed.js → transcript-panel-CLHmv83g.js} +2 -2
  202. package/dist/_chunks/{transcript-panel-B4HiC7ed.js.map → transcript-panel-CLHmv83g.js.map} +1 -1
  203. package/dist/_chunks/type-DZ5OMRA2.js +28 -0
  204. package/dist/_chunks/type-DZ5OMRA2.js.map +1 -0
  205. package/dist/_chunks/{unit-converter-3sINXO3m.js → unit-converter-CHN2cZ4b.js} +3 -3
  206. package/dist/_chunks/{unit-converter-3sINXO3m.js.map → unit-converter-CHN2cZ4b.js.map} +1 -1
  207. package/dist/_chunks/{wallet-pay-button-DuDPBlCO.js → wallet-pay-button--dnR6NfJ.js} +2 -2
  208. package/dist/_chunks/{wallet-pay-button-DuDPBlCO.js.map → wallet-pay-button--dnR6NfJ.js.map} +1 -1
  209. package/dist/_chunks/{workflow-map-BJDUNYlX.js → workflow-map-BX3JY1Bu.js} +3 -3
  210. package/dist/_chunks/{workflow-map-BJDUNYlX.js.map → workflow-map-BX3JY1Bu.js.map} +1 -1
  211. package/dist/_chunks/{zh-CN-CgVJZEzz.js → zh-CN-B-igM5gY.js} +3 -3
  212. package/dist/_chunks/{zh-CN-CgVJZEzz.js.map → zh-CN-B-igM5gY.js.map} +1 -1
  213. package/dist/agent-catalog.json +72 -4
  214. package/dist/components/agenda-tray/index.js +1 -1
  215. package/dist/components/ai-consent-banner/ai-consent-banner.d.ts.map +1 -1
  216. package/dist/components/ai-consent-banner/index.js +1 -1
  217. package/dist/components/ai-prompt-input/index.js +1 -1
  218. package/dist/components/ai-tools-rail/index.js +1 -1
  219. package/dist/components/anamnesis-card/index.js +1 -1
  220. package/dist/components/appointment-card/index.js +1 -1
  221. package/dist/components/audio-recorder/index.js +1 -1
  222. package/dist/components/autocomplete/index.js +1 -1
  223. package/dist/components/bishop-score/index.js +1 -1
  224. package/dist/components/bmi-calculator/index.js +1 -1
  225. package/dist/components/booking/details-form.d.ts.map +1 -1
  226. package/dist/components/booking/index.js +1 -1
  227. package/dist/components/button/icon-button.d.ts.map +1 -1
  228. package/dist/components/button/index.js +1 -1
  229. package/dist/components/calendar/index.js +1 -1
  230. package/dist/components/care-plan-card/index.js +1 -1
  231. package/dist/components/care-plan-entry-card/index.js +1 -1
  232. package/dist/components/carousel/index.js +1 -1
  233. package/dist/components/chat-input/index.js +1 -1
  234. package/dist/components/chat-message/index.js +1 -1
  235. package/dist/components/contact-profile-card/index.js +1 -1
  236. package/dist/components/cycle-calculator/index.js +1 -1
  237. package/dist/components/data-table/filters/date-range-filter.d.ts.map +1 -1
  238. package/dist/components/data-table/filters/select-filter.d.ts.map +1 -1
  239. package/dist/components/data-table/index.js +1 -1
  240. package/dist/components/date-picker/index.js +1 -1
  241. package/dist/components/date-range-picker/date-range-picker.d.ts.map +1 -1
  242. package/dist/components/date-range-picker/index.js +1 -1
  243. package/dist/components/date-time-picker/index.js +1 -1
  244. package/dist/components/description-list/index.js +1 -1
  245. package/dist/components/due-date-calculator/index.js +2 -2
  246. package/dist/components/editor-overlay/editor-overlay.d.ts +19 -0
  247. package/dist/components/editor-overlay/editor-overlay.d.ts.map +1 -0
  248. package/dist/components/editor-overlay/index.d.ts +3 -0
  249. package/dist/components/editor-overlay/index.d.ts.map +1 -0
  250. package/dist/components/editor-overlay/index.js +5 -0
  251. package/dist/components/editor-overlay/index.js.map +1 -0
  252. package/dist/components/fetal-weight/index.js +1 -1
  253. package/dist/components/fiscal-code-input/index.js +1 -1
  254. package/dist/components/freemium-paywall/index.js +1 -1
  255. package/dist/components/gestational-age-calculator/index.js +1 -1
  256. package/dist/components/hcg-doubling/index.js +1 -1
  257. package/dist/components/header/index.js +1 -1
  258. package/dist/components/header-settings/index.js +1 -1
  259. package/dist/components/icon-button/index.js +1 -1
  260. package/dist/components/index.d.ts +2 -0
  261. package/dist/components/index.d.ts.map +1 -1
  262. package/dist/components/key-value-pair/index.js +1 -1
  263. package/dist/components/locale-picker/index.js +1 -1
  264. package/dist/components/message-card/index.js +1 -1
  265. package/dist/components/message-tray/index.js +1 -1
  266. package/dist/components/multi-select/index.js +1 -1
  267. package/dist/components/multi-select/multi-select.d.ts.map +1 -1
  268. package/dist/components/notification-card/index.js +1 -1
  269. package/dist/components/notification-tray/index.js +1 -1
  270. package/dist/components/patient-search/index.js +1 -1
  271. package/dist/components/patient-summary-card/index.js +1 -1
  272. package/dist/components/payment-card/index.js +1 -1
  273. package/dist/components/payment-form/index.js +1 -1
  274. package/dist/components/payment-form/payment-form.d.ts.map +1 -1
  275. package/dist/components/pdf-viewer/index.js +1 -1
  276. package/dist/components/periodontal-chart-card/index.js +1 -1
  277. package/dist/components/phone-input/index.js +1 -1
  278. package/dist/components/phone-input/phone-input.d.ts +9 -0
  279. package/dist/components/phone-input/phone-input.d.ts.map +1 -1
  280. package/dist/components/popover/index.js +1 -1
  281. package/dist/components/practice-results/index.js +1 -1
  282. package/dist/components/pregnancy-dating/index.js +1 -1
  283. package/dist/components/pregnancy-weight-gain/index.js +1 -1
  284. package/dist/components/privacy-lock/index.js +1 -1
  285. package/dist/components/product-hub-tray/index.js +1 -1
  286. package/dist/components/public-header/index.js +1 -1
  287. package/dist/components/reviews-panel/index.js +1 -1
  288. package/dist/components/rich-text-editor/editor-toolbar.d.ts +16 -0
  289. package/dist/components/rich-text-editor/editor-toolbar.d.ts.map +1 -0
  290. package/dist/components/rich-text-editor/help-me-write-overlay.d.ts +25 -0
  291. package/dist/components/rich-text-editor/help-me-write-overlay.d.ts.map +1 -0
  292. package/dist/components/rich-text-editor/index.js +1 -1
  293. package/dist/components/rich-text-editor/rich-text-editor.agent.d.ts.map +1 -1
  294. package/dist/components/rich-text-editor/rich-text-editor.d.ts +43 -0
  295. package/dist/components/rich-text-editor/rich-text-editor.d.ts.map +1 -1
  296. package/dist/components/search-bar/index.js +1 -1
  297. package/dist/components/search-input/index.js +1 -1
  298. package/dist/components/select/index.js +1 -1
  299. package/dist/components/select/select.d.ts +8 -0
  300. package/dist/components/select/select.d.ts.map +1 -1
  301. package/dist/components/sheet/index.js +1 -1
  302. package/dist/components/sign-document/index.js +1 -1
  303. package/dist/components/sign-in-with-alfadocs-button/index.js +1 -1
  304. package/dist/components/signature-field/index.js +1 -1
  305. package/dist/components/signature-field/signature-field.d.ts.map +1 -1
  306. package/dist/components/slot-grid/index.js +1 -1
  307. package/dist/components/smart-date/index.d.ts +3 -0
  308. package/dist/components/smart-date/index.d.ts.map +1 -0
  309. package/dist/components/smart-date/index.js +5 -0
  310. package/dist/components/smart-date/index.js.map +1 -0
  311. package/dist/components/smart-date/smart-date.d.ts +32 -0
  312. package/dist/components/smart-date/smart-date.d.ts.map +1 -0
  313. package/dist/components/social-sign-in-button/index.js +1 -1
  314. package/dist/components/spinner/index.js +1 -1
  315. package/dist/components/streaming-text/index.js +1 -1
  316. package/dist/components/tabs/index.js +1 -1
  317. package/dist/components/task-tray/index.js +1 -1
  318. package/dist/components/theme-toggle/index.js +1 -1
  319. package/dist/components/toast/index.js +1 -1
  320. package/dist/components/tooth-scheme/index.d.ts +2 -2
  321. package/dist/components/tooth-scheme/index.d.ts.map +1 -1
  322. package/dist/components/tooth-scheme/index.js +22 -15
  323. package/dist/components/tooth-scheme/tooth-data.d.ts +79 -18
  324. package/dist/components/tooth-scheme/tooth-data.d.ts.map +1 -1
  325. package/dist/components/tooth-scheme/tooth-scheme.agent.d.ts +2 -0
  326. package/dist/components/tooth-scheme/tooth-scheme.agent.d.ts.map +1 -1
  327. package/dist/components/tooth-scheme/tooth-scheme.d.ts +48 -1
  328. package/dist/components/tooth-scheme/tooth-scheme.d.ts.map +1 -1
  329. package/dist/components/transcript-panel/index.js +1 -1
  330. package/dist/components/unit-converter/index.js +1 -1
  331. package/dist/components/wallet-pay-button/index.js +1 -1
  332. package/dist/components/workflow/index.js +1 -1
  333. package/dist/i18n/locales/ar.d.ts +61 -0
  334. package/dist/i18n/locales/ar.d.ts.map +1 -1
  335. package/dist/i18n/locales/ar.js +63 -2
  336. package/dist/i18n/locales/ar.js.map +1 -1
  337. package/dist/i18n/locales/de.d.ts +61 -0
  338. package/dist/i18n/locales/de.d.ts.map +1 -1
  339. package/dist/i18n/locales/de.js +63 -2
  340. package/dist/i18n/locales/de.js.map +1 -1
  341. package/dist/i18n/locales/el.d.ts +61 -0
  342. package/dist/i18n/locales/el.d.ts.map +1 -1
  343. package/dist/i18n/locales/el.js +63 -2
  344. package/dist/i18n/locales/el.js.map +1 -1
  345. package/dist/i18n/locales/en.d.ts +61 -0
  346. package/dist/i18n/locales/en.d.ts.map +1 -1
  347. package/dist/i18n/locales/en.js +67 -2
  348. package/dist/i18n/locales/en.js.map +1 -1
  349. package/dist/i18n/locales/es.d.ts +61 -0
  350. package/dist/i18n/locales/es.d.ts.map +1 -1
  351. package/dist/i18n/locales/es.js +63 -2
  352. package/dist/i18n/locales/es.js.map +1 -1
  353. package/dist/i18n/locales/fr.d.ts +61 -0
  354. package/dist/i18n/locales/fr.d.ts.map +1 -1
  355. package/dist/i18n/locales/fr.js +63 -2
  356. package/dist/i18n/locales/fr.js.map +1 -1
  357. package/dist/i18n/locales/hi.d.ts +61 -0
  358. package/dist/i18n/locales/hi.d.ts.map +1 -1
  359. package/dist/i18n/locales/hi.js +63 -2
  360. package/dist/i18n/locales/hi.js.map +1 -1
  361. package/dist/i18n/locales/it.d.ts +61 -0
  362. package/dist/i18n/locales/it.d.ts.map +1 -1
  363. package/dist/i18n/locales/it.js +63 -2
  364. package/dist/i18n/locales/it.js.map +1 -1
  365. package/dist/i18n/locales/ja.d.ts +61 -0
  366. package/dist/i18n/locales/ja.d.ts.map +1 -1
  367. package/dist/i18n/locales/ja.js +63 -2
  368. package/dist/i18n/locales/ja.js.map +1 -1
  369. package/dist/i18n/locales/nl.d.ts +61 -0
  370. package/dist/i18n/locales/nl.d.ts.map +1 -1
  371. package/dist/i18n/locales/nl.js +63 -2
  372. package/dist/i18n/locales/nl.js.map +1 -1
  373. package/dist/i18n/locales/pl.d.ts +61 -0
  374. package/dist/i18n/locales/pl.d.ts.map +1 -1
  375. package/dist/i18n/locales/pl.js +63 -2
  376. package/dist/i18n/locales/pl.js.map +1 -1
  377. package/dist/i18n/locales/pt.d.ts +61 -0
  378. package/dist/i18n/locales/pt.d.ts.map +1 -1
  379. package/dist/i18n/locales/pt.js +63 -2
  380. package/dist/i18n/locales/pt.js.map +1 -1
  381. package/dist/i18n/locales/ro.d.ts +61 -0
  382. package/dist/i18n/locales/ro.d.ts.map +1 -1
  383. package/dist/i18n/locales/ro.js +63 -2
  384. package/dist/i18n/locales/ro.js.map +1 -1
  385. package/dist/i18n/locales/ru.d.ts +61 -0
  386. package/dist/i18n/locales/ru.d.ts.map +1 -1
  387. package/dist/i18n/locales/ru.js +63 -2
  388. package/dist/i18n/locales/ru.js.map +1 -1
  389. package/dist/i18n/locales/sq.d.ts +61 -0
  390. package/dist/i18n/locales/sq.d.ts.map +1 -1
  391. package/dist/i18n/locales/sq.js +63 -2
  392. package/dist/i18n/locales/sq.js.map +1 -1
  393. package/dist/i18n/locales/sv.d.ts +61 -0
  394. package/dist/i18n/locales/sv.d.ts.map +1 -1
  395. package/dist/i18n/locales/sv.js +63 -2
  396. package/dist/i18n/locales/sv.js.map +1 -1
  397. package/dist/i18n/locales/tr.d.ts +61 -0
  398. package/dist/i18n/locales/tr.d.ts.map +1 -1
  399. package/dist/i18n/locales/tr.js +63 -2
  400. package/dist/i18n/locales/tr.js.map +1 -1
  401. package/dist/i18n/locales/zh.d.ts +61 -0
  402. package/dist/i18n/locales/zh.d.ts.map +1 -1
  403. package/dist/i18n/locales/zh.js +63 -2
  404. package/dist/i18n/locales/zh.js.map +1 -1
  405. package/dist/index.js +511 -500
  406. package/dist/index.js.map +1 -1
  407. package/dist/locales/ar.json +63 -2
  408. package/dist/locales/de.json +63 -2
  409. package/dist/locales/el.json +63 -2
  410. package/dist/locales/en.json +63 -2
  411. package/dist/locales/es.json +63 -2
  412. package/dist/locales/fr.json +63 -2
  413. package/dist/locales/hi.json +63 -2
  414. package/dist/locales/it.json +63 -2
  415. package/dist/locales/ja.json +63 -2
  416. package/dist/locales/nl.json +63 -2
  417. package/dist/locales/pl.json +63 -2
  418. package/dist/locales/pt.json +63 -2
  419. package/dist/locales/ro.json +63 -2
  420. package/dist/locales/ru.json +63 -2
  421. package/dist/locales/sq.json +63 -2
  422. package/dist/locales/sv.json +63 -2
  423. package/dist/locales/tr.json +63 -2
  424. package/dist/locales/zh.json +63 -2
  425. package/dist/patterns/alia-assistant/index.js +1 -1
  426. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  427. package/dist/patterns/patient-shell/index.js +1 -1
  428. package/dist/tokens.css +36 -22
  429. package/package.json +10 -1
  430. package/dist/_chunks/booking-BUV9fspj.js.map +0 -1
  431. package/dist/_chunks/date-picker-variants-CXEAx3O_.js.map +0 -1
  432. package/dist/_chunks/editable-currency-cell-renderer-D5C5tCfu.js.map +0 -1
  433. package/dist/_chunks/icon-button-CKEOrN37.js +0 -70
  434. package/dist/_chunks/icon-button-CKEOrN37.js.map +0 -1
  435. package/dist/_chunks/insert-result-C1SYdueh.js.map +0 -1
  436. package/dist/_chunks/multi-select-DOLO3K_z.js.map +0 -1
  437. package/dist/_chunks/pdf-viewer-chMpwpA4.js.map +0 -1
  438. package/dist/_chunks/phone-input-DfZbPPvh.js +0 -525
  439. package/dist/_chunks/phone-input-DfZbPPvh.js.map +0 -1
  440. package/dist/_chunks/rich-text-editor-B03qM22-.js +0 -334
  441. package/dist/_chunks/rich-text-editor-B03qM22-.js.map +0 -1
  442. package/dist/_chunks/select-hsCaJSX3.js.map +0 -1
  443. package/dist/_chunks/subDays-Bs00akhK.js +0 -8
  444. package/dist/_chunks/tooth-scheme-CxlsLjfN.js +0 -753
  445. package/dist/_chunks/tooth-scheme-CxlsLjfN.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"public-header.agent-CYQK6T6F.js","sources":["../../src/components/public-header/public-header.tsx","../../src/components/public-header/public-header.agent.ts"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* PublicHeader — anonymous / pre-auth site header. */\n/* */\n/* Distinct from the kit's `<Header>` (authenticated app shell): this */\n/* one is for booking-website, signature-website, marketing surfaces — */\n/* anywhere the chrome should read as continuous with `alfadocs.com`, */\n/* not as the logged-in app. */\n/* */\n/* DOM (default / transparent / dark / brand variants): */\n/* <header role=banner data-component=public-header data-stuck=…> */\n/* <a aria-label=homeLabel>{logo}</a> */\n/* <Radix.NavigationMenu>…{navSlot}</Radix.NavigationMenu> ≥ md */\n/* <div class=actions>{actionsSlot}</div> ≥ md only */\n/* <IconButton menu trigger /> ↔ Sheet (partial drawer) < md only */\n/* </header> */\n/* */\n/* DOM (pill variant — matches alfadocs.com floating-pill header): */\n/* <header role=banner data-component=public-header> transparent */\n/* <div data-component=public-header-container> rounded */\n/* …same children as flat variants… */\n/* </div> */\n/* </header> */\n/* ------------------------------------------------------------------ */\n\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useImperativeHandle,\n useRef,\n useState,\n type AnchorHTMLAttributes,\n type ComponentPropsWithoutRef,\n type ElementRef,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ChevronDown, Menu, X } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';\nimport { IconButton } from '../button/icon-button';\nimport { Sheet } from '../sheet';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface PublicHeaderHandle {\n openMenu: () => void;\n closeMenu: () => void;\n getMenuOpen: () => boolean;\n}\n\nexport interface PublicHeaderProps\n extends\n Omit<ComponentPropsWithoutRef<'header'>, 'children'>,\n VariantProps<typeof rootVariants> {\n /** Logo lockup, typically `<Logo variant=\"wordmark\" tone=\"primary\" size=\"md\" />`. */\n logo: ReactNode;\n /** Optional href for the logo link. Defaults to `/`. */\n homeHref?: string;\n /** Accessible label for the logo link (falls back to `t('publicHeader.homeLabel')`). */\n homeLabel?: string;\n /** Primary nav links rendered inline ≥ md, collapsed into the mobile sheet below md. */\n navSlot?: ReactNode;\n /** Right-side actions (sign-in / register / role-switch CTAs). */\n actionsSlot?: ReactNode;\n /** Sticky behaviour. Default `none`. */\n sticky?: 'none' | 'top' | 'scroll-up';\n /** Pixel offset above which `sticky=\"scroll-up\"` engages and `transparent` fades to default. */\n stickyOffset?: number;\n /** Override the mobile menu trigger's accessible label (`t('publicHeader.openMenu')`). */\n menuLabel?: string;\n /** Override the navigation landmark label (`t('publicHeader.primaryNavLabel')`). */\n navLabel?: string;\n /**\n * Keep `actionsSlot` visible inline at every breakpoint instead of\n * collapsing it into the mobile menu. When there is no `navSlot`, the\n * mobile menu trigger is omitted entirely (nothing left to collapse) — use\n * this for a header whose only action is a single always-relevant control,\n * e.g. a public signer's \"Sign out\". Default `false`.\n */\n persistActions?: boolean;\n /** Consumer-supplied instance id, surfaced as `data-component-id`. */\n id?: string;\n}\n\nexport interface PublicHeaderNavLinkProps extends Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n 'children'\n> {\n href: string;\n active?: boolean;\n children: ReactNode;\n}\n\nexport interface PublicHeaderNavDropdownProps {\n /** Trigger label (the visible nav item text). */\n label: ReactNode;\n /**\n * `false` (default) renders a single-card dropdown anchored near the trigger\n * (Settori-style). `true` renders a wide multi-card mega-menu spanning the\n * pill's full inline width (Soluzioni-style).\n */\n wide?: boolean;\n /** Cards / content inside the dropdown panel. */\n children: ReactNode;\n /** Optional id; not required — used only for analytics / test selectors. */\n id?: string;\n}\n\nexport interface PublicHeaderDropdownCardProps {\n /**\n * Optional href — when provided the card title becomes a clickable\n * anchor with a `→` arrow indicator. Without href, the title is\n * a static heading (Settori-style).\n */\n href?: string;\n title: ReactNode;\n /** Optional subtitle / muted helper text under the title. */\n subtitle?: ReactNode;\n /** Sub-list contents (typically PublicHeader.DropdownLink children). */\n children?: ReactNode;\n}\n\nexport interface PublicHeaderDropdownLinkProps extends Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n 'children'\n> {\n href: string;\n active?: boolean;\n children: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* Context — drives the rendering surface for nav subcomponents. */\n/* */\n/* The same navSlot is rendered twice: once inside the desktop Radix */\n/* NavigationMenu (≥ md, flyout mode) and once inside the mobile Sheet */\n/* drawer (< md, disclosure mode). NavLink / NavDropdown / DropdownCard */\n/* / DropdownLink switch their rendering off this flag so the mobile */\n/* tree doesn't depend on the Radix Root being present. */\n/* ------------------------------------------------------------------ */\n\ntype PublicHeaderSurface = 'desktop' | 'mobile';\n\nconst PublicHeaderSurfaceContext =\n createContext<PublicHeaderSurface>('desktop');\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst rootVariants = cva(\n [\n 'ds:w-full ds:z-[var(--z-sticky)]',\n 'ds:transition-[background-color,box-shadow,transform] ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n variant: {\n // Transparent fades to a solid pill chrome once data-stuck=\"true\"\n // (set by the rAF scroll listener). The fade is handled via the\n // same background utility so `data-stuck` swaps cleanly between\n // states.\n transparent: [\n 'ds:flex ds:items-center ds:gap-[var(--spacing-md)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)]',\n 'ds:h-14 ds:md:h-16',\n 'ds:bg-transparent ds:text-[var(--foreground)]',\n 'ds:data-[stuck=true]:bg-[var(--card)]',\n 'ds:data-[stuck=true]:shadow-[var(--shadow-md)]',\n // Once stuck, pair the elevation shadow with a tokenized\n // block-end border so the header has a clear edge against the\n // page below it — shadow alone fades to a faint halo on dark\n // surfaces, leaving the bar reading as unbounded.\n 'ds:data-[stuck=true]:border-block-end ds:data-[stuck=true]:border-[color:var(--border)]',\n 'ds:forced-colors:border-b ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n // `dark` flips its own scope into the dark token set so nav\n // links + buttons inside read off-white text on the dark\n // surface. Without the `theme-dark` scope the children inherit\n // the light-theme `--foreground` and fail color-contrast at\n // ~1.3:1. `--background` already resolves to a dark step under\n // `theme-dark`, so we compose the surface from the standard\n // theme token rather than locking to a raw ramp step.\n dark: [\n 'ds:flex ds:items-center ds:gap-[var(--spacing-md)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)]',\n 'ds:h-14 ds:md:h-16',\n 'theme-dark ds:bg-[var(--background)] ds:text-[var(--foreground)]',\n ].join(' '),\n // brand: on-primary bar for public signer/marketing surfaces —\n // e.g. sign.alfadocs.com signing nav. Tokens only; logo should be\n // <Logo variant=\"monochrome\" tone=\"inherit\" /> to read on the\n // primary fill.\n brand: [\n 'ds:flex ds:items-center ds:gap-[var(--spacing-md)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)]',\n 'ds:h-14 ds:md:h-16',\n 'ds:bg-[var(--primary)] ds:text-[var(--primary-foreground)]',\n ].join(' '),\n // `pill` matches alfadocs.com's floating rounded-pill header.\n // The outer header is fully transparent (no border, no bg) and\n // simply provides a top-side gutter so the inner container reads\n // as floating. The inner `data-component=\"public-header-container\"`\n // div is the visible chrome — border, rounded, card background.\n pill: [\n 'ds:bg-transparent',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pt-[var(--spacing-md)]',\n 'ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)] ds:sm:pt-[var(--spacing-md)]',\n ].join(' '),\n },\n sticky: {\n none: '',\n top: 'ds:sticky ds:top-0',\n // `scroll-up` is sticky but translates off-screen when scrolling\n // down past `stickyOffset` (handled by data-hidden=\"true\") and\n // slides back in when scrolling up.\n 'scroll-up': [\n 'ds:sticky ds:top-0',\n 'ds:data-[hidden=true]:-translate-y-full',\n ].join(' '),\n },\n },\n defaultVariants: { variant: 'pill', sticky: 'none' },\n },\n);\n\n// Inner pill chrome — only rendered when variant === 'pill'. The actual\n// \"header look\" (rounded, border, card surface) lives here so the outer\n// <header> can stay transparent and provide just the floating offset.\nconst pillContainerClasses = [\n 'ds:flex ds:items-center ds:gap-[var(--spacing-md)]',\n 'ds:w-full ds:max-w-[1400px] ds:mx-auto',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)]',\n // 76px isn't a kit token; the closest is h-16 (64px) which reads tight\n // against alfadocs.com's chrome — keep an explicit min-block-size so\n // the pill reads as substantial without bloating beyond live reference.\n 'ds:min-h-16 ds:md:min-h-[76px]',\n 'ds:bg-[var(--card)] ds:text-[var(--foreground)]',\n 'ds:rounded-[var(--radius-lg)]',\n // Surface-border hairline shared with `Card`. Tuned to ~14% black\n // (light) / 16% white (dark) at the token level so the edge stays\n // visible against tinted page backgrounds — see `--card-border` in\n // `src/tokens/index.css`. Matches alfadocs.com's slate-200 reference\n // pill border without introducing a pill-specific token.\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:transition-none',\n].join(' ');\n\nconst navLinkVariants = cva(\n [\n 'ds:inline-flex ds:items-center',\n 'type-body-sm ds:font-medium',\n // Muted-foreground reads as secondary text and matches alfadocs.com's\n // nav-link colour (the reference's slate-grey). `--foreground` was too\n // dark vs the ref.\n 'ds:text-[var(--muted-foreground)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:py-[var(--spacing-xs)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:hover:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:data-[active=true]:text-[var(--primary)]',\n 'ds:data-[active=true]:[box-shadow:inset_0_-2px_0_var(--primary)]',\n ].join(' '),\n);\n\n// Trigger styling shares the link look + adds the chevron rotation hook.\nconst dropdownTriggerClasses = [\n 'ds:group ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'type-body-sm ds:font-medium',\n // Mirror the navLinkVariants colour + inline padding so triggers and\n // plain links share weight, colour and target size.\n 'ds:text-[var(--muted-foreground)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:bg-transparent ds:border-0 ds:cursor-pointer',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:py-[var(--spacing-xs)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:hover:text-[var(--primary)]',\n 'ds:data-[state=open]:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n].join(' ');\n\nconst dropdownChevronClasses = [\n 'ds:size-3 ds:shrink-0',\n 'ds:transition-transform ds:duration-[var(--animation-duration)]',\n 'ds:group-data-[state=open]:rotate-180',\n 'ds:motion-reduce:transition-none',\n].join(' ');\n\nconst dropdownContentVariants = cva(\n [\n // Radix portals Content into the Viewport; sizing + position is\n // governed by the Viewport — keep Content's own paint to padding\n // + inner layout so motion / position stay consistent across\n // trigger placements.\n 'ds:data-[motion=from-start]:animate-in ds:data-[motion=from-start]:fade-in-0',\n 'ds:data-[motion=from-end]:animate-in ds:data-[motion=from-end]:fade-in-0',\n 'ds:data-[motion=to-start]:animate-out ds:data-[motion=to-start]:fade-out-0',\n 'ds:data-[motion=to-end]:animate-out ds:data-[motion=to-end]:fade-out-0',\n 'ds:motion-reduce:animate-none',\n ].join(' '),\n {\n variants: {\n wide: {\n true: [\n 'ds:grid ds:grid-cols-2 ds:lg:grid-cols-4',\n 'ds:gap-[var(--spacing-lg)]',\n 'ds:p-[var(--spacing-lg)]',\n 'ds:w-screen ds:max-w-[1400px]',\n ].join(' '),\n false: ['ds:p-[var(--spacing-md)]', 'ds:min-w-[280px]'].join(' '),\n },\n },\n defaultVariants: { wide: false },\n },\n);\n\nconst viewportClasses = [\n // Position the Viewport flush below the pill / nav row. Radix sets\n // `--radix-navigation-menu-viewport-width` and `…-height` so the\n // panel sizes itself to whichever Content is currently active.\n 'ds:absolute ds:top-full ds:start-1/2 ds:-translate-x-1/2',\n 'ds:mt-[var(--spacing-sm)]',\n 'ds:w-[var(--radix-navigation-menu-viewport-width)]',\n 'ds:h-[var(--radix-navigation-menu-viewport-height)]',\n 'ds:overflow-hidden',\n 'ds:bg-[var(--card)] ds:text-[var(--foreground)]',\n 'ds:rounded-[var(--radius-lg)] ds:border ds:border-[color:var(--border)]',\n 'ds:shadow-[var(--shadow-lg)]',\n 'ds:data-[state=open]:animate-in ds:data-[state=closed]:animate-out',\n 'ds:data-[state=open]:fade-in-0 ds:data-[state=closed]:fade-out-0',\n 'ds:data-[state=open]:zoom-in-95 ds:data-[state=closed]:zoom-out-95',\n 'ds:origin-top ds:transition-[width,height] ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:animate-none ds:motion-reduce:transition-none',\n].join(' ');\n\nconst cardLinkClasses = [\n 'ds:flex ds:items-start ds:justify-between ds:gap-[var(--spacing-sm)]',\n 'ds:no-underline ds:text-[var(--foreground)]',\n 'ds:pb-[var(--spacing-sm)]',\n // alfadocs.com renders the card header flush against the sub-list with\n // no separator rule — match that by dropping the border-b that earlier\n // versions of this component carried.\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:hover:[&_[data-card-title]]:text-[var(--primary)]',\n 'ds:hover:[&_[data-card-arrow]]:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:group/cardlink',\n].join(' ');\n\nconst cardHeaderStaticClasses = [\n 'ds:pb-[var(--spacing-sm)]',\n // Match the linked-card variant: no separator rule under the title.\n].join(' ');\n\nconst subLinkClasses = [\n 'ds:block ds:no-underline',\n 'type-body-sm ds:font-medium ds:text-[var(--muted-foreground)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:py-[var(--spacing-xs)]',\n 'ds:hover:bg-[var(--muted)]/30 ds:hover:text-[var(--primary)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:data-[active=true]:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n].join(' ');\n\n/* ------------------------------------------------------------------ */\n/* Reduced motion */\n/* ------------------------------------------------------------------ */\n\nfunction usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(() => {\n if (typeof window === 'undefined' || !window.matchMedia) return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n });\n useEffect(() => {\n if (typeof window === 'undefined' || !window.matchMedia) return;\n const mq = window.matchMedia('(prefers-reduced-motion: reduce)');\n const onChange = (): void => setReduced(mq.matches);\n mq.addEventListener('change', onChange);\n return () => mq.removeEventListener('change', onChange);\n }, []);\n return reduced;\n}\n\n/* ------------------------------------------------------------------ */\n/* Scroll listener */\n/* */\n/* rAF-throttled tracker for two flags on the header root: */\n/* - `data-stuck`: scrollY > stickyOffset (drives the transparent → */\n/* solid fade + the scroll-up shadow lift). */\n/* - `data-hidden`: scrolling DOWN past stickyOffset hides the header */\n/* via transform; scrolling UP slides it back. Only emitted when */\n/* `sticky === 'scroll-up'`. */\n/* ------------------------------------------------------------------ */\n\nfunction useHeaderScrollState(\n enabled: boolean,\n sticky: NonNullable<PublicHeaderProps['sticky']>,\n stickyOffset: number,\n): {\n stuck: boolean;\n hidden: boolean;\n} {\n const [stuck, setStuck] = useState(false);\n const [hidden, setHidden] = useState(false);\n const lastYRef = useRef(0);\n const tickingRef = useRef(false);\n\n useEffect(() => {\n if (!enabled || typeof window === 'undefined') return;\n lastYRef.current = window.scrollY;\n\n const update = (): void => {\n const y = window.scrollY;\n setStuck(y > stickyOffset);\n if (sticky === 'scroll-up') {\n const delta = y - lastYRef.current;\n // Hide on a meaningful downward delta past the offset; show on\n // any upward delta. 4px deadband keeps minor wheel inertia from\n // flapping the bar.\n if (delta > 4 && y > stickyOffset) setHidden(true);\n else if (delta < -4 || y <= stickyOffset) setHidden(false);\n }\n lastYRef.current = y;\n tickingRef.current = false;\n };\n const onScroll = (): void => {\n if (tickingRef.current) return;\n tickingRef.current = true;\n window.requestAnimationFrame(update);\n };\n window.addEventListener('scroll', onScroll, { passive: true });\n // Initial sync so we don't miss state when mounted past the offset.\n update();\n return () => {\n window.removeEventListener('scroll', onScroll);\n };\n }, [enabled, sticky, stickyOffset]);\n\n return { stuck, hidden };\n}\n\n/* ------------------------------------------------------------------ */\n/* Inner content (shared between flat + pill variants) */\n/* ------------------------------------------------------------------ */\n\ninterface InnerContentProps {\n logo: ReactNode;\n homeHref: string;\n resolvedHomeLabel: string;\n resolvedNavLabel: string;\n resolvedMenuLabel: string;\n navSlot?: ReactNode;\n actionsSlot?: ReactNode;\n persistActions: boolean;\n menuOpen: boolean;\n setMenuOpen: (open: boolean) => void;\n sheetId: string;\n}\n\nfunction InnerContent({\n logo,\n homeHref,\n resolvedHomeLabel,\n resolvedNavLabel,\n resolvedMenuLabel,\n navSlot,\n actionsSlot,\n persistActions,\n menuOpen,\n setMenuOpen,\n sheetId,\n}: InnerContentProps): React.JSX.Element {\n // The mobile menu only needs to exist when something would otherwise be\n // hidden on small screens: the nav (always collapses) or — unless the\n // consumer pins them — the actions. With persisted actions and no nav there\n // is nothing to collapse, so no hamburger renders at all.\n const showMobileMenu =\n Boolean(navSlot) || (Boolean(actionsSlot) && !persistActions);\n return (\n <>\n <a\n href={homeHref}\n aria-label={resolvedHomeLabel}\n className=\"ds:inline-flex ds:items-center ds:rounded-[var(--radius-sm)] ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]\"\n >\n {logo}\n </a>\n\n {navSlot ? (\n <PublicHeaderSurfaceContext.Provider value=\"desktop\">\n <NavigationMenuPrimitive.Root\n aria-label={resolvedNavLabel}\n // Radix wraps the List in an unstyled `<div>` between Root and\n // <ul>. The `[&>div:first-of-type]:flex` arbitrary selector\n // forces that wrapper into flex so the List's flex-1 actually\n // stretches it across the available width.\n className=\"ds:hidden ds:md:flex ds:relative ds:items-center ds:ms-[var(--spacing-lg)] ds:flex-1 ds:[&>div:first-of-type]:flex ds:[&>div:first-of-type]:flex-1\"\n delayDuration={150}\n >\n <NavigationMenuPrimitive.List className=\"ds:flex ds:flex-1 ds:items-center ds:justify-center ds:gap-[var(--spacing-md)] ds:list-none ds:m-0 ds:ps-0\">\n {navSlot}\n </NavigationMenuPrimitive.List>\n {/* Viewport renders the active panel below the nav row. The\n wrapper centres it horizontally relative to the trigger row;\n Radix sets viewport-width/-height vars so the panel sizes\n to whichever Content is open. */}\n <div className=\"ds:absolute ds:top-full ds:start-0 ds:end-0 ds:flex ds:justify-center ds:pointer-events-none\">\n <div className=\"ds:pointer-events-auto\">\n <NavigationMenuPrimitive.Viewport className={viewportClasses} />\n </div>\n </div>\n </NavigationMenuPrimitive.Root>\n </PublicHeaderSurfaceContext.Provider>\n ) : null}\n\n {actionsSlot ? (\n <div\n className={[\n // Pinned actions stay inline at every breakpoint; otherwise they\n // are hidden < md and collapse into the mobile menu below.\n persistActions ? 'ds:flex' : 'ds:hidden ds:md:flex',\n 'ds:items-center ds:gap-[var(--spacing-sm)] ds:ms-auto',\n ].join(' ')}\n >\n {actionsSlot}\n </div>\n ) : null}\n\n {/* Mobile menu trigger (< md). Wired to a Sheet (partial drawer\n from inline-end) so navSlot + actionsSlot collapse there. Omitted\n entirely when there is nothing left to collapse (persisted actions,\n no nav). */}\n {showMobileMenu ? (\n <Sheet open={menuOpen} onOpenChange={setMenuOpen}>\n <Sheet.Trigger asChild>\n <IconButton\n size=\"md\"\n intent=\"ghost\"\n className=\"ds:ms-auto ds:md:hidden\"\n icon={\n menuOpen ? (\n <X aria-hidden=\"true\" />\n ) : (\n <Menu aria-hidden=\"true\" />\n )\n }\n aria-controls={sheetId}\n aria-expanded={menuOpen}\n aria-label={resolvedMenuLabel}\n />\n </Sheet.Trigger>\n <Sheet.Content side=\"end\" size=\"md\" id={sheetId}>\n <Sheet.Header>\n <Sheet.Title>{resolvedNavLabel}</Sheet.Title>\n </Sheet.Header>\n <Sheet.Body>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {navSlot ? (\n <PublicHeaderSurfaceContext.Provider value=\"mobile\">\n <nav\n aria-label={resolvedNavLabel}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n data-mobile-nav=\"true\"\n >\n {navSlot}\n </nav>\n </PublicHeaderSurfaceContext.Provider>\n ) : null}\n {actionsSlot && !persistActions ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:mt-[var(--spacing-md)]\">\n {actionsSlot}\n </div>\n ) : null}\n </div>\n </Sheet.Body>\n </Sheet.Content>\n </Sheet>\n ) : null}\n </>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderRoot = forwardRef<HTMLElement, PublicHeaderProps>(\n (\n {\n logo,\n homeHref = '/',\n homeLabel,\n navSlot,\n actionsSlot,\n variant = 'pill',\n sticky = 'none',\n stickyOffset = 80,\n menuLabel,\n navLabel,\n persistActions = false,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const reduced = usePrefersReducedMotion();\n const autoId = useId();\n const sheetId = `${id ?? autoId}-sheet`;\n const [menuOpen, setMenuOpen] = useState(false);\n\n // Scroll listener is only active when `transparent` or `scroll-up`\n // need it. Hidden state is disabled under reduced motion (the bar\n // stays visible — translating off-screen is precisely the motion\n // class of user the preference targets).\n const scrollEnabled = variant === 'transparent' || sticky === 'scroll-up';\n const { stuck, hidden } = useHeaderScrollState(\n scrollEnabled,\n sticky,\n stickyOffset,\n );\n const effectiveHidden = reduced ? false : hidden;\n\n const openMenu = useCallback((): void => setMenuOpen(true), []);\n const closeMenu = useCallback((): void => setMenuOpen(false), []);\n\n useImperativeHandle(\n ref as React.Ref<PublicHeaderHandle> | null | undefined,\n () => ({\n openMenu,\n closeMenu,\n getMenuOpen: () => menuOpen,\n }),\n [openMenu, closeMenu, menuOpen],\n );\n\n const resolvedHomeLabel =\n homeLabel ?? t('publicHeader.homeLabel', 'AlfaDocs — home');\n const resolvedNavLabel =\n navLabel ?? t('publicHeader.primaryNavLabel', 'Primary');\n const resolvedMenuLabel =\n menuLabel ??\n (menuOpen\n ? t('publicHeader.closeMenu', 'Close menu')\n : t('publicHeader.openMenu', 'Open menu'));\n\n const innerProps: InnerContentProps = {\n logo,\n homeHref,\n resolvedHomeLabel,\n resolvedNavLabel,\n resolvedMenuLabel,\n navSlot,\n actionsSlot,\n persistActions,\n menuOpen,\n setMenuOpen,\n sheetId,\n };\n\n return (\n <header\n {...rest}\n data-component=\"public-header\"\n data-component-id={id}\n data-variant={variant}\n data-stuck={stuck ? 'true' : undefined}\n data-hidden={effectiveHidden ? 'true' : undefined}\n data-state={reduced ? 'reduced-motion' : undefined}\n className={rootVariants({ variant, sticky, className })}\n >\n {variant === 'pill' ? (\n <div\n data-component=\"public-header-container\"\n className={pillContainerClasses}\n >\n <InnerContent {...innerProps} />\n </div>\n ) : (\n <InnerContent {...innerProps} />\n )}\n </header>\n );\n },\n);\nPublicHeaderRoot.displayName = 'PublicHeader';\n\n/* ------------------------------------------------------------------ */\n/* NavLink */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderNavLink = forwardRef<\n HTMLAnchorElement,\n PublicHeaderNavLinkProps\n>(({ active, className, children, ...rest }, ref) => {\n const surface = useContext(PublicHeaderSurfaceContext);\n // Desktop: NavigationMenu.Item + .Link give Radix the keyboard / focus\n // semantics across the trigger row. We render the actual <a> via\n // asChild so consumers can swap in router links transparently.\n // Mobile: plain <a> inside the Sheet's <nav> — no Radix Root in scope,\n // so we render outside the NavigationMenu primitive.\n if (surface === 'mobile') {\n return (\n <a\n ref={ref}\n {...rest}\n data-active={active ? 'true' : undefined}\n aria-current={active ? 'page' : undefined}\n className={[\n 'ds:block ds:no-underline',\n 'type-body-sm ds:font-medium',\n 'ds:text-[var(--foreground)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:py-[var(--spacing-sm)]',\n 'ds:hover:bg-[var(--muted)]/30 ds:hover:text-[var(--primary)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:data-[active=true]:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {children}\n </a>\n );\n }\n return (\n <NavigationMenuPrimitive.Item>\n <NavigationMenuPrimitive.Link asChild active={active}>\n <a\n ref={ref}\n {...rest}\n data-active={active ? 'true' : undefined}\n aria-current={active ? 'page' : undefined}\n className={[navLinkVariants(), className].filter(Boolean).join(' ')}\n >\n {children}\n </a>\n </NavigationMenuPrimitive.Link>\n </NavigationMenuPrimitive.Item>\n );\n});\nPublicHeaderNavLink.displayName = 'PublicHeader.NavLink';\n\n/* ------------------------------------------------------------------ */\n/* NavDropdown */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderNavDropdown = forwardRef<\n ElementRef<typeof NavigationMenuPrimitive.Trigger>,\n PublicHeaderNavDropdownProps\n>(({ label, wide = false, children, id }, ref) => {\n const surface = useContext(PublicHeaderSurfaceContext);\n if (surface === 'mobile') {\n // <details>/<summary> gives semantic disclosure for free —\n // Enter/Space toggles, summary is focusable, content collapses\n // when not open. No JS needed.\n return (\n <details\n id={id}\n data-component=\"public-header-nav-dropdown\"\n className=\"ds:group ds:border-b ds:border-[color:var(--border)]\"\n >\n <summary\n className={[\n 'ds:flex ds:items-center ds:justify-between ds:cursor-pointer',\n 'type-body-sm ds:font-medium ds:text-[var(--foreground)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:py-[var(--spacing-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:list-none ds:[&::-webkit-details-marker]:hidden',\n ].join(' ')}\n >\n <span>{label}</span>\n <ChevronDown\n aria-hidden=\"true\"\n className=\"ds:size-3 ds:shrink-0 ds:transition-transform ds:duration-[var(--animation-duration)] ds:group-[[open]]:rotate-180 ds:motion-reduce:transition-none\"\n />\n </summary>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:py-[var(--spacing-sm)]\">\n {children}\n </div>\n </details>\n );\n }\n return (\n <NavigationMenuPrimitive.Item data-component=\"public-header-nav-dropdown\">\n <NavigationMenuPrimitive.Trigger\n ref={ref}\n id={id}\n className={dropdownTriggerClasses}\n // Radix already wires aria-expanded + aria-controls. The\n // group / data-state hooks let the chevron rotate via Tailwind.\n >\n {label}\n <ChevronDown aria-hidden=\"true\" className={dropdownChevronClasses} />\n </NavigationMenuPrimitive.Trigger>\n <NavigationMenuPrimitive.Content\n className={dropdownContentVariants({ wide })}\n >\n {children}\n </NavigationMenuPrimitive.Content>\n </NavigationMenuPrimitive.Item>\n );\n});\nPublicHeaderNavDropdown.displayName = 'PublicHeader.NavDropdown';\n\n/* ------------------------------------------------------------------ */\n/* DropdownCard */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderDropdownCard = forwardRef<\n HTMLDivElement,\n PublicHeaderDropdownCardProps\n>(({ href, title, subtitle, children }, ref) => {\n const surface = useContext(PublicHeaderSurfaceContext);\n // The Card header. In mobile we render a plain <a> when href is set —\n // no Radix Link wrapper because the NavigationMenu root isn't in scope\n // inside the Sheet.\n const titleNode = (\n <span\n data-card-title\n className=\"type-title-card ds:text-[var(--foreground)] ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none\"\n >\n {title}\n </span>\n );\n const subtitleNode = subtitle ? (\n <span className=\"type-body-sm ds:text-[var(--muted-foreground)]\">\n {subtitle}\n </span>\n ) : null;\n\n const arrow = (\n <span\n data-card-arrow\n aria-hidden=\"true\"\n className=\"ds:flex-none ds:text-[var(--muted-foreground)] ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none ds:rtl:-scale-x-100\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </span>\n );\n\n const linkInner = (\n <>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n {titleNode}\n {subtitleNode}\n </div>\n {arrow}\n </>\n );\n\n let header: React.JSX.Element;\n if (href) {\n if (surface === 'mobile') {\n header = (\n <a href={href} className={cardLinkClasses}>\n {linkInner}\n </a>\n );\n } else {\n header = (\n <NavigationMenuPrimitive.Link asChild>\n <a href={href} className={cardLinkClasses}>\n {linkInner}\n </a>\n </NavigationMenuPrimitive.Link>\n );\n }\n } else {\n header = (\n <div className={cardHeaderStaticClasses}>\n {titleNode}\n {subtitle ? (\n <span className=\"ds:block type-body-sm ds:text-[var(--muted-foreground)] ds:mt-[var(--spacing-xs)]\">\n {subtitle}\n </span>\n ) : null}\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n data-component=\"public-header-dropdown-card\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n {header}\n {children ? (\n <ul className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:list-none ds:m-0 ds:ps-0\">\n {children}\n </ul>\n ) : null}\n </div>\n );\n});\nPublicHeaderDropdownCard.displayName = 'PublicHeader.DropdownCard';\n\n/* ------------------------------------------------------------------ */\n/* DropdownLink */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderDropdownLink = forwardRef<\n HTMLAnchorElement,\n PublicHeaderDropdownLinkProps\n>(({ active, className, children, ...rest }, ref) => {\n const surface = useContext(PublicHeaderSurfaceContext);\n const anchor = (\n <a\n ref={ref}\n {...rest}\n data-active={active ? 'true' : undefined}\n aria-current={active ? 'page' : undefined}\n className={[subLinkClasses, className].filter(Boolean).join(' ')}\n >\n {children}\n </a>\n );\n return (\n <li data-component=\"public-header-dropdown-link\">\n {surface === 'mobile' ? (\n anchor\n ) : (\n <NavigationMenuPrimitive.Link asChild active={active}>\n {anchor}\n </NavigationMenuPrimitive.Link>\n )}\n </li>\n );\n});\nPublicHeaderDropdownLink.displayName = 'PublicHeader.DropdownLink';\n\n/* ------------------------------------------------------------------ */\n/* Public surface */\n/* ------------------------------------------------------------------ */\n\nexport const PublicHeader = Object.assign(PublicHeaderRoot, {\n NavLink: PublicHeaderNavLink,\n NavDropdown: PublicHeaderNavDropdown,\n DropdownCard: PublicHeaderDropdownCard,\n DropdownLink: PublicHeaderDropdownLink,\n});\n","import type { AgentAdapter } from '../../agent/types';\nimport type { PublicHeaderHandle } from './public-header';\n\nexport const publicHeaderAgent: AgentAdapter<PublicHeaderHandle> = {\n id: 'public-header',\n capabilities: ['open', 'close'],\n state: {\n menuOpen: {\n type: 'boolean',\n description: 'Whether the mobile drawer is currently open.',\n read: (handle) => handle.getMenuOpen(),\n },\n },\n actions: {\n open_menu: {\n safety: 'read',\n description: 'Open the mobile drawer.',\n invoke: (handle) => {\n handle.openMenu();\n },\n },\n close_menu: {\n safety: 'read',\n description: 'Close the mobile drawer.',\n invoke: (handle) => {\n handle.closeMenu();\n },\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'public-header' },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop on PublicHeader.',\n },\n },\n};\n"],"names":["PublicHeaderSurfaceContext","createContext","rootVariants","cva","pillContainerClasses","navLinkVariants","dropdownTriggerClasses","dropdownChevronClasses","dropdownContentVariants","viewportClasses","cardLinkClasses","cardHeaderStaticClasses","subLinkClasses","usePrefersReducedMotion","reduced","setReduced","useState","useEffect","mq","onChange","useHeaderScrollState","enabled","sticky","stickyOffset","stuck","setStuck","hidden","setHidden","lastYRef","useRef","tickingRef","update","y","delta","onScroll","InnerContent","logo","homeHref","resolvedHomeLabel","resolvedNavLabel","resolvedMenuLabel","navSlot","actionsSlot","persistActions","menuOpen","setMenuOpen","sheetId","showMobileMenu","jsxs","Fragment","jsx","NavigationMenuPrimitive","Sheet","IconButton","X","Menu","PublicHeaderRoot","forwardRef","homeLabel","variant","menuLabel","navLabel","id","className","rest","ref","t","useTranslation","autoId","useId","scrollEnabled","effectiveHidden","openMenu","useCallback","closeMenu","useImperativeHandle","innerProps","PublicHeaderNavLink","active","children","useContext","PublicHeaderNavDropdown","label","wide","ChevronDown","PublicHeaderDropdownCard","href","title","subtitle","surface","titleNode","linkInner","header","PublicHeaderDropdownLink","anchor","PublicHeader","publicHeaderAgent","handle"],"mappings":"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"}
1
+ {"version":3,"file":"public-header.agent-BOhJgZEU.js","sources":["../../src/components/public-header/public-header.tsx","../../src/components/public-header/public-header.agent.ts"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* PublicHeader — anonymous / pre-auth site header. */\n/* */\n/* Distinct from the kit's `<Header>` (authenticated app shell): this */\n/* one is for booking-website, signature-website, marketing surfaces — */\n/* anywhere the chrome should read as continuous with `alfadocs.com`, */\n/* not as the logged-in app. */\n/* */\n/* DOM (default / transparent / dark / brand variants): */\n/* <header role=banner data-component=public-header data-stuck=…> */\n/* <a aria-label=homeLabel>{logo}</a> */\n/* <Radix.NavigationMenu>…{navSlot}</Radix.NavigationMenu> ≥ md */\n/* <div class=actions>{actionsSlot}</div> ≥ md only */\n/* <IconButton menu trigger /> ↔ Sheet (partial drawer) < md only */\n/* </header> */\n/* */\n/* DOM (pill variant — matches alfadocs.com floating-pill header): */\n/* <header role=banner data-component=public-header> transparent */\n/* <div data-component=public-header-container> rounded */\n/* …same children as flat variants… */\n/* </div> */\n/* </header> */\n/* ------------------------------------------------------------------ */\n\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useImperativeHandle,\n useRef,\n useState,\n type AnchorHTMLAttributes,\n type ComponentPropsWithoutRef,\n type ElementRef,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ChevronDown, Menu, X } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';\nimport { IconButton } from '../button/icon-button';\nimport { Sheet } from '../sheet';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface PublicHeaderHandle {\n openMenu: () => void;\n closeMenu: () => void;\n getMenuOpen: () => boolean;\n}\n\nexport interface PublicHeaderProps\n extends\n Omit<ComponentPropsWithoutRef<'header'>, 'children'>,\n VariantProps<typeof rootVariants> {\n /** Logo lockup, typically `<Logo variant=\"wordmark\" tone=\"primary\" size=\"md\" />`. */\n logo: ReactNode;\n /** Optional href for the logo link. Defaults to `/`. */\n homeHref?: string;\n /** Accessible label for the logo link (falls back to `t('publicHeader.homeLabel')`). */\n homeLabel?: string;\n /** Primary nav links rendered inline ≥ md, collapsed into the mobile sheet below md. */\n navSlot?: ReactNode;\n /** Right-side actions (sign-in / register / role-switch CTAs). */\n actionsSlot?: ReactNode;\n /** Sticky behaviour. Default `none`. */\n sticky?: 'none' | 'top' | 'scroll-up';\n /** Pixel offset above which `sticky=\"scroll-up\"` engages and `transparent` fades to default. */\n stickyOffset?: number;\n /** Override the mobile menu trigger's accessible label (`t('publicHeader.openMenu')`). */\n menuLabel?: string;\n /** Override the navigation landmark label (`t('publicHeader.primaryNavLabel')`). */\n navLabel?: string;\n /**\n * Keep `actionsSlot` visible inline at every breakpoint instead of\n * collapsing it into the mobile menu. When there is no `navSlot`, the\n * mobile menu trigger is omitted entirely (nothing left to collapse) — use\n * this for a header whose only action is a single always-relevant control,\n * e.g. a public signer's \"Sign out\". Default `false`.\n */\n persistActions?: boolean;\n /** Consumer-supplied instance id, surfaced as `data-component-id`. */\n id?: string;\n}\n\nexport interface PublicHeaderNavLinkProps extends Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n 'children'\n> {\n href: string;\n active?: boolean;\n children: ReactNode;\n}\n\nexport interface PublicHeaderNavDropdownProps {\n /** Trigger label (the visible nav item text). */\n label: ReactNode;\n /**\n * `false` (default) renders a single-card dropdown anchored near the trigger\n * (Settori-style). `true` renders a wide multi-card mega-menu spanning the\n * pill's full inline width (Soluzioni-style).\n */\n wide?: boolean;\n /** Cards / content inside the dropdown panel. */\n children: ReactNode;\n /** Optional id; not required — used only for analytics / test selectors. */\n id?: string;\n}\n\nexport interface PublicHeaderDropdownCardProps {\n /**\n * Optional href — when provided the card title becomes a clickable\n * anchor with a `→` arrow indicator. Without href, the title is\n * a static heading (Settori-style).\n */\n href?: string;\n title: ReactNode;\n /** Optional subtitle / muted helper text under the title. */\n subtitle?: ReactNode;\n /** Sub-list contents (typically PublicHeader.DropdownLink children). */\n children?: ReactNode;\n}\n\nexport interface PublicHeaderDropdownLinkProps extends Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n 'children'\n> {\n href: string;\n active?: boolean;\n children: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* Context — drives the rendering surface for nav subcomponents. */\n/* */\n/* The same navSlot is rendered twice: once inside the desktop Radix */\n/* NavigationMenu (≥ md, flyout mode) and once inside the mobile Sheet */\n/* drawer (< md, disclosure mode). NavLink / NavDropdown / DropdownCard */\n/* / DropdownLink switch their rendering off this flag so the mobile */\n/* tree doesn't depend on the Radix Root being present. */\n/* ------------------------------------------------------------------ */\n\ntype PublicHeaderSurface = 'desktop' | 'mobile';\n\nconst PublicHeaderSurfaceContext =\n createContext<PublicHeaderSurface>('desktop');\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst rootVariants = cva(\n [\n 'ds:w-full ds:z-[var(--z-sticky)]',\n 'ds:transition-[background-color,box-shadow,transform] ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n variant: {\n // Transparent fades to a solid pill chrome once data-stuck=\"true\"\n // (set by the rAF scroll listener). The fade is handled via the\n // same background utility so `data-stuck` swaps cleanly between\n // states.\n transparent: [\n 'ds:flex ds:items-center ds:gap-[var(--spacing-md)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)]',\n 'ds:h-14 ds:md:h-16',\n 'ds:bg-transparent ds:text-[var(--foreground)]',\n 'ds:data-[stuck=true]:bg-[var(--card)]',\n 'ds:data-[stuck=true]:shadow-[var(--shadow-md)]',\n // Once stuck, pair the elevation shadow with a tokenized\n // block-end border so the header has a clear edge against the\n // page below it — shadow alone fades to a faint halo on dark\n // surfaces, leaving the bar reading as unbounded.\n 'ds:data-[stuck=true]:border-block-end ds:data-[stuck=true]:border-[color:var(--border)]',\n 'ds:forced-colors:border-b ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n // `dark` flips its own scope into the dark token set so nav\n // links + buttons inside read off-white text on the dark\n // surface. Without the `theme-dark` scope the children inherit\n // the light-theme `--foreground` and fail color-contrast at\n // ~1.3:1. `--background` already resolves to a dark step under\n // `theme-dark`, so we compose the surface from the standard\n // theme token rather than locking to a raw ramp step.\n dark: [\n 'ds:flex ds:items-center ds:gap-[var(--spacing-md)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)]',\n 'ds:h-14 ds:md:h-16',\n 'theme-dark ds:bg-[var(--background)] ds:text-[var(--foreground)]',\n ].join(' '),\n // brand: on-primary bar for public signer/marketing surfaces —\n // e.g. sign.alfadocs.com signing nav. Tokens only; logo should be\n // <Logo variant=\"monochrome\" tone=\"inherit\" /> to read on the\n // primary fill.\n brand: [\n 'ds:flex ds:items-center ds:gap-[var(--spacing-md)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)]',\n 'ds:h-14 ds:md:h-16',\n 'ds:bg-[var(--primary)] ds:text-[var(--primary-foreground)]',\n ].join(' '),\n // `pill` matches alfadocs.com's floating rounded-pill header.\n // The outer header is fully transparent (no border, no bg) and\n // simply provides a top-side gutter so the inner container reads\n // as floating. The inner `data-component=\"public-header-container\"`\n // div is the visible chrome — border, rounded, card background.\n pill: [\n 'ds:bg-transparent',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pt-[var(--spacing-md)]',\n 'ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)] ds:sm:pt-[var(--spacing-md)]',\n ].join(' '),\n },\n sticky: {\n none: '',\n top: 'ds:sticky ds:top-0',\n // `scroll-up` is sticky but translates off-screen when scrolling\n // down past `stickyOffset` (handled by data-hidden=\"true\") and\n // slides back in when scrolling up.\n 'scroll-up': [\n 'ds:sticky ds:top-0',\n 'ds:data-[hidden=true]:-translate-y-full',\n ].join(' '),\n },\n },\n defaultVariants: { variant: 'pill', sticky: 'none' },\n },\n);\n\n// Inner pill chrome — only rendered when variant === 'pill'. The actual\n// \"header look\" (rounded, border, card surface) lives here so the outer\n// <header> can stay transparent and provide just the floating offset.\nconst pillContainerClasses = [\n 'ds:flex ds:items-center ds:gap-[var(--spacing-md)]',\n 'ds:w-full ds:max-w-[1400px] ds:mx-auto',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)]',\n // 76px isn't a kit token; the closest is h-16 (64px) which reads tight\n // against alfadocs.com's chrome — keep an explicit min-block-size so\n // the pill reads as substantial without bloating beyond live reference.\n 'ds:min-h-16 ds:md:min-h-[76px]',\n 'ds:bg-[var(--card)] ds:text-[var(--foreground)]',\n 'ds:rounded-[var(--radius-lg)]',\n // Surface-border hairline shared with `Card`. Tuned to ~14% black\n // (light) / 16% white (dark) at the token level so the edge stays\n // visible against tinted page backgrounds — see `--card-border` in\n // `src/tokens/index.css`. Matches alfadocs.com's slate-200 reference\n // pill border without introducing a pill-specific token.\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:transition-none',\n].join(' ');\n\nconst navLinkVariants = cva(\n [\n 'ds:inline-flex ds:items-center',\n 'type-body-sm ds:font-medium',\n // Muted-foreground reads as secondary text and matches alfadocs.com's\n // nav-link colour (the reference's slate-grey). `--foreground` was too\n // dark vs the ref.\n 'ds:text-[var(--muted-foreground)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:py-[var(--spacing-xs)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:hover:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:data-[active=true]:text-[var(--primary)]',\n 'ds:data-[active=true]:[box-shadow:inset_0_-2px_0_var(--primary)]',\n ].join(' '),\n);\n\n// Trigger styling shares the link look + adds the chevron rotation hook.\nconst dropdownTriggerClasses = [\n 'ds:group ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'type-body-sm ds:font-medium',\n // Mirror the navLinkVariants colour + inline padding so triggers and\n // plain links share weight, colour and target size.\n 'ds:text-[var(--muted-foreground)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:bg-transparent ds:border-0 ds:cursor-pointer',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:py-[var(--spacing-xs)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:hover:text-[var(--primary)]',\n 'ds:data-[state=open]:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n].join(' ');\n\nconst dropdownChevronClasses = [\n 'ds:size-3 ds:shrink-0',\n 'ds:transition-transform ds:duration-[var(--animation-duration)]',\n 'ds:group-data-[state=open]:rotate-180',\n 'ds:motion-reduce:transition-none',\n].join(' ');\n\nconst dropdownContentVariants = cva(\n [\n // Radix portals Content into the Viewport; sizing + position is\n // governed by the Viewport — keep Content's own paint to padding\n // + inner layout so motion / position stay consistent across\n // trigger placements.\n 'ds:data-[motion=from-start]:animate-in ds:data-[motion=from-start]:fade-in-0',\n 'ds:data-[motion=from-end]:animate-in ds:data-[motion=from-end]:fade-in-0',\n 'ds:data-[motion=to-start]:animate-out ds:data-[motion=to-start]:fade-out-0',\n 'ds:data-[motion=to-end]:animate-out ds:data-[motion=to-end]:fade-out-0',\n 'ds:motion-reduce:animate-none',\n ].join(' '),\n {\n variants: {\n wide: {\n true: [\n 'ds:grid ds:grid-cols-2 ds:lg:grid-cols-4',\n 'ds:gap-[var(--spacing-lg)]',\n 'ds:p-[var(--spacing-lg)]',\n 'ds:w-screen ds:max-w-[1400px]',\n ].join(' '),\n false: ['ds:p-[var(--spacing-md)]', 'ds:min-w-[280px]'].join(' '),\n },\n },\n defaultVariants: { wide: false },\n },\n);\n\nconst viewportClasses = [\n // Position the Viewport flush below the pill / nav row. Radix sets\n // `--radix-navigation-menu-viewport-width` and `…-height` so the\n // panel sizes itself to whichever Content is currently active.\n 'ds:absolute ds:top-full ds:start-1/2 ds:-translate-x-1/2',\n 'ds:mt-[var(--spacing-sm)]',\n 'ds:w-[var(--radix-navigation-menu-viewport-width)]',\n 'ds:h-[var(--radix-navigation-menu-viewport-height)]',\n 'ds:overflow-hidden',\n 'ds:bg-[var(--card)] ds:text-[var(--foreground)]',\n 'ds:rounded-[var(--radius-lg)] ds:border ds:border-[color:var(--border)]',\n 'ds:shadow-[var(--shadow-lg)]',\n 'ds:data-[state=open]:animate-in ds:data-[state=closed]:animate-out',\n 'ds:data-[state=open]:fade-in-0 ds:data-[state=closed]:fade-out-0',\n 'ds:data-[state=open]:zoom-in-95 ds:data-[state=closed]:zoom-out-95',\n 'ds:origin-top ds:transition-[width,height] ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:animate-none ds:motion-reduce:transition-none',\n].join(' ');\n\nconst cardLinkClasses = [\n 'ds:flex ds:items-start ds:justify-between ds:gap-[var(--spacing-sm)]',\n 'ds:no-underline ds:text-[var(--foreground)]',\n 'ds:pb-[var(--spacing-sm)]',\n // alfadocs.com renders the card header flush against the sub-list with\n // no separator rule — match that by dropping the border-b that earlier\n // versions of this component carried.\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:hover:[&_[data-card-title]]:text-[var(--primary)]',\n 'ds:hover:[&_[data-card-arrow]]:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:group/cardlink',\n].join(' ');\n\nconst cardHeaderStaticClasses = [\n 'ds:pb-[var(--spacing-sm)]',\n // Match the linked-card variant: no separator rule under the title.\n].join(' ');\n\nconst subLinkClasses = [\n 'ds:block ds:no-underline',\n 'type-body-sm ds:font-medium ds:text-[var(--muted-foreground)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:py-[var(--spacing-xs)]',\n 'ds:hover:bg-[var(--muted)]/30 ds:hover:text-[var(--primary)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:data-[active=true]:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n].join(' ');\n\n/* ------------------------------------------------------------------ */\n/* Reduced motion */\n/* ------------------------------------------------------------------ */\n\nfunction usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(() => {\n if (typeof window === 'undefined' || !window.matchMedia) return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n });\n useEffect(() => {\n if (typeof window === 'undefined' || !window.matchMedia) return;\n const mq = window.matchMedia('(prefers-reduced-motion: reduce)');\n const onChange = (): void => setReduced(mq.matches);\n mq.addEventListener('change', onChange);\n return () => mq.removeEventListener('change', onChange);\n }, []);\n return reduced;\n}\n\n/* ------------------------------------------------------------------ */\n/* Scroll listener */\n/* */\n/* rAF-throttled tracker for two flags on the header root: */\n/* - `data-stuck`: scrollY > stickyOffset (drives the transparent → */\n/* solid fade + the scroll-up shadow lift). */\n/* - `data-hidden`: scrolling DOWN past stickyOffset hides the header */\n/* via transform; scrolling UP slides it back. Only emitted when */\n/* `sticky === 'scroll-up'`. */\n/* ------------------------------------------------------------------ */\n\nfunction useHeaderScrollState(\n enabled: boolean,\n sticky: NonNullable<PublicHeaderProps['sticky']>,\n stickyOffset: number,\n): {\n stuck: boolean;\n hidden: boolean;\n} {\n const [stuck, setStuck] = useState(false);\n const [hidden, setHidden] = useState(false);\n const lastYRef = useRef(0);\n const tickingRef = useRef(false);\n\n useEffect(() => {\n if (!enabled || typeof window === 'undefined') return;\n lastYRef.current = window.scrollY;\n\n const update = (): void => {\n const y = window.scrollY;\n setStuck(y > stickyOffset);\n if (sticky === 'scroll-up') {\n const delta = y - lastYRef.current;\n // Hide on a meaningful downward delta past the offset; show on\n // any upward delta. 4px deadband keeps minor wheel inertia from\n // flapping the bar.\n if (delta > 4 && y > stickyOffset) setHidden(true);\n else if (delta < -4 || y <= stickyOffset) setHidden(false);\n }\n lastYRef.current = y;\n tickingRef.current = false;\n };\n const onScroll = (): void => {\n if (tickingRef.current) return;\n tickingRef.current = true;\n window.requestAnimationFrame(update);\n };\n window.addEventListener('scroll', onScroll, { passive: true });\n // Initial sync so we don't miss state when mounted past the offset.\n update();\n return () => {\n window.removeEventListener('scroll', onScroll);\n };\n }, [enabled, sticky, stickyOffset]);\n\n return { stuck, hidden };\n}\n\n/* ------------------------------------------------------------------ */\n/* Inner content (shared between flat + pill variants) */\n/* ------------------------------------------------------------------ */\n\ninterface InnerContentProps {\n logo: ReactNode;\n homeHref: string;\n resolvedHomeLabel: string;\n resolvedNavLabel: string;\n resolvedMenuLabel: string;\n navSlot?: ReactNode;\n actionsSlot?: ReactNode;\n persistActions: boolean;\n menuOpen: boolean;\n setMenuOpen: (open: boolean) => void;\n sheetId: string;\n}\n\nfunction InnerContent({\n logo,\n homeHref,\n resolvedHomeLabel,\n resolvedNavLabel,\n resolvedMenuLabel,\n navSlot,\n actionsSlot,\n persistActions,\n menuOpen,\n setMenuOpen,\n sheetId,\n}: InnerContentProps): React.JSX.Element {\n // The mobile menu only needs to exist when something would otherwise be\n // hidden on small screens: the nav (always collapses) or — unless the\n // consumer pins them — the actions. With persisted actions and no nav there\n // is nothing to collapse, so no hamburger renders at all.\n const showMobileMenu =\n Boolean(navSlot) || (Boolean(actionsSlot) && !persistActions);\n return (\n <>\n <a\n href={homeHref}\n aria-label={resolvedHomeLabel}\n className=\"ds:inline-flex ds:items-center ds:rounded-[var(--radius-sm)] ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]\"\n >\n {logo}\n </a>\n\n {navSlot ? (\n <PublicHeaderSurfaceContext.Provider value=\"desktop\">\n <NavigationMenuPrimitive.Root\n aria-label={resolvedNavLabel}\n // Radix wraps the List in an unstyled `<div>` between Root and\n // <ul>. The `[&>div:first-of-type]:flex` arbitrary selector\n // forces that wrapper into flex so the List's flex-1 actually\n // stretches it across the available width.\n className=\"ds:hidden ds:md:flex ds:relative ds:items-center ds:ms-[var(--spacing-lg)] ds:flex-1 ds:[&>div:first-of-type]:flex ds:[&>div:first-of-type]:flex-1\"\n delayDuration={150}\n >\n <NavigationMenuPrimitive.List className=\"ds:flex ds:flex-1 ds:items-center ds:justify-center ds:gap-[var(--spacing-md)] ds:list-none ds:m-0 ds:ps-0\">\n {navSlot}\n </NavigationMenuPrimitive.List>\n {/* Viewport renders the active panel below the nav row. The\n wrapper centres it horizontally relative to the trigger row;\n Radix sets viewport-width/-height vars so the panel sizes\n to whichever Content is open. */}\n <div className=\"ds:absolute ds:top-full ds:start-0 ds:end-0 ds:flex ds:justify-center ds:pointer-events-none\">\n <div className=\"ds:pointer-events-auto\">\n <NavigationMenuPrimitive.Viewport className={viewportClasses} />\n </div>\n </div>\n </NavigationMenuPrimitive.Root>\n </PublicHeaderSurfaceContext.Provider>\n ) : null}\n\n {actionsSlot ? (\n <div\n className={[\n // Pinned actions stay inline at every breakpoint; otherwise they\n // are hidden < md and collapse into the mobile menu below.\n persistActions ? 'ds:flex' : 'ds:hidden ds:md:flex',\n 'ds:items-center ds:gap-[var(--spacing-sm)] ds:ms-auto',\n ].join(' ')}\n >\n {actionsSlot}\n </div>\n ) : null}\n\n {/* Mobile menu trigger (< md). Wired to a Sheet (partial drawer\n from inline-end) so navSlot + actionsSlot collapse there. Omitted\n entirely when there is nothing left to collapse (persisted actions,\n no nav). */}\n {showMobileMenu ? (\n <Sheet open={menuOpen} onOpenChange={setMenuOpen}>\n <Sheet.Trigger asChild>\n <IconButton\n size=\"md\"\n intent=\"ghost\"\n className=\"ds:ms-auto ds:md:hidden\"\n icon={\n menuOpen ? (\n <X aria-hidden=\"true\" />\n ) : (\n <Menu aria-hidden=\"true\" />\n )\n }\n aria-controls={sheetId}\n aria-expanded={menuOpen}\n aria-label={resolvedMenuLabel}\n />\n </Sheet.Trigger>\n <Sheet.Content side=\"end\" size=\"md\" id={sheetId}>\n <Sheet.Header>\n <Sheet.Title>{resolvedNavLabel}</Sheet.Title>\n </Sheet.Header>\n <Sheet.Body>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {navSlot ? (\n <PublicHeaderSurfaceContext.Provider value=\"mobile\">\n <nav\n aria-label={resolvedNavLabel}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n data-mobile-nav=\"true\"\n >\n {navSlot}\n </nav>\n </PublicHeaderSurfaceContext.Provider>\n ) : null}\n {actionsSlot && !persistActions ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:mt-[var(--spacing-md)]\">\n {actionsSlot}\n </div>\n ) : null}\n </div>\n </Sheet.Body>\n </Sheet.Content>\n </Sheet>\n ) : null}\n </>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderRoot = forwardRef<HTMLElement, PublicHeaderProps>(\n (\n {\n logo,\n homeHref = '/',\n homeLabel,\n navSlot,\n actionsSlot,\n variant = 'pill',\n sticky = 'none',\n stickyOffset = 80,\n menuLabel,\n navLabel,\n persistActions = false,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const reduced = usePrefersReducedMotion();\n const autoId = useId();\n const sheetId = `${id ?? autoId}-sheet`;\n const [menuOpen, setMenuOpen] = useState(false);\n\n // Scroll listener is only active when `transparent` or `scroll-up`\n // need it. Hidden state is disabled under reduced motion (the bar\n // stays visible — translating off-screen is precisely the motion\n // class of user the preference targets).\n const scrollEnabled = variant === 'transparent' || sticky === 'scroll-up';\n const { stuck, hidden } = useHeaderScrollState(\n scrollEnabled,\n sticky,\n stickyOffset,\n );\n const effectiveHidden = reduced ? false : hidden;\n\n const openMenu = useCallback((): void => setMenuOpen(true), []);\n const closeMenu = useCallback((): void => setMenuOpen(false), []);\n\n useImperativeHandle(\n ref as React.Ref<PublicHeaderHandle> | null | undefined,\n () => ({\n openMenu,\n closeMenu,\n getMenuOpen: () => menuOpen,\n }),\n [openMenu, closeMenu, menuOpen],\n );\n\n const resolvedHomeLabel =\n homeLabel ?? t('publicHeader.homeLabel', 'AlfaDocs — home');\n const resolvedNavLabel =\n navLabel ?? t('publicHeader.primaryNavLabel', 'Primary');\n const resolvedMenuLabel =\n menuLabel ??\n (menuOpen\n ? t('publicHeader.closeMenu', 'Close menu')\n : t('publicHeader.openMenu', 'Open menu'));\n\n const innerProps: InnerContentProps = {\n logo,\n homeHref,\n resolvedHomeLabel,\n resolvedNavLabel,\n resolvedMenuLabel,\n navSlot,\n actionsSlot,\n persistActions,\n menuOpen,\n setMenuOpen,\n sheetId,\n };\n\n return (\n <header\n {...rest}\n data-component=\"public-header\"\n data-component-id={id}\n data-variant={variant}\n data-stuck={stuck ? 'true' : undefined}\n data-hidden={effectiveHidden ? 'true' : undefined}\n data-state={reduced ? 'reduced-motion' : undefined}\n className={rootVariants({ variant, sticky, className })}\n >\n {variant === 'pill' ? (\n <div\n data-component=\"public-header-container\"\n className={pillContainerClasses}\n >\n <InnerContent {...innerProps} />\n </div>\n ) : (\n <InnerContent {...innerProps} />\n )}\n </header>\n );\n },\n);\nPublicHeaderRoot.displayName = 'PublicHeader';\n\n/* ------------------------------------------------------------------ */\n/* NavLink */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderNavLink = forwardRef<\n HTMLAnchorElement,\n PublicHeaderNavLinkProps\n>(({ active, className, children, ...rest }, ref) => {\n const surface = useContext(PublicHeaderSurfaceContext);\n // Desktop: NavigationMenu.Item + .Link give Radix the keyboard / focus\n // semantics across the trigger row. We render the actual <a> via\n // asChild so consumers can swap in router links transparently.\n // Mobile: plain <a> inside the Sheet's <nav> — no Radix Root in scope,\n // so we render outside the NavigationMenu primitive.\n if (surface === 'mobile') {\n return (\n <a\n ref={ref}\n {...rest}\n data-active={active ? 'true' : undefined}\n aria-current={active ? 'page' : undefined}\n className={[\n 'ds:block ds:no-underline',\n 'type-body-sm ds:font-medium',\n 'ds:text-[var(--foreground)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:py-[var(--spacing-sm)]',\n 'ds:hover:bg-[var(--muted)]/30 ds:hover:text-[var(--primary)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:data-[active=true]:text-[var(--primary)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {children}\n </a>\n );\n }\n return (\n <NavigationMenuPrimitive.Item>\n <NavigationMenuPrimitive.Link asChild active={active}>\n <a\n ref={ref}\n {...rest}\n data-active={active ? 'true' : undefined}\n aria-current={active ? 'page' : undefined}\n className={[navLinkVariants(), className].filter(Boolean).join(' ')}\n >\n {children}\n </a>\n </NavigationMenuPrimitive.Link>\n </NavigationMenuPrimitive.Item>\n );\n});\nPublicHeaderNavLink.displayName = 'PublicHeader.NavLink';\n\n/* ------------------------------------------------------------------ */\n/* NavDropdown */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderNavDropdown = forwardRef<\n ElementRef<typeof NavigationMenuPrimitive.Trigger>,\n PublicHeaderNavDropdownProps\n>(({ label, wide = false, children, id }, ref) => {\n const surface = useContext(PublicHeaderSurfaceContext);\n if (surface === 'mobile') {\n // <details>/<summary> gives semantic disclosure for free —\n // Enter/Space toggles, summary is focusable, content collapses\n // when not open. No JS needed.\n return (\n <details\n id={id}\n data-component=\"public-header-nav-dropdown\"\n className=\"ds:group ds:border-b ds:border-[color:var(--border)]\"\n >\n <summary\n className={[\n 'ds:flex ds:items-center ds:justify-between ds:cursor-pointer',\n 'type-body-sm ds:font-medium ds:text-[var(--foreground)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:py-[var(--spacing-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:list-none ds:[&::-webkit-details-marker]:hidden',\n ].join(' ')}\n >\n <span>{label}</span>\n <ChevronDown\n aria-hidden=\"true\"\n className=\"ds:size-3 ds:shrink-0 ds:transition-transform ds:duration-[var(--animation-duration)] ds:group-[[open]]:rotate-180 ds:motion-reduce:transition-none\"\n />\n </summary>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:py-[var(--spacing-sm)]\">\n {children}\n </div>\n </details>\n );\n }\n return (\n <NavigationMenuPrimitive.Item data-component=\"public-header-nav-dropdown\">\n <NavigationMenuPrimitive.Trigger\n ref={ref}\n id={id}\n className={dropdownTriggerClasses}\n // Radix already wires aria-expanded + aria-controls. The\n // group / data-state hooks let the chevron rotate via Tailwind.\n >\n {label}\n <ChevronDown aria-hidden=\"true\" className={dropdownChevronClasses} />\n </NavigationMenuPrimitive.Trigger>\n <NavigationMenuPrimitive.Content\n className={dropdownContentVariants({ wide })}\n >\n {children}\n </NavigationMenuPrimitive.Content>\n </NavigationMenuPrimitive.Item>\n );\n});\nPublicHeaderNavDropdown.displayName = 'PublicHeader.NavDropdown';\n\n/* ------------------------------------------------------------------ */\n/* DropdownCard */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderDropdownCard = forwardRef<\n HTMLDivElement,\n PublicHeaderDropdownCardProps\n>(({ href, title, subtitle, children }, ref) => {\n const surface = useContext(PublicHeaderSurfaceContext);\n // The Card header. In mobile we render a plain <a> when href is set —\n // no Radix Link wrapper because the NavigationMenu root isn't in scope\n // inside the Sheet.\n const titleNode = (\n <span\n data-card-title\n className=\"type-title-card ds:text-[var(--foreground)] ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none\"\n >\n {title}\n </span>\n );\n const subtitleNode = subtitle ? (\n <span className=\"type-body-sm ds:text-[var(--muted-foreground)]\">\n {subtitle}\n </span>\n ) : null;\n\n const arrow = (\n <span\n data-card-arrow\n aria-hidden=\"true\"\n className=\"ds:flex-none ds:text-[var(--muted-foreground)] ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none ds:rtl:-scale-x-100\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </span>\n );\n\n const linkInner = (\n <>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n {titleNode}\n {subtitleNode}\n </div>\n {arrow}\n </>\n );\n\n let header: React.JSX.Element;\n if (href) {\n if (surface === 'mobile') {\n header = (\n <a href={href} className={cardLinkClasses}>\n {linkInner}\n </a>\n );\n } else {\n header = (\n <NavigationMenuPrimitive.Link asChild>\n <a href={href} className={cardLinkClasses}>\n {linkInner}\n </a>\n </NavigationMenuPrimitive.Link>\n );\n }\n } else {\n header = (\n <div className={cardHeaderStaticClasses}>\n {titleNode}\n {subtitle ? (\n <span className=\"ds:block type-body-sm ds:text-[var(--muted-foreground)] ds:mt-[var(--spacing-xs)]\">\n {subtitle}\n </span>\n ) : null}\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n data-component=\"public-header-dropdown-card\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n {header}\n {children ? (\n <ul className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:list-none ds:m-0 ds:ps-0\">\n {children}\n </ul>\n ) : null}\n </div>\n );\n});\nPublicHeaderDropdownCard.displayName = 'PublicHeader.DropdownCard';\n\n/* ------------------------------------------------------------------ */\n/* DropdownLink */\n/* ------------------------------------------------------------------ */\n\nconst PublicHeaderDropdownLink = forwardRef<\n HTMLAnchorElement,\n PublicHeaderDropdownLinkProps\n>(({ active, className, children, ...rest }, ref) => {\n const surface = useContext(PublicHeaderSurfaceContext);\n const anchor = (\n <a\n ref={ref}\n {...rest}\n data-active={active ? 'true' : undefined}\n aria-current={active ? 'page' : undefined}\n className={[subLinkClasses, className].filter(Boolean).join(' ')}\n >\n {children}\n </a>\n );\n return (\n <li data-component=\"public-header-dropdown-link\">\n {surface === 'mobile' ? (\n anchor\n ) : (\n <NavigationMenuPrimitive.Link asChild active={active}>\n {anchor}\n </NavigationMenuPrimitive.Link>\n )}\n </li>\n );\n});\nPublicHeaderDropdownLink.displayName = 'PublicHeader.DropdownLink';\n\n/* ------------------------------------------------------------------ */\n/* Public surface */\n/* ------------------------------------------------------------------ */\n\nexport const PublicHeader = Object.assign(PublicHeaderRoot, {\n NavLink: PublicHeaderNavLink,\n NavDropdown: PublicHeaderNavDropdown,\n DropdownCard: PublicHeaderDropdownCard,\n DropdownLink: PublicHeaderDropdownLink,\n});\n","import type { AgentAdapter } from '../../agent/types';\nimport type { PublicHeaderHandle } from './public-header';\n\nexport const publicHeaderAgent: AgentAdapter<PublicHeaderHandle> = {\n id: 'public-header',\n capabilities: ['open', 'close'],\n state: {\n menuOpen: {\n type: 'boolean',\n description: 'Whether the mobile drawer is currently open.',\n read: (handle) => handle.getMenuOpen(),\n },\n },\n actions: {\n open_menu: {\n safety: 'read',\n description: 'Open the mobile drawer.',\n invoke: (handle) => {\n handle.openMenu();\n },\n },\n close_menu: {\n safety: 'read',\n description: 'Close the mobile drawer.',\n invoke: (handle) => {\n handle.closeMenu();\n },\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'public-header' },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop on PublicHeader.',\n },\n },\n};\n"],"names":["PublicHeaderSurfaceContext","createContext","rootVariants","cva","pillContainerClasses","navLinkVariants","dropdownTriggerClasses","dropdownChevronClasses","dropdownContentVariants","viewportClasses","cardLinkClasses","cardHeaderStaticClasses","subLinkClasses","usePrefersReducedMotion","reduced","setReduced","useState","useEffect","mq","onChange","useHeaderScrollState","enabled","sticky","stickyOffset","stuck","setStuck","hidden","setHidden","lastYRef","useRef","tickingRef","update","y","delta","onScroll","InnerContent","logo","homeHref","resolvedHomeLabel","resolvedNavLabel","resolvedMenuLabel","navSlot","actionsSlot","persistActions","menuOpen","setMenuOpen","sheetId","showMobileMenu","jsxs","Fragment","jsx","NavigationMenuPrimitive","Sheet","IconButton","X","Menu","PublicHeaderRoot","forwardRef","homeLabel","variant","menuLabel","navLabel","id","className","rest","ref","t","useTranslation","autoId","useId","scrollEnabled","effectiveHidden","openMenu","useCallback","closeMenu","useImperativeHandle","innerProps","PublicHeaderNavLink","active","children","useContext","PublicHeaderNavDropdown","label","wide","ChevronDown","PublicHeaderDropdownCard","href","title","subtitle","surface","titleNode","linkInner","header","PublicHeaderDropdownLink","anchor","PublicHeader","publicHeaderAgent","handle"],"mappings":"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"}
@@ -6,7 +6,7 @@ import { u as W } from "./registry-nPAVE19X.js";
6
6
  import { R as N } from "./rating-BRD7O74e.js";
7
7
  import { C as A } from "./card-DPmk26CL.js";
8
8
  import { C as X, b as Y, a as Z } from "./collapsible-X3oaLPU3.js";
9
- import { D as l } from "./description-list-BEbK2g93.js";
9
+ import { D as l } from "./description-list-gkNGWk5G.js";
10
10
  import { E as ee } from "./empty-state-BLy7tigq.js";
11
11
  import { S as T } from "./skeleton-CZbwyJAA.js";
12
12
  import { B as se } from "./button-DD_0Xdmr.js";
@@ -533,4 +533,4 @@ export {
533
533
  oe as R,
534
534
  re as r
535
535
  };
536
- //# sourceMappingURL=reviews-panel-CPrXu5TX.js.map
536
+ //# sourceMappingURL=reviews-panel-DBktKm7i.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reviews-panel-CPrXu5TX.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 safety: 'read',\n argsType: '{ filter: \"all\" | 1 | 2 | 3 | 4 | 5 }',\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 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 } 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';\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/* FilterSidebar — hand-rolled radiogroup with roving tabindex */\n/* */\n/* Mirrors `ServiceGrid` in `booking.tsx`: the WAI-ARIA RadioGroup */\n/* pattern with full-row click target + icon column. NOT Radix */\n/* `RadioGroup` because we need a row layout with a non-text leading */\n/* glyph (the star ramp) and a trailing count. */\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:flex ds:w-full ds:items-center ds:justify-between',\n 'ds:gap-[var(--spacing-sm)]',\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 FilterSidebarProps {\n filter: ReviewFilter;\n histogram: Record<1 | 2 | 3 | 4 | 5, number>;\n totalCount: number;\n onChange: (next: ReviewFilter) => void;\n}\n\nfunction FilterSidebar({\n filter,\n histogram,\n totalCount,\n onChange,\n}: FilterSidebarProps) {\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 <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\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-col 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 </div>\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 <div\n className={\n hideFilter\n ? 'ds:flex ds:flex-col ds:gap-[var(--spacing-md)]'\n : 'ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:md:grid-cols-[minmax(0,30%)_minmax(0,1fr)]'\n }\n >\n {!hideFilter ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n {Array.from({ length: 6 }, (_, i) => (\n <Skeleton key={`rp-fs-${i}`} variant=\"rounded\" height=\"2.5rem\" />\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 </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Root variants */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva(\n 'ds:flex ds:w-full ds:flex-col ds:gap-[var(--spacing-md)] ds:text-[var(--foreground)]',\n {\n variants: {\n // `surface=\"elevated\"` matches `Card variant=\"elevated\"` — same\n // tokens, same padding, same boundary behaviour — so consumers can\n // drop their own Card wraps without producing a double-card look.\n // Default `'flat'` preserves 0.30.x rendering (no wrapping).\n surface: {\n flat: '',\n elevated: [\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 'ds:p-[var(--spacing-md)]',\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 <PanelSkeleton hideFilter={hideFilter} />\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 <EmptyState\n variant=\"no-results\"\n title={t('reviewsPanel.empty.title')}\n description={t('reviewsPanel.empty.description')}\n />\n </section>\n );\n }\n\n const showFilterSidebar = !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 {/* Header row — plain <div>, not <header>: the panel root is a\n region landmark with an accessible name, so a nested <header>\n would emit a banner-inside-region pair that axe's\n landmark-banner-is-top-level rule flags. */}\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <h2 className=\"type-title-section ds:m-0 ds:text-[var(--foreground)]\">\n {t('reviewsPanel.title')}\n </h2>\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-md)]\">\n {headerActionSlot}\n <Rating\n value={aggregate.averageScore}\n reviews={{ count: aggregate.count }}\n size=\"md\"\n />\n </div>\n </div>\n\n <div\n className={\n showFilterSidebar\n ? 'ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:md:grid-cols-[minmax(0,30%)_minmax(0,1fr)]'\n : 'ds:flex ds:flex-col ds:gap-[var(--spacing-md)]'\n }\n >\n {showFilterSidebar ? (\n <FilterSidebar\n filter={filter}\n histogram={histogram}\n totalCount={aggregate.count}\n onChange={handleFilterChange}\n />\n ) : null}\n\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:min-w-0\">\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 </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","FilterSidebar","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","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","showFilterSidebar","Button"],"mappings":"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"}
1
+ {"version":3,"file":"reviews-panel-DBktKm7i.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 safety: 'read',\n argsType: '{ filter: \"all\" | 1 | 2 | 3 | 4 | 5 }',\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 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 } 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';\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/* FilterSidebar — hand-rolled radiogroup with roving tabindex */\n/* */\n/* Mirrors `ServiceGrid` in `booking.tsx`: the WAI-ARIA RadioGroup */\n/* pattern with full-row click target + icon column. NOT Radix */\n/* `RadioGroup` because we need a row layout with a non-text leading */\n/* glyph (the star ramp) and a trailing count. */\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:flex ds:w-full ds:items-center ds:justify-between',\n 'ds:gap-[var(--spacing-sm)]',\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 FilterSidebarProps {\n filter: ReviewFilter;\n histogram: Record<1 | 2 | 3 | 4 | 5, number>;\n totalCount: number;\n onChange: (next: ReviewFilter) => void;\n}\n\nfunction FilterSidebar({\n filter,\n histogram,\n totalCount,\n onChange,\n}: FilterSidebarProps) {\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 <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\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-col 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 </div>\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 <div\n className={\n hideFilter\n ? 'ds:flex ds:flex-col ds:gap-[var(--spacing-md)]'\n : 'ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:md:grid-cols-[minmax(0,30%)_minmax(0,1fr)]'\n }\n >\n {!hideFilter ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n {Array.from({ length: 6 }, (_, i) => (\n <Skeleton key={`rp-fs-${i}`} variant=\"rounded\" height=\"2.5rem\" />\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 </div>\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* Root variants */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva(\n 'ds:flex ds:w-full ds:flex-col ds:gap-[var(--spacing-md)] ds:text-[var(--foreground)]',\n {\n variants: {\n // `surface=\"elevated\"` matches `Card variant=\"elevated\"` — same\n // tokens, same padding, same boundary behaviour — so consumers can\n // drop their own Card wraps without producing a double-card look.\n // Default `'flat'` preserves 0.30.x rendering (no wrapping).\n surface: {\n flat: '',\n elevated: [\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 'ds:p-[var(--spacing-md)]',\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 <PanelSkeleton hideFilter={hideFilter} />\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 <EmptyState\n variant=\"no-results\"\n title={t('reviewsPanel.empty.title')}\n description={t('reviewsPanel.empty.description')}\n />\n </section>\n );\n }\n\n const showFilterSidebar = !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 {/* Header row — plain <div>, not <header>: the panel root is a\n region landmark with an accessible name, so a nested <header>\n would emit a banner-inside-region pair that axe's\n landmark-banner-is-top-level rule flags. */}\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <h2 className=\"type-title-section ds:m-0 ds:text-[var(--foreground)]\">\n {t('reviewsPanel.title')}\n </h2>\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-md)]\">\n {headerActionSlot}\n <Rating\n value={aggregate.averageScore}\n reviews={{ count: aggregate.count }}\n size=\"md\"\n />\n </div>\n </div>\n\n <div\n className={\n showFilterSidebar\n ? 'ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:md:grid-cols-[minmax(0,30%)_minmax(0,1fr)]'\n : 'ds:flex ds:flex-col ds:gap-[var(--spacing-md)]'\n }\n >\n {showFilterSidebar ? (\n <FilterSidebar\n filter={filter}\n histogram={histogram}\n totalCount={aggregate.count}\n onChange={handleFilterChange}\n />\n ) : null}\n\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:min-w-0\">\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 </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","FilterSidebar","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","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","showFilterSidebar","Button"],"mappings":"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"}