@alfadocs/ui-kit-debug 1.65.0 → 1.67.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 (264) hide show
  1. package/dist/_chunks/ai-credits-exhausted-notice-DfAgfZDF.js +287 -0
  2. package/dist/_chunks/ai-credits-exhausted-notice-DfAgfZDF.js.map +1 -0
  3. package/dist/_chunks/ai-credits-exhausted-notice.agent-DgTSTgez.js +43 -0
  4. package/dist/_chunks/ai-credits-exhausted-notice.agent-DgTSTgez.js.map +1 -0
  5. package/dist/_chunks/ai-credits-notice-DQ-r3iQU.js +191 -0
  6. package/dist/_chunks/ai-credits-notice-DQ-r3iQU.js.map +1 -0
  7. package/dist/_chunks/{ai-permission-notice-DpRmZ9Q3.js → ai-permission-notice-qsdm4Sx4.js} +2 -2
  8. package/dist/_chunks/{ai-permission-notice-DpRmZ9Q3.js.map → ai-permission-notice-qsdm4Sx4.js.map} +1 -1
  9. package/dist/_chunks/{alert-DdDpOi-P.js → alert-DjsJMGRE.js} +3 -2
  10. package/dist/_chunks/{alert-DdDpOi-P.js.map → alert-DjsJMGRE.js.map} +1 -1
  11. package/dist/_chunks/{anamnesis-summary-rows-BIfw890v.js → anamnesis-summary-rows-BQ_EokKz.js} +2 -2
  12. package/dist/_chunks/{anamnesis-summary-rows-BIfw890v.js.map → anamnesis-summary-rows-BQ_EokKz.js.map} +1 -1
  13. package/dist/_chunks/{audio-recorder-DR-u1qbl.js → audio-recorder-B11RR-rC.js} +2 -2
  14. package/dist/_chunks/{audio-recorder-DR-u1qbl.js.map → audio-recorder-B11RR-rC.js.map} +1 -1
  15. package/dist/_chunks/{auth-form-parts-Cmb41LSQ.js → auth-form-parts-DwUTH6YN.js} +2 -2
  16. package/dist/_chunks/{auth-form-parts-Cmb41LSQ.js.map → auth-form-parts-DwUTH6YN.js.map} +1 -1
  17. package/dist/_chunks/{booking-DkjatiXc.js → booking-tTVxKPQY.js} +2 -2
  18. package/dist/_chunks/{booking-DkjatiXc.js.map → booking-tTVxKPQY.js.map} +1 -1
  19. package/dist/_chunks/{calendar-workspace-Cp8yTZ1g.js → calendar-workspace-MRrzcxAy.js} +6 -6
  20. package/dist/_chunks/{calendar-workspace-Cp8yTZ1g.js.map → calendar-workspace-MRrzcxAy.js.map} +1 -1
  21. package/dist/_chunks/chart-CwmyCuWe.js +1340 -0
  22. package/dist/_chunks/chart-CwmyCuWe.js.map +1 -0
  23. package/dist/_chunks/{document-preview-B1dQm292.js → document-preview-VyQOjFVL.js} +2 -2
  24. package/dist/_chunks/{document-preview-B1dQm292.js.map → document-preview-VyQOjFVL.js.map} +1 -1
  25. package/dist/_chunks/{document-scanner-CVPVLK7z.js → document-scanner-CXH_GYh4.js} +2 -2
  26. package/dist/_chunks/{document-scanner-CVPVLK7z.js.map → document-scanner-CXH_GYh4.js.map} +1 -1
  27. package/dist/_chunks/{entity-summary-BQ9_KA8S.js → entity-summary-Bj-Wxq7Y.js} +2 -2
  28. package/dist/_chunks/{entity-summary-BQ9_KA8S.js.map → entity-summary-Bj-Wxq7Y.js.map} +1 -1
  29. package/dist/_chunks/{error-summary-DrUfuKu1.js → error-summary-PUE5Zxp9.js} +2 -2
  30. package/dist/_chunks/{error-summary-DrUfuKu1.js.map → error-summary-PUE5Zxp9.js.map} +1 -1
  31. package/dist/_chunks/{forgot-password-form-CgZkEvZy.js → forgot-password-form-CPOfRE0C.js} +4 -4
  32. package/dist/_chunks/{forgot-password-form-CgZkEvZy.js.map → forgot-password-form-CPOfRE0C.js.map} +1 -1
  33. package/dist/_chunks/{freemium-paywall-DKJHRFpp.js → freemium-paywall-6DO7noHX.js} +2 -2
  34. package/dist/_chunks/{freemium-paywall-DKJHRFpp.js.map → freemium-paywall-6DO7noHX.js.map} +1 -1
  35. package/dist/_chunks/heatmap-C1TeC7wT.js +3650 -0
  36. package/dist/_chunks/heatmap-C1TeC7wT.js.map +1 -0
  37. package/dist/_chunks/help-me-write-templates-Bw3Q58x-.js +687 -0
  38. package/dist/_chunks/help-me-write-templates-Bw3Q58x-.js.map +1 -0
  39. package/dist/_chunks/hourglass-BEAzW1wE.js +26 -0
  40. package/dist/_chunks/hourglass-BEAzW1wE.js.map +1 -0
  41. package/dist/_chunks/{login-dev-card-PnADNcI9.js → login-dev-card-A-CL3mjt.js} +3 -3
  42. package/dist/_chunks/{login-dev-card-PnADNcI9.js.map → login-dev-card-A-CL3mjt.js.map} +1 -1
  43. package/dist/_chunks/{marketplace-app-shell-C-2e4eCD.js → marketplace-app-shell-DtSX8sYb.js} +2 -2
  44. package/dist/_chunks/{marketplace-app-shell-C-2e4eCD.js.map → marketplace-app-shell-DtSX8sYb.js.map} +1 -1
  45. package/dist/_chunks/{notes-panel-uEGIL7mi.js → notes-panel-IdsmqRFC.js} +3 -3
  46. package/dist/_chunks/{notes-panel-uEGIL7mi.js.map → notes-panel-IdsmqRFC.js.map} +1 -1
  47. package/dist/_chunks/{patient-details-4P1vA9Ls.js → patient-details-C-EWQTms.js} +2 -2
  48. package/dist/_chunks/{patient-details-4P1vA9Ls.js.map → patient-details-C-EWQTms.js.map} +1 -1
  49. package/dist/_chunks/{patient-field-row-CBXhlfGD.js → patient-field-row-lY-Tb5Mo.js} +155 -176
  50. package/dist/_chunks/patient-field-row-lY-Tb5Mo.js.map +1 -0
  51. package/dist/_chunks/{patient-search-DOnDUVsl.js → patient-search-DpAKidZ5.js} +2 -2
  52. package/dist/_chunks/{patient-search-DOnDUVsl.js.map → patient-search-DpAKidZ5.js.map} +1 -1
  53. package/dist/_chunks/{patient-summary-card-CuDLo8MP.js → patient-summary-card-Bpto_VCD.js} +2 -2
  54. package/dist/_chunks/{patient-summary-card-CuDLo8MP.js.map → patient-summary-card-Bpto_VCD.js.map} +1 -1
  55. package/dist/_chunks/{payment-automation-upsell-C8MEu0t6.js → payment-automation-upsell-BQ307qEX.js} +2 -2
  56. package/dist/_chunks/{payment-automation-upsell-C8MEu0t6.js.map → payment-automation-upsell-BQ307qEX.js.map} +1 -1
  57. package/dist/_chunks/{payment-form-C3dGY7v4.js → payment-form-XKtinW8r.js} +2 -2
  58. package/dist/_chunks/{payment-form-C3dGY7v4.js.map → payment-form-XKtinW8r.js.map} +1 -1
  59. package/dist/_chunks/{pdf-viewer-DJ9VN7cu.js → pdf-viewer-BvoVMjH4.js} +2 -2
  60. package/dist/_chunks/{pdf-viewer-DJ9VN7cu.js.map → pdf-viewer-BvoVMjH4.js.map} +1 -1
  61. package/dist/_chunks/{practice-results-8h2Utpt3.js → practice-results-BrUDDMXC.js} +2 -2
  62. package/dist/_chunks/{practice-results-8h2Utpt3.js.map → practice-results-BrUDDMXC.js.map} +1 -1
  63. package/dist/_chunks/{registration-form-BQyT_kBX.js → registration-form-BxwqUZzk.js} +3 -3
  64. package/dist/_chunks/{registration-form-BQyT_kBX.js.map → registration-form-BxwqUZzk.js.map} +1 -1
  65. package/dist/_chunks/{rich-text-editor-M2gT_E7f.js → rich-text-editor-aCIoptbg.js} +1653 -1743
  66. package/dist/_chunks/{rich-text-editor-M2gT_E7f.js.map → rich-text-editor-aCIoptbg.js.map} +1 -1
  67. package/dist/_chunks/{sign-document-CY7xTXbm.js → sign-document-D1P1nUQA.js} +2 -2
  68. package/dist/_chunks/{sign-document-CY7xTXbm.js.map → sign-document-D1P1nUQA.js.map} +1 -1
  69. package/dist/_chunks/{signature-request-BMCHy2ZO.js → signature-request-3u6TvRt2.js} +2 -2
  70. package/dist/_chunks/{signature-request-BMCHy2ZO.js.map → signature-request-3u6TvRt2.js.map} +1 -1
  71. package/dist/_chunks/{task-editor-CifOznfq.js → task-editor-Bb5MMcid.js} +2 -2
  72. package/dist/_chunks/{task-editor-CifOznfq.js.map → task-editor-Bb5MMcid.js.map} +1 -1
  73. package/dist/_chunks/{tasks-panel-8nLwBw6P.js → tasks-panel-BOb57Ysw.js} +2 -2
  74. package/dist/_chunks/{tasks-panel-8nLwBw6P.js.map → tasks-panel-BOb57Ysw.js.map} +1 -1
  75. package/dist/_chunks/{use-appointment-details-read-B-FEWbQM.js → use-appointment-details-read-CVSPoP5j.js} +4 -4
  76. package/dist/_chunks/{use-appointment-details-read-B-FEWbQM.js.map → use-appointment-details-read-CVSPoP5j.js.map} +1 -1
  77. package/dist/_chunks/voice-control-panel-BJIEbDq6.js +1148 -0
  78. package/dist/_chunks/voice-control-panel-BJIEbDq6.js.map +1 -0
  79. package/dist/_chunks/{warning-stack-HYWAytZV.js → warning-stack-BdY-0bd3.js} +2 -2
  80. package/dist/_chunks/{warning-stack-HYWAytZV.js.map → warning-stack-BdY-0bd3.js.map} +1 -1
  81. package/dist/_chunks/{workflow-map-C2B2qIr1.js → workflow-map-CYbRD9ek.js} +2 -2
  82. package/dist/_chunks/{workflow-map-C2B2qIr1.js.map → workflow-map-CYbRD9ek.js.map} +1 -1
  83. package/dist/agent-catalog.json +50 -3
  84. package/dist/agent-i18n/en.json +7 -4
  85. package/dist/components/_shared/use-apex-radial-centre.d.ts +7 -4
  86. package/dist/components/_shared/use-apex-radial-centre.d.ts.map +1 -1
  87. package/dist/components/ai-credits-notice/ai-credits-exhausted-notice.agent.d.ts +4 -0
  88. package/dist/components/ai-credits-notice/ai-credits-exhausted-notice.agent.d.ts.map +1 -0
  89. package/dist/components/ai-credits-notice/ai-credits-exhausted-notice.d.ts +96 -0
  90. package/dist/components/ai-credits-notice/ai-credits-exhausted-notice.d.ts.map +1 -0
  91. package/dist/components/ai-credits-notice/ai-credits-notice.d.ts +30 -4
  92. package/dist/components/ai-credits-notice/ai-credits-notice.d.ts.map +1 -1
  93. package/dist/components/ai-credits-notice/index.d.ts +3 -0
  94. package/dist/components/ai-credits-notice/index.d.ts.map +1 -1
  95. package/dist/components/ai-credits-notice/index.js +10 -4
  96. package/dist/components/ai-credits-notice/index.js.map +1 -1
  97. package/dist/components/ai-permission-notice/index.js +1 -1
  98. package/dist/components/alert/index.js +1 -1
  99. package/dist/components/appointment-details-panel/index.js +1 -1
  100. package/dist/components/audio-recorder/index.js +1 -1
  101. package/dist/components/booking/index.js +1 -1
  102. package/dist/components/chart/index.js +1 -1
  103. package/dist/components/document-preview/index.js +1 -1
  104. package/dist/components/document-scanner/index.js +1 -1
  105. package/dist/components/entity-summary/index.js +1 -1
  106. package/dist/components/error-summary/index.js +1 -1
  107. package/dist/components/freemium-paywall/index.js +1 -1
  108. package/dist/components/heatmap/heatmap-context.d.ts +3 -0
  109. package/dist/components/heatmap/heatmap-context.d.ts.map +1 -1
  110. package/dist/components/heatmap/heatmap-disclosure.d.ts +67 -0
  111. package/dist/components/heatmap/heatmap-disclosure.d.ts.map +1 -0
  112. package/dist/components/heatmap/heatmap-format.d.ts.map +1 -1
  113. package/dist/components/heatmap/heatmap-grid.d.ts +1 -1
  114. package/dist/components/heatmap/heatmap-grid.d.ts.map +1 -1
  115. package/dist/components/heatmap/heatmap-legend.d.ts +5 -2
  116. package/dist/components/heatmap/heatmap-legend.d.ts.map +1 -1
  117. package/dist/components/heatmap/heatmap-model.d.ts +107 -15
  118. package/dist/components/heatmap/heatmap-model.d.ts.map +1 -1
  119. package/dist/components/heatmap/heatmap-table-view.d.ts +3 -2
  120. package/dist/components/heatmap/heatmap-table-view.d.ts.map +1 -1
  121. package/dist/components/heatmap/heatmap.d.ts +33 -7
  122. package/dist/components/heatmap/heatmap.d.ts.map +1 -1
  123. package/dist/components/heatmap/index.d.ts +1 -1
  124. package/dist/components/heatmap/index.d.ts.map +1 -1
  125. package/dist/components/heatmap/index.js +1 -1
  126. package/dist/components/notes-panel/index.js +1 -1
  127. package/dist/components/patient-details/index.js +1 -1
  128. package/dist/components/patient-search/index.js +1 -1
  129. package/dist/components/patient-summary-card/index.js +1 -1
  130. package/dist/components/payment-form/index.js +1 -1
  131. package/dist/components/pdf-viewer/index.js +1 -1
  132. package/dist/components/practice-results/index.js +1 -1
  133. package/dist/components/rich-text-editor/index.js +1 -1
  134. package/dist/components/rich-text-editor/rich-text-editor.d.ts.map +1 -1
  135. package/dist/components/sign-document/index.js +1 -1
  136. package/dist/components/task-editor/index.js +1 -1
  137. package/dist/components/tasks-panel/index.js +1 -1
  138. package/dist/components/voice-control-panel/index.d.ts +2 -1
  139. package/dist/components/voice-control-panel/index.d.ts.map +1 -1
  140. package/dist/components/voice-control-panel/index.js +1 -1
  141. package/dist/components/voice-control-panel/voice-control-panel.agent.d.ts.map +1 -1
  142. package/dist/components/voice-control-panel/voice-control-panel.d.ts +43 -3
  143. package/dist/components/voice-control-panel/voice-control-panel.d.ts.map +1 -1
  144. package/dist/components/warning-stack/index.js +1 -1
  145. package/dist/components/workflow/index.js +1 -1
  146. package/dist/i18n/locales/ar.d.ts +29 -12
  147. package/dist/i18n/locales/ar.d.ts.map +1 -1
  148. package/dist/i18n/locales/ar.js +29 -12
  149. package/dist/i18n/locales/ar.js.map +1 -1
  150. package/dist/i18n/locales/de.d.ts +29 -12
  151. package/dist/i18n/locales/de.d.ts.map +1 -1
  152. package/dist/i18n/locales/de.js +29 -12
  153. package/dist/i18n/locales/de.js.map +1 -1
  154. package/dist/i18n/locales/el.d.ts +29 -12
  155. package/dist/i18n/locales/el.d.ts.map +1 -1
  156. package/dist/i18n/locales/el.js +29 -12
  157. package/dist/i18n/locales/el.js.map +1 -1
  158. package/dist/i18n/locales/en.d.ts +29 -12
  159. package/dist/i18n/locales/en.d.ts.map +1 -1
  160. package/dist/i18n/locales/en.js +29 -12
  161. package/dist/i18n/locales/en.js.map +1 -1
  162. package/dist/i18n/locales/es.d.ts +29 -12
  163. package/dist/i18n/locales/es.d.ts.map +1 -1
  164. package/dist/i18n/locales/es.js +29 -12
  165. package/dist/i18n/locales/es.js.map +1 -1
  166. package/dist/i18n/locales/fr.d.ts +29 -12
  167. package/dist/i18n/locales/fr.d.ts.map +1 -1
  168. package/dist/i18n/locales/fr.js +29 -12
  169. package/dist/i18n/locales/fr.js.map +1 -1
  170. package/dist/i18n/locales/hi.d.ts +29 -12
  171. package/dist/i18n/locales/hi.d.ts.map +1 -1
  172. package/dist/i18n/locales/hi.js +29 -12
  173. package/dist/i18n/locales/hi.js.map +1 -1
  174. package/dist/i18n/locales/it.d.ts +29 -12
  175. package/dist/i18n/locales/it.d.ts.map +1 -1
  176. package/dist/i18n/locales/it.js +29 -12
  177. package/dist/i18n/locales/it.js.map +1 -1
  178. package/dist/i18n/locales/ja.d.ts +29 -12
  179. package/dist/i18n/locales/ja.d.ts.map +1 -1
  180. package/dist/i18n/locales/ja.js +29 -12
  181. package/dist/i18n/locales/ja.js.map +1 -1
  182. package/dist/i18n/locales/nl.d.ts +29 -12
  183. package/dist/i18n/locales/nl.d.ts.map +1 -1
  184. package/dist/i18n/locales/nl.js +29 -12
  185. package/dist/i18n/locales/nl.js.map +1 -1
  186. package/dist/i18n/locales/pl.d.ts +29 -12
  187. package/dist/i18n/locales/pl.d.ts.map +1 -1
  188. package/dist/i18n/locales/pl.js +29 -12
  189. package/dist/i18n/locales/pl.js.map +1 -1
  190. package/dist/i18n/locales/pt.d.ts +29 -12
  191. package/dist/i18n/locales/pt.d.ts.map +1 -1
  192. package/dist/i18n/locales/pt.js +29 -12
  193. package/dist/i18n/locales/pt.js.map +1 -1
  194. package/dist/i18n/locales/ro.d.ts +29 -12
  195. package/dist/i18n/locales/ro.d.ts.map +1 -1
  196. package/dist/i18n/locales/ro.js +29 -12
  197. package/dist/i18n/locales/ro.js.map +1 -1
  198. package/dist/i18n/locales/ru.d.ts +29 -12
  199. package/dist/i18n/locales/ru.d.ts.map +1 -1
  200. package/dist/i18n/locales/ru.js +29 -12
  201. package/dist/i18n/locales/ru.js.map +1 -1
  202. package/dist/i18n/locales/sq.d.ts +29 -12
  203. package/dist/i18n/locales/sq.d.ts.map +1 -1
  204. package/dist/i18n/locales/sq.js +29 -12
  205. package/dist/i18n/locales/sq.js.map +1 -1
  206. package/dist/i18n/locales/sv.d.ts +29 -12
  207. package/dist/i18n/locales/sv.d.ts.map +1 -1
  208. package/dist/i18n/locales/sv.js +29 -12
  209. package/dist/i18n/locales/sv.js.map +1 -1
  210. package/dist/i18n/locales/tr.d.ts +29 -12
  211. package/dist/i18n/locales/tr.d.ts.map +1 -1
  212. package/dist/i18n/locales/tr.js +29 -12
  213. package/dist/i18n/locales/tr.js.map +1 -1
  214. package/dist/i18n/locales/zh.d.ts +29 -12
  215. package/dist/i18n/locales/zh.d.ts.map +1 -1
  216. package/dist/i18n/locales/zh.js +29 -12
  217. package/dist/i18n/locales/zh.js.map +1 -1
  218. package/dist/index.js +814 -809
  219. package/dist/index.js.map +1 -1
  220. package/dist/locales/ar.json +29 -12
  221. package/dist/locales/de.json +29 -12
  222. package/dist/locales/el.json +29 -12
  223. package/dist/locales/en.json +29 -12
  224. package/dist/locales/es.json +29 -12
  225. package/dist/locales/fr.json +29 -12
  226. package/dist/locales/hi.json +29 -12
  227. package/dist/locales/it.json +29 -12
  228. package/dist/locales/ja.json +29 -12
  229. package/dist/locales/nl.json +29 -12
  230. package/dist/locales/pl.json +29 -12
  231. package/dist/locales/pt.json +29 -12
  232. package/dist/locales/ro.json +29 -12
  233. package/dist/locales/ru.json +29 -12
  234. package/dist/locales/sq.json +29 -12
  235. package/dist/locales/sv.json +29 -12
  236. package/dist/locales/tr.json +29 -12
  237. package/dist/locales/zh.json +29 -12
  238. package/dist/patterns/anamnesis/index.js +1 -1
  239. package/dist/patterns/calendar/index.js +1 -1
  240. package/dist/patterns/forgot-password-form/index.js +1 -1
  241. package/dist/patterns/help-me-write-templates/help-me-write-templates.d.ts +6 -23
  242. package/dist/patterns/help-me-write-templates/help-me-write-templates.d.ts.map +1 -1
  243. package/dist/patterns/help-me-write-templates/index.js +8 -7
  244. package/dist/patterns/help-me-write-templates/index.js.map +1 -1
  245. package/dist/patterns/login-form/index.js +1 -1
  246. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  247. package/dist/patterns/payment-automation-upsell/index.js +1 -1
  248. package/dist/patterns/registration-form/index.js +1 -1
  249. package/dist/patterns/signature-request/index.js +1 -1
  250. package/dist/tokens.css +1 -1
  251. package/package.json +1 -1
  252. package/dist/_chunks/ai-credits-notice-pK9BOmEz.js +0 -90
  253. package/dist/_chunks/ai-credits-notice-pK9BOmEz.js.map +0 -1
  254. package/dist/_chunks/ai-credits-notice.agent-C9L7orrP.js +0 -17
  255. package/dist/_chunks/ai-credits-notice.agent-C9L7orrP.js.map +0 -1
  256. package/dist/_chunks/chart-CIzXxNeM.js +0 -1322
  257. package/dist/_chunks/chart-CIzXxNeM.js.map +0 -1
  258. package/dist/_chunks/heatmap-BxRHM8Et.js +0 -2865
  259. package/dist/_chunks/heatmap-BxRHM8Et.js.map +0 -1
  260. package/dist/_chunks/help-me-write-templates-DFmqnsAa.js +0 -747
  261. package/dist/_chunks/help-me-write-templates-DFmqnsAa.js.map +0 -1
  262. package/dist/_chunks/patient-field-row-CBXhlfGD.js.map +0 -1
  263. package/dist/_chunks/voice-control-panel-C0BfY23Y.js +0 -1009
  264. package/dist/_chunks/voice-control-panel-C0BfY23Y.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-credits-notice-DQ-r3iQU.js","sources":["../../src/components/ai-credits-notice/ai-credits-notice.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '../button';\nimport { Progress } from '../progress';\nimport { HoverCard, useHoverCardTiming } from '../hover-card';\nimport { formatLocale } from '../_shared/intl-locale';\n\n/* -------------------------------------------------------------------- */\n/* AiCreditsNotice */\n/* */\n/* The body of the hover card every AI action trigger in the kit shows: */\n/* AI features cost nothing extra today ('included'), or, once paid */\n/* credit bundles ship beside the practice's allowance, a nudge toward */\n/* them ('bundles'). The host decides which by passing `mode`; nothing */\n/* here reaches a backend or owns the upsell page itself — `onViewBundles` */\n/* is a seam, not a router. */\n/* */\n/* Renders INSIDE a `HoverCard.Content` (it uses `HoverCard.Eyebrow` / */\n/* `.Heading` / `.Body` / `.Footer`, the same composition `AppointmentPeek` */\n/* uses) — it never renders its own `HoverCard.Root`/`Trigger`. Callers */\n/* wrap it: `<HoverCard><HoverCard.Trigger asChild>{button}</HoverCard.Trigger>` */\n/* `<HoverCard.Content side=\"bottom\" align=\"start\" size=\"sm\"><AiCreditsNotice … /></HoverCard.Content></HoverCard>`. */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:flex ds:flex-col ds:items-start', {\n variants: {\n mode: {\n included: '',\n bundles: '',\n },\n },\n defaultVariants: {\n mode: 'included',\n },\n});\n\n/** The practice's current AI allowance, when the host tracks one. */\nexport interface AiCreditsNoticeAllowance {\n /** AI credits left. */\n remaining: number;\n /**\n * The allowance `remaining` counts down from, whatever its period (on\n * the platform, a yearly allowance).\n */\n limit: number;\n /** When the allowance next resets. Omit if unknown. */\n resetsOn?: Date;\n}\n\ninterface AiCreditsNoticeSharedProps {\n /**\n * The practice's current AI allowance. In `included` mode it renders as an\n * optional usage line + meter; in `bundles` mode it drives the heading\n * (\"{{remaining}} of {{limit}} credits\") and the allowance line in the\n * body. Omit either mode's allowance to fall back to a generic line.\n */\n allowance?: AiCreditsNoticeAllowance;\n className?: string;\n}\n\nexport interface AiCreditsNoticeIncludedProps extends AiCreditsNoticeSharedProps {\n mode: 'included';\n /** Shows a quiet \"Learn more\" link — wire it once the credits upsell page ships. */\n onLearnMore?: () => void;\n /**\n * Shows a quiet \"Don't show again\" link. The host decides what \"again\"\n * means — typically stop rendering `aiCreditsNotice` on the editor for the\n * rest of this mount, and persist the choice if it should survive a\n * reload (see the component's docs for a `usePersistentState` example).\n * Use a storage key scoped to the mode: switching from `included` to\n * `bundles` is a different message and should show once more.\n */\n onDismiss?: () => void;\n}\n\nexport interface AiCreditsNoticeBundlesProps extends AiCreditsNoticeSharedProps {\n mode: 'bundles';\n /** Opens the host's AI-credits bundle picker. The kit never builds that page itself. */\n onViewBundles: () => void;\n /** Shows a quiet \"What each action costs\" link. */\n onSeeCosts?: () => void;\n /** Shows a quiet \"Don't show again\" link. See the `included` prop of the\n * same name — the same mode-scoped-key guidance applies here too. */\n onDismiss?: () => void;\n}\n\nexport type AiCreditsNoticeProps =\n | AiCreditsNoticeIncludedProps\n | AiCreditsNoticeBundlesProps;\n\n/* Every callback either mode can carry, all optional at once. The footer\n reads them from `props`; this shape exists only so the component can\n destructure them OUT of the `rest` it spreads onto the root `<div>`.\n React resolves any `on[A-Z]…` prop as a DOM event, so leaving them in\n `rest` logged \"Unknown event handler property: onLearnMore\" (and one per\n sibling) on every render — and the editor renders this card on every AI\n trigger, so the warnings repeated on every hover (caught in review on\n #180). A cast, not four narrowed reads: `props` is a discriminated union\n and TypeScript refuses `onViewBundles` off the `included` arm. */\ntype AiCreditsNoticeCallbacks = Partial<\n Pick<AiCreditsNoticeIncludedProps, 'onLearnMore' | 'onDismiss'> &\n Pick<AiCreditsNoticeBundlesProps, 'onViewBundles' | 'onSeeCosts'>\n>;\n\nexport const AiCreditsNotice = forwardRef<\n HTMLDivElement,\n AiCreditsNoticeProps & Omit<HTMLAttributes<HTMLDivElement>, 'className'>\n>((props, ref) => {\n const { t, i18n } = useTranslation('ui');\n // Two steps, not one. The first reads straight off `props` so that\n // `mode === 'included'` below still narrows `props` itself (TypeScript's\n // aliased-discriminant narrowing) — destructuring off a cast breaks that\n // link and the footer's `props.onLearnMore` stops compiling. The second\n // strips the callbacks out of what is left, so `rest` reaches the DOM node\n // carrying only real HTML attributes. See `AiCreditsNoticeCallbacks`.\n const { allowance, className, mode, ...restWithCallbacks } = props;\n const {\n onLearnMore: _onLearnMore,\n onDismiss: _onDismiss,\n onViewBundles: _onViewBundles,\n onSeeCosts: _onSeeCosts,\n ...rest\n } = restWithCallbacks as typeof restWithCallbacks & AiCreditsNoticeCallbacks;\n\n // A `limit` of 0 (a host still loading, or a plan with no allowance at\n // all) would divide by zero in the Progress meter — treat it the same as\n // no allowance rather than rendering a broken 0/0 meter.\n const hasUsableAllowance = Boolean(allowance && allowance.limit > 0);\n\n const resetsOnText =\n hasUsableAllowance && allowance?.resetsOn\n ? // The allowance is yearly, so the year is part of the date.\n new Intl.DateTimeFormat(formatLocale(i18n.language), {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }).format(allowance.resetsOn)\n : undefined;\n\n const allowanceLine = hasUsableAllowance\n ? t('aiCreditsNotice.included.allowance', {\n remaining: allowance!.remaining,\n limit: allowance!.limit,\n })\n : undefined;\n\n // `hasUsableAllowance`, not a bare `allowance` check: a host still loading\n // sends `{ remaining: 0, limit: 0 }`, which read literally becomes \"0 of 0\n // credits\" and \"Your allowance is 0 AI credits\": two sentences\n // that are wrong rather than merely vague. `included` already treated a\n // zero limit as no allowance; `bundles` now agrees and falls back to the\n // generic lines (caught in review on #180).\n const heading =\n mode === 'included'\n ? t('aiCreditsNotice.included.heading')\n : hasUsableAllowance\n ? t('aiCreditsNotice.bundles.headingWithAllowance', {\n remaining: allowance!.remaining,\n limit: allowance!.limit,\n })\n : t('aiCreditsNotice.bundles.eyebrow');\n\n const body =\n mode === 'included'\n ? t('aiCreditsNotice.included.body')\n : hasUsableAllowance\n ? t('aiCreditsNotice.bundles.body', { limit: allowance!.limit })\n : t('aiCreditsNotice.bundles.bodyGeneric');\n\n return (\n <div\n {...rest}\n ref={ref}\n // AFTER `rest`, not before: these are the required agent-readiness DOM\n // hooks (see 26-agent-readiness.mdx §A3) and must always win over\n // anything a caller passes through the HTMLAttributes spread — a\n // caller-supplied `data-component` must never be able to replace the\n // component's own marker.\n data-component=\"ai-credits-notice\"\n data-mode={mode}\n className={rootVariants({ mode, className })}\n >\n <HoverCard.Eyebrow>\n {mode === 'included'\n ? t('aiCreditsNotice.included.eyebrow')\n : t('aiCreditsNotice.bundles.eyebrow')}\n </HoverCard.Eyebrow>\n <HoverCard.Heading>{heading}</HoverCard.Heading>\n <HoverCard.Body>\n <p className=\"ds:m-0\">{body}</p>\n {mode === 'included' && hasUsableAllowance ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)] ds:[margin-block-start:var(--spacing-sm)]\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span className=\"type-label\">{allowanceLine}</span>\n </div>\n <Progress\n value={Math.max(0, allowance!.limit - allowance!.remaining)}\n max={allowance!.limit}\n size=\"sm\"\n ariaLabel={t('aiCreditsNotice.included.eyebrow')}\n ariaValueText={allowanceLine}\n />\n {resetsOnText ? (\n <p className=\"ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiCreditsNotice.included.resetsOn', { date: resetsOnText })}\n </p>\n ) : null}\n </div>\n ) : null}\n </HoverCard.Body>\n {mode === 'included' ? (\n props.onLearnMore || props.onDismiss ? (\n <HoverCard.Footer>\n {props.onDismiss ? (\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={props.onDismiss}\n className=\"ds:me-auto\"\n >\n {t('aiCreditsNotice.dismiss')}\n </Button>\n ) : null}\n {props.onLearnMore ? (\n <Button intent=\"link\" size=\"sm\" onClick={props.onLearnMore}>\n {t('aiCreditsNotice.included.learnMore')}\n </Button>\n ) : null}\n </HoverCard.Footer>\n ) : null\n ) : (\n <HoverCard.Footer>\n {props.onSeeCosts || props.onDismiss ? (\n <div className=\"ds:me-auto ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {props.onSeeCosts ? (\n <Button intent=\"link\" size=\"sm\" onClick={props.onSeeCosts}>\n {t('aiCreditsNotice.bundles.seeCosts')}\n </Button>\n ) : null}\n {props.onDismiss ? (\n <Button intent=\"link\" size=\"sm\" onClick={props.onDismiss}>\n {t('aiCreditsNotice.dismiss')}\n </Button>\n ) : null}\n </div>\n ) : null}\n <Button intent=\"tonal\" size=\"sm\" onClick={props.onViewBundles}>\n {t('aiCreditsNotice.bundles.viewBundles')}\n </Button>\n </HoverCard.Footer>\n )}\n </div>\n );\n});\nAiCreditsNotice.displayName = 'AiCreditsNotice';\n\n/* ------------------------------------------------------------------ */\n/* AiActionHoverCard */\n/* */\n/* Wraps ONE AI action trigger (a pill segment, the Templates menu's own */\n/* trigger, a selection-bubble button, the VoiceControlPanel's mic) in */\n/* the credits/bundles hover card, when the host passes */\n/* `aiCreditsNotice`. Every AI trigger is wrapped here, in this one */\n/* place, so a future AI action inherits it for free. Moved here from */\n/* RichTextEditor so VoiceControlPanel shares it. */\n/* */\n/* Anchored, not `HoverCard.Trigger asChild` on the button itself: the */\n/* Templates trigger already spends its one `asChild` slot on */\n/* `DropdownMenu.Trigger`, and Radix can only merge one `asChild` layer */\n/* onto a given element. Anchoring sidesteps that entirely and, as a */\n/* side effect, keeps the click path completely untouched: the button's */\n/* own `onClick` (the action, or the consent gate) runs exactly as it */\n/* does with no notice configured, because this wrapper never touches */\n/* `onClick` at all. Escape closes it via Radix's own dismiss layer on */\n/* `HoverCard.Content`, same as any other HoverCard. Tabbing onto the */\n/* button reveals the card WITHOUT moving focus into it (focus stays on */\n/* the button): the same \"look, don't pull me in\" contract HoverCard's */\n/* own Trigger uses for a Tab-driven open. */\n/* */\n/* CLOSING goes through `useHoverCardTiming()`, the SAME timer */\n/* `HoverCard.Content` itself cancels on hover/focus and re-arms on */\n/* leave/blur, never a private `setTimeout`. A private timer here was a */\n/* real bug: leaving the trigger for the (portalled) content cancelled */\n/* the ROOT's timer, which was never the one counting down, so this */\n/* wrapper's own timer fired on schedule and closed the card out from */\n/* under the reader reaching for \"Learn more\" / \"View bundles\" / \"Don't */\n/* show again\". OPENING stays bespoke (a local delay + the */\n/* pointer-vs-keyboard distinction below), since Root's own open timing */\n/* isn't part of the public contract and this wrapper's \"only a genuine */\n/* Tab opens it\" rule deliberately differs from Trigger's default. */\n/* ------------------------------------------------------------------ */\nfunction AiActionHoverCard({\n notice,\n side,\n children,\n}: {\n notice: AiCreditsNoticeProps;\n side: AiActionHoverCardSide;\n children: ReactNode;\n}): ReactNode {\n const [open, setOpen] = useState(false);\n return (\n <HoverCard open={open} onOpenChange={setOpen}>\n <AiActionHoverCardAnchor\n onOpen={() => setOpen(true)}\n onPress={() => setOpen(false)}\n >\n {children}\n </AiActionHoverCardAnchor>\n <HoverCard.Content\n side={side}\n align=\"start\"\n size=\"sm\"\n collisionPadding={8}\n >\n <AiCreditsNotice {...notice} />\n </HoverCard.Content>\n </HoverCard>\n );\n}\n\n/** The anchor + hover/focus timing for `AiActionHoverCard`, split out so it\n * can call `useHoverCardTiming()` as a descendant of the `<HoverCard>` it's\n * rendered inside. */\nfunction AiActionHoverCardAnchor({\n onOpen,\n onPress,\n children,\n}: {\n onOpen: () => void;\n /** Called on a pointer press, to drop a card this press must not leave up. */\n onPress: () => void;\n children: ReactNode;\n}): ReactNode {\n const { cancelClose, closeWithDelay } = useHoverCardTiming();\n const openTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const clearOpenTimer = useCallback(() => {\n if (openTimerRef.current) {\n clearTimeout(openTimerRef.current);\n openTimerRef.current = null;\n }\n }, []);\n useEffect(() => clearOpenTimer, [clearOpenTimer]);\n\n const openWithDelay = useCallback(() => {\n clearOpenTimer();\n // In case a close was already scheduled from a rapid leave-then-reenter\n // of the anchor itself.\n cancelClose();\n openTimerRef.current = setTimeout(onOpen, 300);\n }, [clearOpenTimer, cancelClose, onOpen]);\n const scheduleClose = useCallback(() => {\n clearOpenTimer();\n closeWithDelay();\n }, [clearOpenTimer, closeWithDelay]);\n\n // A pointer press must leave NO card up, or a click on a trigger that\n // opens its own menu (Templates) stacks a second dismissable layer on top\n // of it and Escape closes ours instead of the menu's (Radix only lets the\n // highest layer act on Escape). `notePointerDown` is the single choke\n // point for both routes a press opens this card by: the focus that follows\n // a click (suppressed once via the flag) and the hover that preceded it\n // (its 300 ms timer cancelled, and any card already up dropped).\n //\n // The flag only gets CONSUMED inside `openOnFocus`, so a press that never\n // produces a focus event at all (several selection-bubble buttons call\n // `preventDefault()` on their own `mousedown` to keep the text selection\n // alive, which also suppresses the browser's default focus-follows-click)\n // left it stuck `true` forever, silently swallowing the NEXT genuine Tab\n // onto that same trigger. A document-level `keydown` (any key, not just\n // this trigger's own) means \"the user is on the keyboard now\" and drops\n // the stale flag before that Tab's own focus event is evaluated.\n const pointerPressedRef = useRef(false);\n const notePointerDown = useCallback(() => {\n pointerPressedRef.current = true;\n clearOpenTimer();\n onPress();\n }, [clearOpenTimer, onPress]);\n useEffect(() => {\n const clearPointerFlag = () => {\n pointerPressedRef.current = false;\n };\n document.addEventListener('keydown', clearPointerFlag);\n return () => document.removeEventListener('keydown', clearPointerFlag);\n }, []);\n const openOnFocus = useCallback(() => {\n if (pointerPressedRef.current) {\n pointerPressedRef.current = false;\n return;\n }\n clearOpenTimer();\n cancelClose();\n onOpen();\n }, [clearOpenTimer, cancelClose, onOpen]);\n\n return (\n // `ds:inline-flex`, NOT `ds:contents`, so this span has a real box\n // that hugs the button and Floating UI has a real rect to measure.\n // `display: contents` generates no box of its own; inside the pill's\n // flex/absolute layout that collapsed to a zero-size rect at the\n // editor's origin, so the card rendered top-left instead of at the\n // trigger (caught in review on :6007).\n <HoverCard.Anchor asChild>\n <span\n className=\"ds:inline-flex\"\n onMouseEnter={openWithDelay}\n onMouseLeave={scheduleClose}\n onPointerDown={notePointerDown}\n onFocusCapture={openOnFocus}\n onBlurCapture={scheduleClose}\n >\n {children}\n </span>\n </HoverCard.Anchor>\n );\n}\n\n/** Which side of the trigger the card opens on. A trigger fixed to the\n * bottom of the viewport (the VoiceControlPanel pill) opens it on top. */\nexport type AiActionHoverCardSide = 'top' | 'bottom';\n\n/**\n * Wraps `trigger` in the credits notice when `notice` is given, else returns\n * it unchanged: the one seam every kit AI trigger goes through (the\n * RichTextEditor's pill, bubble and mics, and the VoiceControlPanel's mic).\n * Internal to the kit: not exported from the component's index.\n */\nexport function withAiCreditsNotice(\n trigger: ReactNode,\n notice: AiCreditsNoticeProps | undefined,\n side: AiActionHoverCardSide = 'bottom',\n): ReactNode {\n return notice ? (\n <AiActionHoverCard notice={notice} side={side}>\n {trigger}\n </AiActionHoverCard>\n ) : (\n trigger\n );\n}\n\n/**\n * \"Don't show again\" (`onDismiss`) stops the card on EVERY trigger for the\n * rest of this mount, not just the trigger it was dismissed from. Scoped to\n * the MODE that was dismissed: `included` and `bundles` are different\n * messages, so a host that flips the same mounted component's mode (for\n * example once bundles ship) must see the new one, matching the\n * mode-scoped storage key the docs tell a host to use across a remount. A\n * SET, not a single slot: dismissing both modes in turn must remember both.\n * Reset only by remounting; a host that wants a dismissal to survive a\n * reload persists it itself and omits the notice on the next mount. Moved\n * here from RichTextEditor so VoiceControlPanel shares it.\n */\nexport function useDismissibleAiCreditsNotice(\n notice: AiCreditsNoticeProps | undefined,\n): AiCreditsNoticeProps | undefined {\n const [dismissedModes, setDismissedModes] = useState<\n ReadonlySet<AiCreditsNoticeProps['mode']>\n >(() => new Set());\n return useMemo<AiCreditsNoticeProps | undefined>(() => {\n if (!notice) return undefined;\n if (dismissedModes.has(notice.mode)) return undefined;\n if (!notice.onDismiss) return notice;\n const hostOnDismiss = notice.onDismiss;\n const modeBeingShown = notice.mode;\n return {\n ...notice,\n onDismiss: () => {\n setDismissedModes((prev) => new Set(prev).add(modeBeingShown));\n hostOnDismiss();\n },\n } as AiCreditsNoticeProps;\n }, [notice, dismissedModes]);\n}\n"],"names":["rootVariants","cva","AiCreditsNotice","forwardRef","props","ref","t","i18n","useTranslation","allowance","className","mode","restWithCallbacks","_onLearnMore","_onDismiss","_onViewBundles","_onSeeCosts","rest","hasUsableAllowance","resetsOnText","formatLocale","allowanceLine","heading","body","jsxs","jsx","HoverCard","Progress","Button","AiActionHoverCard","notice","side","children","open","setOpen","useState","AiActionHoverCardAnchor","onOpen","onPress","cancelClose","closeWithDelay","useHoverCardTiming","openTimerRef","useRef","clearOpenTimer","useCallback","useEffect","openWithDelay","scheduleClose","pointerPressedRef","notePointerDown","clearPointerFlag","openOnFocus","withAiCreditsNotice","trigger","useDismissibleAiCreditsNotice","dismissedModes","setDismissedModes","useMemo","hostOnDismiss","modeBeingShown","prev"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { jsxs as d, jsx as n } from "react/jsx-runtime";
2
2
  import { forwardRef as z, useState as C, useRef as E, useMemo as F } from "react";
3
3
  import { c as M } from "./index-D2ZczOXr.js";
4
4
  import { useTranslation as P } from "react-i18next";
5
- import { A as g } from "./alert-DdDpOi-P.js";
5
+ import { A as g } from "./alert-DjsJMGRE.js";
6
6
  import { B as D } from "./badge-BUk4RjTS.js";
7
7
  import { B as H } from "./button-D-MQxsA_.js";
8
8
  import { C as J } from "./checkbox-BjDv-r3o.js";
@@ -203,4 +203,4 @@ export {
203
203
  Q as A,
204
204
  $ as a
205
205
  };
206
- //# sourceMappingURL=ai-permission-notice-DpRmZ9Q3.js.map
206
+ //# sourceMappingURL=ai-permission-notice-qsdm4Sx4.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-permission-notice-DpRmZ9Q3.js","sources":["../../src/components/ai-permission-notice/ai-permission-notice.agent.ts","../../src/components/ai-permission-notice/ai-permission-notice.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — AiConsentBanner. */\n/* */\n/* Read-only structural surface: the current consent state and whether */\n/* the grant affordance is armed. Identifiers / structural state ONLY — */\n/* never the grantee's name or any PHI. The real consent gate lives */\n/* server-side; this adapter does not expose a grant action so an agent */\n/* cannot consent on a user's behalf. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AiConsentBannerHandle } from './ai-permission-notice';\n\nexport const aiConsentBannerAgent: AgentAdapter<AiConsentBannerHandle> = {\n id: 'ai-consent-banner',\n capabilities: [],\n state: {\n consentState: {\n type: \"'granted' | 'required' | 'pending'\",\n descriptionKey: 'ui.agent.aiConsentBanner.state.consentState',\n description:\n 'Current consent state. Structural only — never the grantee identity.',\n read: (handle) => handle.getState(),\n },\n armed: {\n type: 'boolean',\n descriptionKey: 'ui.agent.aiConsentBanner.state.armed',\n description:\n 'Whether the consent confirmation checkbox is ticked (required state only).',\n read: (handle) => handle.isArmed(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'ai-consent-banner',\n description: 'Marks the AiConsentBanner root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific banner from the agent.',\n },\n },\n};\n","import {\n forwardRef,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Alert } from '../alert/alert';\nimport { Badge } from '../badge/badge';\nimport { Button } from '../button/button';\nimport { Checkbox } from '../checkbox/checkbox';\nimport { Spinner } from '../spinner/spinner';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { aiConsentBannerAgent } from './ai-permission-notice.agent';\n\n/* -------------------------------------------------------------------- */\n/* AiConsentBanner */\n/* */\n/* Presentational AI-consent gate surfaced above an AI-assisted surface */\n/* (e.g. Alfascribe consultation transcription). The SERVER owns the */\n/* real gate — this component only reflects the consent record and lets */\n/* the operator initiate a grant; it never enforces access itself. */\n/* */\n/* Three states drive the Alert variant + body: */\n/* - granted → success Alert with a Badge + when/who it was granted. */\n/* - required → info Alert with a Checkbox-gated Grant Button. */\n/* - pending → info Alert in a disabled, Spinner-busy state while the */\n/* server persists the grant. */\n/* */\n/* All kit text flows through useTranslation('ui') against the */\n/* `aiConsentBanner.*` namespace. `subject` picks the kit-owned wording */\n/* preset; `copy` lets a host replace single strings with its own text. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA — root */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n state: {\n granted: '',\n required: '',\n pending: '',\n },\n },\n defaultVariants: {\n state: 'required',\n },\n});\n\n/* -------------------------------------------------------------------- */\n/* State derivation */\n/* -------------------------------------------------------------------- */\n\nexport type AiConsentState = NonNullable<\n VariantProps<typeof rootVariants>['state']\n>;\n\n/** Heading levels `AiConsentBanner.headingLevel` accepts. */\nexport type AiConsentBannerHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\n/** Pending wins over granted/required so the busy state is never masked. */\nfunction deriveState(granted: boolean, pending: boolean): AiConsentState {\n if (pending) return 'pending';\n return granted ? 'granted' : 'required';\n}\n\n/* -------------------------------------------------------------------- */\n/* Subject presets */\n/* -------------------------------------------------------------------- */\n\n/** What the consent covers; each subject has kit-owned, translated wording.\n * `'patient-record'` (default) is one patient's record. `'practice-statistics'`\n * is the practice's aggregate figures (totals, rates), never patient data. */\nexport type AiConsentSubject = 'patient-record' | 'practice-statistics';\n\ntype AiConsentSubjectField =\n | 'descriptionRequired'\n | 'descriptionGranted'\n | 'confirmLabel'\n | 'notAllowed';\n\n/* Only these four strings differ by subject; the rest share one key each. */\nconst SUBJECT_KEYS = {\n 'patient-record': {\n descriptionRequired: {\n key: 'aiConsentBanner.description.required',\n fallback: 'AI assistance requires recorded consent before it can run.',\n },\n descriptionGranted: {\n key: 'aiConsentBanner.description.granted',\n fallback: 'AI assistance is enabled for this record.',\n },\n confirmLabel: {\n key: 'aiConsentBanner.confirmLabel',\n fallback: 'I confirm consent has been obtained for AI assistance.',\n },\n notAllowed: {\n key: 'aiConsentBanner.notAllowed',\n fallback: 'You do not have permission to grant AI assistance consent.',\n },\n },\n 'practice-statistics': {\n descriptionRequired: {\n key: 'aiConsentBanner.practiceStatistics.description.required',\n fallback:\n \"AI assistance needs consent before it can read this practice's statistics. It uses aggregate figures only, never patient data.\",\n },\n descriptionGranted: {\n key: 'aiConsentBanner.practiceStatistics.description.granted',\n fallback:\n \"AI assistance can read this practice's statistics. It uses aggregate figures only, never patient data.\",\n },\n confirmLabel: {\n key: 'aiConsentBanner.practiceStatistics.confirmLabel',\n fallback:\n 'I may decide for this practice, and I agree to AI assistance reading its statistics.',\n },\n notAllowed: {\n key: 'aiConsentBanner.practiceStatistics.notAllowed',\n fallback:\n 'You do not have permission to grant AI assistance consent for this practice.',\n },\n },\n} as const satisfies Record<\n AiConsentSubject,\n Record<AiConsentSubjectField, { key: string; fallback: string }>\n>;\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/**\n * Patient AI-consent gate for an AI surface that sends patient data to a\n * service: the RichTextEditor's Help-me-write action and dictation mics, and\n * the VoiceControlPanel's microphone. Omit entirely for today's ungated\n * behaviour — no existing host breaks.\n *\n * Present and `granted: false`: the affordances stay visible (this never\n * hides a control), but using one shows the kit's `AiConsentBanner` instead\n * of starting the AI action. When `granted` flips `true` after a Grant click\n * in that banner, the surface resumes exactly the action it gated; when it\n * flips for any other reason (another patient, another tab) it only closes\n * the banner.\n *\n * Present and `granted: true`: normal behaviour.\n */\nexport interface AiConsentGate {\n /** Whether AI consent has already been recorded for the current patient. */\n granted: boolean;\n /** When consent was granted — passed straight to `AiConsentBanner`. */\n grantedAt?: string | number | Date;\n /** Who granted consent — passed straight to `AiConsentBanner`. */\n grantedBy?: string;\n /** Whether the signed-in reader may grant consent. Default `true`; treated\n * as `false` when `onGrant` is absent, so no dead Grant control shows. */\n canGrant?: boolean;\n /** The grant is being persisted server-side (host-driven busy state). */\n pending?: boolean;\n /**\n * Fired when the reader confirms the grant in the banner. A returned\n * promise drives the banner's own pending/Spinner state until it settles,\n * in addition to (or absent) a host-supplied `pending`.\n */\n onGrant?: () => void | Promise<void>;\n}\n\n/** Host-translated strings; the host owns their wording and translation.\n * Each one replaces the `subject` preset for that string only. Plain text,\n * not i18n keys: interpolate any values (a practice name) before passing. */\nexport interface AiConsentBannerCopy {\n /** Banner heading. */\n title?: string;\n /** Description in the required and pending states. */\n descriptionRequired?: string;\n /** Description in the granted state. */\n descriptionGranted?: string;\n /** Label of the confirmation checkbox. */\n confirmLabel?: string;\n /** Label of the Grant button. */\n grantButton?: string;\n /** Note shown instead of the grant controls when `canGrant` is false. */\n notAllowed?: string;\n /** Badge text in the granted state. */\n badgeGranted?: string;\n /** Busy text (and Spinner label) in the pending state. */\n pendingLabel?: string;\n}\n\n/** Agent-readiness curated handle. Exposes the structural consent state only. */\nexport interface AiConsentBannerHandle {\n /** Current derived state: 'granted' | 'required' | 'pending'. */\n getState: () => AiConsentState;\n /** Whether the Grant affordance is currently armed (checkbox ticked). */\n isArmed: () => boolean;\n}\n\nexport interface AiConsentBannerProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children' | 'role'\n> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so an\n * agent / MCP UI bridge can address this specific banner. Mirrored to the\n * real DOM `id`.\n */\n id?: string;\n /** Whether consent has already been granted. Server-sourced. */\n granted: boolean;\n /**\n * When consent was granted — ISO-8601 string, ms-epoch, or Date. Rendered\n * via `Timestamp` in the granted state.\n */\n grantedAt?: string | number | Date;\n /** Who granted consent (operator display name / role). Granted state only. */\n grantedBy?: string;\n /**\n * Whether the current user is allowed to grant consent. When `false`, the\n * required-state Grant affordance is hidden and a not-allowed note shows.\n * Default `true`.\n */\n canGrant?: boolean;\n /** The grant is being persisted server-side — shows the busy Spinner state. */\n pending?: boolean;\n /** Fired when the operator confirms the consent grant. */\n onGrantConsent?: () => void;\n /**\n * Heading level for the banner's own title, so it can be nested under a\n * host section's heading without skipping levels (axe `heading-order`).\n * Additive: default `5` matches the banner's original, unconditional\n * `<h5>` — every existing consumer is unaffected.\n */\n headingLevel?: AiConsentBannerHeadingLevel;\n /** What the consent covers; picks the kit's translated wording. Default\n * `'patient-record'`, which renders exactly as before this prop existed. */\n subject?: AiConsentSubject;\n /** Host-translated strings; the host owns their wording and translation.\n * Each key overrides only its own string. `title` also names the region,\n * unless `aria-label` is passed. */\n copy?: Partial<AiConsentBannerCopy>;\n /** Override the region's accessible name. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const AiConsentBanner = forwardRef<HTMLDivElement, AiConsentBannerProps>(\n (\n {\n id,\n granted,\n grantedAt,\n grantedBy,\n canGrant = true,\n pending = false,\n onGrantConsent,\n headingLevel = 5,\n subject = 'patient-record',\n copy,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const state = deriveState(granted, pending);\n\n // A host string wins over the preset for that string only. A blank or\n // whitespace-only one counts as missing, so no control loses its name.\n const own = (value?: string) => value?.trim() || undefined;\n // An unknown subject from an untyped host falls back to the default.\n const keys = SUBJECT_KEYS[subject] ?? SUBJECT_KEYS['patient-record'];\n const text = {\n title:\n own(copy?.title) || t('aiConsentBanner.title', 'AI assistance consent'),\n descriptionRequired:\n own(copy?.descriptionRequired) ||\n t(keys.descriptionRequired.key, keys.descriptionRequired.fallback),\n descriptionGranted:\n own(copy?.descriptionGranted) ||\n t(keys.descriptionGranted.key, keys.descriptionGranted.fallback),\n confirmLabel:\n own(copy?.confirmLabel) ||\n t(keys.confirmLabel.key, keys.confirmLabel.fallback),\n grantButton:\n own(copy?.grantButton) ||\n t('aiConsentBanner.grantButton', 'Grant consent'),\n notAllowed:\n own(copy?.notAllowed) ||\n t(keys.notAllowed.key, keys.notAllowed.fallback),\n badgeGranted:\n own(copy?.badgeGranted) ||\n t('aiConsentBanner.badge.granted', 'Consent granted'),\n pendingLabel:\n own(copy?.pendingLabel) ||\n t('aiConsentBanner.pendingLabel', 'Saving consent…'),\n };\n\n // Grant stays disabled until the checkbox is ticked. Any change of subject\n // or statement unticks it, even back to an earlier one, so a tick only\n // confirms what was on screen when it was given.\n const statement = [\n subject,\n text.confirmLabel,\n text.descriptionRequired,\n ].join('\\u0000');\n const [ticked, setTicked] = useState(false);\n const [tickedFor, setTickedFor] = useState(statement);\n if (tickedFor !== statement) {\n setTickedFor(statement);\n setTicked(false);\n }\n const armed = ticked && tickedFor === statement;\n\n const armedRef = useRef(armed);\n armedRef.current = armed;\n\n const handle = useMemo<AiConsentBannerHandle>(\n () => ({\n getState: () => deriveState(granted, pending),\n isArmed: () => armedRef.current,\n }),\n [granted, pending],\n );\n useAgentRegistration(aiConsentBannerAgent, handle, id);\n\n // A host title also names the region, so the name matches the heading.\n const resolvedAriaLabel =\n own(ariaLabel) ||\n own(copy?.title) ||\n t('aiConsentBanner.regionLabel', 'AI assistance consent');\n\n // Alert variant per state: granted → success, required/pending → info.\n const alertVariant = state === 'granted' ? 'success' : 'info';\n\n let body: React.ReactNode;\n if (state === 'granted') {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Badge variant=\"success\">{text.badgeGranted}</Badge>\n {grantedAt !== undefined ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedAtPrefix', 'Granted')}{' '}\n <Timestamp value={grantedAt} format=\"relative\" shape=\"inline\" />\n </span>\n ) : null}\n </div>\n {grantedBy ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedBy', {\n name: grantedBy,\n defaultValue: 'By {{name}}',\n })}\n </p>\n ) : null}\n </div>\n );\n } else if (state === 'pending') {\n body = (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Spinner variant=\"pulse\" size=\"sm\" label={text.pendingLabel} />\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {text.pendingLabel}\n </span>\n </div>\n );\n } else {\n // required\n body = canGrant ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <Checkbox\n checked={armed}\n onCheckedChange={(next) => setTicked(next === true)}\n label={text.confirmLabel}\n />\n <Alert.Action>\n <Button\n intent=\"primary\"\n size=\"sm\"\n disabled={!armed}\n onClick={onGrantConsent}\n >\n {text.grantButton}\n </Button>\n </Alert.Action>\n </div>\n ) : (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {text.notAllowed}\n </p>\n );\n }\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-busy={state === 'pending' ? true : undefined}\n data-component=\"ai-consent-banner\"\n data-component-id={id}\n data-state={state}\n id={id}\n className={rootVariants({ state, className })}\n {...rest}\n >\n <Alert\n variant={alertVariant}\n icon={state === 'pending' ? null : undefined}\n >\n <Alert.Title as={`h${headingLevel}` as const}>\n {text.title}\n </Alert.Title>\n <Alert.Description>\n {state === 'granted'\n ? text.descriptionGranted\n : text.descriptionRequired}\n </Alert.Description>\n {body}\n </Alert>\n </div>\n );\n },\n);\n\nAiConsentBanner.displayName = 'AiConsentBanner';\n"],"names":["aiConsentBannerAgent","handle","rootVariants","cva","deriveState","granted","pending","SUBJECT_KEYS","AiConsentBanner","forwardRef","id","grantedAt","grantedBy","canGrant","onGrantConsent","headingLevel","subject","copy","ariaLabel","className","rest","ref","useTranslation","state","own","value","keys","text","statement","ticked","setTicked","useState","tickedFor","setTickedFor","armed","armedRef","useRef","useMemo","useAgentRegistration","resolvedAriaLabel","alertVariant","body","jsxs","jsx","Badge","Timestamp","Spinner","Checkbox","next","Alert","Button"],"mappings":"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"}
1
+ {"version":3,"file":"ai-permission-notice-qsdm4Sx4.js","sources":["../../src/components/ai-permission-notice/ai-permission-notice.agent.ts","../../src/components/ai-permission-notice/ai-permission-notice.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — AiConsentBanner. */\n/* */\n/* Read-only structural surface: the current consent state and whether */\n/* the grant affordance is armed. Identifiers / structural state ONLY — */\n/* never the grantee's name or any PHI. The real consent gate lives */\n/* server-side; this adapter does not expose a grant action so an agent */\n/* cannot consent on a user's behalf. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AiConsentBannerHandle } from './ai-permission-notice';\n\nexport const aiConsentBannerAgent: AgentAdapter<AiConsentBannerHandle> = {\n id: 'ai-consent-banner',\n capabilities: [],\n state: {\n consentState: {\n type: \"'granted' | 'required' | 'pending'\",\n descriptionKey: 'ui.agent.aiConsentBanner.state.consentState',\n description:\n 'Current consent state. Structural only — never the grantee identity.',\n read: (handle) => handle.getState(),\n },\n armed: {\n type: 'boolean',\n descriptionKey: 'ui.agent.aiConsentBanner.state.armed',\n description:\n 'Whether the consent confirmation checkbox is ticked (required state only).',\n read: (handle) => handle.isArmed(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'ai-consent-banner',\n description: 'Marks the AiConsentBanner root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific banner from the agent.',\n },\n },\n};\n","import {\n forwardRef,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Alert } from '../alert/alert';\nimport { Badge } from '../badge/badge';\nimport { Button } from '../button/button';\nimport { Checkbox } from '../checkbox/checkbox';\nimport { Spinner } from '../spinner/spinner';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { aiConsentBannerAgent } from './ai-permission-notice.agent';\n\n/* -------------------------------------------------------------------- */\n/* AiConsentBanner */\n/* */\n/* Presentational AI-consent gate surfaced above an AI-assisted surface */\n/* (e.g. Alfascribe consultation transcription). The SERVER owns the */\n/* real gate — this component only reflects the consent record and lets */\n/* the operator initiate a grant; it never enforces access itself. */\n/* */\n/* Three states drive the Alert variant + body: */\n/* - granted → success Alert with a Badge + when/who it was granted. */\n/* - required → info Alert with a Checkbox-gated Grant Button. */\n/* - pending → info Alert in a disabled, Spinner-busy state while the */\n/* server persists the grant. */\n/* */\n/* All kit text flows through useTranslation('ui') against the */\n/* `aiConsentBanner.*` namespace. `subject` picks the kit-owned wording */\n/* preset; `copy` lets a host replace single strings with its own text. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA — root */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n state: {\n granted: '',\n required: '',\n pending: '',\n },\n },\n defaultVariants: {\n state: 'required',\n },\n});\n\n/* -------------------------------------------------------------------- */\n/* State derivation */\n/* -------------------------------------------------------------------- */\n\nexport type AiConsentState = NonNullable<\n VariantProps<typeof rootVariants>['state']\n>;\n\n/** Heading levels `AiConsentBanner.headingLevel` accepts. */\nexport type AiConsentBannerHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\n/** Pending wins over granted/required so the busy state is never masked. */\nfunction deriveState(granted: boolean, pending: boolean): AiConsentState {\n if (pending) return 'pending';\n return granted ? 'granted' : 'required';\n}\n\n/* -------------------------------------------------------------------- */\n/* Subject presets */\n/* -------------------------------------------------------------------- */\n\n/** What the consent covers; each subject has kit-owned, translated wording.\n * `'patient-record'` (default) is one patient's record. `'practice-statistics'`\n * is the practice's aggregate figures (totals, rates), never patient data. */\nexport type AiConsentSubject = 'patient-record' | 'practice-statistics';\n\ntype AiConsentSubjectField =\n | 'descriptionRequired'\n | 'descriptionGranted'\n | 'confirmLabel'\n | 'notAllowed';\n\n/* Only these four strings differ by subject; the rest share one key each. */\nconst SUBJECT_KEYS = {\n 'patient-record': {\n descriptionRequired: {\n key: 'aiConsentBanner.description.required',\n fallback: 'AI assistance requires recorded consent before it can run.',\n },\n descriptionGranted: {\n key: 'aiConsentBanner.description.granted',\n fallback: 'AI assistance is enabled for this record.',\n },\n confirmLabel: {\n key: 'aiConsentBanner.confirmLabel',\n fallback: 'I confirm consent has been obtained for AI assistance.',\n },\n notAllowed: {\n key: 'aiConsentBanner.notAllowed',\n fallback: 'You do not have permission to grant AI assistance consent.',\n },\n },\n 'practice-statistics': {\n descriptionRequired: {\n key: 'aiConsentBanner.practiceStatistics.description.required',\n fallback:\n \"AI assistance needs consent before it can read this practice's statistics. It uses aggregate figures only, never patient data.\",\n },\n descriptionGranted: {\n key: 'aiConsentBanner.practiceStatistics.description.granted',\n fallback:\n \"AI assistance can read this practice's statistics. It uses aggregate figures only, never patient data.\",\n },\n confirmLabel: {\n key: 'aiConsentBanner.practiceStatistics.confirmLabel',\n fallback:\n 'I may decide for this practice, and I agree to AI assistance reading its statistics.',\n },\n notAllowed: {\n key: 'aiConsentBanner.practiceStatistics.notAllowed',\n fallback:\n 'You do not have permission to grant AI assistance consent for this practice.',\n },\n },\n} as const satisfies Record<\n AiConsentSubject,\n Record<AiConsentSubjectField, { key: string; fallback: string }>\n>;\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/**\n * Patient AI-consent gate for an AI surface that sends patient data to a\n * service: the RichTextEditor's Help-me-write action and dictation mics, and\n * the VoiceControlPanel's microphone. Omit entirely for today's ungated\n * behaviour — no existing host breaks.\n *\n * Present and `granted: false`: the affordances stay visible (this never\n * hides a control), but using one shows the kit's `AiConsentBanner` instead\n * of starting the AI action. When `granted` flips `true` after a Grant click\n * in that banner, the surface resumes exactly the action it gated; when it\n * flips for any other reason (another patient, another tab) it only closes\n * the banner.\n *\n * Present and `granted: true`: normal behaviour.\n */\nexport interface AiConsentGate {\n /** Whether AI consent has already been recorded for the current patient. */\n granted: boolean;\n /** When consent was granted — passed straight to `AiConsentBanner`. */\n grantedAt?: string | number | Date;\n /** Who granted consent — passed straight to `AiConsentBanner`. */\n grantedBy?: string;\n /** Whether the signed-in reader may grant consent. Default `true`; treated\n * as `false` when `onGrant` is absent, so no dead Grant control shows. */\n canGrant?: boolean;\n /** The grant is being persisted server-side (host-driven busy state). */\n pending?: boolean;\n /**\n * Fired when the reader confirms the grant in the banner. A returned\n * promise drives the banner's own pending/Spinner state until it settles,\n * in addition to (or absent) a host-supplied `pending`.\n */\n onGrant?: () => void | Promise<void>;\n}\n\n/** Host-translated strings; the host owns their wording and translation.\n * Each one replaces the `subject` preset for that string only. Plain text,\n * not i18n keys: interpolate any values (a practice name) before passing. */\nexport interface AiConsentBannerCopy {\n /** Banner heading. */\n title?: string;\n /** Description in the required and pending states. */\n descriptionRequired?: string;\n /** Description in the granted state. */\n descriptionGranted?: string;\n /** Label of the confirmation checkbox. */\n confirmLabel?: string;\n /** Label of the Grant button. */\n grantButton?: string;\n /** Note shown instead of the grant controls when `canGrant` is false. */\n notAllowed?: string;\n /** Badge text in the granted state. */\n badgeGranted?: string;\n /** Busy text (and Spinner label) in the pending state. */\n pendingLabel?: string;\n}\n\n/** Agent-readiness curated handle. Exposes the structural consent state only. */\nexport interface AiConsentBannerHandle {\n /** Current derived state: 'granted' | 'required' | 'pending'. */\n getState: () => AiConsentState;\n /** Whether the Grant affordance is currently armed (checkbox ticked). */\n isArmed: () => boolean;\n}\n\nexport interface AiConsentBannerProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children' | 'role'\n> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so an\n * agent / MCP UI bridge can address this specific banner. Mirrored to the\n * real DOM `id`.\n */\n id?: string;\n /** Whether consent has already been granted. Server-sourced. */\n granted: boolean;\n /**\n * When consent was granted — ISO-8601 string, ms-epoch, or Date. Rendered\n * via `Timestamp` in the granted state.\n */\n grantedAt?: string | number | Date;\n /** Who granted consent (operator display name / role). Granted state only. */\n grantedBy?: string;\n /**\n * Whether the current user is allowed to grant consent. When `false`, the\n * required-state Grant affordance is hidden and a not-allowed note shows.\n * Default `true`.\n */\n canGrant?: boolean;\n /** The grant is being persisted server-side — shows the busy Spinner state. */\n pending?: boolean;\n /** Fired when the operator confirms the consent grant. */\n onGrantConsent?: () => void;\n /**\n * Heading level for the banner's own title, so it can be nested under a\n * host section's heading without skipping levels (axe `heading-order`).\n * Additive: default `5` matches the banner's original, unconditional\n * `<h5>` — every existing consumer is unaffected.\n */\n headingLevel?: AiConsentBannerHeadingLevel;\n /** What the consent covers; picks the kit's translated wording. Default\n * `'patient-record'`, which renders exactly as before this prop existed. */\n subject?: AiConsentSubject;\n /** Host-translated strings; the host owns their wording and translation.\n * Each key overrides only its own string. `title` also names the region,\n * unless `aria-label` is passed. */\n copy?: Partial<AiConsentBannerCopy>;\n /** Override the region's accessible name. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const AiConsentBanner = forwardRef<HTMLDivElement, AiConsentBannerProps>(\n (\n {\n id,\n granted,\n grantedAt,\n grantedBy,\n canGrant = true,\n pending = false,\n onGrantConsent,\n headingLevel = 5,\n subject = 'patient-record',\n copy,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const state = deriveState(granted, pending);\n\n // A host string wins over the preset for that string only. A blank or\n // whitespace-only one counts as missing, so no control loses its name.\n const own = (value?: string) => value?.trim() || undefined;\n // An unknown subject from an untyped host falls back to the default.\n const keys = SUBJECT_KEYS[subject] ?? SUBJECT_KEYS['patient-record'];\n const text = {\n title:\n own(copy?.title) || t('aiConsentBanner.title', 'AI assistance consent'),\n descriptionRequired:\n own(copy?.descriptionRequired) ||\n t(keys.descriptionRequired.key, keys.descriptionRequired.fallback),\n descriptionGranted:\n own(copy?.descriptionGranted) ||\n t(keys.descriptionGranted.key, keys.descriptionGranted.fallback),\n confirmLabel:\n own(copy?.confirmLabel) ||\n t(keys.confirmLabel.key, keys.confirmLabel.fallback),\n grantButton:\n own(copy?.grantButton) ||\n t('aiConsentBanner.grantButton', 'Grant consent'),\n notAllowed:\n own(copy?.notAllowed) ||\n t(keys.notAllowed.key, keys.notAllowed.fallback),\n badgeGranted:\n own(copy?.badgeGranted) ||\n t('aiConsentBanner.badge.granted', 'Consent granted'),\n pendingLabel:\n own(copy?.pendingLabel) ||\n t('aiConsentBanner.pendingLabel', 'Saving consent…'),\n };\n\n // Grant stays disabled until the checkbox is ticked. Any change of subject\n // or statement unticks it, even back to an earlier one, so a tick only\n // confirms what was on screen when it was given.\n const statement = [\n subject,\n text.confirmLabel,\n text.descriptionRequired,\n ].join('\\u0000');\n const [ticked, setTicked] = useState(false);\n const [tickedFor, setTickedFor] = useState(statement);\n if (tickedFor !== statement) {\n setTickedFor(statement);\n setTicked(false);\n }\n const armed = ticked && tickedFor === statement;\n\n const armedRef = useRef(armed);\n armedRef.current = armed;\n\n const handle = useMemo<AiConsentBannerHandle>(\n () => ({\n getState: () => deriveState(granted, pending),\n isArmed: () => armedRef.current,\n }),\n [granted, pending],\n );\n useAgentRegistration(aiConsentBannerAgent, handle, id);\n\n // A host title also names the region, so the name matches the heading.\n const resolvedAriaLabel =\n own(ariaLabel) ||\n own(copy?.title) ||\n t('aiConsentBanner.regionLabel', 'AI assistance consent');\n\n // Alert variant per state: granted → success, required/pending → info.\n const alertVariant = state === 'granted' ? 'success' : 'info';\n\n let body: React.ReactNode;\n if (state === 'granted') {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Badge variant=\"success\">{text.badgeGranted}</Badge>\n {grantedAt !== undefined ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedAtPrefix', 'Granted')}{' '}\n <Timestamp value={grantedAt} format=\"relative\" shape=\"inline\" />\n </span>\n ) : null}\n </div>\n {grantedBy ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedBy', {\n name: grantedBy,\n defaultValue: 'By {{name}}',\n })}\n </p>\n ) : null}\n </div>\n );\n } else if (state === 'pending') {\n body = (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Spinner variant=\"pulse\" size=\"sm\" label={text.pendingLabel} />\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {text.pendingLabel}\n </span>\n </div>\n );\n } else {\n // required\n body = canGrant ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <Checkbox\n checked={armed}\n onCheckedChange={(next) => setTicked(next === true)}\n label={text.confirmLabel}\n />\n <Alert.Action>\n <Button\n intent=\"primary\"\n size=\"sm\"\n disabled={!armed}\n onClick={onGrantConsent}\n >\n {text.grantButton}\n </Button>\n </Alert.Action>\n </div>\n ) : (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {text.notAllowed}\n </p>\n );\n }\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-busy={state === 'pending' ? true : undefined}\n data-component=\"ai-consent-banner\"\n data-component-id={id}\n data-state={state}\n id={id}\n className={rootVariants({ state, className })}\n {...rest}\n >\n <Alert\n variant={alertVariant}\n icon={state === 'pending' ? null : undefined}\n >\n <Alert.Title as={`h${headingLevel}` as const}>\n {text.title}\n </Alert.Title>\n <Alert.Description>\n {state === 'granted'\n ? text.descriptionGranted\n : text.descriptionRequired}\n </Alert.Description>\n {body}\n </Alert>\n </div>\n );\n },\n);\n\nAiConsentBanner.displayName = 'AiConsentBanner';\n"],"names":["aiConsentBannerAgent","handle","rootVariants","cva","deriveState","granted","pending","SUBJECT_KEYS","AiConsentBanner","forwardRef","id","grantedAt","grantedBy","canGrant","onGrantConsent","headingLevel","subject","copy","ariaLabel","className","rest","ref","useTranslation","state","own","value","keys","text","statement","ticked","setTicked","useState","tickedFor","setTickedFor","armed","armedRef","useRef","useMemo","useAgentRegistration","resolvedAriaLabel","alertVariant","body","jsxs","jsx","Badge","Timestamp","Spinner","Checkbox","next","Alert","Button"],"mappings":"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"}
@@ -314,6 +314,7 @@ const Ne = Object.assign(B, {
314
314
  Action: z
315
315
  });
316
316
  export {
317
- Ne as A
317
+ Ne as A,
318
+ re as C
318
319
  };
319
- //# sourceMappingURL=alert-DdDpOi-P.js.map
320
+ //# sourceMappingURL=alert-DjsJMGRE.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"alert-DdDpOi-P.js","sources":["../../node_modules/lucide-react/dist/esm/icons/circle-arrow-up.mjs","../../src/components/alert/alert.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m16 12-4-4-4 4\", key: \"177agl\" }],\n [\"path\", { d: \"M12 16V8\", key: \"1sbj14\" }]\n];\nconst CircleArrowUp = createLucideIcon(\"circle-arrow-up\", __iconNode);\n\nexport { __iconNode, CircleArrowUp as default };\n//# sourceMappingURL=circle-arrow-up.mjs.map\n","import {\n Children,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type MutableRefObject,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport {\n CircleAlert,\n CircleArrowUp,\n CircleCheck,\n Info,\n TriangleAlert,\n X,\n} from 'lucide-react';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { useClampOverflow } from '../../hooks/use-clamp-overflow';\nimport { Tooltip } from '../tooltip';\n\n/* ------------------------------------------------------------------ */\n/* Clamp context — opt-in compact mode propagated from the root Alert */\n/* to its Title / Description so a consumer enables it with one prop. */\n/* ------------------------------------------------------------------ */\n\nconst AlertClampContext = createContext(false);\n\n/** Inline \"Read more / Read less\" disclosure. Tinted with `text-current` so it\n * inherits the alert variant's foreground rather than the link palette. */\nconst DISCLOSURE_BUTTON_CLASSES = [\n // Full-opacity `text-current` so it matches the body text's contrast (an\n // `opacity` dim would drop the variant-tinted text below AA). Underline\n // carries the affordance instead. No `--min-target-size` floor: this is an\n // inline text disclosure sitting in the flow of the body copy, which is\n // exempt from WCAG 2.5.8 target-size the same way an inline link is.\n 'ds:mt-[var(--spacing-2xs)] ds:inline-flex ds:items-center ds:self-start',\n 'ds:text-[length:var(--font-size-xs)] ds:font-semibold',\n 'ds:underline ds:underline-offset-2 ds:text-current ds:hover:no-underline',\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-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\nconst alertVariants = cva(\n [\n // Default `items-center` keeps the icon + dismiss optically aligned\n // with a single-line description. The `data-[has-title=true]`\n // selector flips to `items-start` when an `<Alert.Title>` is\n // present so the icon anchors to the heading's top instead of\n // floating against the centre of the title+description block.\n // For multi-line descriptions without a title, `items-center` still\n // looks right at 2–3 lines and matches Toast / Notification.\n 'ds:flex ds:items-center ds:data-[has-title=true]:items-start ds:gap-[var(--spacing-md)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:border ds:border-[length:var(--border-width-sm)]',\n 'ds:p-[var(--spacing-md)]',\n 'ds:break-words',\n ].join(' '),\n {\n variants: {\n // Each variant paints `<Button intent=\"tonal\">` descendants via a\n // child selector — the button carries `data-intent=\"tonal\"`, the\n // Alert applies the matching tint (`*-foreground` for bg + the\n // surface `--background` for fg). Descendant selectors sidestep\n // custom-property inheritance and are rock-solid across themes.\n variant: {\n info: [\n 'ds:border-[color:var(--info)]',\n 'ds:bg-[color-mix(in_srgb,var(--info)_10%,transparent)]',\n 'ds:text-[var(--info-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--info-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n success: [\n 'ds:border-[color:var(--success)]',\n 'ds:bg-[color-mix(in_srgb,var(--success)_10%,transparent)]',\n 'ds:text-[var(--success-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--success-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n warning: [\n 'ds:border-[color:var(--warning)]',\n 'ds:bg-[color-mix(in_srgb,var(--warning)_10%,transparent)]',\n 'ds:text-[var(--warning-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--warning-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n error: [\n 'ds:border-[color:var(--error)]',\n 'ds:bg-[color-mix(in_srgb,var(--error)_10%,transparent)]',\n 'ds:text-[var(--error-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--error-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n // Sales / marketing upsell — accent magenta via the --promo\n // semantic pair so marketing pushes (product hub → warning\n // stack) read as offers, not operational warnings. Surface is\n // the same subtle accent gradient as SidebarUpgradeChip (it\n // flattens in the accessible themes and follows Canvas in\n // forced-colors), keeping the two upsell affordances kin.\n promo: [\n 'ds:border-[color:var(--promo)]',\n 'ds:bg-[image:var(--gradient-surface-subtle-accent)]',\n 'ds:text-[var(--promo-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--promo-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n },\n },\n defaultVariants: {\n variant: 'info',\n },\n },\n);\n\n// Icon stays `mt-0.5` only when an `<Alert.Title>` is present — that\n// offset compensates for the title's cap-height vs. line-box origin so\n// the glyph aligns with the heading's caps. Without a title, the\n// container uses `items-center` and the offset would push the icon\n// 2px off the optical axis.\nconst ICON_BASE = 'ds:shrink-0 ds:size-5';\nconst ICON_WITH_TITLE = `${ICON_BASE} ds:mt-0.5`;\n\nconst CLOSE_BUTTON_CLASSES = [\n // Default (no title): the alert root uses `items-center` and the\n // button centres in the cross-axis. A centred 16×16 glyph inside a\n // 44×44 button aligns optically with a single-line description.\n // With a title: the root flips to `items-start` so the button's top\n // edge aligns with the title row top. A centred glyph would then\n // land ~11 px below the title's optical centre (button height is\n // --min-target-size, much taller than the title's line-height). The\n // `[data-has-title=true]` variant below flips the button to\n // `items-start` and adds a block-start padding that pulls the glyph\n // up onto the title row — same cap-height compensation idea as the\n // leading icon's `mt-0.5`.\n 'ds:ms-auto ds:shrink-0 ds:inline-flex ds:items-center ds:justify-center',\n 'ds:[[data-has-title=true]_&]:items-start',\n 'ds:[[data-has-title=true]_&]:pt-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:-mt-[var(--spacing-xs)] ds:-me-[var(--spacing-xs)]',\n 'ds:text-current ds:opacity-70',\n 'ds:hover:opacity-100',\n 'ds:transition-opacity ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\n// `role` / `live` here are only the *default* announcement for each tint.\n// The `announce` prop overrides both — visual severity and announcement\n// urgency are independent (a warning-tinted static notice must not interrupt).\nconst VARIANT_CONFIG = {\n info: { icon: <Info aria-hidden=\"true\" />, role: 'status', live: 'polite' },\n success: {\n icon: <CircleCheck aria-hidden=\"true\" />,\n role: 'status',\n live: 'polite',\n },\n warning: {\n icon: <TriangleAlert aria-hidden=\"true\" />,\n role: 'alert',\n live: 'assertive',\n },\n error: {\n icon: <CircleAlert aria-hidden=\"true\" />,\n role: 'alert',\n live: 'assertive',\n },\n // Promotions never interrupt — same polite semantics as info.\n promo: {\n icon: <CircleArrowUp aria-hidden=\"true\" />,\n role: 'status',\n live: 'polite',\n },\n} as const;\n\n// `off` emits neither role nor aria-live: a permanently-mounted notice is\n// read in document order and is not a live region at all.\nconst ANNOUNCE_CONFIG = {\n off: { role: undefined, live: undefined },\n polite: { role: 'status', live: 'polite' },\n assertive: { role: 'alert', live: 'assertive' },\n} as const;\n\ninterface AlertTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span';\n}\n\nconst AlertTitle = forwardRef<HTMLHeadingElement, AlertTitleProps>(\n ({ as: Tag = 'h5', className, children, ...props }, ref) => {\n const clamp = useContext(AlertClampContext);\n const { ref: clampRef, isOverflowing } =\n useClampOverflow<HTMLHeadingElement>(clamp);\n const setRefs = useCallback(\n (node: HTMLHeadingElement | null) => {\n (clampRef as MutableRefObject<HTMLHeadingElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as MutableRefObject<HTMLHeadingElement | null>).current = node;\n },\n [ref, clampRef],\n );\n\n // The full title stays in the DOM (line-clamp only clips it visually), so\n // screen readers always read it whole. The tooltip is a sighted-user\n // affordance, shown only when the title is actually cut — and only for\n // string titles, since the Tooltip label must be plain text.\n const tooltipReady = clamp && isOverflowing && typeof children === 'string';\n\n const heading = (\n <Tag\n ref={setRefs}\n // Focusable only when truncated, so keyboard users can surface the\n // tooltip too (otherwise it would be mouse/hover-only).\n tabIndex={tooltipReady ? 0 : undefined}\n className={[\n 'type-title-item',\n clamp ? 'ds:line-clamp-2' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n {children}\n </Tag>\n );\n\n return tooltipReady ? (\n <Tooltip label={children as string}>{heading}</Tooltip>\n ) : (\n heading\n );\n },\n);\nAlertTitle.displayName = 'Alert.Title';\n\nconst AlertDescription = forwardRef<\n HTMLParagraphElement,\n HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const clamp = useContext(AlertClampContext);\n const { t } = useTranslation('ui');\n const bodyId = useId();\n const [expanded, setExpanded] = useState(false);\n // Only measure while clamped — once expanded there's nothing to clip.\n const { ref: clampRef, isOverflowing } =\n useClampOverflow<HTMLParagraphElement>(clamp && !expanded);\n const setRefs = useCallback(\n (node: HTMLParagraphElement | null) => {\n (clampRef as MutableRefObject<HTMLParagraphElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as MutableRefObject<HTMLParagraphElement | null>).current = node;\n },\n [ref, clampRef],\n );\n // Show the toggle once the body has overflowed; keep it while expanded so\n // the user can collapse again.\n const showToggle = clamp && (isOverflowing || expanded);\n\n return (\n <>\n <p\n ref={setRefs}\n id={clamp ? bodyId : undefined}\n // `mt` is gated on the root's `data-has-title=\"true\"` attribute so\n // the margin only paints when there's a Title above the\n // Description to separate from. Without this gate, a Description\n // rendered alone sits a few pixels below the icon + dismiss ×\n // optical centre — visible on the AlfaDocs marketing privacy\n // generator before HTP-4860's follow-up fix.\n className={[\n 'ds:[[data-has-title=true]_&]:mt-[var(--spacing-xs)] type-body-sm',\n clamp && !expanded ? 'ds:line-clamp-2' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n {children}\n </p>\n {showToggle ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n aria-controls={bodyId}\n onClick={() => setExpanded((prev) => !prev)}\n className={DISCLOSURE_BUTTON_CLASSES}\n >\n {expanded\n ? t('feedback.alert.readLess', 'Read less')\n : t('feedback.alert.readMore', 'Read more')}\n </button>\n ) : null}\n </>\n );\n});\nAlertDescription.displayName = 'Alert.Description';\n\nconst AlertAction = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={[\n 'ds:mt-[var(--spacing-md)] ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n />\n ),\n);\nAlertAction.displayName = 'Alert.Action';\n\n/** How urgently the alert is announced — independent of the visual `variant`.\n *\n * - `off` — not a live region. No `role`, no `aria-live`. Correct for a\n * static notice that is present from mount (a read-only banner, a summary\n * of missing answers on a form the user is still typing into).\n * - `polite` — `role=\"status\"` + `aria-live=\"polite\"`. Queued behind the\n * current utterance. The right default for anything that appears in\n * response to a user action but is not an emergency.\n * - `assertive` — `role=\"alert\"` + `aria-live=\"assertive\"`. Interrupts the\n * screen reader immediately. Reserve for content the user cannot miss.\n */\nexport type AlertAnnounce = 'off' | 'polite' | 'assertive';\n\nexport interface AlertProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'role'>,\n VariantProps<typeof alertVariants> {\n variant?: 'info' | 'success' | 'warning' | 'error' | 'promo';\n dismissible?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n icon?: ReactNode;\n /** Announcement urgency — sets `role` **and** `aria-live` together, so the\n * tint (`variant`) and the interruption are chosen independently. Defaults\n * to the variant's historical mapping: `info` / `success` / `promo` →\n * `polite`, `warning` / `error` → `assertive`. Wins over `live`. */\n announce?: AlertAnnounce;\n /** @deprecated Use `announce`. Sets `aria-live` only and leaves `role`\n * variant-derived, which can pair `role=\"alert\"` with `aria-live=\"polite\"`.\n * Kept for the consumers already shipping it. */\n live?: 'assertive' | 'polite' | 'off';\n /** Compact mode: clamps `Alert.Title` to 2 lines (with a tooltip when the\n * title is truncated) and `Alert.Description` to 2 lines (with a \"Read more\"\n * toggle). Opt-in — leave off for standalone alerts whose full message must\n * always be visible. */\n clamp?: boolean;\n}\n\nexport type { AlertTitleProps };\n\nconst AlertRoot = forwardRef<HTMLDivElement, AlertProps>(\n (\n {\n variant = 'info',\n dismissible = false,\n open: controlledOpen,\n onOpenChange,\n icon,\n announce,\n live,\n clamp = false,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const [isOpenRaw, setOpen] = useControllableState<boolean>({\n value: controlledOpen,\n defaultValue: true,\n onChange: onOpenChange,\n });\n const isOpen = isOpenRaw ?? true;\n const [isClosing, setIsClosing] = useState(false);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const animationDurationMs = useCallback((): number => {\n if (typeof window === 'undefined') return 200;\n const raw = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration');\n if (!raw) return 200;\n const trimmed = raw.trim();\n const n = parseFloat(trimmed);\n if (!Number.isFinite(n)) return 200;\n return trimmed.endsWith('ms') ? n : n * 1000;\n }, []);\n\n if (!isOpen) return null;\n\n const config = VARIANT_CONFIG[variant];\n const effectiveIcon = icon !== undefined ? icon : config.icon;\n\n // `announce` owns role + aria-live together. Without it we keep the\n // shipped behaviour exactly: role from the variant, aria-live from the\n // legacy `live` prop or the variant default.\n const announcement = announce\n ? ANNOUNCE_CONFIG[announce]\n : { role: config.role, live: live ?? config.live };\n\n // Detect an `<Alert.Title>` anywhere in the immediate children so\n // the root can flip its cross-axis alignment. Nested wrappers\n // around a Title aren't supported — keep the API as flat as the\n // existing `Alert.Title` / `Alert.Description` convention.\n const hasTitle = Children.toArray(children).some(\n (child) => isValidElement(child) && child.type === AlertTitle,\n );\n\n const handleDismiss = () => {\n if (isClosing) return;\n setIsClosing(true);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n closeTimerRef.current = setTimeout(() => {\n setIsClosing(false);\n setOpen(false);\n }, animationDurationMs());\n };\n\n return (\n <div\n ref={ref}\n role={announcement.role}\n aria-live={announcement.live}\n data-component=\"alert\"\n data-has-title={hasTitle ? 'true' : 'false'}\n data-state={isClosing ? 'closing' : 'open'}\n className={[\n alertVariants({ variant, className }),\n // Entry: fade + slide-down on mount. Exit: fade + slide-up + slight\n // scale when dismissed. Driven by `tw-animate-css`. Respects\n // `prefers-reduced-motion` via `motion-safe:` and zeroes under the\n // accessible theme (`--animation-duration: 0ms`).\n 'ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:slide-in-from-top-2',\n 'ds:motion-safe:data-[state=closing]:animate-out ds:motion-safe:data-[state=closing]:fade-out-0',\n 'ds:motion-safe:data-[state=closing]:slide-out-to-top-2 ds:motion-safe:data-[state=closing]:zoom-out-95',\n // Pin the exit's end-state until React unmounts. Without\n // `fill-mode-forwards` the element snaps back to opacity:1 for one\n // paint frame after the animation ends.\n 'ds:motion-safe:data-[state=closing]:fill-mode-forwards',\n 'ds:motion-safe:duration-[var(--animation-duration)]',\n ].join(' ')}\n {...props}\n >\n {effectiveIcon ? (\n <span className={hasTitle ? ICON_WITH_TITLE : ICON_BASE}>\n {effectiveIcon}\n </span>\n ) : null}\n\n <div className=\"ds:flex-1 ds:min-w-0\">\n <AlertClampContext.Provider value={clamp}>\n {children}\n </AlertClampContext.Provider>\n </div>\n\n {dismissible ? (\n <button\n type=\"button\"\n aria-label={t('common.close', 'Close')}\n onClick={handleDismiss}\n // Stable hook for containers (WarningStack) that hand focus to\n // a neighbouring dismiss control after this one unmounts.\n data-alert-dismiss=\"\"\n className={CLOSE_BUTTON_CLASSES}\n >\n <X aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n ) : null}\n </div>\n );\n },\n);\n\nAlertRoot.displayName = 'Alert';\n\nexport const Alert = Object.assign(AlertRoot, {\n Title: AlertTitle,\n Description: AlertDescription,\n Action: AlertAction,\n});\n"],"names":["__iconNode","CircleArrowUp","createLucideIcon","AlertClampContext","createContext","DISCLOSURE_BUTTON_CLASSES","alertVariants","cva","ICON_BASE","ICON_WITH_TITLE","CLOSE_BUTTON_CLASSES","VARIANT_CONFIG","jsx","Info","CircleCheck","TriangleAlert","CircleAlert","ANNOUNCE_CONFIG","AlertTitle","forwardRef","Tag","className","children","props","ref","clamp","useContext","clampRef","isOverflowing","useClampOverflow","setRefs","useCallback","node","tooltipReady","heading","Tooltip","AlertDescription","t","useTranslation","bodyId","useId","expanded","setExpanded","useState","showToggle","jsxs","Fragment","prev","AlertAction","AlertRoot","variant","dismissible","controlledOpen","onOpenChange","icon","announce","live","isOpenRaw","setOpen","useControllableState","isOpen","isClosing","setIsClosing","closeTimerRef","useRef","animationDurationMs","raw","trimmed","n","config","effectiveIcon","announcement","hasTitle","Children","child","isValidElement","handleDismiss","X","Alert"],"mappings":";;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,KAAa;AAAA,EACjB,CAAC,UAAU,EAAE,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,KAAK,UAAU;AAAA,EACzD,CAAC,QAAQ,EAAE,GAAG,kBAAkB,KAAK,SAAQ,CAAE;AAAA,EAC/C,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAC3C,GACMC,KAAgBC,EAAiB,mBAAmBF,EAAU,GCmB9DG,IAAoBC,EAAc,EAAK,GAIvCC,KAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,KAAgBC;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMR,SAAS;AAAA,QACP,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,QACV,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,QACV,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,QACV,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOV,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,MAAA;AAAA,IACZ;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ,GAOMC,IAAY,yBACZC,KAAkB,GAAGD,CAAS,cAE9BE,KAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAKJC,KAAiB;AAAA,EACrB,MAAM,EAAE,MAAM,gBAAAC,EAACC,IAAA,EAAK,eAAY,OAAA,CAAO,GAAI,MAAM,UAAU,MAAM,SAAA;AAAA,EACjE,SAAS;AAAA,IACP,MAAM,gBAAAD,EAACE,IAAA,EAAY,eAAY,OAAA,CAAO;AAAA,IACtC,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA,EAER,SAAS;AAAA,IACP,MAAM,gBAAAF,EAACG,IAAA,EAAc,eAAY,OAAA,CAAO;AAAA,IACxC,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA,EAER,OAAO;AAAA,IACL,MAAM,gBAAAH,EAACI,GAAA,EAAY,eAAY,OAAA,CAAO;AAAA,IACtC,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA;AAAA,EAGR,OAAO;AAAA,IACL,MAAM,gBAAAJ,EAACX,IAAA,EAAc,eAAY,OAAA,CAAO;AAAA,IACxC,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAEV,GAIMgB,KAAkB;AAAA,EACtB,KAAK,EAAE,MAAM,QAAW,MAAM,OAAA;AAAA,EAC9B,QAAQ,EAAE,MAAM,UAAU,MAAM,SAAA;AAAA,EAChC,WAAW,EAAE,MAAM,SAAS,MAAM,YAAA;AACpC,GAMMC,IAAaC;AAAA,EACjB,CAAC,EAAE,IAAIC,IAAM,MAAM,WAAAC,GAAW,UAAAC,GAAU,GAAGC,EAAA,GAASC,MAAQ;AAC1D,UAAMC,IAAQC,EAAWvB,CAAiB,GACpC,EAAE,KAAKwB,GAAU,eAAAC,EAAA,IACrBC,EAAqCJ,CAAK,GACtCK,IAAUC;AAAA,MACd,CAACC,MAAoC;AAClC,QAAAL,EAAyD,UACxDK,GACE,OAAOR,KAAQ,aAAYA,EAAIQ,CAAI,IAC9BR,MACNA,EAAoD,UAAUQ;AAAA,MACnE;AAAA,MACA,CAACR,GAAKG,CAAQ;AAAA,IAAA,GAOVM,IAAeR,KAASG,KAAiB,OAAON,KAAa,UAE7DY,IACJ,gBAAAtB;AAAA,MAACQ;AAAA,MAAA;AAAA,QACC,KAAKU;AAAA,QAGL,UAAUG,IAAe,IAAI;AAAA,QAC7B,WAAW;AAAA,UACT;AAAA,UACAR,IAAQ,oBAAoB;AAAA,UAC5BJ;AAAA,QAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,QACV,GAAGE;AAAA,QAEH,UAAAD;AAAA,MAAA;AAAA,IAAA;AAIL,WAAOW,IACL,gBAAArB,EAACuB,GAAA,EAAQ,OAAOb,GAAqB,aAAQ,IAE7CY;AAAA,EAEJ;AACF;AACAhB,EAAW,cAAc;AAEzB,MAAMkB,IAAmBjB,EAGvB,CAAC,EAAE,WAAAE,GAAW,UAAAC,GAAU,GAAGC,EAAA,GAASC,MAAQ;AAC5C,QAAMC,IAAQC,EAAWvB,CAAiB,GACpC,EAAE,GAAAkC,EAAA,IAAMC,EAAe,IAAI,GAC3BC,IAASC,EAAA,GACT,CAACC,GAAUC,CAAW,IAAIC,EAAS,EAAK,GAExC,EAAE,KAAKhB,GAAU,eAAAC,EAAA,IACrBC,EAAuCJ,KAAS,CAACgB,CAAQ,GACrDX,IAAUC;AAAA,IACd,CAACC,MAAsC;AACpC,MAAAL,EAA2D,UAC1DK,GACE,OAAOR,KAAQ,aAAYA,EAAIQ,CAAI,IAC9BR,MACNA,EAAsD,UAAUQ;AAAA,IACrE;AAAA,IACA,CAACR,GAAKG,CAAQ;AAAA,EAAA,GAIViB,IAAanB,MAAUG,KAAiBa;AAE9C,SACE,gBAAAI,EAAAC,GAAA,EACE,UAAA;AAAA,IAAA,gBAAAlC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKkB;AAAA,QACL,IAAIL,IAAQc,IAAS;AAAA,QAOrB,WAAW;AAAA,UACT;AAAA,UACAd,KAAS,CAACgB,IAAW,oBAAoB;AAAA,UACzCpB;AAAA,QAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,QACV,GAAGE;AAAA,QAEH,UAAAD;AAAA,MAAA;AAAA,IAAA;AAAA,IAEFsB,IACC,gBAAAhC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,iBAAe6B;AAAA,QACf,iBAAeF;AAAA,QACf,SAAS,MAAMG,EAAY,CAACK,MAAS,CAACA,CAAI;AAAA,QAC1C,WAAW1C;AAAA,QAEV,cACGgC,EAAE,2BAA2B,WAAW,IACxCA,EAAE,2BAA2B,WAAW;AAAA,MAAA;AAAA,IAAA,IAE5C;AAAA,EAAA,GACN;AAEJ,CAAC;AACDD,EAAiB,cAAc;AAE/B,MAAMY,IAAc7B;AAAA,EAClB,CAAC,EAAE,WAAAE,GAAW,GAAGE,EAAA,GAASC,MACxB,gBAAAZ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAY;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACAH;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MACV,GAAGE;AAAA,IAAA;AAAA,EAAA;AAGV;AACAyB,EAAY,cAAc;AA0C1B,MAAMC,IAAY9B;AAAA,EAChB,CACE;AAAA,IACE,SAAA+B,IAAU;AAAA,IACV,aAAAC,IAAc;AAAA,IACd,MAAMC;AAAA,IACN,cAAAC;AAAA,IACA,MAAAC;AAAA,IACA,UAAAC;AAAA,IACA,MAAAC;AAAA,IACA,OAAA/B,IAAQ;AAAA,IACR,WAAAJ;AAAA,IACA,UAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAM,EAAE,GAAAa,EAAA,IAAMC,EAAe,IAAI,GAC3B,CAACmB,GAAWC,CAAO,IAAIC,EAA8B;AAAA,MACzD,OAAOP;AAAA,MACP,cAAc;AAAA,MACd,UAAUC;AAAA,IAAA,CACX,GACKO,IAASH,KAAa,IACtB,CAACI,GAAWC,CAAY,IAAInB,EAAS,EAAK,GAC1CoB,IAAgBC,EAA6C,IAAI,GAEjEC,IAAsBlC,EAAY,MAAc;AACpD,UAAI,OAAO,SAAW,IAAa,QAAO;AAC1C,YAAMmC,IAAM,OACT,iBAAiB,SAAS,eAAe,EACzC,iBAAiB,sBAAsB;AAC1C,UAAI,CAACA,EAAK,QAAO;AACjB,YAAMC,IAAUD,EAAI,KAAA,GACdE,IAAI,WAAWD,CAAO;AAC5B,aAAK,OAAO,SAASC,CAAC,IACfD,EAAQ,SAAS,IAAI,IAAIC,IAAIA,IAAI,MADR;AAAA,IAElC,GAAG,CAAA,CAAE;AAEL,QAAI,CAACR,EAAQ,QAAO;AAEpB,UAAMS,IAAS1D,GAAeuC,CAAO,GAC/BoB,IAAgBhB,MAAS,SAAYA,IAAOe,EAAO,MAKnDE,IAAehB,IACjBtC,GAAgBsC,CAAQ,IACxB,EAAE,MAAMc,EAAO,MAAM,MAAMb,KAAQa,EAAO,KAAA,GAMxCG,IAAWC,EAAS,QAAQnD,CAAQ,EAAE;AAAA,MAC1C,CAACoD,MAAUC,EAAeD,CAAK,KAAKA,EAAM,SAASxD;AAAA,IAAA,GAG/C0D,IAAgB,MAAM;AAC1B,MAAIf,MACJC,EAAa,EAAI,GACbC,EAAc,WAAS,aAAaA,EAAc,OAAO,GAC7DA,EAAc,UAAU,WAAW,MAAM;AACvC,QAAAD,EAAa,EAAK,GAClBJ,EAAQ,EAAK;AAAA,MACf,GAAGO,GAAqB;AAAA,IAC1B;AAEA,WACE,gBAAApB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAArB;AAAA,QACA,MAAM+C,EAAa;AAAA,QACnB,aAAWA,EAAa;AAAA,QACxB,kBAAe;AAAA,QACf,kBAAgBC,IAAW,SAAS;AAAA,QACpC,cAAYX,IAAY,YAAY;AAAA,QACpC,WAAW;AAAA,UACTvD,GAAc,EAAE,SAAA4C,GAAS,WAAA7B,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA,UAKpC;AAAA,UACA;AAAA,UACA;AAAA;AAAA;AAAA;AAAA,UAIA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,QACT,GAAGE;AAAA,QAEH,UAAA;AAAA,UAAA+C,sBACE,QAAA,EAAK,WAAWE,IAAW/D,KAAkBD,GAC3C,aACH,IACE;AAAA,UAEJ,gBAAAI,EAAC,OAAA,EAAI,WAAU,wBACb,UAAA,gBAAAA,EAACT,EAAkB,UAAlB,EAA2B,OAAOsB,GAChC,UAAAH,EAAA,CACH,EAAA,CACF;AAAA,UAEC6B,IACC,gBAAAvC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAYyB,EAAE,gBAAgB,OAAO;AAAA,cACrC,SAASuC;AAAA,cAGT,sBAAmB;AAAA,cACnB,WAAWlE;AAAA,cAEX,UAAA,gBAAAE,EAACiE,GAAA,EAAE,eAAY,QAAO,WAAU,YAAA,CAAY;AAAA,YAAA;AAAA,UAAA,IAE5C;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEA5B,EAAU,cAAc;AAEjB,MAAM6B,KAAQ,OAAO,OAAO7B,GAAW;AAAA,EAC5C,OAAO/B;AAAA,EACP,aAAakB;AAAA,EACb,QAAQY;AACV,CAAC;","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"alert-DjsJMGRE.js","sources":["../../node_modules/lucide-react/dist/esm/icons/circle-arrow-up.mjs","../../src/components/alert/alert.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m16 12-4-4-4 4\", key: \"177agl\" }],\n [\"path\", { d: \"M12 16V8\", key: \"1sbj14\" }]\n];\nconst CircleArrowUp = createLucideIcon(\"circle-arrow-up\", __iconNode);\n\nexport { __iconNode, CircleArrowUp as default };\n//# sourceMappingURL=circle-arrow-up.mjs.map\n","import {\n Children,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type MutableRefObject,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport {\n CircleAlert,\n CircleArrowUp,\n CircleCheck,\n Info,\n TriangleAlert,\n X,\n} from 'lucide-react';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { useClampOverflow } from '../../hooks/use-clamp-overflow';\nimport { Tooltip } from '../tooltip';\n\n/* ------------------------------------------------------------------ */\n/* Clamp context — opt-in compact mode propagated from the root Alert */\n/* to its Title / Description so a consumer enables it with one prop. */\n/* ------------------------------------------------------------------ */\n\nconst AlertClampContext = createContext(false);\n\n/** Inline \"Read more / Read less\" disclosure. Tinted with `text-current` so it\n * inherits the alert variant's foreground rather than the link palette. */\nconst DISCLOSURE_BUTTON_CLASSES = [\n // Full-opacity `text-current` so it matches the body text's contrast (an\n // `opacity` dim would drop the variant-tinted text below AA). Underline\n // carries the affordance instead. No `--min-target-size` floor: this is an\n // inline text disclosure sitting in the flow of the body copy, which is\n // exempt from WCAG 2.5.8 target-size the same way an inline link is.\n 'ds:mt-[var(--spacing-2xs)] ds:inline-flex ds:items-center ds:self-start',\n 'ds:text-[length:var(--font-size-xs)] ds:font-semibold',\n 'ds:underline ds:underline-offset-2 ds:text-current ds:hover:no-underline',\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-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\nconst alertVariants = cva(\n [\n // Default `items-center` keeps the icon + dismiss optically aligned\n // with a single-line description. The `data-[has-title=true]`\n // selector flips to `items-start` when an `<Alert.Title>` is\n // present so the icon anchors to the heading's top instead of\n // floating against the centre of the title+description block.\n // For multi-line descriptions without a title, `items-center` still\n // looks right at 2–3 lines and matches Toast / Notification.\n 'ds:flex ds:items-center ds:data-[has-title=true]:items-start ds:gap-[var(--spacing-md)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:border ds:border-[length:var(--border-width-sm)]',\n 'ds:p-[var(--spacing-md)]',\n 'ds:break-words',\n ].join(' '),\n {\n variants: {\n // Each variant paints `<Button intent=\"tonal\">` descendants via a\n // child selector — the button carries `data-intent=\"tonal\"`, the\n // Alert applies the matching tint (`*-foreground` for bg + the\n // surface `--background` for fg). Descendant selectors sidestep\n // custom-property inheritance and are rock-solid across themes.\n variant: {\n info: [\n 'ds:border-[color:var(--info)]',\n 'ds:bg-[color-mix(in_srgb,var(--info)_10%,transparent)]',\n 'ds:text-[var(--info-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--info-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n success: [\n 'ds:border-[color:var(--success)]',\n 'ds:bg-[color-mix(in_srgb,var(--success)_10%,transparent)]',\n 'ds:text-[var(--success-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--success-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n warning: [\n 'ds:border-[color:var(--warning)]',\n 'ds:bg-[color-mix(in_srgb,var(--warning)_10%,transparent)]',\n 'ds:text-[var(--warning-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--warning-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n error: [\n 'ds:border-[color:var(--error)]',\n 'ds:bg-[color-mix(in_srgb,var(--error)_10%,transparent)]',\n 'ds:text-[var(--error-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--error-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n // Sales / marketing upsell — accent magenta via the --promo\n // semantic pair so marketing pushes (product hub → warning\n // stack) read as offers, not operational warnings. Surface is\n // the same subtle accent gradient as SidebarUpgradeChip (it\n // flattens in the accessible themes and follows Canvas in\n // forced-colors), keeping the two upsell affordances kin.\n promo: [\n 'ds:border-[color:var(--promo)]',\n 'ds:bg-[image:var(--gradient-surface-subtle-accent)]',\n 'ds:text-[var(--promo-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--promo-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n },\n },\n defaultVariants: {\n variant: 'info',\n },\n },\n);\n\n// Icon stays `mt-0.5` only when an `<Alert.Title>` is present — that\n// offset compensates for the title's cap-height vs. line-box origin so\n// the glyph aligns with the heading's caps. Without a title, the\n// container uses `items-center` and the offset would push the icon\n// 2px off the optical axis.\nconst ICON_BASE = 'ds:shrink-0 ds:size-5';\nconst ICON_WITH_TITLE = `${ICON_BASE} ds:mt-0.5`;\n\nconst CLOSE_BUTTON_CLASSES = [\n // Default (no title): the alert root uses `items-center` and the\n // button centres in the cross-axis. A centred 16×16 glyph inside a\n // 44×44 button aligns optically with a single-line description.\n // With a title: the root flips to `items-start` so the button's top\n // edge aligns with the title row top. A centred glyph would then\n // land ~11 px below the title's optical centre (button height is\n // --min-target-size, much taller than the title's line-height). The\n // `[data-has-title=true]` variant below flips the button to\n // `items-start` and adds a block-start padding that pulls the glyph\n // up onto the title row — same cap-height compensation idea as the\n // leading icon's `mt-0.5`.\n 'ds:ms-auto ds:shrink-0 ds:inline-flex ds:items-center ds:justify-center',\n 'ds:[[data-has-title=true]_&]:items-start',\n 'ds:[[data-has-title=true]_&]:pt-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:-mt-[var(--spacing-xs)] ds:-me-[var(--spacing-xs)]',\n 'ds:text-current ds:opacity-70',\n 'ds:hover:opacity-100',\n 'ds:transition-opacity ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\n// `role` / `live` here are only the *default* announcement for each tint.\n// The `announce` prop overrides both — visual severity and announcement\n// urgency are independent (a warning-tinted static notice must not interrupt).\nconst VARIANT_CONFIG = {\n info: { icon: <Info aria-hidden=\"true\" />, role: 'status', live: 'polite' },\n success: {\n icon: <CircleCheck aria-hidden=\"true\" />,\n role: 'status',\n live: 'polite',\n },\n warning: {\n icon: <TriangleAlert aria-hidden=\"true\" />,\n role: 'alert',\n live: 'assertive',\n },\n error: {\n icon: <CircleAlert aria-hidden=\"true\" />,\n role: 'alert',\n live: 'assertive',\n },\n // Promotions never interrupt — same polite semantics as info.\n promo: {\n icon: <CircleArrowUp aria-hidden=\"true\" />,\n role: 'status',\n live: 'polite',\n },\n} as const;\n\n// `off` emits neither role nor aria-live: a permanently-mounted notice is\n// read in document order and is not a live region at all.\nconst ANNOUNCE_CONFIG = {\n off: { role: undefined, live: undefined },\n polite: { role: 'status', live: 'polite' },\n assertive: { role: 'alert', live: 'assertive' },\n} as const;\n\ninterface AlertTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span';\n}\n\nconst AlertTitle = forwardRef<HTMLHeadingElement, AlertTitleProps>(\n ({ as: Tag = 'h5', className, children, ...props }, ref) => {\n const clamp = useContext(AlertClampContext);\n const { ref: clampRef, isOverflowing } =\n useClampOverflow<HTMLHeadingElement>(clamp);\n const setRefs = useCallback(\n (node: HTMLHeadingElement | null) => {\n (clampRef as MutableRefObject<HTMLHeadingElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as MutableRefObject<HTMLHeadingElement | null>).current = node;\n },\n [ref, clampRef],\n );\n\n // The full title stays in the DOM (line-clamp only clips it visually), so\n // screen readers always read it whole. The tooltip is a sighted-user\n // affordance, shown only when the title is actually cut — and only for\n // string titles, since the Tooltip label must be plain text.\n const tooltipReady = clamp && isOverflowing && typeof children === 'string';\n\n const heading = (\n <Tag\n ref={setRefs}\n // Focusable only when truncated, so keyboard users can surface the\n // tooltip too (otherwise it would be mouse/hover-only).\n tabIndex={tooltipReady ? 0 : undefined}\n className={[\n 'type-title-item',\n clamp ? 'ds:line-clamp-2' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n {children}\n </Tag>\n );\n\n return tooltipReady ? (\n <Tooltip label={children as string}>{heading}</Tooltip>\n ) : (\n heading\n );\n },\n);\nAlertTitle.displayName = 'Alert.Title';\n\nconst AlertDescription = forwardRef<\n HTMLParagraphElement,\n HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const clamp = useContext(AlertClampContext);\n const { t } = useTranslation('ui');\n const bodyId = useId();\n const [expanded, setExpanded] = useState(false);\n // Only measure while clamped — once expanded there's nothing to clip.\n const { ref: clampRef, isOverflowing } =\n useClampOverflow<HTMLParagraphElement>(clamp && !expanded);\n const setRefs = useCallback(\n (node: HTMLParagraphElement | null) => {\n (clampRef as MutableRefObject<HTMLParagraphElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as MutableRefObject<HTMLParagraphElement | null>).current = node;\n },\n [ref, clampRef],\n );\n // Show the toggle once the body has overflowed; keep it while expanded so\n // the user can collapse again.\n const showToggle = clamp && (isOverflowing || expanded);\n\n return (\n <>\n <p\n ref={setRefs}\n id={clamp ? bodyId : undefined}\n // `mt` is gated on the root's `data-has-title=\"true\"` attribute so\n // the margin only paints when there's a Title above the\n // Description to separate from. Without this gate, a Description\n // rendered alone sits a few pixels below the icon + dismiss ×\n // optical centre — visible on the AlfaDocs marketing privacy\n // generator before HTP-4860's follow-up fix.\n className={[\n 'ds:[[data-has-title=true]_&]:mt-[var(--spacing-xs)] type-body-sm',\n clamp && !expanded ? 'ds:line-clamp-2' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n {children}\n </p>\n {showToggle ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n aria-controls={bodyId}\n onClick={() => setExpanded((prev) => !prev)}\n className={DISCLOSURE_BUTTON_CLASSES}\n >\n {expanded\n ? t('feedback.alert.readLess', 'Read less')\n : t('feedback.alert.readMore', 'Read more')}\n </button>\n ) : null}\n </>\n );\n});\nAlertDescription.displayName = 'Alert.Description';\n\nconst AlertAction = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={[\n 'ds:mt-[var(--spacing-md)] ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n />\n ),\n);\nAlertAction.displayName = 'Alert.Action';\n\n/** How urgently the alert is announced — independent of the visual `variant`.\n *\n * - `off` — not a live region. No `role`, no `aria-live`. Correct for a\n * static notice that is present from mount (a read-only banner, a summary\n * of missing answers on a form the user is still typing into).\n * - `polite` — `role=\"status\"` + `aria-live=\"polite\"`. Queued behind the\n * current utterance. The right default for anything that appears in\n * response to a user action but is not an emergency.\n * - `assertive` — `role=\"alert\"` + `aria-live=\"assertive\"`. Interrupts the\n * screen reader immediately. Reserve for content the user cannot miss.\n */\nexport type AlertAnnounce = 'off' | 'polite' | 'assertive';\n\nexport interface AlertProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'role'>,\n VariantProps<typeof alertVariants> {\n variant?: 'info' | 'success' | 'warning' | 'error' | 'promo';\n dismissible?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n icon?: ReactNode;\n /** Announcement urgency — sets `role` **and** `aria-live` together, so the\n * tint (`variant`) and the interruption are chosen independently. Defaults\n * to the variant's historical mapping: `info` / `success` / `promo` →\n * `polite`, `warning` / `error` → `assertive`. Wins over `live`. */\n announce?: AlertAnnounce;\n /** @deprecated Use `announce`. Sets `aria-live` only and leaves `role`\n * variant-derived, which can pair `role=\"alert\"` with `aria-live=\"polite\"`.\n * Kept for the consumers already shipping it. */\n live?: 'assertive' | 'polite' | 'off';\n /** Compact mode: clamps `Alert.Title` to 2 lines (with a tooltip when the\n * title is truncated) and `Alert.Description` to 2 lines (with a \"Read more\"\n * toggle). Opt-in — leave off for standalone alerts whose full message must\n * always be visible. */\n clamp?: boolean;\n}\n\nexport type { AlertTitleProps };\n\nconst AlertRoot = forwardRef<HTMLDivElement, AlertProps>(\n (\n {\n variant = 'info',\n dismissible = false,\n open: controlledOpen,\n onOpenChange,\n icon,\n announce,\n live,\n clamp = false,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const [isOpenRaw, setOpen] = useControllableState<boolean>({\n value: controlledOpen,\n defaultValue: true,\n onChange: onOpenChange,\n });\n const isOpen = isOpenRaw ?? true;\n const [isClosing, setIsClosing] = useState(false);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const animationDurationMs = useCallback((): number => {\n if (typeof window === 'undefined') return 200;\n const raw = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration');\n if (!raw) return 200;\n const trimmed = raw.trim();\n const n = parseFloat(trimmed);\n if (!Number.isFinite(n)) return 200;\n return trimmed.endsWith('ms') ? n : n * 1000;\n }, []);\n\n if (!isOpen) return null;\n\n const config = VARIANT_CONFIG[variant];\n const effectiveIcon = icon !== undefined ? icon : config.icon;\n\n // `announce` owns role + aria-live together. Without it we keep the\n // shipped behaviour exactly: role from the variant, aria-live from the\n // legacy `live` prop or the variant default.\n const announcement = announce\n ? ANNOUNCE_CONFIG[announce]\n : { role: config.role, live: live ?? config.live };\n\n // Detect an `<Alert.Title>` anywhere in the immediate children so\n // the root can flip its cross-axis alignment. Nested wrappers\n // around a Title aren't supported — keep the API as flat as the\n // existing `Alert.Title` / `Alert.Description` convention.\n const hasTitle = Children.toArray(children).some(\n (child) => isValidElement(child) && child.type === AlertTitle,\n );\n\n const handleDismiss = () => {\n if (isClosing) return;\n setIsClosing(true);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n closeTimerRef.current = setTimeout(() => {\n setIsClosing(false);\n setOpen(false);\n }, animationDurationMs());\n };\n\n return (\n <div\n ref={ref}\n role={announcement.role}\n aria-live={announcement.live}\n data-component=\"alert\"\n data-has-title={hasTitle ? 'true' : 'false'}\n data-state={isClosing ? 'closing' : 'open'}\n className={[\n alertVariants({ variant, className }),\n // Entry: fade + slide-down on mount. Exit: fade + slide-up + slight\n // scale when dismissed. Driven by `tw-animate-css`. Respects\n // `prefers-reduced-motion` via `motion-safe:` and zeroes under the\n // accessible theme (`--animation-duration: 0ms`).\n 'ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:slide-in-from-top-2',\n 'ds:motion-safe:data-[state=closing]:animate-out ds:motion-safe:data-[state=closing]:fade-out-0',\n 'ds:motion-safe:data-[state=closing]:slide-out-to-top-2 ds:motion-safe:data-[state=closing]:zoom-out-95',\n // Pin the exit's end-state until React unmounts. Without\n // `fill-mode-forwards` the element snaps back to opacity:1 for one\n // paint frame after the animation ends.\n 'ds:motion-safe:data-[state=closing]:fill-mode-forwards',\n 'ds:motion-safe:duration-[var(--animation-duration)]',\n ].join(' ')}\n {...props}\n >\n {effectiveIcon ? (\n <span className={hasTitle ? ICON_WITH_TITLE : ICON_BASE}>\n {effectiveIcon}\n </span>\n ) : null}\n\n <div className=\"ds:flex-1 ds:min-w-0\">\n <AlertClampContext.Provider value={clamp}>\n {children}\n </AlertClampContext.Provider>\n </div>\n\n {dismissible ? (\n <button\n type=\"button\"\n aria-label={t('common.close', 'Close')}\n onClick={handleDismiss}\n // Stable hook for containers (WarningStack) that hand focus to\n // a neighbouring dismiss control after this one unmounts.\n data-alert-dismiss=\"\"\n className={CLOSE_BUTTON_CLASSES}\n >\n <X aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n ) : null}\n </div>\n );\n },\n);\n\nAlertRoot.displayName = 'Alert';\n\nexport const Alert = Object.assign(AlertRoot, {\n Title: AlertTitle,\n Description: AlertDescription,\n Action: AlertAction,\n});\n"],"names":["__iconNode","CircleArrowUp","createLucideIcon","AlertClampContext","createContext","DISCLOSURE_BUTTON_CLASSES","alertVariants","cva","ICON_BASE","ICON_WITH_TITLE","CLOSE_BUTTON_CLASSES","VARIANT_CONFIG","jsx","Info","CircleCheck","TriangleAlert","CircleAlert","ANNOUNCE_CONFIG","AlertTitle","forwardRef","Tag","className","children","props","ref","clamp","useContext","clampRef","isOverflowing","useClampOverflow","setRefs","useCallback","node","tooltipReady","heading","Tooltip","AlertDescription","t","useTranslation","bodyId","useId","expanded","setExpanded","useState","showToggle","jsxs","Fragment","prev","AlertAction","AlertRoot","variant","dismissible","controlledOpen","onOpenChange","icon","announce","live","isOpenRaw","setOpen","useControllableState","isOpen","isClosing","setIsClosing","closeTimerRef","useRef","animationDurationMs","raw","trimmed","n","config","effectiveIcon","announcement","hasTitle","Children","child","isValidElement","handleDismiss","X","Alert"],"mappings":";;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,KAAa;AAAA,EACjB,CAAC,UAAU,EAAE,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,KAAK,UAAU;AAAA,EACzD,CAAC,QAAQ,EAAE,GAAG,kBAAkB,KAAK,SAAQ,CAAE;AAAA,EAC/C,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAC3C,GACMC,KAAgBC,EAAiB,mBAAmBF,EAAU,GCmB9DG,IAAoBC,EAAc,EAAK,GAIvCC,KAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,KAAgBC;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMR,SAAS;AAAA,QACP,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,QACV,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,QACV,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,QACV,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOV,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,MAAA;AAAA,IACZ;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ,GAOMC,IAAY,yBACZC,KAAkB,GAAGD,CAAS,cAE9BE,KAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAKJC,KAAiB;AAAA,EACrB,MAAM,EAAE,MAAM,gBAAAC,EAACC,IAAA,EAAK,eAAY,OAAA,CAAO,GAAI,MAAM,UAAU,MAAM,SAAA;AAAA,EACjE,SAAS;AAAA,IACP,MAAM,gBAAAD,EAACE,IAAA,EAAY,eAAY,OAAA,CAAO;AAAA,IACtC,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA,EAER,SAAS;AAAA,IACP,MAAM,gBAAAF,EAACG,IAAA,EAAc,eAAY,OAAA,CAAO;AAAA,IACxC,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA,EAER,OAAO;AAAA,IACL,MAAM,gBAAAH,EAACI,GAAA,EAAY,eAAY,OAAA,CAAO;AAAA,IACtC,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA;AAAA,EAGR,OAAO;AAAA,IACL,MAAM,gBAAAJ,EAACX,IAAA,EAAc,eAAY,OAAA,CAAO;AAAA,IACxC,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAEV,GAIMgB,KAAkB;AAAA,EACtB,KAAK,EAAE,MAAM,QAAW,MAAM,OAAA;AAAA,EAC9B,QAAQ,EAAE,MAAM,UAAU,MAAM,SAAA;AAAA,EAChC,WAAW,EAAE,MAAM,SAAS,MAAM,YAAA;AACpC,GAMMC,IAAaC;AAAA,EACjB,CAAC,EAAE,IAAIC,IAAM,MAAM,WAAAC,GAAW,UAAAC,GAAU,GAAGC,EAAA,GAASC,MAAQ;AAC1D,UAAMC,IAAQC,EAAWvB,CAAiB,GACpC,EAAE,KAAKwB,GAAU,eAAAC,EAAA,IACrBC,EAAqCJ,CAAK,GACtCK,IAAUC;AAAA,MACd,CAACC,MAAoC;AAClC,QAAAL,EAAyD,UACxDK,GACE,OAAOR,KAAQ,aAAYA,EAAIQ,CAAI,IAC9BR,MACNA,EAAoD,UAAUQ;AAAA,MACnE;AAAA,MACA,CAACR,GAAKG,CAAQ;AAAA,IAAA,GAOVM,IAAeR,KAASG,KAAiB,OAAON,KAAa,UAE7DY,IACJ,gBAAAtB;AAAA,MAACQ;AAAA,MAAA;AAAA,QACC,KAAKU;AAAA,QAGL,UAAUG,IAAe,IAAI;AAAA,QAC7B,WAAW;AAAA,UACT;AAAA,UACAR,IAAQ,oBAAoB;AAAA,UAC5BJ;AAAA,QAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,QACV,GAAGE;AAAA,QAEH,UAAAD;AAAA,MAAA;AAAA,IAAA;AAIL,WAAOW,IACL,gBAAArB,EAACuB,GAAA,EAAQ,OAAOb,GAAqB,aAAQ,IAE7CY;AAAA,EAEJ;AACF;AACAhB,EAAW,cAAc;AAEzB,MAAMkB,IAAmBjB,EAGvB,CAAC,EAAE,WAAAE,GAAW,UAAAC,GAAU,GAAGC,EAAA,GAASC,MAAQ;AAC5C,QAAMC,IAAQC,EAAWvB,CAAiB,GACpC,EAAE,GAAAkC,EAAA,IAAMC,EAAe,IAAI,GAC3BC,IAASC,EAAA,GACT,CAACC,GAAUC,CAAW,IAAIC,EAAS,EAAK,GAExC,EAAE,KAAKhB,GAAU,eAAAC,EAAA,IACrBC,EAAuCJ,KAAS,CAACgB,CAAQ,GACrDX,IAAUC;AAAA,IACd,CAACC,MAAsC;AACpC,MAAAL,EAA2D,UAC1DK,GACE,OAAOR,KAAQ,aAAYA,EAAIQ,CAAI,IAC9BR,MACNA,EAAsD,UAAUQ;AAAA,IACrE;AAAA,IACA,CAACR,GAAKG,CAAQ;AAAA,EAAA,GAIViB,IAAanB,MAAUG,KAAiBa;AAE9C,SACE,gBAAAI,EAAAC,GAAA,EACE,UAAA;AAAA,IAAA,gBAAAlC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKkB;AAAA,QACL,IAAIL,IAAQc,IAAS;AAAA,QAOrB,WAAW;AAAA,UACT;AAAA,UACAd,KAAS,CAACgB,IAAW,oBAAoB;AAAA,UACzCpB;AAAA,QAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,QACV,GAAGE;AAAA,QAEH,UAAAD;AAAA,MAAA;AAAA,IAAA;AAAA,IAEFsB,IACC,gBAAAhC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,iBAAe6B;AAAA,QACf,iBAAeF;AAAA,QACf,SAAS,MAAMG,EAAY,CAACK,MAAS,CAACA,CAAI;AAAA,QAC1C,WAAW1C;AAAA,QAEV,cACGgC,EAAE,2BAA2B,WAAW,IACxCA,EAAE,2BAA2B,WAAW;AAAA,MAAA;AAAA,IAAA,IAE5C;AAAA,EAAA,GACN;AAEJ,CAAC;AACDD,EAAiB,cAAc;AAE/B,MAAMY,IAAc7B;AAAA,EAClB,CAAC,EAAE,WAAAE,GAAW,GAAGE,EAAA,GAASC,MACxB,gBAAAZ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAY;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACAH;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MACV,GAAGE;AAAA,IAAA;AAAA,EAAA;AAGV;AACAyB,EAAY,cAAc;AA0C1B,MAAMC,IAAY9B;AAAA,EAChB,CACE;AAAA,IACE,SAAA+B,IAAU;AAAA,IACV,aAAAC,IAAc;AAAA,IACd,MAAMC;AAAA,IACN,cAAAC;AAAA,IACA,MAAAC;AAAA,IACA,UAAAC;AAAA,IACA,MAAAC;AAAA,IACA,OAAA/B,IAAQ;AAAA,IACR,WAAAJ;AAAA,IACA,UAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAM,EAAE,GAAAa,EAAA,IAAMC,EAAe,IAAI,GAC3B,CAACmB,GAAWC,CAAO,IAAIC,EAA8B;AAAA,MACzD,OAAOP;AAAA,MACP,cAAc;AAAA,MACd,UAAUC;AAAA,IAAA,CACX,GACKO,IAASH,KAAa,IACtB,CAACI,GAAWC,CAAY,IAAInB,EAAS,EAAK,GAC1CoB,IAAgBC,EAA6C,IAAI,GAEjEC,IAAsBlC,EAAY,MAAc;AACpD,UAAI,OAAO,SAAW,IAAa,QAAO;AAC1C,YAAMmC,IAAM,OACT,iBAAiB,SAAS,eAAe,EACzC,iBAAiB,sBAAsB;AAC1C,UAAI,CAACA,EAAK,QAAO;AACjB,YAAMC,IAAUD,EAAI,KAAA,GACdE,IAAI,WAAWD,CAAO;AAC5B,aAAK,OAAO,SAASC,CAAC,IACfD,EAAQ,SAAS,IAAI,IAAIC,IAAIA,IAAI,MADR;AAAA,IAElC,GAAG,CAAA,CAAE;AAEL,QAAI,CAACR,EAAQ,QAAO;AAEpB,UAAMS,IAAS1D,GAAeuC,CAAO,GAC/BoB,IAAgBhB,MAAS,SAAYA,IAAOe,EAAO,MAKnDE,IAAehB,IACjBtC,GAAgBsC,CAAQ,IACxB,EAAE,MAAMc,EAAO,MAAM,MAAMb,KAAQa,EAAO,KAAA,GAMxCG,IAAWC,EAAS,QAAQnD,CAAQ,EAAE;AAAA,MAC1C,CAACoD,MAAUC,EAAeD,CAAK,KAAKA,EAAM,SAASxD;AAAA,IAAA,GAG/C0D,IAAgB,MAAM;AAC1B,MAAIf,MACJC,EAAa,EAAI,GACbC,EAAc,WAAS,aAAaA,EAAc,OAAO,GAC7DA,EAAc,UAAU,WAAW,MAAM;AACvC,QAAAD,EAAa,EAAK,GAClBJ,EAAQ,EAAK;AAAA,MACf,GAAGO,GAAqB;AAAA,IAC1B;AAEA,WACE,gBAAApB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAArB;AAAA,QACA,MAAM+C,EAAa;AAAA,QACnB,aAAWA,EAAa;AAAA,QACxB,kBAAe;AAAA,QACf,kBAAgBC,IAAW,SAAS;AAAA,QACpC,cAAYX,IAAY,YAAY;AAAA,QACpC,WAAW;AAAA,UACTvD,GAAc,EAAE,SAAA4C,GAAS,WAAA7B,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA,UAKpC;AAAA,UACA;AAAA,UACA;AAAA;AAAA;AAAA;AAAA,UAIA;AAAA,UACA;AAAA,QAAA,EACA,KAAK,GAAG;AAAA,QACT,GAAGE;AAAA,QAEH,UAAA;AAAA,UAAA+C,sBACE,QAAA,EAAK,WAAWE,IAAW/D,KAAkBD,GAC3C,aACH,IACE;AAAA,UAEJ,gBAAAI,EAAC,OAAA,EAAI,WAAU,wBACb,UAAA,gBAAAA,EAACT,EAAkB,UAAlB,EAA2B,OAAOsB,GAChC,UAAAH,EAAA,CACH,EAAA,CACF;AAAA,UAEC6B,IACC,gBAAAvC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAYyB,EAAE,gBAAgB,OAAO;AAAA,cACrC,SAASuC;AAAA,cAGT,sBAAmB;AAAA,cACnB,WAAWlE;AAAA,cAEX,UAAA,gBAAAE,EAACiE,GAAA,EAAE,eAAY,QAAO,WAAU,YAAA,CAAY;AAAA,YAAA;AAAA,UAAA,IAE5C;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEA5B,EAAU,cAAc;AAEjB,MAAM6B,KAAQ,OAAO,OAAO7B,GAAW;AAAA,EAC5C,OAAO/B;AAAA,EACP,aAAakB;AAAA,EACb,QAAQY;AACV,CAAC;","x_google_ignoreList":[0]}
@@ -17,7 +17,7 @@ import { T as na } from "./text-area-COMVJ1yE.js";
17
17
  import { S as te } from "./state-backed-text-input-Cgh4ms3p.js";
18
18
  import { T as Ze } from "./timestamp-DPLDWdxA.js";
19
19
  import { D as sn } from "./date-picker-KcoNNsM0.js";
20
- import { A as Ue } from "./alert-DdDpOi-P.js";
20
+ import { A as Ue } from "./alert-DjsJMGRE.js";
21
21
  import { D as L } from "./description-list-Q8640NHu.js";
22
22
  import { c as Xt } from "./index-D2ZczOXr.js";
23
23
  import { S as dn } from "./sparkline-SnniCoCl.js";
@@ -20924,4 +20924,4 @@ export {
20924
20924
  Vi as t,
20925
20925
  nd as u
20926
20926
  };
20927
- //# sourceMappingURL=anamnesis-summary-rows-BIfw890v.js.map
20927
+ //# sourceMappingURL=anamnesis-summary-rows-BQ_EokKz.js.map