@alfadocs/ui-kit-debug 1.90.2 → 1.91.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 (272) hide show
  1. package/dist/_chunks/{agenda-card-BDuvreCe.js → agenda-card-BhY342MA.js} +2 -2
  2. package/dist/_chunks/{agenda-card-BDuvreCe.js.map → agenda-card-BhY342MA.js.map} +1 -1
  3. package/dist/_chunks/{agenda-tray-D-jvptdo.js → agenda-tray-BmxBGEci.js} +2 -2
  4. package/dist/_chunks/{agenda-tray-D-jvptdo.js.map → agenda-tray-BmxBGEci.js.map} +1 -1
  5. package/dist/_chunks/{alia-sidebar-CsTRAxC8.js → alia-sidebar-ovRX_oti.js} +3 -3
  6. package/dist/_chunks/{alia-sidebar-CsTRAxC8.js.map → alia-sidebar-ovRX_oti.js.map} +1 -1
  7. package/dist/_chunks/{appointment-card-5JMWi9_f.js → appointment-card-Bstc1p7a.js} +2 -2
  8. package/dist/_chunks/{appointment-card-5JMWi9_f.js.map → appointment-card-Bstc1p7a.js.map} +1 -1
  9. package/dist/_chunks/{appointment-peek-39BwVMUf.js → appointment-peek-C0kKqnFk.js} +2 -2
  10. package/dist/_chunks/{appointment-peek-39BwVMUf.js.map → appointment-peek-C0kKqnFk.js.map} +1 -1
  11. package/dist/_chunks/{appointment-timeline-1-Za2miy.js → appointment-timeline-rbt9AwHO.js} +2 -2
  12. package/dist/_chunks/{appointment-timeline-1-Za2miy.js.map → appointment-timeline-rbt9AwHO.js.map} +1 -1
  13. package/dist/_chunks/{appointment-tray-Dwc8MSIQ.js → appointment-tray-6zd8RLIL.js} +2 -2
  14. package/dist/_chunks/{appointment-tray-Dwc8MSIQ.js.map → appointment-tray-6zd8RLIL.js.map} +1 -1
  15. package/dist/_chunks/{avatar-BPiPL7ND.js → avatar-a6042Ox2.js} +52 -52
  16. package/dist/_chunks/avatar-a6042Ox2.js.map +1 -0
  17. package/dist/_chunks/{balance-badge-cell-D9VhFp0L.js → balance-badge-cell-BtJvre1-.js} +2 -2
  18. package/dist/_chunks/{balance-badge-cell-D9VhFp0L.js.map → balance-badge-cell-BtJvre1-.js.map} +1 -1
  19. package/dist/_chunks/booking-opt_h7Uc.js +4590 -0
  20. package/dist/_chunks/booking-opt_h7Uc.js.map +1 -0
  21. package/dist/_chunks/{calendar-ClB-jWH1.js → calendar-CmiMS4FJ.js} +2 -2
  22. package/dist/_chunks/{calendar-ClB-jWH1.js.map → calendar-CmiMS4FJ.js.map} +1 -1
  23. package/dist/_chunks/{calendar-appointment-editor-dialog-CiAGAX2t.js → calendar-appointment-editor-dialog-sJKLoVJ2.js} +7 -7
  24. package/dist/_chunks/{calendar-appointment-editor-dialog-CiAGAX2t.js.map → calendar-appointment-editor-dialog-sJKLoVJ2.js.map} +1 -1
  25. package/dist/_chunks/{care-plan-card-BYCPNDvA.js → care-plan-card-DD9rEWYN.js} +2 -2
  26. package/dist/_chunks/{care-plan-card-BYCPNDvA.js.map → care-plan-card-DD9rEWYN.js.map} +1 -1
  27. package/dist/_chunks/{care-plan-header-BzsAg6oY.js → care-plan-header-CXUJQt8Q.js} +2 -2
  28. package/dist/_chunks/{care-plan-header-BzsAg6oY.js.map → care-plan-header-CXUJQt8Q.js.map} +1 -1
  29. package/dist/_chunks/{chat-message-CmFJdEre.js → chat-message-LRO_6Ee3.js} +2 -2
  30. package/dist/_chunks/{chat-message-CmFJdEre.js.map → chat-message-LRO_6Ee3.js.map} +1 -1
  31. package/dist/_chunks/{clinical-note-card-Caidqcwa.js → clinical-note-card-Cut2lNmu.js} +3 -3
  32. package/dist/_chunks/{clinical-note-card-Caidqcwa.js.map → clinical-note-card-Cut2lNmu.js.map} +1 -1
  33. package/dist/_chunks/{contact-card-Czu60UvU.js → contact-card-ClvEDM9e.js} +2 -2
  34. package/dist/_chunks/{contact-card-Czu60UvU.js.map → contact-card-ClvEDM9e.js.map} +1 -1
  35. package/dist/_chunks/{contact-profile-card-Da1vmJQI.js → contact-profile-card-CX45mZA3.js} +106 -95
  36. package/dist/_chunks/contact-profile-card-CX45mZA3.js.map +1 -0
  37. package/dist/_chunks/{dependent-selector-C4kOgO8b.js → dependent-selector-CyNi7M_f.js} +2 -2
  38. package/dist/_chunks/{dependent-selector-C4kOgO8b.js.map → dependent-selector-CyNi7M_f.js.map} +1 -1
  39. package/dist/_chunks/{entity-summary-BLxzSSXK.js → entity-summary-B_bOloqP.js} +3 -3
  40. package/dist/_chunks/{entity-summary-BLxzSSXK.js.map → entity-summary-B_bOloqP.js.map} +1 -1
  41. package/dist/_chunks/error-page-B0fGNTRB.js +419 -0
  42. package/dist/_chunks/error-page-B0fGNTRB.js.map +1 -0
  43. package/dist/_chunks/{languages-CZqBaPwI.js → languages-CGLX6Qpe.js} +3 -15
  44. package/dist/_chunks/languages-CGLX6Qpe.js.map +1 -0
  45. package/dist/_chunks/link-DtCfnLnF.js +332 -0
  46. package/dist/_chunks/link-DtCfnLnF.js.map +1 -0
  47. package/dist/_chunks/{link-cell-renderer-CnCgudvq.js → link-cell-renderer-BS3V4LA6.js} +2 -2
  48. package/dist/_chunks/{link-cell-renderer-CnCgudvq.js.map → link-cell-renderer-BS3V4LA6.js.map} +1 -1
  49. package/dist/_chunks/{marketplace-app-shell-CmZx0Oam.js → marketplace-app-shell-CJQtx3sv.js} +2 -2
  50. package/dist/_chunks/{marketplace-app-shell-CmZx0Oam.js.map → marketplace-app-shell-CJQtx3sv.js.map} +1 -1
  51. package/dist/_chunks/{message-card-CvCnCssc.js → message-card-B6SduXJv.js} +2 -2
  52. package/dist/_chunks/{message-card-CvCnCssc.js.map → message-card-B6SduXJv.js.map} +1 -1
  53. package/dist/_chunks/{message-tray-IJYvy6Cf.js → message-tray-Cllf-v0G.js} +2 -2
  54. package/dist/_chunks/{message-tray-IJYvy6Cf.js.map → message-tray-Cllf-v0G.js.map} +1 -1
  55. package/dist/_chunks/{nav-grid-Oc4aCPrg.js → nav-grid-D2xVcHTO.js} +2 -2
  56. package/dist/_chunks/{nav-grid-Oc4aCPrg.js.map → nav-grid-D2xVcHTO.js.map} +1 -1
  57. package/dist/_chunks/{note-attachment-DIlIQ7JF.js → note-attachment-cnj2JRrg.js} +2 -2
  58. package/dist/_chunks/{note-attachment-DIlIQ7JF.js.map → note-attachment-cnj2JRrg.js.map} +1 -1
  59. package/dist/_chunks/{note-timeline-KzL52MmB.js → note-timeline-BrjHBQfx.js} +2 -2
  60. package/dist/_chunks/{note-timeline-KzL52MmB.js.map → note-timeline-BrjHBQfx.js.map} +1 -1
  61. package/dist/_chunks/{notes-panel-Dywo6R55.js → notes-panel-ib7I3aNf.js} +2 -2
  62. package/dist/_chunks/{notes-panel-Dywo6R55.js.map → notes-panel-ib7I3aNf.js.map} +1 -1
  63. package/dist/_chunks/{operator-hero-6aAIQaFZ.js → operator-hero-C_5B-8Qp.js} +43 -41
  64. package/dist/_chunks/operator-hero-C_5B-8Qp.js.map +1 -0
  65. package/dist/_chunks/{patient-details-BUr7Oemx.js → patient-details-BjcUpD9S.js} +3 -3
  66. package/dist/_chunks/{patient-details-BUr7Oemx.js.map → patient-details-BjcUpD9S.js.map} +1 -1
  67. package/dist/_chunks/{patient-field-row-bJk8Q_qr.js → patient-field-row-B0tdiaWi.js} +2 -2
  68. package/dist/_chunks/{patient-field-row-bJk8Q_qr.js.map → patient-field-row-B0tdiaWi.js.map} +1 -1
  69. package/dist/_chunks/{patient-summary-card-CCQZ8X37.js → patient-summary-card-Cvv6_Ugk.js} +4 -4
  70. package/dist/_chunks/{patient-summary-card-CCQZ8X37.js.map → patient-summary-card-Cvv6_Ugk.js.map} +1 -1
  71. package/dist/_chunks/{payment-request-card-MndSlVoK.js → payment-request-card-BfGauFY0.js} +2 -2
  72. package/dist/_chunks/{payment-request-card-MndSlVoK.js.map → payment-request-card-BfGauFY0.js.map} +1 -1
  73. package/dist/_chunks/{practice-profile-hero-qfrsFQI_.js → practice-profile-hero-ClzE-4CB.js} +76 -73
  74. package/dist/_chunks/practice-profile-hero-ClzE-4CB.js.map +1 -0
  75. package/dist/_chunks/{practice-results-DQuOfqej.js → practice-results-CQ_KvEXK.js} +517 -514
  76. package/dist/_chunks/practice-results-CQ_KvEXK.js.map +1 -0
  77. package/dist/_chunks/{product-hub-panel-Blag8t8f.js → product-hub-panel-bHi7lkVD.js} +2 -2
  78. package/dist/_chunks/{product-hub-panel-Blag8t8f.js.map → product-hub-panel-bHi7lkVD.js.map} +1 -1
  79. package/dist/_chunks/public-footer-IoRWoAMz.js +596 -0
  80. package/dist/_chunks/public-footer-IoRWoAMz.js.map +1 -0
  81. package/dist/_chunks/{signature-request-DjY-X62H.js → signature-request-DvhyrRpn.js} +3 -3
  82. package/dist/_chunks/{signature-request-DjY-X62H.js.map → signature-request-DvhyrRpn.js.map} +1 -1
  83. package/dist/_chunks/{signed-out-frame-G-3ATOdu.js → signed-out-frame-CgRXOUzi.js} +2 -2
  84. package/dist/_chunks/{signed-out-frame-G-3ATOdu.js.map → signed-out-frame-CgRXOUzi.js.map} +1 -1
  85. package/dist/_chunks/{slot-grid-DrwynKeN.js → slot-grid-B-IAFX3C.js} +180 -169
  86. package/dist/_chunks/slot-grid-B-IAFX3C.js.map +1 -0
  87. package/dist/_chunks/{timeline-wUuTDFY_.js → timeline-BcYHdP56.js} +2 -2
  88. package/dist/_chunks/{timeline-wUuTDFY_.js.map → timeline-BcYHdP56.js.map} +1 -1
  89. package/dist/_chunks/{use-appointment-details-read-BytPq3Ux.js → use-appointment-details-read-D8vDg0sg.js} +5 -5
  90. package/dist/_chunks/{use-appointment-details-read-BytPq3Ux.js.map → use-appointment-details-read-D8vDg0sg.js.map} +1 -1
  91. package/dist/agent-catalog.json +2 -2
  92. package/dist/components/_shared/social-brand-icons.d.ts +29 -0
  93. package/dist/components/_shared/social-brand-icons.d.ts.map +1 -0
  94. package/dist/components/agenda-card/index.js +1 -1
  95. package/dist/components/agenda-tray/index.js +1 -1
  96. package/dist/components/appointment-card/index.js +2 -2
  97. package/dist/components/appointment-details-panel/index.js +1 -1
  98. package/dist/components/appointment-peek/index.js +1 -1
  99. package/dist/components/appointment-timeline/index.js +1 -1
  100. package/dist/components/avatar/avatar.d.ts +14 -0
  101. package/dist/components/avatar/avatar.d.ts.map +1 -1
  102. package/dist/components/avatar/index.js +1 -1
  103. package/dist/components/booking/booking-types.d.ts +26 -0
  104. package/dist/components/booking/booking-types.d.ts.map +1 -1
  105. package/dist/components/booking/booking.d.ts.map +1 -1
  106. package/dist/components/booking/details-form.d.ts.map +1 -1
  107. package/dist/components/booking/index.js +1 -1
  108. package/dist/components/booking/slot-load-state.d.ts +11 -0
  109. package/dist/components/booking/slot-load-state.d.ts.map +1 -0
  110. package/dist/components/calendar/index.js +1 -1
  111. package/dist/components/care-plan-card/index.js +1 -1
  112. package/dist/components/care-plan-header/index.js +1 -1
  113. package/dist/components/chat-message/index.js +1 -1
  114. package/dist/components/clinical-note-card/index.js +1 -1
  115. package/dist/components/contact-card/index.js +1 -1
  116. package/dist/components/contact-profile-card/index.js +1 -1
  117. package/dist/components/data-table/index.js +1 -1
  118. package/dist/components/dependent-selector/index.js +1 -1
  119. package/dist/components/entity-summary/index.js +1 -1
  120. package/dist/components/link/index.js +1 -1
  121. package/dist/components/link/link.d.ts +10 -1
  122. package/dist/components/link/link.d.ts.map +1 -1
  123. package/dist/components/link/social-url.d.ts +71 -0
  124. package/dist/components/link/social-url.d.ts.map +1 -0
  125. package/dist/components/message-card/index.js +1 -1
  126. package/dist/components/message-tray/index.js +1 -1
  127. package/dist/components/nav-grid/index.js +1 -1
  128. package/dist/components/note-timeline/index.js +1 -1
  129. package/dist/components/notes-panel/index.js +1 -1
  130. package/dist/components/operator-hero/index.js +1 -1
  131. package/dist/components/operator-hero/operator-hero.d.ts +6 -0
  132. package/dist/components/operator-hero/operator-hero.d.ts.map +1 -1
  133. package/dist/components/patient-details/index.js +1 -1
  134. package/dist/components/patient-summary-card/index.js +1 -1
  135. package/dist/components/patient-table/index.js +1 -1
  136. package/dist/components/payment-card/index.js +1 -1
  137. package/dist/components/practice-profile-hero/index.js +1 -1
  138. package/dist/components/practice-profile-hero/practice-profile-hero.d.ts +6 -0
  139. package/dist/components/practice-profile-hero/practice-profile-hero.d.ts.map +1 -1
  140. package/dist/components/practice-results/index.js +1 -1
  141. package/dist/components/practice-results/practice-results.d.ts +8 -2
  142. package/dist/components/practice-results/practice-results.d.ts.map +1 -1
  143. package/dist/components/product-hub-tray/index.js +1 -1
  144. package/dist/components/public-footer/index.js +1 -1
  145. package/dist/components/public-footer/public-footer.d.ts +13 -1
  146. package/dist/components/public-footer/public-footer.d.ts.map +1 -1
  147. package/dist/components/public-footer/socials.d.ts +6 -5
  148. package/dist/components/public-footer/socials.d.ts.map +1 -1
  149. package/dist/components/slot-grid/index.js +1 -1
  150. package/dist/components/slot-grid/slot-grid.d.ts +2 -0
  151. package/dist/components/slot-grid/slot-grid.d.ts.map +1 -1
  152. package/dist/components/timeline/index.js +1 -1
  153. package/dist/i18n/config.d.ts.map +1 -1
  154. package/dist/i18n/config.js +224 -96
  155. package/dist/i18n/config.js.map +1 -1
  156. package/dist/i18n/locales/ar.d.ts +3 -0
  157. package/dist/i18n/locales/ar.d.ts.map +1 -1
  158. package/dist/i18n/locales/ar.js +4 -1
  159. package/dist/i18n/locales/ar.js.map +1 -1
  160. package/dist/i18n/locales/de.d.ts +3 -0
  161. package/dist/i18n/locales/de.d.ts.map +1 -1
  162. package/dist/i18n/locales/de.js +4 -1
  163. package/dist/i18n/locales/de.js.map +1 -1
  164. package/dist/i18n/locales/el.d.ts +3 -0
  165. package/dist/i18n/locales/el.d.ts.map +1 -1
  166. package/dist/i18n/locales/el.js +4 -1
  167. package/dist/i18n/locales/el.js.map +1 -1
  168. package/dist/i18n/locales/en.d.ts +3 -0
  169. package/dist/i18n/locales/en.d.ts.map +1 -1
  170. package/dist/i18n/locales/en.js +3 -0
  171. package/dist/i18n/locales/en.js.map +1 -1
  172. package/dist/i18n/locales/es.d.ts +3 -0
  173. package/dist/i18n/locales/es.d.ts.map +1 -1
  174. package/dist/i18n/locales/es.js +4 -1
  175. package/dist/i18n/locales/es.js.map +1 -1
  176. package/dist/i18n/locales/fr.d.ts +3 -0
  177. package/dist/i18n/locales/fr.d.ts.map +1 -1
  178. package/dist/i18n/locales/fr.js +4 -1
  179. package/dist/i18n/locales/fr.js.map +1 -1
  180. package/dist/i18n/locales/hi.d.ts +3 -0
  181. package/dist/i18n/locales/hi.d.ts.map +1 -1
  182. package/dist/i18n/locales/hi.js +4 -1
  183. package/dist/i18n/locales/hi.js.map +1 -1
  184. package/dist/i18n/locales/it.d.ts +3 -0
  185. package/dist/i18n/locales/it.d.ts.map +1 -1
  186. package/dist/i18n/locales/it.js +4 -1
  187. package/dist/i18n/locales/it.js.map +1 -1
  188. package/dist/i18n/locales/ja.d.ts +3 -0
  189. package/dist/i18n/locales/ja.d.ts.map +1 -1
  190. package/dist/i18n/locales/ja.js +4 -1
  191. package/dist/i18n/locales/ja.js.map +1 -1
  192. package/dist/i18n/locales/nl.d.ts +3 -0
  193. package/dist/i18n/locales/nl.d.ts.map +1 -1
  194. package/dist/i18n/locales/nl.js +4 -1
  195. package/dist/i18n/locales/nl.js.map +1 -1
  196. package/dist/i18n/locales/pl.d.ts +3 -0
  197. package/dist/i18n/locales/pl.d.ts.map +1 -1
  198. package/dist/i18n/locales/pl.js +4 -1
  199. package/dist/i18n/locales/pl.js.map +1 -1
  200. package/dist/i18n/locales/pt.d.ts +3 -0
  201. package/dist/i18n/locales/pt.d.ts.map +1 -1
  202. package/dist/i18n/locales/pt.js +4 -1
  203. package/dist/i18n/locales/pt.js.map +1 -1
  204. package/dist/i18n/locales/ro.d.ts +3 -0
  205. package/dist/i18n/locales/ro.d.ts.map +1 -1
  206. package/dist/i18n/locales/ro.js +4 -1
  207. package/dist/i18n/locales/ro.js.map +1 -1
  208. package/dist/i18n/locales/ru.d.ts +3 -0
  209. package/dist/i18n/locales/ru.d.ts.map +1 -1
  210. package/dist/i18n/locales/ru.js +4 -1
  211. package/dist/i18n/locales/ru.js.map +1 -1
  212. package/dist/i18n/locales/sq.d.ts +3 -0
  213. package/dist/i18n/locales/sq.d.ts.map +1 -1
  214. package/dist/i18n/locales/sq.js +4 -1
  215. package/dist/i18n/locales/sq.js.map +1 -1
  216. package/dist/i18n/locales/sv.d.ts +3 -0
  217. package/dist/i18n/locales/sv.d.ts.map +1 -1
  218. package/dist/i18n/locales/sv.js +4 -1
  219. package/dist/i18n/locales/sv.js.map +1 -1
  220. package/dist/i18n/locales/tr.d.ts +3 -0
  221. package/dist/i18n/locales/tr.d.ts.map +1 -1
  222. package/dist/i18n/locales/tr.js +4 -1
  223. package/dist/i18n/locales/tr.js.map +1 -1
  224. package/dist/i18n/locales/zh.d.ts +3 -0
  225. package/dist/i18n/locales/zh.d.ts.map +1 -1
  226. package/dist/i18n/locales/zh.js +4 -1
  227. package/dist/i18n/locales/zh.js.map +1 -1
  228. package/dist/index.js +42 -42
  229. package/dist/locales/ar.json +4 -1
  230. package/dist/locales/de.json +4 -1
  231. package/dist/locales/el.json +4 -1
  232. package/dist/locales/en.json +3 -0
  233. package/dist/locales/es.json +4 -1
  234. package/dist/locales/fr.json +4 -1
  235. package/dist/locales/hi.json +4 -1
  236. package/dist/locales/it.json +4 -1
  237. package/dist/locales/ja.json +4 -1
  238. package/dist/locales/nl.json +4 -1
  239. package/dist/locales/pl.json +4 -1
  240. package/dist/locales/pt.json +4 -1
  241. package/dist/locales/ro.json +4 -1
  242. package/dist/locales/ru.json +4 -1
  243. package/dist/locales/sq.json +4 -1
  244. package/dist/locales/sv.json +4 -1
  245. package/dist/locales/tr.json +4 -1
  246. package/dist/locales/zh.json +4 -1
  247. package/dist/patterns/alia-assistant/index.js +1 -1
  248. package/dist/patterns/calendar/index.js +1 -1
  249. package/dist/patterns/error-page/error-page-english.d.ts +71 -0
  250. package/dist/patterns/error-page/error-page-english.d.ts.map +1 -0
  251. package/dist/patterns/error-page/error-page.d.ts.map +1 -1
  252. package/dist/patterns/error-page/index.js +1 -1
  253. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  254. package/dist/patterns/signature-request/index.js +1 -1
  255. package/dist/patterns/signed-out-frame/index.js +1 -1
  256. package/dist/tokens.css +1 -1
  257. package/package.json +1 -1
  258. package/dist/_chunks/avatar-BPiPL7ND.js.map +0 -1
  259. package/dist/_chunks/booking-CcE_oviI.js +0 -4373
  260. package/dist/_chunks/booking-CcE_oviI.js.map +0 -1
  261. package/dist/_chunks/contact-profile-card-Da1vmJQI.js.map +0 -1
  262. package/dist/_chunks/error-page-Bhai-spN.js +0 -344
  263. package/dist/_chunks/error-page-Bhai-spN.js.map +0 -1
  264. package/dist/_chunks/languages-CZqBaPwI.js.map +0 -1
  265. package/dist/_chunks/link-N5_YpLtm.js +0 -138
  266. package/dist/_chunks/link-N5_YpLtm.js.map +0 -1
  267. package/dist/_chunks/operator-hero-6aAIQaFZ.js.map +0 -1
  268. package/dist/_chunks/practice-profile-hero-qfrsFQI_.js.map +0 -1
  269. package/dist/_chunks/practice-results-DQuOfqej.js.map +0 -1
  270. package/dist/_chunks/public-footer-CXOrdAaS.js +0 -568
  271. package/dist/_chunks/public-footer-CXOrdAaS.js.map +0 -1
  272. package/dist/_chunks/slot-grid-DrwynKeN.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace-app-shell-CmZx0Oam.js","sources":["../../src/brand/product-lockup/product-lockup.tsx","../../src/patterns/marketplace-app-shell/marketplace-app-shell.tsx"],"sourcesContent":["import { forwardRef, type ComponentPropsWithoutRef } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { Logo } from '../../components/logo/logo';\nimport { AlfadocsLogoMark, AlfadocsLogoNeg } from '../logo-asset';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\n// Outer lockup row. ~4px logical gap between the wordmark and the product\n// name (`--spacing-xs`), centre-aligned so the name's cap height sits\n// against the wordmark's letterforms.\nconst lockup = cva('ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]');\n\n// The product name. Marketing serif (Fraunces, `--font-serif`) — permitted\n// here because this file lives under `src/brand/`, never in `src/components/`\n// or `src/patterns/` (constraint 10). Sized to ~95% of the wordmark height so\n// its cap height matches the logo letterforms across every size and theme\n// (the `--logo-size-*` tokens shift up in the accessible themes; the calc\n// keeps the name proportional for free).\nconst productName = cva(\n [\n 'ds:[font-family:var(--font-serif)]',\n 'ds:font-semibold',\n 'ds:leading-none',\n 'ds:tracking-[0.01em]',\n 'ds:whitespace-nowrap',\n // Forced-colors: drop the transparent text-fill and paint the label\n // as solid CanvasText so it never disappears under Windows HCM —\n // a gradient/transparent fill has no meaning there.\n 'ds:forced-colors:text-[CanvasText]',\n 'ds:forced-colors:[-webkit-text-fill-color:CanvasText]',\n ],\n {\n variants: {\n size: {\n sm: 'ds:text-[calc(var(--logo-size-sm)*0.95)]',\n md: 'ds:text-[calc(var(--logo-size-md)*0.95)]',\n lg: 'ds:text-[calc(var(--logo-size-lg)*0.95)]',\n xl: 'ds:text-[calc(var(--logo-size-xl)*0.95)]',\n },\n tone: {\n // Brand gradient filled into the glyphs via background-clip:text.\n // `--gradient-wordmark` rides the theme aliases, so it stays\n // AA-safe and adapts per theme on its own (and flattens to a solid\n // ink in the accessible / forced-colors blocks — see tokens).\n gradient: [\n 'ds:italic',\n 'ds:bg-[image:var(--gradient-wordmark)]',\n 'ds:bg-clip-text',\n 'ds:text-transparent',\n 'ds:[-webkit-text-fill-color:transparent]',\n ],\n // Monochrome: solid currentColor ink, upright, no gradient — for\n // print, single-colour work, and coloured chrome (e.g. app-shell\n // headers) where the lockup must ride the surrounding ink.\n solid: 'ds:text-current',\n },\n },\n defaultVariants: { size: 'md', tone: 'gradient' },\n },\n);\n\n// Maker lockup root. Sets a single `--lockup-unit` custom property to the\n// matching `--logo-size-*` token; every maker sub-element (mark, name, the\n// \"by Alfadocs\" tag) sizes off `var(--lockup-unit)`, so there's one per-size\n// source of truth that shifts up with the accessible themes for free.\n// `whitespace-nowrap` keeps \"[mark] Name by Alfadocs\" on one line.\nconst makerRoot = cva('ds:whitespace-nowrap', {\n variants: {\n size: {\n sm: 'ds:[--lockup-unit:var(--logo-size-sm)]',\n md: 'ds:[--lockup-unit:var(--logo-size-md)]',\n lg: 'ds:[--lockup-unit:var(--logo-size-lg)]',\n xl: 'ds:[--lockup-unit:var(--logo-size-xl)]',\n },\n },\n defaultVariants: { size: 'md' },\n});\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\ntype LockupSize = NonNullable<VariantProps<typeof productName>['size']>;\n\nexport type ProductLockupProps = {\n /**\n * The product name. Passed verbatim (product names are not translated).\n *\n * - `variant=\"standard\"` (default): renders as \"Alfadocs <name>\" with the\n * wordmark; accessible name is `Alfadocs <name>`.\n * - `variant=\"maker\"`: renders as \"[mark] <name> by Alfadocs\"; accessible\n * name is `<name> by Alfadocs`.\n */\n name: string;\n /**\n * Which lockup composition to use.\n *\n * - `'standard'` (default) — Alfadocs wordmark + product name (\"Alfadocs\n * Builders\"). Use for **internal** Alfadocs products (Alfadocs Builders,\n * Alfadocs API) where the product is part of the Alfadocs family.\n * - `'maker'` — \"<name> by Alfadocs\" with the four-pillar mark and the name\n * as the prominent element. Use for **external** marketplace extensions\n * (\"Scribe by Alfadocs\") where the extension's own name leads and\n * \"by Alfadocs\" is the maker attribution.\n */\n variant?: 'standard' | 'maker';\n /**\n * Render the name as a solid `--foreground` ink, upright (no gradient, no\n * italic), and pair it with the monochrome wordmark. Use for print,\n * single-colour reproductions, or any constrained context where the\n * gradient/serif treatment is inappropriate.\n */\n monochrome?: boolean;\n /**\n * Ink resolution. `'auto'` (default) uses the lockup's intended ink\n * (`--foreground` for monochrome). `'inherit'` makes the whole lockup ride\n * `currentColor` — use it with `monochrome` on a coloured brand surface (a\n * tinted header or split-login panel) so the wordmark + name both take the\n * surface's text colour rather than clashing with a fixed `--foreground`.\n */\n tone?: 'auto' | 'inherit';\n /** Lockup size. Drives both the wordmark and the name's cap height. */\n size?: LockupSize;\n className?: string;\n} & Omit<\n ComponentPropsWithoutRef<'span'>,\n 'role' | 'aria-label' | 'aria-hidden' | 'children' | 'className'\n>;\n\n/* ------------------------------------------------------------------ */\n/* ProductLockup */\n/* ------------------------------------------------------------------ */\n\n/**\n * Pairs a product name with the Alfadocs brand. Two compositions:\n *\n * - `variant=\"standard\"` (default) — the Alfadocs wordmark + product name\n * (\"Alfadocs Builders\"). For internal Alfadocs products. Exposed to\n * assistive tech as a single `img` named `Alfadocs <name>`.\n * - `variant=\"maker\"` — \"[mark] <name> by Alfadocs\". For external marketplace\n * extensions where the extension's name leads. Exposed as a single `img`\n * named `<name> by Alfadocs`.\n *\n * In both cases the inner wordmark/mark and the visible name are decorative so\n * the brand isn't announced twice. Every marketplace app should use this\n * rather than hand-rolling a wordmark + typed span.\n */\nexport const ProductLockup = forwardRef<HTMLSpanElement, ProductLockupProps>(\n (\n {\n name,\n variant = 'standard',\n monochrome = false,\n tone = 'auto',\n size = 'md',\n className,\n ...props\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n if (import.meta.env.DEV && !name.trim()) {\n console.warn(\n '[ProductLockup] `name` is empty — the lockup will render the bare wordmark with no product name. Pass the product name (e.g. \"Builders\").',\n );\n }\n\n if (variant === 'maker') {\n // Ink matrix mirrors the standard variant's tone/monochrome model:\n // - tone=\"inherit\": every element rides currentColor (no explicit ink),\n // for coloured surfaces.\n // - monochrome (tone auto): foreground ink, with the attribution muted.\n // - default (colour, tone auto): the name + mark take --primary; the\n // wordmark lettering stays --foreground; the attribution is muted.\n const inherit = tone === 'inherit';\n const markInk = inherit\n ? ''\n : monochrome\n ? 'ds:text-[color:var(--foreground)]'\n : 'ds:text-[color:var(--primary)]';\n const nameInk = inherit\n ? ''\n : monochrome\n ? 'ds:text-[color:var(--foreground)]'\n : 'ds:text-[color:var(--primary)]';\n const byInk = inherit ? '' : 'ds:text-[color:var(--muted-foreground)]';\n const letteringInk = inherit ? '' : 'ds:text-[color:var(--foreground)]';\n\n return (\n <span\n ref={ref}\n role=\"img\"\n aria-label={t('productLockup.makerLabel', { name: name.trim() })}\n className={makerRoot({ size, className })}\n data-component=\"product-lockup\"\n {...props}\n >\n {/* Pillar mark sized close to the app name (≈0.88 of the serif em),\n vertically centred on it. Inline (not flex) so the maker tag can\n use vertical-align. */}\n <AlfadocsLogoMark\n aria-hidden\n className={`ds:inline-block ds:align-middle ds:me-[var(--spacing-sm)] ds:h-[calc(var(--lockup-unit)*0.88)] ds:w-auto ds:forced-colors:text-[CanvasText] ${markInk}`}\n />\n <span\n aria-hidden\n className={`ds:align-middle ds:[font-family:var(--font-serif)] ds:font-semibold ds:italic ds:leading-none ds:tracking-[0.01em] ${nameInk} ds:text-[calc(var(--lockup-unit)*0.95)]`}\n >\n {name}\n </span>\n {/* Maker tag — superscript style, its top aligned to the app name's\n cap-height via vertical-align: text-top. */}\n <span\n aria-hidden\n className={`ds:align-text-top ds:ms-[var(--spacing-sm)] ds:inline-flex ds:items-baseline ds:gap-[var(--spacing-2xs)] ${byInk}`}\n >\n <Trans\n ns=\"ui\"\n t={t}\n i18nKey=\"productLockup.attribution\"\n components={{\n text: (\n <span className=\"ds:text-[calc(var(--lockup-unit)*0.4)] ds:leading-none\" />\n ),\n brand: (\n <AlfadocsLogoNeg\n aria-hidden\n viewBox=\"168 0 637 125\"\n className={`ds:h-[calc(var(--lockup-unit)*0.45)] ds:w-auto ds:forced-colors:text-[CanvasText] ${letteringInk}`}\n />\n ),\n }}\n />\n </span>\n </span>\n );\n }\n\n return (\n <span\n ref={ref}\n role=\"img\"\n aria-label={`Alfadocs ${name}`.trim()}\n className={lockup({ className })}\n data-component=\"product-lockup\"\n {...props}\n >\n <Logo\n variant={monochrome ? 'monochrome' : 'wordmark'}\n tone={tone}\n size={size}\n decorative\n />\n <span\n aria-hidden\n className={productName({\n size,\n tone: monochrome ? 'solid' : 'gradient',\n })}\n >\n {name}\n </span>\n </span>\n );\n },\n);\nProductLockup.displayName = 'ProductLockup';\n","/**\n * Marketplace App Shell — the standard chrome for an app built on top of\n * AlfaDocs (the kind a partner scaffolds with Claude Code, Lovable, etc.).\n *\n * It is a thin, opinionated composition of kit primitives: an `AppFrame` with\n * a branded `Header` (the maker `ProductLockup` — \"<Product> by Alfadocs\" —\n * rendered `monochrome` so it rides the header's ink; maker is the lockup\n * style for external marketplace extensions), a `Sidebar` for app\n * navigation, `HeaderSettings` (theme/locale/accessibility), and a bare-avatar\n * account menu (fullscreen + sign-out) matching the main app shell. An\n * optional `endSidebar` docks a tool rail (for example Alia) on the inline-end.\n * `sidebarContent`, `sidebarHeader` and `sidebarActions` let the host build\n * the sidebar from the kit's Sidebar parts instead of the flat `nav`.\n * `ConnectWithAlfadocs` is the matching pre-auth screen, with the full-colour\n * maker lockup and `SignInWithAlfadocsButton`.\n *\n * Like `AliaSidebar`, this pattern ships a RUNTIME component (surfaced via\n * `src/patterns/index.ts` and the library bundle) because consuming apps mount\n * it in production rather than copying the source.\n *\n * Auth is intentionally decoupled: the shell takes the signed-in `user` and an\n * `onSignOut` callback as props, and `ConnectWithAlfadocs` takes a `status` +\n * `onConnect`. Wire them to `@alfadocs/auth/react`'s `useAlfadocsAuth()` in the\n * consuming app — the kit never touches OAuth or secrets (those live in the\n * server-side `@alfadocs/auth` BFF).\n *\n * All user-visible copy is consumer-provided (props) so each app localises in\n * its own i18n; the only kit-owned strings reuse existing translated `ui.*`\n * keys (sidebar label, skip link, menu button).\n */\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n useState,\n type MouseEvent,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cva } from 'class-variance-authority';\nimport { LogOut, Maximize2 } from 'lucide-react';\n\nimport { AppFrame } from '../../components/app-frame';\nimport { Avatar } from '../../components/avatar';\nimport { Alert } from '../../components/alert';\nimport { Card } from '../../components/card';\nimport { DropdownMenu } from '../../components/dropdown-menu';\nimport { TabBar } from '../../components/tab-bar';\nimport {\n Header,\n HeaderBrand,\n HeaderCenter,\n HeaderEnd,\n HeaderMenuButton,\n HeaderSkipLink,\n HeaderStart,\n} from '../../components/header';\nimport { HeaderSettings } from '../../components/header-settings';\nimport { ProductLockup } from '../../brand/product-lockup';\nimport { SignInWithAlfadocsButton } from '../../components/sign-in-with-alfadocs-button';\nimport {\n Sidebar,\n SidebarBody,\n SidebarCloseTrigger,\n SidebarCollapseTrigger,\n SidebarHeader,\n SidebarItem,\n SidebarItemBadge,\n SidebarItemIcon,\n SidebarItemLabel,\n SidebarSectionsToggle,\n useSidebar,\n type SidebarItemMove,\n type SidebarMode,\n} from '../../components/sidebar';\nimport { NavigationDismissContext } from '../../components/_shared/navigation-dismiss';\nimport { ThemeRoot } from '../../components/theme-root';\nimport { TooltipProvider } from '../../components/tooltip';\nimport { useTheme } from '../../hooks/use-theme';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport { useMediaQuery } from '../../hooks/use-media-query';\n\n// Below AppFrame's `md` (768px, --breakpoint-md), where it hides the rail.\nconst PHONE_QUERY = '(max-width: 767.98px)';\n\n/* ------------------------------------------------------------------ */\n/* Public API */\n/* ------------------------------------------------------------------ */\n\nexport interface MarketplaceNavItem {\n id: string;\n /** Pre-translated label — apps localise their own nav copy. */\n label: string;\n href: string;\n /** Optional leading icon (a lucide-react element or equivalent). */\n icon?: ReactNode;\n /** Optional unseen-item count rendered as a pill badge. */\n badgeCount?: number;\n /** Mark the item as the current page (`aria-current='page'`). */\n isActive?: boolean;\n /**\n * Optional click handler threaded onto the nav link's `<a>`. The lightweight\n * alternative to `renderLink`: intercept a same-origin click (call\n * `event.preventDefault()`) and route client-side without a full page load —\n * no router `<Link>` needed. Applies to both the standalone sidebar item and\n * the embedded tab. When `renderLink` is supplied it's handed through to the\n * consumer's link element instead.\n */\n onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;\n}\n\n/**\n * Props the shell hands to `renderLink` for each nav item. The consumer returns\n * their router's `<Link to={href}>` carrying the same `className` (the kit's\n * active styling) and `aria-current` (`'page'` on the active item) so a tab /\n * sidebar-item click is a client-side route change, not a full page reload.\n */\nexport interface MarketplaceRenderLinkProps {\n /** The item's destination — feed it to your router's `to` / `href`. */\n href: string;\n /** The kit's classes — apply verbatim to the link element. */\n className?: string;\n /** Icon + label + badge — render as the link's children. */\n children: ReactNode;\n /** `'page'` on the active item, otherwise omitted — forward to the link. */\n 'aria-current'?: 'page';\n /**\n * The item's stable id, as the agent / automation DOM hook. Spread it onto\n * your router link so the item stays addressable by `[data-tab-id]` — see\n * PRS §26 §6. Only supplied on the bottom-tab-bar path.\n */\n 'data-tab-id'?: string;\n}\n\n/**\n * Render a nav item through the consumer's router instead of the kit's own\n * `<a>`. Returned by the consumer; the shell forwards `href`, the kit's\n * `className`, the item children, and `aria-current` so the active styling and\n * the `aria-current=\"page\"` marker survive a client-side route change.\n */\nexport type MarketplaceRenderLink = (\n props: MarketplaceRenderLinkProps,\n) => ReactNode;\n\nexport interface MarketplaceAppUser {\n /** Display name — drives the avatar initials + the account-menu header. */\n name: string;\n /** Optional email shown under the name in the account menu. */\n email?: string;\n /** Optional avatar image URL. */\n avatarSrc?: string;\n}\n\nexport interface MarketplaceAppShellLabels {\n /** Accessible name for the account-menu trigger, e.g. \"Account menu\". */\n accountMenu: string;\n /** The sign-out menu item, e.g. \"Sign out\". */\n signOut: string;\n /**\n * Optional fullscreen menu item label, e.g. \"Toggle fullscreen\". The item\n * renders whenever `onToggleFullscreen` is supplied; when this label is\n * omitted it falls back to the translated `ui.*` \"Toggle fullscreen\" string.\n */\n fullscreen?: string;\n}\n\nexport interface MarketplaceAppShellProps {\n /** Extension name — renders as the maker lockup \"<productName> by Alfadocs\". */\n productName: string;\n /** Link target for the brand lockup. Default `'/'`. */\n productHref?: string;\n /**\n * Nav items, in order. Standalone ignores them when `sidebarContent` is set;\n * the embedded tab strip always uses them. Never-embedded apps can pass `[]`.\n */\n nav: MarketplaceNavItem[];\n /**\n * Standalone sidebar body built from the kit's Sidebar parts. When set, even\n * to `null`, it replaces the flat `nav` in every mode, inside the shell's own\n * `SidebarBody` and `<nav>`. Ignored in `'embedded'`.\n */\n sidebarContent?: ReactNode;\n /**\n * Extra standalone sidebar header content, such as an inline `SearchBar`,\n * below the collapse trigger and any `sidebarActions`. Hidden in the icon\n * rail. Ignored in `'embedded'`.\n */\n sidebarHeader?: ReactNode;\n /**\n * Header tools, usually `SidebarHeaderAction`s, in the collapse trigger's\n * row after it (and after the sections toggle), above `sidebarHeader`.\n * Stacked under the expand button in the icon rail; beside the close\n * button in the phone overlay. Ignored in `'embedded'`.\n */\n sidebarActions?: ReactNode;\n /**\n * Adds `SidebarSectionsToggle` to that row, right after the collapse\n * trigger: it folds or unfolds every section in `sidebarContent`, and hides\n * itself while there are none. @default false\n */\n sidebarSectionsToggle?: boolean;\n /**\n * One call when the sections toggle folds or unfolds every section, with\n * their `sectionId`s, in place of each section's `onOpenChange`; see\n * `Sidebar`'s `onSetAllSectionsOpen`.\n */\n onSetAllSidebarSectionsOpen?: (open: boolean, sectionIds: string[]) => void;\n /**\n * Lets users move `sidebarContent` items between sections, by drag and drop\n * or keyboard; see `Sidebar`'s `onMoveItem`. Apply each move and re-render.\n * Off when omitted, in the icon rail, and in `'embedded'`.\n */\n onMoveSidebarItem?: (move: SidebarItemMove) => void;\n /**\n * Render nav items (and the brand lockup) through the consumer's router so a\n * tab / item click is a client-side route change with **no full-page reload\n * or session flash**. Wire it to your router's `<Link>`:\n *\n * ```tsx\n * import { Link } from '@tanstack/react-router';\n * <MarketplaceAppShell\n * nav={nav}\n * renderLink={({ href, className, children, ...rest }) => (\n * <Link to={href} className={className} {...rest}>{children}</Link>\n * )}\n * />\n * ```\n *\n * Threaded to the standalone sidebar items, the embedded top tab strip, and\n * the brand lockup. The kit forwards the same `className` + `aria-current` so\n * the active styling and the `aria-current=\"page\"` marker survive in both\n * modes. Omit it to render the plain `<a href>` exactly as before — non-routed\n * consumers are byte-for-byte unaffected. A per-item `onClick` (a\n * click-interceptor shim) is the lighter alternative when you don't want to\n * thread a router `<Link>`.\n */\n renderLink?: MarketplaceRenderLink;\n /** The signed-in user shown in the account menu. */\n user: MarketplaceAppUser;\n /** Consumer-localised chrome labels owned by the shell. */\n labels: MarketplaceAppShellLabels;\n /** Fires when the user picks \"Sign out\". Wire to `useAlfadocsAuth().signOut`. */\n onSignOut?: () => void;\n /** Fires when the user toggles fullscreen. Omit to hide the fullscreen item. */\n onToggleFullscreen?: () => void;\n /**\n * Force the sidebar into a specific mode. Leave it undefined and the shell\n * uses the menu-button drawer below `md` by itself, and the user's saved\n * mode (expanded unless they collapsed it) above.\n */\n sidebarState?: SidebarMode;\n /**\n * Render a collapse/expand toggle in the sidebar header, letting the user\n * shrink the standalone sidebar (the flat `nav` or your `sidebarContent`)\n * to an icon rail. The chosen mode persists\n * per-user (the underlying `Sidebar` stores it) and survives reloads. Opt-in\n * so existing consumers are unaffected; ignored when `sidebarState` forces a\n * mode or in the `'embedded'` variant (no sidebar). @default false\n */\n collapsibleSidebar?: boolean;\n /** Override the accessible name of the `<main>` landmark. */\n mainAriaLabel?: string;\n /**\n * Chrome variant. `'standalone'` (default) renders the full shell — branded\n * Header, Sidebar, and account menu. `'embedded'` is for apps running INSIDE\n * the AlfaDocs platform iframe (consumers detect this with\n * `window !== window.top`): it drops the Header, Sidebar, account menu, and\n * product lockup — the platform already brands and identifies the session\n * around the iframe — and renders the `nav` items as a single slim top tab\n * strip. `onSignOut`, `onToggleFullscreen`, `productName`, `productHref`,\n * `sidebarState`, `sidebarContent` and `sidebarHeader` are ignored in\n * `'embedded'`; the `<main>` landmark, `mainAriaLabel`, the skip link and\n * `endSidebar` are kept.\n */\n variant?: 'standalone' | 'embedded';\n /** Inline-end panel (e.g. a `ControlRoomRail`) forwarded to `AppFrame` in both variants.\n * Hidden below `md`: keep it mounted and add `AliaPopout` there. In `'embedded'` it\n * pins the tab strip and scrolls `<main>` beside it; omitted, embedded is unchanged. */\n endSidebar?: ReactNode;\n /** The narrowest `<main>` may get, px, passed to `AppFrame` in both\n * variants: an open `endSidebar` panel shows over the content instead. */\n minMainWidth?: number;\n /** Children render inside the main content region. */\n children: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* Internals */\n/* ------------------------------------------------------------------ */\n\nfunction formatBadgeCount(count: number): string {\n return count > 99 ? '99+' : String(count);\n}\n\nfunction AccountMenu({\n user,\n labels,\n onSignOut,\n onToggleFullscreen,\n}: {\n user: MarketplaceAppUser;\n labels: MarketplaceAppShellLabels;\n onSignOut?: () => void;\n onToggleFullscreen?: () => void;\n}) {\n const { t } = useTranslation('ui');\n // Default to the translated `ui.*` label so a consumer that wires\n // `onToggleFullscreen` but omits the label still gets a localised item.\n const fullscreenLabel =\n labels.fullscreen ?? t('marketplaceAppShell.settings.fullscreen');\n return (\n // Non-modal: an account menu shouldn't inert/aria-hide the whole shell\n // behind it (which leaves the still-focusable chrome inside an\n // aria-hidden region — an `aria-hidden-focus` violation).\n <DropdownMenu.Root modal={false}>\n <DropdownMenu.Trigger asChild>\n {/* Bare avatar circle — matches the main app shell's account\n trigger. The name lives inside the menu, not beside the avatar. */}\n <button\n type=\"button\"\n aria-label={labels.accountMenu}\n data-testid=\"marketplace-account-trigger\"\n className=\"ds:inline-flex ds:items-center ds:justify-center ds:shrink-0 ds:size-10 ds:rounded-[var(--radius-full)] ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)] ds:forced-colors:focus-visible:outline-[CanvasText]\"\n >\n <span aria-hidden=\"true\">\n <Avatar name={user.name} src={user.avatarSrc} size=\"md\" />\n </span>\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\" collisionPadding={16}>\n {/* GitHub-style identity header — small avatar + name + secondary\n line, matching the main app shell's account menu. */}\n <DropdownMenu.Label>\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span aria-hidden=\"true\">\n <Avatar name={user.name} src={user.avatarSrc} size=\"sm\" />\n </span>\n <span className=\"ds:flex ds:flex-col ds:min-w-0\">\n <span className=\"type-label ds:text-[color:var(--foreground)] ds:truncate\">\n {user.name}\n </span>\n {user.email ? (\n <span className=\"type-meta ds:truncate\">{user.email}</span>\n ) : null}\n </span>\n </span>\n </DropdownMenu.Label>\n {onToggleFullscreen ? (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n startIcon={<Maximize2 aria-hidden />}\n onSelect={onToggleFullscreen}\n data-testid=\"marketplace-fullscreen\"\n >\n {fullscreenLabel}\n </DropdownMenu.Item>\n </>\n ) : null}\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n startIcon={<LogOut aria-hidden />}\n onSelect={onSignOut}\n data-testid=\"marketplace-sign-out\"\n >\n {labels.signOut}\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\nfunction MarketplaceSidebarNav({\n nav,\n renderLink,\n}: {\n nav: MarketplaceNavItem[];\n renderLink?: MarketplaceRenderLink;\n}) {\n return (\n <SidebarBody>\n {nav.map((item) => {\n const badge =\n typeof item.badgeCount === 'number' && item.badgeCount > 0\n ? item.badgeCount\n : undefined;\n const inner = (\n <>\n {item.icon ? <SidebarItemIcon>{item.icon}</SidebarItemIcon> : null}\n <SidebarItemLabel>{item.label}</SidebarItemLabel>\n {badge !== undefined ? (\n <SidebarItemBadge>{formatBadgeCount(badge)}</SidebarItemBadge>\n ) : null}\n </>\n );\n\n // Consumer-router mode: render the item through Radix `Slot`\n // (`SidebarItem asChild`) so the consumer's `<Link>` takes over the\n // anchor while keeping the kit's item styling + `aria-current=\"page\"`.\n // Clicking routes client-side — no full-page reload.\n if (renderLink) {\n return (\n <SidebarItem key={item.id} asChild isActive={item.isActive}>\n {renderLink({\n href: item.href,\n children: inner,\n 'aria-current': item.isActive ? 'page' : undefined,\n })}\n </SidebarItem>\n );\n }\n\n // Default: plain anchor — byte-identical to before when no per-item\n // `onClick` is supplied (it's omitted entirely, not passed as\n // undefined, so the rendered `<a>` is unchanged).\n return (\n <SidebarItem\n key={item.id}\n href={item.href}\n aria-label={item.label}\n isActive={item.isActive}\n {...(item.onClick ? { onClick: item.onClick } : {})}\n >\n {inner}\n </SidebarItem>\n );\n })}\n </SidebarBody>\n );\n}\n\n// The tool row: the collapse trigger, the sections toggle, then the host's\n// actions; the drawer ends it with the close button. The rail stacks it.\n// One tree in every mode, so the collapse trigger keeps focus.\nconst sidebarHeaderStackVariants = cva(\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]',\n {\n variants: {\n mode: {\n expanded: 'ds:min-w-0 ds:flex-1',\n icon: 'ds:items-center',\n overlay: 'ds:min-w-0 ds:flex-1',\n },\n },\n defaultVariants: { mode: 'expanded' },\n },\n);\nconst sidebarHeaderRowVariants = cva(\n // Wraps rather than push a tool off the edge at the accessible size. Empty\n // when the sections toggle, alone in it, finds no section.\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)] ds:empty:hidden',\n {\n variants: {\n mode: {\n expanded: '',\n icon: 'ds:flex-col',\n overlay: 'ds:justify-end',\n },\n },\n defaultVariants: { mode: 'expanded' },\n },\n);\n\nconst hasNode = (node: ReactNode) =>\n node !== undefined && node !== null && typeof node !== 'boolean';\n\nfunction MarketplaceSidebarHeader({\n collapseTrigger,\n sectionsToggle,\n actions,\n content,\n}: {\n collapseTrigger: boolean;\n sectionsToggle: boolean;\n actions: ReactNode;\n content: ReactNode;\n}) {\n const { mode } = useSidebar();\n const hasActions = hasNode(actions);\n const overlay = mode === 'overlay';\n // SidebarCollapseTrigger renders nothing in the overlay, so skip it there.\n const showTrigger = collapseTrigger && !overlay;\n const showContent = hasNode(content) && mode !== 'icon';\n const showRow = showTrigger || sectionsToggle || hasActions || overlay;\n if (!showRow && !showContent) return null;\n return (\n // With nothing below it, an empty row hides the whole band too.\n <SidebarHeader\n className={\n showContent\n ? undefined\n : 'ds:has-[[data-sidebar-header-row]:empty]:hidden'\n }\n >\n <div className={sidebarHeaderStackVariants({ mode })}>\n {showRow ? (\n <div\n data-sidebar-header-row=\"\"\n className={sidebarHeaderRowVariants({ mode })}\n >\n {showTrigger ? <SidebarCollapseTrigger /> : null}\n {sectionsToggle ? <SidebarSectionsToggle /> : null}\n {hasActions ? actions : null}\n {overlay ? <SidebarCloseTrigger /> : null}\n </div>\n ) : null}\n {showContent ? content : null}\n </div>\n </SidebarHeader>\n );\n}\n\n/* CVA for the chrome variant — drives the `<main>` surface; the structural\n header/sidebar-vs-tab-strip difference is conditional in the render.\n\n The `standalone` `<main>` gets its content inset from AppFrame's own\n `mainVariants({ padded: true })` (`--spacing-md` on every logical side), so\n this variant only carries the canvas colour there. The `embedded` `<main>`\n is a plain element (no AppFrame), so it has to supply its own inset:\n `--spacing-md` inline + block-end to match the standalone inset, and a\n larger `--spacing-lg` block-start so content clears the floating tab strip's\n pill instead of butting up against it. All logical — RTL mirrors for free. */\nconst EMBEDDED_CONTENT_INSET = [\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:pt-[var(--spacing-lg)] ds:pb-[var(--spacing-md)]',\n].join(' ');\n\nconst shellMainVariants = cva('ds:bg-[color:var(--app-shell-background)]', {\n variants: {\n variant: {\n standalone: '',\n embedded: `ds:flex-1 ${EMBEDDED_CONTENT_INSET}`,\n },\n },\n defaultVariants: { variant: 'standalone' },\n});\n\n// Embedded with an end panel: the strip sits in AppFrame's header slot, so it\n// carries the shell canvas itself rather than AppFrame's `--background`.\nconst EMBEDDED_DOCKED_CHROME =\n 'ds:shrink-0 ds:bg-[color:var(--app-shell-background)]';\n\n/**\n * Embedded chrome: the slim floating tab strip (no Header / Sidebar / account\n * menu) for apps running inside the AlfaDocs platform iframe. It's the shared\n * {@link TabBar} fed the shell's nav items — the platform brands and identifies\n * the session around the iframe, so the strip is the only chrome. The\n * `MarketplaceNavItem` shape is structurally a `TabBarItem`, so the nav passes\n * straight through.\n */\nfunction EmbeddedTabStrip({\n nav,\n ariaLabel,\n renderLink,\n}: {\n nav: MarketplaceNavItem[];\n ariaLabel: string;\n renderLink?: MarketplaceRenderLink;\n}) {\n // Adapt the shell's `renderLink` to TabBar's `renderLink` signature — TabBar\n // also offers the per-item `onClick`, but in consumer-router mode the\n // `<Link>` owns navigation (matching the standalone sidebar), so we forward\n // only `href` / `className` / `children` / `aria-current`. With `renderLink`\n // omitted, TabBar renders its own plain `<a href>` exactly as before, and a\n // per-item `onClick` rides through `nav` → `TabBarItem` untouched.\n const tabRenderLink = renderLink\n ? ({\n href,\n className,\n children,\n 'aria-current': ariaCurrent,\n 'data-tab-id': tabId,\n }: {\n href: string;\n className: string;\n children: ReactNode;\n 'aria-current'?: 'page';\n 'data-tab-id'?: string;\n }) =>\n renderLink({\n href,\n className,\n children,\n 'aria-current': ariaCurrent,\n // Forward the agent DOM hook — without it a consumer-router tab is\n // invisible to `[data-tab-id]` lookups (PRS §26 §6).\n 'data-tab-id': tabId,\n })\n : undefined;\n\n return (\n <TabBar\n items={nav}\n ariaLabel={ariaLabel}\n {...(tabRenderLink ? { renderLink: tabRenderLink } : {})}\n />\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* MarketplaceAppShell */\n/* ------------------------------------------------------------------ */\n\nexport const MarketplaceAppShell = forwardRef<\n HTMLDivElement,\n MarketplaceAppShellProps\n>(\n (\n {\n productName,\n productHref = '/',\n nav,\n renderLink,\n user,\n labels,\n onSignOut,\n onToggleFullscreen,\n sidebarState,\n collapsibleSidebar = false,\n sidebarContent,\n sidebarHeader,\n sidebarActions,\n sidebarSectionsToggle = false,\n onSetAllSidebarSectionsOpen,\n onMoveSidebarItem,\n mainAriaLabel,\n variant = 'standalone',\n endSidebar,\n minMainWidth,\n children,\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n\n // The brand lockup as a consumer-router link: when `renderLink` is\n // supplied, the brand anchor routes client-side too (no session flash when\n // jumping home). The maker lockup's \"<productName> by Alfadocs\" supplies\n // the link's accessible name, matching the default `HeaderBrand` anchor.\n const headerBrand = renderLink ? (\n <HeaderBrand asChild>\n {renderLink({\n href: productHref,\n children: (\n <ProductLockup\n name={productName}\n size=\"md\"\n monochrome\n variant=\"maker\"\n />\n ),\n })}\n </HeaderBrand>\n ) : (\n <HeaderBrand\n href={productHref}\n logo={\n <ProductLockup\n name={productName}\n size=\"md\"\n monochrome\n variant=\"maker\"\n />\n }\n />\n );\n\n // Only wrap in a nested ThemeRoot when the user has an\n // explicit theme/accessibility override, so we don't clobber the consuming\n // app's (or Storybook's) outer theme cascade.\n const { theme: themePref, accessibility, resolvedTheme } = useTheme();\n const hasExplicitOverride =\n themePref !== 'system' || accessibility !== 'system';\n const themeBase = resolvedTheme.startsWith('dark') ? 'dark' : 'light';\n const themeAccessible = resolvedTheme.endsWith('-accessible');\n\n // Below `md` AppFrame hides the docked sidebar and HeaderMenuButton\n // shows, so the shell switches to the drawer there by itself. An explicit\n // `sidebarState` wins; above `md` the user's saved mode stays.\n const isPhone = useMediaQuery(PHONE_QUERY);\n const effectiveSidebarState =\n sidebarState ?? (isPhone ? ('overlay' as const) : undefined);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const closeSidebar = useCallback(() => setSidebarOpen(false), []);\n\n // Leaving the drawer (a phone turned to landscape past `md`) shuts it,\n // so it never reopens, taking focus, on the way back.\n useEffect(() => {\n if (effectiveSidebarState !== 'overlay') setSidebarOpen(false);\n }, [effectiveSidebarState]);\n\n // The drawer closes when the route changes, however the host changed it:\n // the URL, or the item marked current. No router needed. The flat `nav`\n // says which item that is; custom content is read from the open drawer.\n const sidebarRef = useRef<HTMLElement>(null);\n const routeRef = useRef<{\n open: boolean;\n url: string;\n current: string | null;\n } | null>(null);\n const navCurrent =\n sidebarContent === undefined\n ? (nav.find((item) => item.isActive)?.id ?? '')\n : undefined;\n useIsomorphicLayoutEffect(() => {\n const url = window.location.href;\n let current: string | null = navCurrent ?? null;\n if (navCurrent === undefined && sidebarRef.current) {\n const node = sidebarRef.current.querySelector('[aria-current=\"page\"]');\n current = node?.getAttribute('href') ?? node?.textContent ?? '';\n }\n const previous = routeRef.current;\n routeRef.current = { open: sidebarOpen, url, current };\n if (!previous?.open || !sidebarOpen) return;\n // A side not read (the drawer's portal mounts a commit late) says\n // nothing about the route, so only two real readings are compared.\n const changedItem =\n previous.current !== null &&\n current !== null &&\n previous.current !== current;\n if (previous.url !== url || changedItem) setSidebarOpen(false);\n });\n useEffect(() => {\n if (!sidebarOpen) return undefined;\n window.addEventListener('popstate', closeSidebar);\n window.addEventListener('hashchange', closeSidebar);\n return () => {\n window.removeEventListener('popstate', closeSidebar);\n window.removeEventListener('hashchange', closeSidebar);\n };\n }, [sidebarOpen, closeSidebar]);\n\n const shell = (\n <TooltipProvider>\n <AppFrame\n mainAriaLabel={mainAriaLabel}\n mainClassName={shellMainVariants({ variant: 'standalone' })}\n header={\n <Header>\n <HeaderStart>\n <HeaderSkipLink href=\"#main-content\" />\n <HeaderMenuButton onMenuOpen={() => setSidebarOpen(true)} />\n {headerBrand}\n </HeaderStart>\n <HeaderCenter />\n <HeaderEnd>\n <HeaderSettings size=\"sm\" />\n <AccountMenu\n user={user}\n labels={labels}\n onSignOut={onSignOut}\n onToggleFullscreen={onToggleFullscreen}\n />\n </HeaderEnd>\n </Header>\n }\n sidebar={\n <Sidebar\n ref={sidebarRef}\n {...(effectiveSidebarState !== undefined\n ? { state: effectiveSidebarState }\n : { defaultState: 'expanded' as const })}\n open={sidebarOpen}\n onOpenChange={setSidebarOpen}\n onMoveItem={onMoveSidebarItem}\n onSetAllSectionsOpen={onSetAllSidebarSectionsOpen}\n // A link tapped in the phone drawer navigates, so the drawer\n // closes, whether the link is the flat nav's or the host's.\n onClick={(event) => {\n if (\n event.target instanceof Element &&\n event.target.closest('a[href]')\n ) {\n closeSidebar();\n }\n }}\n aria-label={t('navigation.sidebar.label')}\n data-testid=\"marketplace-app-shell-sidebar\"\n >\n {/* So does a pick that navigates without a link, such as a\n SearchBar result. */}\n <NavigationDismissContext.Provider value={closeSidebar}>\n <MarketplaceSidebarHeader\n collapseTrigger={\n collapsibleSidebar && effectiveSidebarState === undefined\n }\n sectionsToggle={sidebarSectionsToggle}\n actions={sidebarActions}\n content={sidebarHeader}\n />\n {sidebarContent !== undefined ? (\n <SidebarBody>{sidebarContent}</SidebarBody>\n ) : (\n <MarketplaceSidebarNav nav={nav} renderLink={renderLink} />\n )}\n </NavigationDismissContext.Provider>\n </Sidebar>\n }\n endSidebar={endSidebar}\n minMainWidth={minMainWidth}\n >\n {children}\n </AppFrame>\n </TooltipProvider>\n );\n\n const embeddedChrome = (\n <>\n <HeaderSkipLink href=\"#main-content\" />\n <EmbeddedTabStrip\n nav={nav}\n ariaLabel={t('navigation.sidebar.label')}\n renderLink={renderLink}\n />\n </>\n );\n\n // An end panel needs a height-bounded row to dock in, which AppFrame owns.\n // The inset moves inside its scroll area, so `<main>` reads as it does\n // without the panel. No sidebar: the tab strip stays the only nav.\n const embeddedDocked = (\n <TooltipProvider>\n <AppFrame\n mainAriaLabel={mainAriaLabel}\n mainClassName={shellMainVariants({ variant: 'standalone' })}\n padded={false}\n header={\n <div className={EMBEDDED_DOCKED_CHROME}>{embeddedChrome}</div>\n }\n sidebar={null}\n endSidebar={endSidebar}\n minMainWidth={minMainWidth}\n >\n <div className={EMBEDDED_CONTENT_INSET}>{children}</div>\n </AppFrame>\n </TooltipProvider>\n );\n\n const embedded = (\n // The shell owns the warm-grey canvas; TabBar's strip is transparent and\n // floats its pill on it, and `<main>` continues the same surface.\n <div className=\"ds:flex ds:min-h-dvh ds:flex-col ds:bg-[color:var(--app-shell-background)]\">\n {embeddedChrome}\n <main\n id=\"main-content\"\n tabIndex={-1}\n aria-label={\n mainAriaLabel ?? t('navigation.main.label', 'Main content')\n }\n className={shellMainVariants({ variant: 'embedded' })}\n >\n {children}\n </main>\n </div>\n );\n\n const content =\n variant === 'embedded' ? (endSidebar ? embeddedDocked : embedded) : shell;\n\n if (!hasExplicitOverride) {\n return (\n <div\n ref={ref}\n className=\"ds:contents\"\n data-component=\"marketplace-app-shell\"\n >\n {content}\n </div>\n );\n }\n\n return (\n <ThemeRoot\n ref={ref}\n theme={themeBase}\n accessible={themeAccessible}\n className=\"ds:contents\"\n data-component=\"marketplace-app-shell\"\n >\n {content}\n </ThemeRoot>\n );\n },\n);\n\nMarketplaceAppShell.displayName = 'MarketplaceAppShell';\n\n/* ------------------------------------------------------------------ */\n/* ConnectWithAlfadocs */\n/* ------------------------------------------------------------------ */\n\nexport type ConnectStatus = 'idle' | 'connecting' | 'error';\n\nexport interface ConnectWithAlfadocsProps {\n /** Product name shown next to the wordmark at the top of the card. */\n productName: string;\n /** Heading, e.g. \"Connect your AlfaDocs account\". */\n title: string;\n /** Supporting copy below the heading. */\n description: ReactNode;\n /** The connect button label, e.g. \"Connect with AlfaDocs\". */\n connectLabel: string;\n /** Connection lifecycle. `connecting` shows a loading button; `error` shows the alert. */\n status?: ConnectStatus;\n /** Error message shown (as an alert) when `status === 'error'`. */\n error?: ReactNode;\n /** Fires when the connect button is pressed. Wire to `useAlfadocsAuth().connect`. */\n onConnect?: () => void;\n /** Optional footer content below the button (e.g. a \"what's this?\" link). */\n footer?: ReactNode;\n /**\n * Visual layout. `'card'` (default) is the centred card on the warm-grey\n * canvas — unchanged. `'split'` adds, at `lg:` and up, a two-panel desktop\n * layout: a brand panel on the inline-start and the connect card on the\n * inline-end. Below `lg:`, `'split'` collapses to exactly the card layout —\n * so it falls back gracefully inside iframes / embeds that never reach\n * desktop width. Use `'split'` for full-page desktop logins.\n */\n layout?: 'card' | 'split';\n /**\n * Optional content shown under the lockup in the `'split'` brand panel (a\n * tagline, value props, an illustration). Ignored in `'card'` and below `lg:`.\n */\n brandPanel?: ReactNode;\n className?: string;\n}\n\n/* Split-layout CVAs (lg+ two-panel; collapses to the centred card below lg). */\nconst connectRootVariants = cva(\n 'ds:flex ds:min-h-dvh ds:bg-[color:var(--app-shell-background)]',\n {\n variants: {\n layout: {\n card: '',\n split: 'ds:flex-col ds:lg:flex-row',\n },\n },\n defaultVariants: { layout: 'card' },\n },\n);\n\nconst connectCardWidthVariants = cva('ds:w-full', {\n variants: {\n layout: {\n card: 'ds:max-w-[400px]',\n split: 'ds:max-w-[400px] ds:lg:max-w-[480px]',\n },\n },\n defaultVariants: { layout: 'card' },\n});\n\n// The card's own lockup hides at lg+ in `split` (the brand panel shows it there).\nconst connectCardLockupVariants = cva('', {\n variants: {\n layout: { card: '', split: 'ds:lg:hidden' },\n },\n defaultVariants: { layout: 'card' },\n});\n\n/**\n * The pre-auth \"Connect with AlfaDocs\" screen. Centred white card on the\n * warm-grey canvas with the AlfaDocs wordmark + product name, copy, an error\n * slot, and the primary connect CTA. An opt-in `layout=\"split\"` adds a desktop\n * two-panel brand layout (lg+). Presentational — `onConnect` should call\n * `useAlfadocsAuth().connect()`, which redirects the browser to the server-side\n * BFF that runs the real OAuth2 + PKCE flow.\n */\nexport const ConnectWithAlfadocs = forwardRef<\n HTMLDivElement,\n ConnectWithAlfadocsProps\n>(\n (\n {\n productName,\n title,\n description,\n connectLabel,\n status = 'idle',\n error,\n onConnect,\n footer,\n layout = 'card',\n brandPanel,\n className,\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n data-component=\"connect-with-alfadocs\"\n className={`${connectRootVariants({ layout })} ${className ?? ''}`}\n >\n {layout === 'split' ? (\n // Desktop brand panel (lg+ only): a bold `--primary` surface with the\n // monochrome lockup riding the `--primary-foreground` ink, plus an\n // optional `brandPanel` slot. Decorative — the card carries the real\n // heading + CTA, and shows its own lockup below `lg:`.\n <div className=\"ds:hidden ds:lg:flex ds:lg:w-[55%] ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-lg)] ds:bg-[color:var(--primary)] ds:text-[color:var(--primary-foreground)] ds:ps-[var(--spacing-2xl)] ds:pe-[var(--spacing-2xl)] ds:pt-[var(--spacing-2xl)] ds:pb-[var(--spacing-2xl)] ds:text-start\">\n <ProductLockup\n name={productName}\n size=\"lg\"\n monochrome\n tone=\"inherit\"\n variant=\"maker\"\n />\n {brandPanel ? (\n <div className=\"type-body ds:max-w-[28rem] ds:text-start\">\n {brandPanel}\n </div>\n ) : null}\n </div>\n ) : null}\n <div className=\"ds:flex ds:flex-1 ds:items-center ds:justify-center ds:p-[var(--spacing-lg)]\">\n <Card className={connectCardWidthVariants({ layout })}>\n <Card.Body className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-lg)] ds:text-center\">\n <ProductLockup\n name={productName}\n size=\"lg\"\n variant=\"maker\"\n className={connectCardLockupVariants({ layout })}\n />\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <h1 className=\"type-title-card\">{title}</h1>\n <p className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {description}\n </p>\n </div>\n {status === 'error' && error ? (\n <Alert variant=\"error\" className=\"ds:w-full ds:text-start\">\n {error}\n </Alert>\n ) : null}\n <SignInWithAlfadocsButton\n intent=\"primary\"\n className=\"ds:w-full\"\n loading={status === 'connecting'}\n onClick={onConnect}\n label={connectLabel}\n data-testid=\"connect-with-alfadocs-button\"\n />\n {footer ? (\n <div className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {footer}\n </div>\n ) : null}\n </Card.Body>\n </Card>\n </div>\n </div>\n );\n },\n);\n\nConnectWithAlfadocs.displayName = 'ConnectWithAlfadocs';\n"],"names":["lockup","cva","productName","makerRoot","ProductLockup","forwardRef","name","variant","monochrome","tone","size","className","props","ref","t","useTranslation","inherit","markInk","nameInk","byInk","letteringInk","jsxs","jsx","AlfadocsLogoMark","Trans","AlfadocsLogoNeg","Logo","PHONE_QUERY","formatBadgeCount","count","AccountMenu","user","labels","onSignOut","onToggleFullscreen","fullscreenLabel","DropdownMenu","Avatar","Fragment","Maximize2","LogOut","MarketplaceSidebarNav","nav","renderLink","SidebarBody","item","badge","inner","SidebarItemIcon","SidebarItemLabel","SidebarItemBadge","SidebarItem","sidebarHeaderStackVariants","sidebarHeaderRowVariants","hasNode","node","MarketplaceSidebarHeader","collapseTrigger","sectionsToggle","actions","content","mode","useSidebar","hasActions","overlay","showTrigger","showContent","showRow","SidebarHeader","SidebarCollapseTrigger","SidebarSectionsToggle","SidebarCloseTrigger","EMBEDDED_CONTENT_INSET","shellMainVariants","EMBEDDED_DOCKED_CHROME","EmbeddedTabStrip","ariaLabel","tabRenderLink","href","children","ariaCurrent","tabId","TabBar","MarketplaceAppShell","productHref","sidebarState","collapsibleSidebar","sidebarContent","sidebarHeader","sidebarActions","sidebarSectionsToggle","onSetAllSidebarSectionsOpen","onMoveSidebarItem","mainAriaLabel","endSidebar","minMainWidth","headerBrand","HeaderBrand","themePref","accessibility","resolvedTheme","useTheme","hasExplicitOverride","themeBase","themeAccessible","isPhone","useMediaQuery","effectiveSidebarState","sidebarOpen","setSidebarOpen","useState","closeSidebar","useCallback","useEffect","sidebarRef","useRef","routeRef","navCurrent","_a","useIsomorphicLayoutEffect","url","current","previous","changedItem","shell","TooltipProvider","AppFrame","Header","HeaderStart","HeaderSkipLink","HeaderMenuButton","HeaderCenter","HeaderEnd","HeaderSettings","Sidebar","event","NavigationDismissContext","embeddedChrome","embeddedDocked","embedded","ThemeRoot","connectRootVariants","connectCardWidthVariants","connectCardLockupVariants","ConnectWithAlfadocs","title","description","connectLabel","status","error","onConnect","footer","layout","brandPanel","Card","Alert","SignInWithAlfadocsButton"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAaA,MAAMA,KAASC,EAAI,2DAA2D,GAQxEC,KAAcD;AAAA,EAClB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA,IACA;AAAA,EAAA;AAAA,EAEF;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MAAA;AAAA,MAEN,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,QAKJ,UAAU;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA;AAAA;AAAA;AAAA,QAKF,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB,EAAE,MAAM,MAAM,MAAM,WAAA;AAAA,EAAW;AAEpD,GAOME,KAAYF,EAAI,wBAAwB;AAAA,EAC5C,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IAAA;AAAA,EACN;AAAA,EAEF,iBAAiB,EAAE,MAAM,KAAA;AAC3B,CAAC,GAuEYG,IAAgBC;AAAA,EAC3B,CACE;AAAA,IACE,MAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,YAAAC,IAAa;AAAA,IACb,MAAAC,IAAO;AAAA,IACP,MAAAC,IAAO;AAAA,IACP,WAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAM,EAAE,GAAAC,EAAA,IAAMC,EAAe,IAAI;AAOjC,QAAIR,MAAY,SAAS;AAOvB,YAAMS,IAAUP,MAAS,WACnBQ,IAAUD,IACZ,KACAR,IACE,sCACA,kCACAU,IAAUF,IACZ,KACAR,IACE,sCACA,kCACAW,IAAQH,IAAU,KAAK,2CACvBI,IAAeJ,IAAU,KAAK;AAEpC,aACE,gBAAAK;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAAR;AAAA,UACA,MAAK;AAAA,UACL,cAAYC,EAAE,4BAA4B,EAAE,MAAMR,EAAK,KAAA,GAAQ;AAAA,UAC/D,WAAWH,GAAU,EAAE,MAAAO,GAAM,WAAAC,GAAW;AAAA,UACxC,kBAAe;AAAA,UACd,GAAGC;AAAA,UAKJ,UAAA;AAAA,YAAA,gBAAAU;AAAA,cAACC;AAAA,cAAA;AAAA,gBACC,eAAW;AAAA,gBACX,WAAW,+IAA+IN,CAAO;AAAA,cAAA;AAAA,YAAA;AAAA,YAEnK,gBAAAK;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAW;AAAA,gBACX,WAAW,sHAAsHJ,CAAO;AAAA,gBAEvI,UAAAZ;AAAA,cAAA;AAAA,YAAA;AAAA,YAIH,gBAAAgB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAW;AAAA,gBACX,WAAW,4GAA4GH,CAAK;AAAA,gBAE5H,UAAA,gBAAAG;AAAA,kBAACE;AAAA,kBAAA;AAAA,oBACC,IAAG;AAAA,oBACH,GAAAV;AAAA,oBACA,SAAQ;AAAA,oBACR,YAAY;AAAA,sBACV,MACE,gBAAAQ,EAAC,QAAA,EAAK,WAAU,0DAAyD;AAAA,sBAE3E,OACE,gBAAAA;AAAA,wBAACG;AAAA,wBAAA;AAAA,0BACC,eAAW;AAAA,0BACX,SAAQ;AAAA,0BACR,WAAW,qFAAqFL,CAAY;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBAC9G;AAAA,kBAEJ;AAAA,gBAAA;AAAA,cACF;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAGN;AAEA,WACE,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAR;AAAA,QACA,MAAK;AAAA,QACL,cAAY,YAAYP,CAAI,GAAG,KAAA;AAAA,QAC/B,WAAWN,GAAO,EAAE,WAAAW,GAAW;AAAA,QAC/B,kBAAe;AAAA,QACd,GAAGC;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAAU;AAAA,YAACI;AAAA,YAAA;AAAA,cACC,SAASlB,IAAa,eAAe;AAAA,cACrC,MAAAC;AAAA,cACA,MAAAC;AAAA,cACA,YAAU;AAAA,YAAA;AAAA,UAAA;AAAA,UAEZ,gBAAAY;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAW;AAAA,cACX,WAAWpB,GAAY;AAAA,gBACrB,MAAAQ;AAAA,gBACA,MAAMF,IAAa,UAAU;AAAA,cAAA,CAC9B;AAAA,cAEA,UAAAF;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AACAF,EAAc,cAAc;ACzL5B,MAAMuB,KAAc;AA+MpB,SAASC,GAAiBC,GAAuB;AAC/C,SAAOA,IAAQ,KAAK,QAAQ,OAAOA,CAAK;AAC1C;AAEA,SAASC,GAAY;AAAA,EACnB,MAAAC;AAAA,EACA,QAAAC;AAAA,EACA,WAAAC;AAAA,EACA,oBAAAC;AACF,GAKG;AACD,QAAM,EAAE,GAAApB,EAAA,IAAMC,EAAe,IAAI,GAG3BoB,IACJH,EAAO,cAAclB,EAAE,yCAAyC;AAClE;AAAA;AAAA;AAAA;AAAA,IAIE,gBAAAO,EAACe,EAAa,MAAb,EAAkB,OAAO,IACxB,UAAA;AAAA,MAAA,gBAAAd,EAACc,EAAa,SAAb,EAAqB,SAAO,IAG3B,UAAA,gBAAAd;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAYU,EAAO;AAAA,UACnB,eAAY;AAAA,UACZ,WAAU;AAAA,UAEV,UAAA,gBAAAV,EAAC,QAAA,EAAK,eAAY,QAChB,4BAACe,GAAA,EAAO,MAAMN,EAAK,MAAM,KAAKA,EAAK,WAAW,MAAK,MAAK,EAAA,CAC1D;AAAA,QAAA;AAAA,MAAA,GAEJ;AAAA,wBACCK,EAAa,SAAb,EAAqB,OAAM,OAAM,kBAAkB,IAGlD,UAAA;AAAA,QAAA,gBAAAd,EAACc,EAAa,OAAb,EACC,UAAA,gBAAAf,EAAC,QAAA,EAAK,WAAU,sDACd,UAAA;AAAA,UAAA,gBAAAC,EAAC,QAAA,EAAK,eAAY,QAChB,UAAA,gBAAAA,EAACe,GAAA,EAAO,MAAMN,EAAK,MAAM,KAAKA,EAAK,WAAW,MAAK,MAAK,GAC1D;AAAA,UACA,gBAAAV,EAAC,QAAA,EAAK,WAAU,kCACd,UAAA;AAAA,YAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,4DACb,UAAAS,EAAK,MACR;AAAA,YACCA,EAAK,QACJ,gBAAAT,EAAC,QAAA,EAAK,WAAU,yBAAyB,UAAAS,EAAK,OAAM,IAClD;AAAA,UAAA,EAAA,CACN;AAAA,QAAA,EAAA,CACF,EAAA,CACF;AAAA,QACCG,IACC,gBAAAb,EAAAiB,GAAA,EACE,UAAA;AAAA,UAAA,gBAAAhB,EAACc,EAAa,WAAb,EAAuB;AAAA,UACxB,gBAAAd;AAAA,YAACc,EAAa;AAAA,YAAb;AAAA,cACC,WAAW,gBAAAd,EAACiB,IAAA,EAAU,eAAW,GAAA,CAAC;AAAA,cAClC,UAAUL;AAAA,cACV,eAAY;AAAA,cAEX,UAAAC;AAAA,YAAA;AAAA,UAAA;AAAA,QACH,EAAA,CACF,IACE;AAAA,QACJ,gBAAAb,EAACc,EAAa,WAAb,EAAuB;AAAA,QACxB,gBAAAd;AAAA,UAACc,EAAa;AAAA,UAAb;AAAA,YACC,WAAW,gBAAAd,EAACkB,IAAA,EAAO,eAAW,GAAA,CAAC;AAAA,YAC/B,UAAUP;AAAA,YACV,eAAY;AAAA,YAEX,UAAAD,EAAO;AAAA,UAAA;AAAA,QAAA;AAAA,MACV,EAAA,CACF;AAAA,IAAA,EAAA,CACF;AAAA;AAEJ;AAEA,SAASS,GAAsB;AAAA,EAC7B,KAAAC;AAAA,EACA,YAAAC;AACF,GAGG;AACD,SACE,gBAAArB,EAACsB,IAAA,EACE,UAAAF,EAAI,IAAI,CAACG,MAAS;AACjB,UAAMC,IACJ,OAAOD,EAAK,cAAe,YAAYA,EAAK,aAAa,IACrDA,EAAK,aACL,QACAE,IACJ,gBAAA1B,EAAAiB,GAAA,EACG,UAAA;AAAA,MAAAO,EAAK,OAAO,gBAAAvB,EAAC0B,IAAA,EAAiB,UAAAH,EAAK,MAAK,IAAqB;AAAA,MAC9D,gBAAAvB,EAAC2B,IAAA,EAAkB,UAAAJ,EAAK,MAAA,CAAM;AAAA,MAC7BC,MAAU,SACT,gBAAAxB,EAAC4B,MAAkB,UAAAtB,GAAiBkB,CAAK,GAAE,IACzC;AAAA,IAAA,GACN;AAOF,WAAIH,sBAECQ,GAAA,EAA0B,SAAO,IAAC,UAAUN,EAAK,UAC/C,UAAAF,EAAW;AAAA,MACV,MAAME,EAAK;AAAA,MACX,UAAUE;AAAA,MACV,gBAAgBF,EAAK,WAAW,SAAS;AAAA,IAAA,CAC1C,EAAA,GALeA,EAAK,EAMvB,IAQF,gBAAAvB;AAAA,MAAC6B;AAAA,MAAA;AAAA,QAEC,MAAMN,EAAK;AAAA,QACX,cAAYA,EAAK;AAAA,QACjB,UAAUA,EAAK;AAAA,QACd,GAAIA,EAAK,UAAU,EAAE,SAASA,EAAK,QAAA,IAAY,CAAA;AAAA,QAE/C,UAAAE;AAAA,MAAA;AAAA,MANIF,EAAK;AAAA,IAAA;AAAA,EAShB,CAAC,EAAA,CACH;AAEJ;AAKA,MAAMO,KAA6BnD;AAAA,EACjC;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,MAAA;AAAA,IACX;AAAA,IAEF,iBAAiB,EAAE,MAAM,WAAA;AAAA,EAAW;AAExC,GACMoD,KAA2BpD;AAAA;AAAA;AAAA,EAG/B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,MAAA;AAAA,IACX;AAAA,IAEF,iBAAiB,EAAE,MAAM,WAAA;AAAA,EAAW;AAExC,GAEMqD,IAAU,CAACC,MACOA,KAAS,QAAQ,OAAOA,KAAS;AAEzD,SAASC,GAAyB;AAAA,EAChC,iBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC;AACF,GAKG;AACD,QAAM,EAAE,MAAAC,EAAA,IAASC,GAAA,GACXC,IAAaT,EAAQK,CAAO,GAC5BK,IAAUH,MAAS,WAEnBI,IAAcR,KAAmB,CAACO,GAClCE,IAAcZ,EAAQM,CAAO,KAAKC,MAAS,QAC3CM,IAAUF,KAAeP,KAAkBK,KAAcC;AAC/D,SAAI,CAACG,KAAW,CAACD,IAAoB;AAAA;AAAA,IAGnC,gBAAA5C;AAAA,MAAC8C;AAAA,MAAA;AAAA,QACC,WACEF,IACI,SACA;AAAA,QAGN,4BAAC,OAAA,EAAI,WAAWd,GAA2B,EAAE,MAAAS,GAAM,GAChD,UAAA;AAAA,UAAAM,IACC,gBAAA9C;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,2BAAwB;AAAA,cACxB,WAAWgC,GAAyB,EAAE,MAAAQ,GAAM;AAAA,cAE3C,UAAA;AAAA,gBAAAI,IAAc,gBAAA3C,EAAC+C,MAAuB,IAAK;AAAA,gBAC3CX,IAAiB,gBAAApC,EAACgD,IAAA,CAAA,CAAsB,IAAK;AAAA,gBAC7CP,IAAaJ,IAAU;AAAA,gBACvBK,IAAU,gBAAA1C,EAACiD,IAAA,CAAA,CAAoB,IAAK;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA,IAErC;AAAA,UACHL,IAAcN,IAAU;AAAA,QAAA,EAAA,CAC3B;AAAA,MAAA;AAAA,IAAA;AAAA;AAGN;AAYA,MAAMY,KAAyB;AAAA,EAC7B;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,IAAoBxE,EAAI,6CAA6C;AAAA,EACzE,UAAU;AAAA,IACR,SAAS;AAAA,MACP,YAAY;AAAA,MACZ,UAAU,aAAauE,EAAsB;AAAA,IAAA;AAAA,EAC/C;AAAA,EAEF,iBAAiB,EAAE,SAAS,aAAA;AAC9B,CAAC,GAIKE,KACJ;AAUF,SAASC,GAAiB;AAAA,EACxB,KAAAjC;AAAA,EACA,WAAAkC;AAAA,EACA,YAAAjC;AACF,GAIG;AAOD,QAAMkC,IAAgBlC,IAClB,CAAC;AAAA,IACC,MAAAmC;AAAA,IACA,WAAAnE;AAAA,IACA,UAAAoE;AAAA,IACA,gBAAgBC;AAAA,IAChB,eAAeC;AAAA,EAAA,MAQftC,EAAW;AAAA,IACT,MAAAmC;AAAA,IACA,WAAAnE;AAAA,IACA,UAAAoE;AAAA,IACA,gBAAgBC;AAAA;AAAA;AAAA,IAGhB,eAAeC;AAAA,EAAA,CAChB,IACH;AAEJ,SACE,gBAAA3D;AAAA,IAAC4D;AAAA,IAAA;AAAA,MACC,OAAOxC;AAAA,MACP,WAAAkC;AAAA,MACC,GAAIC,IAAgB,EAAE,YAAYA,MAAkB,CAAA;AAAA,IAAC;AAAA,EAAA;AAG5D;AAMO,MAAMM,KAAsB9E;AAAA,EAIjC,CACE;AAAA,IACE,aAAAH;AAAA,IACA,aAAAkF,IAAc;AAAA,IACd,KAAA1C;AAAA,IACA,YAAAC;AAAA,IACA,MAAAZ;AAAA,IACA,QAAAC;AAAA,IACA,WAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,cAAAmD;AAAA,IACA,oBAAAC,IAAqB;AAAA,IACrB,gBAAAC;AAAA,IACA,eAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,uBAAAC,IAAwB;AAAA,IACxB,6BAAAC;AAAA,IACA,mBAAAC;AAAA,IACA,eAAAC;AAAA,IACA,SAAAtF,KAAU;AAAA,IACV,YAAAuF;AAAA,IACA,cAAAC;AAAA,IACA,UAAAhB;AAAA,EAAA,GAEFlE,MACG;;AACH,UAAM,EAAE,GAAAC,EAAA,IAAMC,EAAe,IAAI,GAM3BiF,KAAcrD,IAClB,gBAAArB,EAAC2E,GAAA,EAAY,SAAO,IACjB,UAAAtD,EAAW;AAAA,MACV,MAAMyC;AAAA,MACN,UACE,gBAAA9D;AAAA,QAAClB;AAAA,QAAA;AAAA,UACC,MAAMF;AAAA,UACN,MAAK;AAAA,UACL,YAAU;AAAA,UACV,SAAQ;AAAA,QAAA;AAAA,MAAA;AAAA,IACV,CAEH,GACH,IAEA,gBAAAoB;AAAA,MAAC2E;AAAA,MAAA;AAAA,QACC,MAAMb;AAAA,QACN,MACE,gBAAA9D;AAAA,UAAClB;AAAA,UAAA;AAAA,YACC,MAAMF;AAAA,YACN,MAAK;AAAA,YACL,YAAU;AAAA,YACV,SAAQ;AAAA,UAAA;AAAA,QAAA;AAAA,MACV;AAAA,IAAA,GAQA,EAAE,OAAOgG,IAAW,eAAAC,IAAe,eAAAC,EAAA,IAAkBC,GAAA,GACrDC,KACJJ,OAAc,YAAYC,OAAkB,UACxCI,KAAYH,EAAc,WAAW,MAAM,IAAI,SAAS,SACxDI,KAAkBJ,EAAc,SAAS,aAAa,GAKtDK,KAAUC,GAAc/E,EAAW,GACnCgF,IACJtB,MAAiBoB,KAAW,YAAsB,SAC9C,CAACG,GAAaC,CAAc,IAAIC,GAAS,EAAK,GAC9CC,IAAeC,GAAY,MAAMH,EAAe,EAAK,GAAG,CAAA,CAAE;AAIhE,IAAAI,EAAU,MAAM;AACd,MAAIN,MAA0B,aAAWE,EAAe,EAAK;AAAA,IAC/D,GAAG,CAACF,CAAqB,CAAC;AAK1B,UAAMO,IAAaC,EAAoB,IAAI,GACrCC,IAAWD,EAIP,IAAI,GACRE,IACJ9B,MAAmB,WACd+B,IAAA5E,EAAI,KAAK,CAACG,MAASA,EAAK,QAAQ,MAAhC,gBAAAyE,EAAmC,OAAM,KAC1C;AACN,IAAAC,GAA0B,MAAM;AAC9B,YAAMC,IAAM,OAAO,SAAS;AAC5B,UAAIC,IAAyBJ,KAAc;AAC3C,UAAIA,MAAe,UAAaH,EAAW,SAAS;AAClD,cAAM3D,IAAO2D,EAAW,QAAQ,cAAc,uBAAuB;AACrE,QAAAO,KAAUlE,KAAA,gBAAAA,EAAM,aAAa,aAAWA,KAAA,gBAAAA,EAAM,gBAAe;AAAA,MAC/D;AACA,YAAMmE,IAAWN,EAAS;AAE1B,UADAA,EAAS,UAAU,EAAE,MAAMR,GAAa,KAAAY,GAAK,SAAAC,EAAA,GACzC,EAACC,KAAA,QAAAA,EAAU,SAAQ,CAACd,EAAa;AAGrC,YAAMe,KACJD,EAAS,YAAY,QACrBD,MAAY,QACZC,EAAS,YAAYD;AACvB,OAAIC,EAAS,QAAQF,KAAOG,SAA4B,EAAK;AAAA,IAC/D,CAAC,GACDV,EAAU,MAAM;AACd,UAAKL;AACL,sBAAO,iBAAiB,YAAYG,CAAY,GAChD,OAAO,iBAAiB,cAAcA,CAAY,GAC3C,MAAM;AACX,iBAAO,oBAAoB,YAAYA,CAAY,GACnD,OAAO,oBAAoB,cAAcA,CAAY;AAAA,QACvD;AAAA,IACF,GAAG,CAACH,GAAaG,CAAY,CAAC;AAE9B,UAAMa,uBACHC,GAAA,EACC,UAAA,gBAAAvG;AAAA,MAACwG;AAAA,MAAA;AAAA,QACC,eAAAjC;AAAA,QACA,eAAepB,EAAkB,EAAE,SAAS,cAAc;AAAA,QAC1D,0BACGsD,IAAA,EACC,UAAA;AAAA,UAAA,gBAAA1G,EAAC2G,IAAA,EACC,UAAA;AAAA,YAAA,gBAAA1G,EAAC2G,GAAA,EAAe,MAAK,gBAAA,CAAgB;AAAA,8BACpCC,IAAA,EAAiB,YAAY,MAAMrB,EAAe,EAAI,GAAG;AAAA,YACzDb;AAAA,UAAA,GACH;AAAA,4BACCmC,IAAA,EAAa;AAAA,4BACbC,IAAA,EACC,UAAA;AAAA,YAAA,gBAAA9G,EAAC+G,IAAA,EAAe,MAAK,KAAA,CAAK;AAAA,YAC1B,gBAAA/G;AAAA,cAACQ;AAAA,cAAA;AAAA,gBACC,MAAAC;AAAA,gBACA,QAAAC;AAAA,gBACA,WAAAC;AAAA,gBACA,oBAAAC;AAAA,cAAA;AAAA,YAAA;AAAA,UACF,EAAA,CACF;AAAA,QAAA,GACF;AAAA,QAEF,SACE,gBAAAZ;AAAA,UAACgH;AAAA,UAAA;AAAA,YACC,KAAKpB;AAAA,YACJ,GAAIP,MAA0B,SAC3B,EAAE,OAAOA,MACT,EAAE,cAAc,WAAA;AAAA,YACpB,MAAMC;AAAA,YACN,cAAcC;AAAA,YACd,YAAYjB;AAAA,YACZ,sBAAsBD;AAAA,YAGtB,SAAS,CAAC4C,MAAU;AAClB,cACEA,EAAM,kBAAkB,WACxBA,EAAM,OAAO,QAAQ,SAAS,KAE9BxB,EAAA;AAAA,YAEJ;AAAA,YACA,cAAYjG,EAAE,0BAA0B;AAAA,YACxC,eAAY;AAAA,YAIZ,UAAA,gBAAAO,EAACmH,GAAyB,UAAzB,EAAkC,OAAOzB,GACxC,UAAA;AAAA,cAAA,gBAAAzF;AAAA,gBAACkC;AAAA,gBAAA;AAAA,kBACC,iBACE8B,KAAsBqB,MAA0B;AAAA,kBAElD,gBAAgBjB;AAAA,kBAChB,SAASD;AAAA,kBACT,SAASD;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEVD,MAAmB,SAClB,gBAAAjE,EAACsB,IAAA,EAAa,aAAe,IAE7B,gBAAAtB,EAACmB,IAAA,EAAsB,KAAAC,GAAU,YAAAC,EAAA,CAAwB;AAAA,YAAA,EAAA,CAE7D;AAAA,UAAA;AAAA,QAAA;AAAA,QAGJ,YAAAmD;AAAA,QACA,cAAAC;AAAA,QAEC,UAAAhB;AAAA,MAAA;AAAA,IAAA,GAEL,GAGI0D,IACJ,gBAAApH,EAAAiB,GAAA,EACE,UAAA;AAAA,MAAA,gBAAAhB,EAAC2G,GAAA,EAAe,MAAK,gBAAA,CAAgB;AAAA,MACrC,gBAAA3G;AAAA,QAACqD;AAAA,QAAA;AAAA,UACC,KAAAjC;AAAA,UACA,WAAW5B,EAAE,0BAA0B;AAAA,UACvC,YAAA6B;AAAA,QAAA;AAAA,MAAA;AAAA,IACF,GACF,GAMI+F,uBACHb,GAAA,EACC,UAAA,gBAAAvG;AAAA,MAACwG;AAAA,MAAA;AAAA,QACC,eAAAjC;AAAA,QACA,eAAepB,EAAkB,EAAE,SAAS,cAAc;AAAA,QAC1D,QAAQ;AAAA,QACR,QACE,gBAAAnD,EAAC,OAAA,EAAI,WAAWoD,IAAyB,UAAA+D,GAAe;AAAA,QAE1D,SAAS;AAAA,QACT,YAAA3C;AAAA,QACA,cAAAC;AAAA,QAEA,UAAA,gBAAAzE,EAAC,OAAA,EAAI,WAAWkD,IAAyB,UAAAO,EAAA,CAAS;AAAA,MAAA;AAAA,IAAA,GAEtD,GAGI4D;AAAA;AAAA;AAAA,MAGJ,gBAAAtH,EAAC,OAAA,EAAI,WAAU,8EACZ,UAAA;AAAA,QAAAoH;AAAA,QACD,gBAAAnH;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,IAAG;AAAA,YACH,UAAU;AAAA,YACV,cACEuE,KAAiB/E,EAAE,yBAAyB,cAAc;AAAA,YAE5D,WAAW2D,EAAkB,EAAE,SAAS,YAAY;AAAA,YAEnD,UAAAM;AAAA,UAAA;AAAA,QAAA;AAAA,MACH,EAAA,CACF;AAAA,OAGInB,IACJrD,OAAY,aAAcuF,IAAa4C,KAAiBC,KAAYf;AAEtE,WAAKtB,KAaH,gBAAAhF;AAAA,MAACsH;AAAA,MAAA;AAAA,QACC,KAAA/H;AAAA,QACA,OAAO0F;AAAA,QACP,YAAYC;AAAA,QACZ,WAAU;AAAA,QACV,kBAAe;AAAA,QAEd,UAAA5C;AAAA,MAAA;AAAA,IAAA,IAlBD,gBAAAtC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAT;AAAA,QACA,WAAU;AAAA,QACV,kBAAe;AAAA,QAEd,UAAA+C;AAAA,MAAA;AAAA,IAAA;AAAA,EAgBT;AACF;AAEAuB,GAAoB,cAAc;AA2ClC,MAAM0D,KAAsB5I;AAAA,EAC1B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB,EAAE,QAAQ,OAAA;AAAA,EAAO;AAEtC,GAEM6I,KAA2B7I,EAAI,aAAa;AAAA,EAChD,UAAU;AAAA,IACR,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,IAAA;AAAA,EACT;AAAA,EAEF,iBAAiB,EAAE,QAAQ,OAAA;AAC7B,CAAC,GAGK8I,KAA4B9I,EAAI,IAAI;AAAA,EACxC,UAAU;AAAA,IACR,QAAQ,EAAE,MAAM,IAAI,OAAO,eAAA;AAAA,EAAe;AAAA,EAE5C,iBAAiB,EAAE,QAAQ,OAAA;AAC7B,CAAC,GAUY+I,KAAsB3I;AAAA,EAIjC,CACE;AAAA,IACE,aAAAH;AAAA,IACA,OAAA+I;AAAA,IACA,aAAAC;AAAA,IACA,cAAAC;AAAA,IACA,QAAAC,IAAS;AAAA,IACT,OAAAC;AAAA,IACA,WAAAC;AAAA,IACA,QAAAC;AAAA,IACA,QAAAC,IAAS;AAAA,IACT,YAAAC;AAAA,IACA,WAAA9I;AAAA,EAAA,GAEFE,MAGE,gBAAAQ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAR;AAAA,MACA,kBAAe;AAAA,MACf,WAAW,GAAGgI,GAAoB,EAAE,QAAAW,GAAQ,CAAC,IAAI7I,KAAa,EAAE;AAAA,MAE/D,UAAA;AAAA,QAAA6I,MAAW;AAAA;AAAA;AAAA;AAAA;AAAA,UAKV,gBAAAnI,EAAC,OAAA,EAAI,WAAU,gTACb,UAAA;AAAA,YAAA,gBAAAC;AAAA,cAAClB;AAAA,cAAA;AAAA,gBACC,MAAMF;AAAA,gBACN,MAAK;AAAA,gBACL,YAAU;AAAA,gBACV,MAAK;AAAA,gBACL,SAAQ;AAAA,cAAA;AAAA,YAAA;AAAA,YAETuJ,IACC,gBAAAnI,EAAC,OAAA,EAAI,WAAU,4CACZ,aACH,IACE;AAAA,UAAA,EAAA,CACN;AAAA,YACE;AAAA,0BACH,OAAA,EAAI,WAAU,gFACb,UAAA,gBAAAA,EAACoI,KAAK,WAAWZ,GAAyB,EAAE,QAAAU,EAAA,CAAQ,GAClD,UAAA,gBAAAnI,EAACqI,EAAK,MAAL,EAAU,WAAU,iFACnB,UAAA;AAAA,UAAA,gBAAApI;AAAA,YAAClB;AAAA,YAAA;AAAA,cACC,MAAMF;AAAA,cACN,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,WAAW6I,GAA0B,EAAE,QAAAS,EAAA,CAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAEjD,gBAAAnI,EAAC,OAAA,EAAI,WAAU,kDACb,UAAA;AAAA,YAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,mBAAmB,UAAA2H,GAAM;AAAA,YACvC,gBAAA3H,EAAC,KAAA,EAAE,WAAU,wDACV,UAAA4H,EAAA,CACH;AAAA,UAAA,GACF;AAAA,UACCE,MAAW,WAAWC,IACrB,gBAAA/H,EAACqI,IAAA,EAAM,SAAQ,SAAQ,WAAU,2BAC9B,UAAAN,EAAA,CACH,IACE;AAAA,UACJ,gBAAA/H;AAAA,YAACsI;AAAA,YAAA;AAAA,cACC,QAAO;AAAA,cACP,WAAU;AAAA,cACV,SAASR,MAAW;AAAA,cACpB,SAASE;AAAA,cACT,OAAOH;AAAA,cACP,eAAY;AAAA,YAAA;AAAA,UAAA;AAAA,UAEbI,IACC,gBAAAjI,EAAC,OAAA,EAAI,WAAU,qDACZ,aACH,IACE;AAAA,QAAA,EAAA,CACN,GACF,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR;AAEA0H,GAAoB,cAAc;"}
1
+ {"version":3,"file":"marketplace-app-shell-CJQtx3sv.js","sources":["../../src/brand/product-lockup/product-lockup.tsx","../../src/patterns/marketplace-app-shell/marketplace-app-shell.tsx"],"sourcesContent":["import { forwardRef, type ComponentPropsWithoutRef } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { Logo } from '../../components/logo/logo';\nimport { AlfadocsLogoMark, AlfadocsLogoNeg } from '../logo-asset';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\n// Outer lockup row. ~4px logical gap between the wordmark and the product\n// name (`--spacing-xs`), centre-aligned so the name's cap height sits\n// against the wordmark's letterforms.\nconst lockup = cva('ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]');\n\n// The product name. Marketing serif (Fraunces, `--font-serif`) — permitted\n// here because this file lives under `src/brand/`, never in `src/components/`\n// or `src/patterns/` (constraint 10). Sized to ~95% of the wordmark height so\n// its cap height matches the logo letterforms across every size and theme\n// (the `--logo-size-*` tokens shift up in the accessible themes; the calc\n// keeps the name proportional for free).\nconst productName = cva(\n [\n 'ds:[font-family:var(--font-serif)]',\n 'ds:font-semibold',\n 'ds:leading-none',\n 'ds:tracking-[0.01em]',\n 'ds:whitespace-nowrap',\n // Forced-colors: drop the transparent text-fill and paint the label\n // as solid CanvasText so it never disappears under Windows HCM —\n // a gradient/transparent fill has no meaning there.\n 'ds:forced-colors:text-[CanvasText]',\n 'ds:forced-colors:[-webkit-text-fill-color:CanvasText]',\n ],\n {\n variants: {\n size: {\n sm: 'ds:text-[calc(var(--logo-size-sm)*0.95)]',\n md: 'ds:text-[calc(var(--logo-size-md)*0.95)]',\n lg: 'ds:text-[calc(var(--logo-size-lg)*0.95)]',\n xl: 'ds:text-[calc(var(--logo-size-xl)*0.95)]',\n },\n tone: {\n // Brand gradient filled into the glyphs via background-clip:text.\n // `--gradient-wordmark` rides the theme aliases, so it stays\n // AA-safe and adapts per theme on its own (and flattens to a solid\n // ink in the accessible / forced-colors blocks — see tokens).\n gradient: [\n 'ds:italic',\n 'ds:bg-[image:var(--gradient-wordmark)]',\n 'ds:bg-clip-text',\n 'ds:text-transparent',\n 'ds:[-webkit-text-fill-color:transparent]',\n ],\n // Monochrome: solid currentColor ink, upright, no gradient — for\n // print, single-colour work, and coloured chrome (e.g. app-shell\n // headers) where the lockup must ride the surrounding ink.\n solid: 'ds:text-current',\n },\n },\n defaultVariants: { size: 'md', tone: 'gradient' },\n },\n);\n\n// Maker lockup root. Sets a single `--lockup-unit` custom property to the\n// matching `--logo-size-*` token; every maker sub-element (mark, name, the\n// \"by Alfadocs\" tag) sizes off `var(--lockup-unit)`, so there's one per-size\n// source of truth that shifts up with the accessible themes for free.\n// `whitespace-nowrap` keeps \"[mark] Name by Alfadocs\" on one line.\nconst makerRoot = cva('ds:whitespace-nowrap', {\n variants: {\n size: {\n sm: 'ds:[--lockup-unit:var(--logo-size-sm)]',\n md: 'ds:[--lockup-unit:var(--logo-size-md)]',\n lg: 'ds:[--lockup-unit:var(--logo-size-lg)]',\n xl: 'ds:[--lockup-unit:var(--logo-size-xl)]',\n },\n },\n defaultVariants: { size: 'md' },\n});\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\ntype LockupSize = NonNullable<VariantProps<typeof productName>['size']>;\n\nexport type ProductLockupProps = {\n /**\n * The product name. Passed verbatim (product names are not translated).\n *\n * - `variant=\"standard\"` (default): renders as \"Alfadocs <name>\" with the\n * wordmark; accessible name is `Alfadocs <name>`.\n * - `variant=\"maker\"`: renders as \"[mark] <name> by Alfadocs\"; accessible\n * name is `<name> by Alfadocs`.\n */\n name: string;\n /**\n * Which lockup composition to use.\n *\n * - `'standard'` (default) — Alfadocs wordmark + product name (\"Alfadocs\n * Builders\"). Use for **internal** Alfadocs products (Alfadocs Builders,\n * Alfadocs API) where the product is part of the Alfadocs family.\n * - `'maker'` — \"<name> by Alfadocs\" with the four-pillar mark and the name\n * as the prominent element. Use for **external** marketplace extensions\n * (\"Scribe by Alfadocs\") where the extension's own name leads and\n * \"by Alfadocs\" is the maker attribution.\n */\n variant?: 'standard' | 'maker';\n /**\n * Render the name as a solid `--foreground` ink, upright (no gradient, no\n * italic), and pair it with the monochrome wordmark. Use for print,\n * single-colour reproductions, or any constrained context where the\n * gradient/serif treatment is inappropriate.\n */\n monochrome?: boolean;\n /**\n * Ink resolution. `'auto'` (default) uses the lockup's intended ink\n * (`--foreground` for monochrome). `'inherit'` makes the whole lockup ride\n * `currentColor` — use it with `monochrome` on a coloured brand surface (a\n * tinted header or split-login panel) so the wordmark + name both take the\n * surface's text colour rather than clashing with a fixed `--foreground`.\n */\n tone?: 'auto' | 'inherit';\n /** Lockup size. Drives both the wordmark and the name's cap height. */\n size?: LockupSize;\n className?: string;\n} & Omit<\n ComponentPropsWithoutRef<'span'>,\n 'role' | 'aria-label' | 'aria-hidden' | 'children' | 'className'\n>;\n\n/* ------------------------------------------------------------------ */\n/* ProductLockup */\n/* ------------------------------------------------------------------ */\n\n/**\n * Pairs a product name with the Alfadocs brand. Two compositions:\n *\n * - `variant=\"standard\"` (default) — the Alfadocs wordmark + product name\n * (\"Alfadocs Builders\"). For internal Alfadocs products. Exposed to\n * assistive tech as a single `img` named `Alfadocs <name>`.\n * - `variant=\"maker\"` — \"[mark] <name> by Alfadocs\". For external marketplace\n * extensions where the extension's name leads. Exposed as a single `img`\n * named `<name> by Alfadocs`.\n *\n * In both cases the inner wordmark/mark and the visible name are decorative so\n * the brand isn't announced twice. Every marketplace app should use this\n * rather than hand-rolling a wordmark + typed span.\n */\nexport const ProductLockup = forwardRef<HTMLSpanElement, ProductLockupProps>(\n (\n {\n name,\n variant = 'standard',\n monochrome = false,\n tone = 'auto',\n size = 'md',\n className,\n ...props\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n if (import.meta.env.DEV && !name.trim()) {\n console.warn(\n '[ProductLockup] `name` is empty — the lockup will render the bare wordmark with no product name. Pass the product name (e.g. \"Builders\").',\n );\n }\n\n if (variant === 'maker') {\n // Ink matrix mirrors the standard variant's tone/monochrome model:\n // - tone=\"inherit\": every element rides currentColor (no explicit ink),\n // for coloured surfaces.\n // - monochrome (tone auto): foreground ink, with the attribution muted.\n // - default (colour, tone auto): the name + mark take --primary; the\n // wordmark lettering stays --foreground; the attribution is muted.\n const inherit = tone === 'inherit';\n const markInk = inherit\n ? ''\n : monochrome\n ? 'ds:text-[color:var(--foreground)]'\n : 'ds:text-[color:var(--primary)]';\n const nameInk = inherit\n ? ''\n : monochrome\n ? 'ds:text-[color:var(--foreground)]'\n : 'ds:text-[color:var(--primary)]';\n const byInk = inherit ? '' : 'ds:text-[color:var(--muted-foreground)]';\n const letteringInk = inherit ? '' : 'ds:text-[color:var(--foreground)]';\n\n return (\n <span\n ref={ref}\n role=\"img\"\n aria-label={t('productLockup.makerLabel', { name: name.trim() })}\n className={makerRoot({ size, className })}\n data-component=\"product-lockup\"\n {...props}\n >\n {/* Pillar mark sized close to the app name (≈0.88 of the serif em),\n vertically centred on it. Inline (not flex) so the maker tag can\n use vertical-align. */}\n <AlfadocsLogoMark\n aria-hidden\n className={`ds:inline-block ds:align-middle ds:me-[var(--spacing-sm)] ds:h-[calc(var(--lockup-unit)*0.88)] ds:w-auto ds:forced-colors:text-[CanvasText] ${markInk}`}\n />\n <span\n aria-hidden\n className={`ds:align-middle ds:[font-family:var(--font-serif)] ds:font-semibold ds:italic ds:leading-none ds:tracking-[0.01em] ${nameInk} ds:text-[calc(var(--lockup-unit)*0.95)]`}\n >\n {name}\n </span>\n {/* Maker tag — superscript style, its top aligned to the app name's\n cap-height via vertical-align: text-top. */}\n <span\n aria-hidden\n className={`ds:align-text-top ds:ms-[var(--spacing-sm)] ds:inline-flex ds:items-baseline ds:gap-[var(--spacing-2xs)] ${byInk}`}\n >\n <Trans\n ns=\"ui\"\n t={t}\n i18nKey=\"productLockup.attribution\"\n components={{\n text: (\n <span className=\"ds:text-[calc(var(--lockup-unit)*0.4)] ds:leading-none\" />\n ),\n brand: (\n <AlfadocsLogoNeg\n aria-hidden\n viewBox=\"168 0 637 125\"\n className={`ds:h-[calc(var(--lockup-unit)*0.45)] ds:w-auto ds:forced-colors:text-[CanvasText] ${letteringInk}`}\n />\n ),\n }}\n />\n </span>\n </span>\n );\n }\n\n return (\n <span\n ref={ref}\n role=\"img\"\n aria-label={`Alfadocs ${name}`.trim()}\n className={lockup({ className })}\n data-component=\"product-lockup\"\n {...props}\n >\n <Logo\n variant={monochrome ? 'monochrome' : 'wordmark'}\n tone={tone}\n size={size}\n decorative\n />\n <span\n aria-hidden\n className={productName({\n size,\n tone: monochrome ? 'solid' : 'gradient',\n })}\n >\n {name}\n </span>\n </span>\n );\n },\n);\nProductLockup.displayName = 'ProductLockup';\n","/**\n * Marketplace App Shell — the standard chrome for an app built on top of\n * AlfaDocs (the kind a partner scaffolds with Claude Code, Lovable, etc.).\n *\n * It is a thin, opinionated composition of kit primitives: an `AppFrame` with\n * a branded `Header` (the maker `ProductLockup` — \"<Product> by Alfadocs\" —\n * rendered `monochrome` so it rides the header's ink; maker is the lockup\n * style for external marketplace extensions), a `Sidebar` for app\n * navigation, `HeaderSettings` (theme/locale/accessibility), and a bare-avatar\n * account menu (fullscreen + sign-out) matching the main app shell. An\n * optional `endSidebar` docks a tool rail (for example Alia) on the inline-end.\n * `sidebarContent`, `sidebarHeader` and `sidebarActions` let the host build\n * the sidebar from the kit's Sidebar parts instead of the flat `nav`.\n * `ConnectWithAlfadocs` is the matching pre-auth screen, with the full-colour\n * maker lockup and `SignInWithAlfadocsButton`.\n *\n * Like `AliaSidebar`, this pattern ships a RUNTIME component (surfaced via\n * `src/patterns/index.ts` and the library bundle) because consuming apps mount\n * it in production rather than copying the source.\n *\n * Auth is intentionally decoupled: the shell takes the signed-in `user` and an\n * `onSignOut` callback as props, and `ConnectWithAlfadocs` takes a `status` +\n * `onConnect`. Wire them to `@alfadocs/auth/react`'s `useAlfadocsAuth()` in the\n * consuming app — the kit never touches OAuth or secrets (those live in the\n * server-side `@alfadocs/auth` BFF).\n *\n * All user-visible copy is consumer-provided (props) so each app localises in\n * its own i18n; the only kit-owned strings reuse existing translated `ui.*`\n * keys (sidebar label, skip link, menu button).\n */\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n useState,\n type MouseEvent,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cva } from 'class-variance-authority';\nimport { LogOut, Maximize2 } from 'lucide-react';\n\nimport { AppFrame } from '../../components/app-frame';\nimport { Avatar } from '../../components/avatar';\nimport { Alert } from '../../components/alert';\nimport { Card } from '../../components/card';\nimport { DropdownMenu } from '../../components/dropdown-menu';\nimport { TabBar } from '../../components/tab-bar';\nimport {\n Header,\n HeaderBrand,\n HeaderCenter,\n HeaderEnd,\n HeaderMenuButton,\n HeaderSkipLink,\n HeaderStart,\n} from '../../components/header';\nimport { HeaderSettings } from '../../components/header-settings';\nimport { ProductLockup } from '../../brand/product-lockup';\nimport { SignInWithAlfadocsButton } from '../../components/sign-in-with-alfadocs-button';\nimport {\n Sidebar,\n SidebarBody,\n SidebarCloseTrigger,\n SidebarCollapseTrigger,\n SidebarHeader,\n SidebarItem,\n SidebarItemBadge,\n SidebarItemIcon,\n SidebarItemLabel,\n SidebarSectionsToggle,\n useSidebar,\n type SidebarItemMove,\n type SidebarMode,\n} from '../../components/sidebar';\nimport { NavigationDismissContext } from '../../components/_shared/navigation-dismiss';\nimport { ThemeRoot } from '../../components/theme-root';\nimport { TooltipProvider } from '../../components/tooltip';\nimport { useTheme } from '../../hooks/use-theme';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport { useMediaQuery } from '../../hooks/use-media-query';\n\n// Below AppFrame's `md` (768px, --breakpoint-md), where it hides the rail.\nconst PHONE_QUERY = '(max-width: 767.98px)';\n\n/* ------------------------------------------------------------------ */\n/* Public API */\n/* ------------------------------------------------------------------ */\n\nexport interface MarketplaceNavItem {\n id: string;\n /** Pre-translated label — apps localise their own nav copy. */\n label: string;\n href: string;\n /** Optional leading icon (a lucide-react element or equivalent). */\n icon?: ReactNode;\n /** Optional unseen-item count rendered as a pill badge. */\n badgeCount?: number;\n /** Mark the item as the current page (`aria-current='page'`). */\n isActive?: boolean;\n /**\n * Optional click handler threaded onto the nav link's `<a>`. The lightweight\n * alternative to `renderLink`: intercept a same-origin click (call\n * `event.preventDefault()`) and route client-side without a full page load —\n * no router `<Link>` needed. Applies to both the standalone sidebar item and\n * the embedded tab. When `renderLink` is supplied it's handed through to the\n * consumer's link element instead.\n */\n onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;\n}\n\n/**\n * Props the shell hands to `renderLink` for each nav item. The consumer returns\n * their router's `<Link to={href}>` carrying the same `className` (the kit's\n * active styling) and `aria-current` (`'page'` on the active item) so a tab /\n * sidebar-item click is a client-side route change, not a full page reload.\n */\nexport interface MarketplaceRenderLinkProps {\n /** The item's destination — feed it to your router's `to` / `href`. */\n href: string;\n /** The kit's classes — apply verbatim to the link element. */\n className?: string;\n /** Icon + label + badge — render as the link's children. */\n children: ReactNode;\n /** `'page'` on the active item, otherwise omitted — forward to the link. */\n 'aria-current'?: 'page';\n /**\n * The item's stable id, as the agent / automation DOM hook. Spread it onto\n * your router link so the item stays addressable by `[data-tab-id]` — see\n * PRS §26 §6. Only supplied on the bottom-tab-bar path.\n */\n 'data-tab-id'?: string;\n}\n\n/**\n * Render a nav item through the consumer's router instead of the kit's own\n * `<a>`. Returned by the consumer; the shell forwards `href`, the kit's\n * `className`, the item children, and `aria-current` so the active styling and\n * the `aria-current=\"page\"` marker survive a client-side route change.\n */\nexport type MarketplaceRenderLink = (\n props: MarketplaceRenderLinkProps,\n) => ReactNode;\n\nexport interface MarketplaceAppUser {\n /** Display name — drives the avatar initials + the account-menu header. */\n name: string;\n /** Optional email shown under the name in the account menu. */\n email?: string;\n /** Optional avatar image URL. */\n avatarSrc?: string;\n}\n\nexport interface MarketplaceAppShellLabels {\n /** Accessible name for the account-menu trigger, e.g. \"Account menu\". */\n accountMenu: string;\n /** The sign-out menu item, e.g. \"Sign out\". */\n signOut: string;\n /**\n * Optional fullscreen menu item label, e.g. \"Toggle fullscreen\". The item\n * renders whenever `onToggleFullscreen` is supplied; when this label is\n * omitted it falls back to the translated `ui.*` \"Toggle fullscreen\" string.\n */\n fullscreen?: string;\n}\n\nexport interface MarketplaceAppShellProps {\n /** Extension name — renders as the maker lockup \"<productName> by Alfadocs\". */\n productName: string;\n /** Link target for the brand lockup. Default `'/'`. */\n productHref?: string;\n /**\n * Nav items, in order. Standalone ignores them when `sidebarContent` is set;\n * the embedded tab strip always uses them. Never-embedded apps can pass `[]`.\n */\n nav: MarketplaceNavItem[];\n /**\n * Standalone sidebar body built from the kit's Sidebar parts. When set, even\n * to `null`, it replaces the flat `nav` in every mode, inside the shell's own\n * `SidebarBody` and `<nav>`. Ignored in `'embedded'`.\n */\n sidebarContent?: ReactNode;\n /**\n * Extra standalone sidebar header content, such as an inline `SearchBar`,\n * below the collapse trigger and any `sidebarActions`. Hidden in the icon\n * rail. Ignored in `'embedded'`.\n */\n sidebarHeader?: ReactNode;\n /**\n * Header tools, usually `SidebarHeaderAction`s, in the collapse trigger's\n * row after it (and after the sections toggle), above `sidebarHeader`.\n * Stacked under the expand button in the icon rail; beside the close\n * button in the phone overlay. Ignored in `'embedded'`.\n */\n sidebarActions?: ReactNode;\n /**\n * Adds `SidebarSectionsToggle` to that row, right after the collapse\n * trigger: it folds or unfolds every section in `sidebarContent`, and hides\n * itself while there are none. @default false\n */\n sidebarSectionsToggle?: boolean;\n /**\n * One call when the sections toggle folds or unfolds every section, with\n * their `sectionId`s, in place of each section's `onOpenChange`; see\n * `Sidebar`'s `onSetAllSectionsOpen`.\n */\n onSetAllSidebarSectionsOpen?: (open: boolean, sectionIds: string[]) => void;\n /**\n * Lets users move `sidebarContent` items between sections, by drag and drop\n * or keyboard; see `Sidebar`'s `onMoveItem`. Apply each move and re-render.\n * Off when omitted, in the icon rail, and in `'embedded'`.\n */\n onMoveSidebarItem?: (move: SidebarItemMove) => void;\n /**\n * Render nav items (and the brand lockup) through the consumer's router so a\n * tab / item click is a client-side route change with **no full-page reload\n * or session flash**. Wire it to your router's `<Link>`:\n *\n * ```tsx\n * import { Link } from '@tanstack/react-router';\n * <MarketplaceAppShell\n * nav={nav}\n * renderLink={({ href, className, children, ...rest }) => (\n * <Link to={href} className={className} {...rest}>{children}</Link>\n * )}\n * />\n * ```\n *\n * Threaded to the standalone sidebar items, the embedded top tab strip, and\n * the brand lockup. The kit forwards the same `className` + `aria-current` so\n * the active styling and the `aria-current=\"page\"` marker survive in both\n * modes. Omit it to render the plain `<a href>` exactly as before — non-routed\n * consumers are byte-for-byte unaffected. A per-item `onClick` (a\n * click-interceptor shim) is the lighter alternative when you don't want to\n * thread a router `<Link>`.\n */\n renderLink?: MarketplaceRenderLink;\n /** The signed-in user shown in the account menu. */\n user: MarketplaceAppUser;\n /** Consumer-localised chrome labels owned by the shell. */\n labels: MarketplaceAppShellLabels;\n /** Fires when the user picks \"Sign out\". Wire to `useAlfadocsAuth().signOut`. */\n onSignOut?: () => void;\n /** Fires when the user toggles fullscreen. Omit to hide the fullscreen item. */\n onToggleFullscreen?: () => void;\n /**\n * Force the sidebar into a specific mode. Leave it undefined and the shell\n * uses the menu-button drawer below `md` by itself, and the user's saved\n * mode (expanded unless they collapsed it) above.\n */\n sidebarState?: SidebarMode;\n /**\n * Render a collapse/expand toggle in the sidebar header, letting the user\n * shrink the standalone sidebar (the flat `nav` or your `sidebarContent`)\n * to an icon rail. The chosen mode persists\n * per-user (the underlying `Sidebar` stores it) and survives reloads. Opt-in\n * so existing consumers are unaffected; ignored when `sidebarState` forces a\n * mode or in the `'embedded'` variant (no sidebar). @default false\n */\n collapsibleSidebar?: boolean;\n /** Override the accessible name of the `<main>` landmark. */\n mainAriaLabel?: string;\n /**\n * Chrome variant. `'standalone'` (default) renders the full shell — branded\n * Header, Sidebar, and account menu. `'embedded'` is for apps running INSIDE\n * the AlfaDocs platform iframe (consumers detect this with\n * `window !== window.top`): it drops the Header, Sidebar, account menu, and\n * product lockup — the platform already brands and identifies the session\n * around the iframe — and renders the `nav` items as a single slim top tab\n * strip. `onSignOut`, `onToggleFullscreen`, `productName`, `productHref`,\n * `sidebarState`, `sidebarContent` and `sidebarHeader` are ignored in\n * `'embedded'`; the `<main>` landmark, `mainAriaLabel`, the skip link and\n * `endSidebar` are kept.\n */\n variant?: 'standalone' | 'embedded';\n /** Inline-end panel (e.g. a `ControlRoomRail`) forwarded to `AppFrame` in both variants.\n * Hidden below `md`: keep it mounted and add `AliaPopout` there. In `'embedded'` it\n * pins the tab strip and scrolls `<main>` beside it; omitted, embedded is unchanged. */\n endSidebar?: ReactNode;\n /** The narrowest `<main>` may get, px, passed to `AppFrame` in both\n * variants: an open `endSidebar` panel shows over the content instead. */\n minMainWidth?: number;\n /** Children render inside the main content region. */\n children: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* Internals */\n/* ------------------------------------------------------------------ */\n\nfunction formatBadgeCount(count: number): string {\n return count > 99 ? '99+' : String(count);\n}\n\nfunction AccountMenu({\n user,\n labels,\n onSignOut,\n onToggleFullscreen,\n}: {\n user: MarketplaceAppUser;\n labels: MarketplaceAppShellLabels;\n onSignOut?: () => void;\n onToggleFullscreen?: () => void;\n}) {\n const { t } = useTranslation('ui');\n // Default to the translated `ui.*` label so a consumer that wires\n // `onToggleFullscreen` but omits the label still gets a localised item.\n const fullscreenLabel =\n labels.fullscreen ?? t('marketplaceAppShell.settings.fullscreen');\n return (\n // Non-modal: an account menu shouldn't inert/aria-hide the whole shell\n // behind it (which leaves the still-focusable chrome inside an\n // aria-hidden region — an `aria-hidden-focus` violation).\n <DropdownMenu.Root modal={false}>\n <DropdownMenu.Trigger asChild>\n {/* Bare avatar circle — matches the main app shell's account\n trigger. The name lives inside the menu, not beside the avatar. */}\n <button\n type=\"button\"\n aria-label={labels.accountMenu}\n data-testid=\"marketplace-account-trigger\"\n className=\"ds:inline-flex ds:items-center ds:justify-center ds:shrink-0 ds:size-10 ds:rounded-[var(--radius-full)] ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)] ds:forced-colors:focus-visible:outline-[CanvasText]\"\n >\n <span aria-hidden=\"true\">\n <Avatar name={user.name} src={user.avatarSrc} size=\"md\" />\n </span>\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\" collisionPadding={16}>\n {/* GitHub-style identity header — small avatar + name + secondary\n line, matching the main app shell's account menu. */}\n <DropdownMenu.Label>\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span aria-hidden=\"true\">\n <Avatar name={user.name} src={user.avatarSrc} size=\"sm\" />\n </span>\n <span className=\"ds:flex ds:flex-col ds:min-w-0\">\n <span className=\"type-label ds:text-[color:var(--foreground)] ds:truncate\">\n {user.name}\n </span>\n {user.email ? (\n <span className=\"type-meta ds:truncate\">{user.email}</span>\n ) : null}\n </span>\n </span>\n </DropdownMenu.Label>\n {onToggleFullscreen ? (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n startIcon={<Maximize2 aria-hidden />}\n onSelect={onToggleFullscreen}\n data-testid=\"marketplace-fullscreen\"\n >\n {fullscreenLabel}\n </DropdownMenu.Item>\n </>\n ) : null}\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n startIcon={<LogOut aria-hidden />}\n onSelect={onSignOut}\n data-testid=\"marketplace-sign-out\"\n >\n {labels.signOut}\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\nfunction MarketplaceSidebarNav({\n nav,\n renderLink,\n}: {\n nav: MarketplaceNavItem[];\n renderLink?: MarketplaceRenderLink;\n}) {\n return (\n <SidebarBody>\n {nav.map((item) => {\n const badge =\n typeof item.badgeCount === 'number' && item.badgeCount > 0\n ? item.badgeCount\n : undefined;\n const inner = (\n <>\n {item.icon ? <SidebarItemIcon>{item.icon}</SidebarItemIcon> : null}\n <SidebarItemLabel>{item.label}</SidebarItemLabel>\n {badge !== undefined ? (\n <SidebarItemBadge>{formatBadgeCount(badge)}</SidebarItemBadge>\n ) : null}\n </>\n );\n\n // Consumer-router mode: render the item through Radix `Slot`\n // (`SidebarItem asChild`) so the consumer's `<Link>` takes over the\n // anchor while keeping the kit's item styling + `aria-current=\"page\"`.\n // Clicking routes client-side — no full-page reload.\n if (renderLink) {\n return (\n <SidebarItem key={item.id} asChild isActive={item.isActive}>\n {renderLink({\n href: item.href,\n children: inner,\n 'aria-current': item.isActive ? 'page' : undefined,\n })}\n </SidebarItem>\n );\n }\n\n // Default: plain anchor — byte-identical to before when no per-item\n // `onClick` is supplied (it's omitted entirely, not passed as\n // undefined, so the rendered `<a>` is unchanged).\n return (\n <SidebarItem\n key={item.id}\n href={item.href}\n aria-label={item.label}\n isActive={item.isActive}\n {...(item.onClick ? { onClick: item.onClick } : {})}\n >\n {inner}\n </SidebarItem>\n );\n })}\n </SidebarBody>\n );\n}\n\n// The tool row: the collapse trigger, the sections toggle, then the host's\n// actions; the drawer ends it with the close button. The rail stacks it.\n// One tree in every mode, so the collapse trigger keeps focus.\nconst sidebarHeaderStackVariants = cva(\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]',\n {\n variants: {\n mode: {\n expanded: 'ds:min-w-0 ds:flex-1',\n icon: 'ds:items-center',\n overlay: 'ds:min-w-0 ds:flex-1',\n },\n },\n defaultVariants: { mode: 'expanded' },\n },\n);\nconst sidebarHeaderRowVariants = cva(\n // Wraps rather than push a tool off the edge at the accessible size. Empty\n // when the sections toggle, alone in it, finds no section.\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)] ds:empty:hidden',\n {\n variants: {\n mode: {\n expanded: '',\n icon: 'ds:flex-col',\n overlay: 'ds:justify-end',\n },\n },\n defaultVariants: { mode: 'expanded' },\n },\n);\n\nconst hasNode = (node: ReactNode) =>\n node !== undefined && node !== null && typeof node !== 'boolean';\n\nfunction MarketplaceSidebarHeader({\n collapseTrigger,\n sectionsToggle,\n actions,\n content,\n}: {\n collapseTrigger: boolean;\n sectionsToggle: boolean;\n actions: ReactNode;\n content: ReactNode;\n}) {\n const { mode } = useSidebar();\n const hasActions = hasNode(actions);\n const overlay = mode === 'overlay';\n // SidebarCollapseTrigger renders nothing in the overlay, so skip it there.\n const showTrigger = collapseTrigger && !overlay;\n const showContent = hasNode(content) && mode !== 'icon';\n const showRow = showTrigger || sectionsToggle || hasActions || overlay;\n if (!showRow && !showContent) return null;\n return (\n // With nothing below it, an empty row hides the whole band too.\n <SidebarHeader\n className={\n showContent\n ? undefined\n : 'ds:has-[[data-sidebar-header-row]:empty]:hidden'\n }\n >\n <div className={sidebarHeaderStackVariants({ mode })}>\n {showRow ? (\n <div\n data-sidebar-header-row=\"\"\n className={sidebarHeaderRowVariants({ mode })}\n >\n {showTrigger ? <SidebarCollapseTrigger /> : null}\n {sectionsToggle ? <SidebarSectionsToggle /> : null}\n {hasActions ? actions : null}\n {overlay ? <SidebarCloseTrigger /> : null}\n </div>\n ) : null}\n {showContent ? content : null}\n </div>\n </SidebarHeader>\n );\n}\n\n/* CVA for the chrome variant — drives the `<main>` surface; the structural\n header/sidebar-vs-tab-strip difference is conditional in the render.\n\n The `standalone` `<main>` gets its content inset from AppFrame's own\n `mainVariants({ padded: true })` (`--spacing-md` on every logical side), so\n this variant only carries the canvas colour there. The `embedded` `<main>`\n is a plain element (no AppFrame), so it has to supply its own inset:\n `--spacing-md` inline + block-end to match the standalone inset, and a\n larger `--spacing-lg` block-start so content clears the floating tab strip's\n pill instead of butting up against it. All logical — RTL mirrors for free. */\nconst EMBEDDED_CONTENT_INSET = [\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:pt-[var(--spacing-lg)] ds:pb-[var(--spacing-md)]',\n].join(' ');\n\nconst shellMainVariants = cva('ds:bg-[color:var(--app-shell-background)]', {\n variants: {\n variant: {\n standalone: '',\n embedded: `ds:flex-1 ${EMBEDDED_CONTENT_INSET}`,\n },\n },\n defaultVariants: { variant: 'standalone' },\n});\n\n// Embedded with an end panel: the strip sits in AppFrame's header slot, so it\n// carries the shell canvas itself rather than AppFrame's `--background`.\nconst EMBEDDED_DOCKED_CHROME =\n 'ds:shrink-0 ds:bg-[color:var(--app-shell-background)]';\n\n/**\n * Embedded chrome: the slim floating tab strip (no Header / Sidebar / account\n * menu) for apps running inside the AlfaDocs platform iframe. It's the shared\n * {@link TabBar} fed the shell's nav items — the platform brands and identifies\n * the session around the iframe, so the strip is the only chrome. The\n * `MarketplaceNavItem` shape is structurally a `TabBarItem`, so the nav passes\n * straight through.\n */\nfunction EmbeddedTabStrip({\n nav,\n ariaLabel,\n renderLink,\n}: {\n nav: MarketplaceNavItem[];\n ariaLabel: string;\n renderLink?: MarketplaceRenderLink;\n}) {\n // Adapt the shell's `renderLink` to TabBar's `renderLink` signature — TabBar\n // also offers the per-item `onClick`, but in consumer-router mode the\n // `<Link>` owns navigation (matching the standalone sidebar), so we forward\n // only `href` / `className` / `children` / `aria-current`. With `renderLink`\n // omitted, TabBar renders its own plain `<a href>` exactly as before, and a\n // per-item `onClick` rides through `nav` → `TabBarItem` untouched.\n const tabRenderLink = renderLink\n ? ({\n href,\n className,\n children,\n 'aria-current': ariaCurrent,\n 'data-tab-id': tabId,\n }: {\n href: string;\n className: string;\n children: ReactNode;\n 'aria-current'?: 'page';\n 'data-tab-id'?: string;\n }) =>\n renderLink({\n href,\n className,\n children,\n 'aria-current': ariaCurrent,\n // Forward the agent DOM hook — without it a consumer-router tab is\n // invisible to `[data-tab-id]` lookups (PRS §26 §6).\n 'data-tab-id': tabId,\n })\n : undefined;\n\n return (\n <TabBar\n items={nav}\n ariaLabel={ariaLabel}\n {...(tabRenderLink ? { renderLink: tabRenderLink } : {})}\n />\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* MarketplaceAppShell */\n/* ------------------------------------------------------------------ */\n\nexport const MarketplaceAppShell = forwardRef<\n HTMLDivElement,\n MarketplaceAppShellProps\n>(\n (\n {\n productName,\n productHref = '/',\n nav,\n renderLink,\n user,\n labels,\n onSignOut,\n onToggleFullscreen,\n sidebarState,\n collapsibleSidebar = false,\n sidebarContent,\n sidebarHeader,\n sidebarActions,\n sidebarSectionsToggle = false,\n onSetAllSidebarSectionsOpen,\n onMoveSidebarItem,\n mainAriaLabel,\n variant = 'standalone',\n endSidebar,\n minMainWidth,\n children,\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n\n // The brand lockup as a consumer-router link: when `renderLink` is\n // supplied, the brand anchor routes client-side too (no session flash when\n // jumping home). The maker lockup's \"<productName> by Alfadocs\" supplies\n // the link's accessible name, matching the default `HeaderBrand` anchor.\n const headerBrand = renderLink ? (\n <HeaderBrand asChild>\n {renderLink({\n href: productHref,\n children: (\n <ProductLockup\n name={productName}\n size=\"md\"\n monochrome\n variant=\"maker\"\n />\n ),\n })}\n </HeaderBrand>\n ) : (\n <HeaderBrand\n href={productHref}\n logo={\n <ProductLockup\n name={productName}\n size=\"md\"\n monochrome\n variant=\"maker\"\n />\n }\n />\n );\n\n // Only wrap in a nested ThemeRoot when the user has an\n // explicit theme/accessibility override, so we don't clobber the consuming\n // app's (or Storybook's) outer theme cascade.\n const { theme: themePref, accessibility, resolvedTheme } = useTheme();\n const hasExplicitOverride =\n themePref !== 'system' || accessibility !== 'system';\n const themeBase = resolvedTheme.startsWith('dark') ? 'dark' : 'light';\n const themeAccessible = resolvedTheme.endsWith('-accessible');\n\n // Below `md` AppFrame hides the docked sidebar and HeaderMenuButton\n // shows, so the shell switches to the drawer there by itself. An explicit\n // `sidebarState` wins; above `md` the user's saved mode stays.\n const isPhone = useMediaQuery(PHONE_QUERY);\n const effectiveSidebarState =\n sidebarState ?? (isPhone ? ('overlay' as const) : undefined);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const closeSidebar = useCallback(() => setSidebarOpen(false), []);\n\n // Leaving the drawer (a phone turned to landscape past `md`) shuts it,\n // so it never reopens, taking focus, on the way back.\n useEffect(() => {\n if (effectiveSidebarState !== 'overlay') setSidebarOpen(false);\n }, [effectiveSidebarState]);\n\n // The drawer closes when the route changes, however the host changed it:\n // the URL, or the item marked current. No router needed. The flat `nav`\n // says which item that is; custom content is read from the open drawer.\n const sidebarRef = useRef<HTMLElement>(null);\n const routeRef = useRef<{\n open: boolean;\n url: string;\n current: string | null;\n } | null>(null);\n const navCurrent =\n sidebarContent === undefined\n ? (nav.find((item) => item.isActive)?.id ?? '')\n : undefined;\n useIsomorphicLayoutEffect(() => {\n const url = window.location.href;\n let current: string | null = navCurrent ?? null;\n if (navCurrent === undefined && sidebarRef.current) {\n const node = sidebarRef.current.querySelector('[aria-current=\"page\"]');\n current = node?.getAttribute('href') ?? node?.textContent ?? '';\n }\n const previous = routeRef.current;\n routeRef.current = { open: sidebarOpen, url, current };\n if (!previous?.open || !sidebarOpen) return;\n // A side not read (the drawer's portal mounts a commit late) says\n // nothing about the route, so only two real readings are compared.\n const changedItem =\n previous.current !== null &&\n current !== null &&\n previous.current !== current;\n if (previous.url !== url || changedItem) setSidebarOpen(false);\n });\n useEffect(() => {\n if (!sidebarOpen) return undefined;\n window.addEventListener('popstate', closeSidebar);\n window.addEventListener('hashchange', closeSidebar);\n return () => {\n window.removeEventListener('popstate', closeSidebar);\n window.removeEventListener('hashchange', closeSidebar);\n };\n }, [sidebarOpen, closeSidebar]);\n\n const shell = (\n <TooltipProvider>\n <AppFrame\n mainAriaLabel={mainAriaLabel}\n mainClassName={shellMainVariants({ variant: 'standalone' })}\n header={\n <Header>\n <HeaderStart>\n <HeaderSkipLink href=\"#main-content\" />\n <HeaderMenuButton onMenuOpen={() => setSidebarOpen(true)} />\n {headerBrand}\n </HeaderStart>\n <HeaderCenter />\n <HeaderEnd>\n <HeaderSettings size=\"sm\" />\n <AccountMenu\n user={user}\n labels={labels}\n onSignOut={onSignOut}\n onToggleFullscreen={onToggleFullscreen}\n />\n </HeaderEnd>\n </Header>\n }\n sidebar={\n <Sidebar\n ref={sidebarRef}\n {...(effectiveSidebarState !== undefined\n ? { state: effectiveSidebarState }\n : { defaultState: 'expanded' as const })}\n open={sidebarOpen}\n onOpenChange={setSidebarOpen}\n onMoveItem={onMoveSidebarItem}\n onSetAllSectionsOpen={onSetAllSidebarSectionsOpen}\n // A link tapped in the phone drawer navigates, so the drawer\n // closes, whether the link is the flat nav's or the host's.\n onClick={(event) => {\n if (\n event.target instanceof Element &&\n event.target.closest('a[href]')\n ) {\n closeSidebar();\n }\n }}\n aria-label={t('navigation.sidebar.label')}\n data-testid=\"marketplace-app-shell-sidebar\"\n >\n {/* So does a pick that navigates without a link, such as a\n SearchBar result. */}\n <NavigationDismissContext.Provider value={closeSidebar}>\n <MarketplaceSidebarHeader\n collapseTrigger={\n collapsibleSidebar && effectiveSidebarState === undefined\n }\n sectionsToggle={sidebarSectionsToggle}\n actions={sidebarActions}\n content={sidebarHeader}\n />\n {sidebarContent !== undefined ? (\n <SidebarBody>{sidebarContent}</SidebarBody>\n ) : (\n <MarketplaceSidebarNav nav={nav} renderLink={renderLink} />\n )}\n </NavigationDismissContext.Provider>\n </Sidebar>\n }\n endSidebar={endSidebar}\n minMainWidth={minMainWidth}\n >\n {children}\n </AppFrame>\n </TooltipProvider>\n );\n\n const embeddedChrome = (\n <>\n <HeaderSkipLink href=\"#main-content\" />\n <EmbeddedTabStrip\n nav={nav}\n ariaLabel={t('navigation.sidebar.label')}\n renderLink={renderLink}\n />\n </>\n );\n\n // An end panel needs a height-bounded row to dock in, which AppFrame owns.\n // The inset moves inside its scroll area, so `<main>` reads as it does\n // without the panel. No sidebar: the tab strip stays the only nav.\n const embeddedDocked = (\n <TooltipProvider>\n <AppFrame\n mainAriaLabel={mainAriaLabel}\n mainClassName={shellMainVariants({ variant: 'standalone' })}\n padded={false}\n header={\n <div className={EMBEDDED_DOCKED_CHROME}>{embeddedChrome}</div>\n }\n sidebar={null}\n endSidebar={endSidebar}\n minMainWidth={minMainWidth}\n >\n <div className={EMBEDDED_CONTENT_INSET}>{children}</div>\n </AppFrame>\n </TooltipProvider>\n );\n\n const embedded = (\n // The shell owns the warm-grey canvas; TabBar's strip is transparent and\n // floats its pill on it, and `<main>` continues the same surface.\n <div className=\"ds:flex ds:min-h-dvh ds:flex-col ds:bg-[color:var(--app-shell-background)]\">\n {embeddedChrome}\n <main\n id=\"main-content\"\n tabIndex={-1}\n aria-label={\n mainAriaLabel ?? t('navigation.main.label', 'Main content')\n }\n className={shellMainVariants({ variant: 'embedded' })}\n >\n {children}\n </main>\n </div>\n );\n\n const content =\n variant === 'embedded' ? (endSidebar ? embeddedDocked : embedded) : shell;\n\n if (!hasExplicitOverride) {\n return (\n <div\n ref={ref}\n className=\"ds:contents\"\n data-component=\"marketplace-app-shell\"\n >\n {content}\n </div>\n );\n }\n\n return (\n <ThemeRoot\n ref={ref}\n theme={themeBase}\n accessible={themeAccessible}\n className=\"ds:contents\"\n data-component=\"marketplace-app-shell\"\n >\n {content}\n </ThemeRoot>\n );\n },\n);\n\nMarketplaceAppShell.displayName = 'MarketplaceAppShell';\n\n/* ------------------------------------------------------------------ */\n/* ConnectWithAlfadocs */\n/* ------------------------------------------------------------------ */\n\nexport type ConnectStatus = 'idle' | 'connecting' | 'error';\n\nexport interface ConnectWithAlfadocsProps {\n /** Product name shown next to the wordmark at the top of the card. */\n productName: string;\n /** Heading, e.g. \"Connect your AlfaDocs account\". */\n title: string;\n /** Supporting copy below the heading. */\n description: ReactNode;\n /** The connect button label, e.g. \"Connect with AlfaDocs\". */\n connectLabel: string;\n /** Connection lifecycle. `connecting` shows a loading button; `error` shows the alert. */\n status?: ConnectStatus;\n /** Error message shown (as an alert) when `status === 'error'`. */\n error?: ReactNode;\n /** Fires when the connect button is pressed. Wire to `useAlfadocsAuth().connect`. */\n onConnect?: () => void;\n /** Optional footer content below the button (e.g. a \"what's this?\" link). */\n footer?: ReactNode;\n /**\n * Visual layout. `'card'` (default) is the centred card on the warm-grey\n * canvas — unchanged. `'split'` adds, at `lg:` and up, a two-panel desktop\n * layout: a brand panel on the inline-start and the connect card on the\n * inline-end. Below `lg:`, `'split'` collapses to exactly the card layout —\n * so it falls back gracefully inside iframes / embeds that never reach\n * desktop width. Use `'split'` for full-page desktop logins.\n */\n layout?: 'card' | 'split';\n /**\n * Optional content shown under the lockup in the `'split'` brand panel (a\n * tagline, value props, an illustration). Ignored in `'card'` and below `lg:`.\n */\n brandPanel?: ReactNode;\n className?: string;\n}\n\n/* Split-layout CVAs (lg+ two-panel; collapses to the centred card below lg). */\nconst connectRootVariants = cva(\n 'ds:flex ds:min-h-dvh ds:bg-[color:var(--app-shell-background)]',\n {\n variants: {\n layout: {\n card: '',\n split: 'ds:flex-col ds:lg:flex-row',\n },\n },\n defaultVariants: { layout: 'card' },\n },\n);\n\nconst connectCardWidthVariants = cva('ds:w-full', {\n variants: {\n layout: {\n card: 'ds:max-w-[400px]',\n split: 'ds:max-w-[400px] ds:lg:max-w-[480px]',\n },\n },\n defaultVariants: { layout: 'card' },\n});\n\n// The card's own lockup hides at lg+ in `split` (the brand panel shows it there).\nconst connectCardLockupVariants = cva('', {\n variants: {\n layout: { card: '', split: 'ds:lg:hidden' },\n },\n defaultVariants: { layout: 'card' },\n});\n\n/**\n * The pre-auth \"Connect with AlfaDocs\" screen. Centred white card on the\n * warm-grey canvas with the AlfaDocs wordmark + product name, copy, an error\n * slot, and the primary connect CTA. An opt-in `layout=\"split\"` adds a desktop\n * two-panel brand layout (lg+). Presentational — `onConnect` should call\n * `useAlfadocsAuth().connect()`, which redirects the browser to the server-side\n * BFF that runs the real OAuth2 + PKCE flow.\n */\nexport const ConnectWithAlfadocs = forwardRef<\n HTMLDivElement,\n ConnectWithAlfadocsProps\n>(\n (\n {\n productName,\n title,\n description,\n connectLabel,\n status = 'idle',\n error,\n onConnect,\n footer,\n layout = 'card',\n brandPanel,\n className,\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n data-component=\"connect-with-alfadocs\"\n className={`${connectRootVariants({ layout })} ${className ?? ''}`}\n >\n {layout === 'split' ? (\n // Desktop brand panel (lg+ only): a bold `--primary` surface with the\n // monochrome lockup riding the `--primary-foreground` ink, plus an\n // optional `brandPanel` slot. Decorative — the card carries the real\n // heading + CTA, and shows its own lockup below `lg:`.\n <div className=\"ds:hidden ds:lg:flex ds:lg:w-[55%] ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-lg)] ds:bg-[color:var(--primary)] ds:text-[color:var(--primary-foreground)] ds:ps-[var(--spacing-2xl)] ds:pe-[var(--spacing-2xl)] ds:pt-[var(--spacing-2xl)] ds:pb-[var(--spacing-2xl)] ds:text-start\">\n <ProductLockup\n name={productName}\n size=\"lg\"\n monochrome\n tone=\"inherit\"\n variant=\"maker\"\n />\n {brandPanel ? (\n <div className=\"type-body ds:max-w-[28rem] ds:text-start\">\n {brandPanel}\n </div>\n ) : null}\n </div>\n ) : null}\n <div className=\"ds:flex ds:flex-1 ds:items-center ds:justify-center ds:p-[var(--spacing-lg)]\">\n <Card className={connectCardWidthVariants({ layout })}>\n <Card.Body className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-lg)] ds:text-center\">\n <ProductLockup\n name={productName}\n size=\"lg\"\n variant=\"maker\"\n className={connectCardLockupVariants({ layout })}\n />\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <h1 className=\"type-title-card\">{title}</h1>\n <p className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {description}\n </p>\n </div>\n {status === 'error' && error ? (\n <Alert variant=\"error\" className=\"ds:w-full ds:text-start\">\n {error}\n </Alert>\n ) : null}\n <SignInWithAlfadocsButton\n intent=\"primary\"\n className=\"ds:w-full\"\n loading={status === 'connecting'}\n onClick={onConnect}\n label={connectLabel}\n data-testid=\"connect-with-alfadocs-button\"\n />\n {footer ? (\n <div className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {footer}\n </div>\n ) : null}\n </Card.Body>\n </Card>\n </div>\n </div>\n );\n },\n);\n\nConnectWithAlfadocs.displayName = 'ConnectWithAlfadocs';\n"],"names":["lockup","cva","productName","makerRoot","ProductLockup","forwardRef","name","variant","monochrome","tone","size","className","props","ref","t","useTranslation","inherit","markInk","nameInk","byInk","letteringInk","jsxs","jsx","AlfadocsLogoMark","Trans","AlfadocsLogoNeg","Logo","PHONE_QUERY","formatBadgeCount","count","AccountMenu","user","labels","onSignOut","onToggleFullscreen","fullscreenLabel","DropdownMenu","Avatar","Fragment","Maximize2","LogOut","MarketplaceSidebarNav","nav","renderLink","SidebarBody","item","badge","inner","SidebarItemIcon","SidebarItemLabel","SidebarItemBadge","SidebarItem","sidebarHeaderStackVariants","sidebarHeaderRowVariants","hasNode","node","MarketplaceSidebarHeader","collapseTrigger","sectionsToggle","actions","content","mode","useSidebar","hasActions","overlay","showTrigger","showContent","showRow","SidebarHeader","SidebarCollapseTrigger","SidebarSectionsToggle","SidebarCloseTrigger","EMBEDDED_CONTENT_INSET","shellMainVariants","EMBEDDED_DOCKED_CHROME","EmbeddedTabStrip","ariaLabel","tabRenderLink","href","children","ariaCurrent","tabId","TabBar","MarketplaceAppShell","productHref","sidebarState","collapsibleSidebar","sidebarContent","sidebarHeader","sidebarActions","sidebarSectionsToggle","onSetAllSidebarSectionsOpen","onMoveSidebarItem","mainAriaLabel","endSidebar","minMainWidth","headerBrand","HeaderBrand","themePref","accessibility","resolvedTheme","useTheme","hasExplicitOverride","themeBase","themeAccessible","isPhone","useMediaQuery","effectiveSidebarState","sidebarOpen","setSidebarOpen","useState","closeSidebar","useCallback","useEffect","sidebarRef","useRef","routeRef","navCurrent","_a","useIsomorphicLayoutEffect","url","current","previous","changedItem","shell","TooltipProvider","AppFrame","Header","HeaderStart","HeaderSkipLink","HeaderMenuButton","HeaderCenter","HeaderEnd","HeaderSettings","Sidebar","event","NavigationDismissContext","embeddedChrome","embeddedDocked","embedded","ThemeRoot","connectRootVariants","connectCardWidthVariants","connectCardLockupVariants","ConnectWithAlfadocs","title","description","connectLabel","status","error","onConnect","footer","layout","brandPanel","Card","Alert","SignInWithAlfadocsButton"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { c as ss } from "./index-D2ZczOXr.js";
4
4
  import { useTranslation as es } from "react-i18next";
5
5
  import { I as as } from "./icon-button-S8_weU3g.js";
6
6
  import { B as V } from "./button-DohK_Ak_.js";
7
- import { A as rs } from "./avatar-BPiPL7ND.js";
7
+ import { A as rs } from "./avatar-a6042Ox2.js";
8
8
  import { T as ds } from "./timestamp-DPLDWdxA.js";
9
9
  import { i as os } from "./is-safe-url-DkETxeHz.js";
10
10
  import { X as ns } from "./x-B5YnXwCz.js";
@@ -324,4 +324,4 @@ ls.displayName = "MessageCard";
324
324
  export {
325
325
  ls as M
326
326
  };
327
- //# sourceMappingURL=message-card-CvCnCssc.js.map
327
+ //# sourceMappingURL=message-card-B6SduXJv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-card-CvCnCssc.js","sources":["../../src/components/message-card/message-card.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { X } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Button } from '../button/button';\nimport { Avatar } from '../avatar/avatar';\nimport { Timestamp } from '../timestamp';\nimport { isSafeEntityUrl } from '../_shared/is-safe-url';\n\n// Back-compat alias — the URL guard now lives in the shared entity-card\n// helper. Existing consumers (and this dir's tests) import isSafeMessageUrl.\nexport { isSafeEntityUrl as isSafeMessageUrl } from '../_shared/is-safe-url';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface MessageSender {\n /** Display name — drives the avatar's deterministic colour + initials. */\n name: string;\n /** Optional avatar image URL. */\n avatarUrl?: string;\n}\n\nexport interface MessageItem {\n /** Unique identifier for the message (or thread). */\n id: string;\n /** Sender identity — avatar + bold display name. */\n sender: MessageSender;\n /** Optional subject / conversation title. Rendered bold when unread. */\n subject?: string;\n /** Last-message preview — rendered as plain text, clamped to two lines. */\n preview: string;\n /** ISO-8601 timestamp of when the message was sent. */\n sentAt: string;\n /** Whether the message has been seen. Unread items get accent styling. */\n read?: boolean;\n /** Optional deep link — when present the card row is an anchor. */\n url?: string;\n /**\n * Count of unread messages inside a thread. Rendered as an end-aligned\n * badge when greater than 1.\n */\n unreadCount?: number;\n}\n\nexport interface MessageCardProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onClick' | 'role' | 'title'>,\n VariantProps<typeof cardVariants> {\n /** The message to render. */\n item: MessageItem;\n /**\n * Layout shape.\n * - `compact` — single-line row with the whole card clickable (used by\n * MessageTray).\n * - `dashboard` — bordered block with explicit CTA and mark-as-read\n * controls (used by dashboards / sidebars).\n */\n variant?: 'compact' | 'dashboard';\n /**\n * Fires when the read/unread status ball (the corner badge on the avatar) is\n * activated. Supply to make the ball an interactive toggle; omit and it\n * renders as a static read-state indicator.\n */\n onToggleRead?: (item: MessageItem) => void;\n /**\n * Row chrome for the `compact` variant (ignored for `dashboard`). `'flat'`\n * (default) — chrome-less row inside a bordered tray. `'elevated'` — own\n * card chrome (border + `--shadow-sm`), matching `AppointmentCard` /\n * `ClinicalNoteCard` for rail feeds (e.g. the Inbox).\n */\n surface?: 'flat' | 'elevated';\n /** Visual density. */\n size?: 'sm' | 'md';\n /** Fires when the row / title is activated. */\n onActivate?: (item: MessageItem) => void;\n /** Fires when the dismiss control is activated. */\n onDismiss?: (item: MessageItem) => void;\n /**\n * Label for the dashboard-variant CTA. Only rendered when `variant` is\n * `'dashboard'` and the item has a `url`.\n */\n ctaLabel?: string;\n /**\n * Label for the dashboard-variant mark-as-read link. Only rendered when\n * `variant` is `'dashboard'` and `onDismiss` is supplied.\n */\n dismissLabel?: string;\n /**\n * External exit-animation control. When supplied the card plays its\n * fade-out when this turns `true` and the consumer owns the subsequent\n * unmount (see MessageTray). If omitted, the card self-manages the\n * exit on internal dismiss.\n */\n leaving?: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst cardVariants = cva(\n [\n 'ds:relative ds:flex ds:gap-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:transition-colors',\n 'ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:slide-in-from-top-2 ds:motion-safe:duration-[var(--animation-duration)]',\n 'ds:data-[leaving=true]:motion-safe:animate-out ds:data-[leaving=true]:motion-safe:fade-out-0 ds:data-[leaving=true]:motion-safe:slide-out-to-top-2',\n 'ds:data-[leaving=true]:motion-safe:fill-mode-forwards',\n 'ds:data-[leaving=true]:pointer-events-none',\n 'ds:motion-reduce:transition-none',\n 'ds:text-start',\n // Compact rows are borderless (flat list — the rail / tray panel is the\n // frame), matching NotificationCard so a mixed inbox feed reads as one\n // flat list; the dashboard variant adds its own card border below.\n // Forced-colors keeps a border on both so rows stay separated in HCM.\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n variant: {\n // Flat rows by default; the accessible (AAA) theme restores a hairline\n // row divider so consecutive rows keep a visible boundary (see the\n // compact + flat compound below).\n compact: 'ds:items-start ds:group',\n dashboard:\n 'ds:flex-col ds:sm:flex-row ds:items-stretch ds:sm:items-start ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)] ds:shadow-[var(--shadow-card)] ds:bg-[color:var(--card)]',\n },\n size: {\n sm: 'ds:p-[var(--spacing-sm)]',\n md: 'ds:p-[var(--spacing-md)]',\n },\n state: {\n unread: '',\n read: 'ds:bg-transparent',\n },\n // Compact-row chrome: flat (tray) vs elevated (own card on a rail).\n // Mirrors AppointmentCard / NotificationCard so a rail feed of mixed\n // cards reads consistently.\n surface: {\n flat: '',\n elevated:\n 'ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)] ds:shadow-[var(--shadow-sm)]',\n },\n },\n compoundVariants: [\n // Compact rows no longer tint the background for unread — the read state\n // is carried by the avatar's corner status ball instead.\n {\n variant: 'compact',\n state: 'unread',\n class: 'ds:hover:bg-[color:var(--muted)]/40',\n },\n {\n variant: 'compact',\n state: 'read',\n class: 'ds:hover:bg-[color:var(--muted)]/40',\n },\n {\n variant: 'dashboard',\n state: 'unread',\n class: 'ds:bg-[color:var(--accent)]/5',\n },\n // The accessible-only row divider. --accessible-edge-width is 0\n // outside the accessible themes. An elevated row has its own edge.\n {\n variant: 'compact',\n surface: 'flat',\n class:\n 'ds:[:where(&)]:border-b-[length:var(--accessible-edge-width,0px)] ds:border-b-[color:var(--card-border)]',\n },\n ],\n defaultVariants: {\n variant: 'compact',\n size: 'sm',\n state: 'read',\n surface: 'flat',\n },\n },\n);\n\nconst stretchedLinkClass = [\n 'ds:focus-visible:outline-none',\n \"ds:after:content-[''] ds:after:absolute ds:after:inset-0 ds:after:rounded-[var(--radius-sm)]\",\n 'ds:after:pointer-events-auto',\n 'ds:focus-visible:after:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:after:outline-solid',\n 'ds:focus-visible:after:outline-[color:var(--ring)]',\n 'ds:focus-visible:after:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:after:outline-[CanvasText]',\n].join(' ');\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const MessageCard = forwardRef<HTMLDivElement, MessageCardProps>(\n (\n {\n item,\n variant = 'compact',\n surface = 'flat',\n size = 'sm',\n onActivate,\n onToggleRead,\n onDismiss,\n ctaLabel,\n dismissLabel,\n leaving,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n\n const accessibleTime = useMemo(() => {\n const date = new Date(item.sentAt);\n if (Number.isNaN(date.getTime())) return '';\n return new Intl.DateTimeFormat(i18n.language, {\n dateStyle: 'medium',\n timeStyle: 'short',\n }).format(date);\n }, [item.sentAt, i18n.language]);\n\n const isControlledLeaving = leaving !== undefined;\n const [isLeaving, setIsLeaving] = useState(false);\n const dismissTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const effectiveLeaving = isControlledLeaving ? leaving : isLeaving;\n\n const prefersReducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const handleDismiss = useCallback(\n (event?: React.MouseEvent) => {\n // The card carries a stretched-link `::after` overlay for the\n // whole-row click target. The dismiss button is rendered above it\n // (z-index), but click events still bubble — stop propagation so the\n // wrapper's navigation does not fire alongside the dismiss action.\n event?.preventDefault();\n event?.stopPropagation();\n if (!onDismiss) return;\n if (isControlledLeaving || prefersReducedMotion) {\n onDismiss(item);\n return;\n }\n setIsLeaving(true);\n if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);\n const raw =\n (typeof window !== 'undefined' &&\n window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration')) ||\n '200ms';\n const ms = raw.trim().endsWith('ms')\n ? parseFloat(raw)\n : parseFloat(raw) * 1000;\n dismissTimerRef.current = setTimeout(\n () => onDismiss(item),\n Number.isFinite(ms) ? ms : 200,\n );\n },\n [onDismiss, item, isControlledLeaving, prefersReducedMotion],\n );\n\n const state = item.read ? 'read' : 'unread';\n\n const unreadSuffix = item.read\n ? ''\n : t('messageCard.unreadSuffix', ', unread');\n const subjectFragment = item.subject\n ? t('messageCard.subjectFragment', {\n subject: item.subject,\n defaultValue: ' — {{subject}}',\n })\n : '';\n const ariaLabel = t('messageCard.itemLabel', {\n sender: item.sender.name,\n subjectFragment,\n time: accessibleTime,\n unreadSuffix,\n defaultValue:\n 'Message from {{sender}}{{subjectFragment}}, {{time}}{{unreadSuffix}}',\n });\n\n const hasSafeUrl = !!item.url && isSafeEntityUrl(item.url);\n\n /* ------- Sender-name rendering (stretched link in compact mode) ------ */\n\n const senderText = (\n <span\n className={[\n 'ds:flex-1 ds:min-w-0 ds:truncate',\n item.read ? 'ds:font-normal' : 'ds:font-semibold',\n ].join(' ')}\n >\n {item.sender.name}\n </span>\n );\n\n let senderNode: ReactNode;\n if (variant === 'compact' && hasSafeUrl && onActivate) {\n senderNode = (\n <a\n href={item.url}\n aria-label={ariaLabel}\n className={stretchedLinkClass + ' ds:contents'}\n onClick={(event) => {\n // Let the browser handle modifier-click (open in new tab,\n // download, etc.) and respect upstream preventDefault.\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n // When the consumer wires `onActivate`, they own routing — stop\n // the browser's default navigation so we don't full-page reload\n // out of an SPA shell or a test iframe.\n event.preventDefault();\n onActivate(item);\n }}\n >\n {senderText}\n </a>\n );\n } else if (variant === 'compact' && onActivate) {\n senderNode = (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n className={\n stretchedLinkClass +\n ' ds:contents ds:bg-transparent ds:border-0 ds:p-0'\n }\n onClick={() => onActivate(item)}\n >\n {senderText}\n </button>\n );\n } else if (variant === 'dashboard' && hasSafeUrl && onActivate) {\n senderNode = (\n <a\n href={item.url}\n className=\"ds:text-[color:var(--foreground)] ds:no-underline ds:hover:underline ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]\"\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n onActivate(item);\n }}\n >\n {senderText}\n </a>\n );\n } else {\n senderNode = senderText;\n }\n\n const showThreadCount =\n typeof item.unreadCount === 'number' && item.unreadCount > 1;\n\n const threadCountLabel = t('messageCard.threadCount', {\n count: item.unreadCount,\n defaultValue_one: '{{count}} new message in thread',\n defaultValue_other: '{{count}} new messages in thread',\n });\n\n // Dashboard variant keeps its inline title-row count badge.\n const threadCountBadge = showThreadCount ? (\n <span\n role=\"img\"\n aria-label={threadCountLabel}\n className=\"ds:relative ds:z-[1] ds:shrink-0 ds:inline-flex ds:items-center ds:justify-center ds:min-w-[calc(var(--spacing-md)+var(--spacing-xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-xs))] ds:ps-[calc(var(--spacing-xs)/1.5)] ds:pe-[calc(var(--spacing-xs)/1.5)] ds:rounded-[var(--radius-full)] ds:border ds:border-[color:color-mix(in_srgb,var(--foreground)_15%,transparent)] ds:bg-[color:var(--accent)] ds:text-[color:var(--accent-foreground)] ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]\"\n >\n {item.unreadCount}\n </span>\n ) : null;\n\n // Compact \"status ball\" — a corner badge on the avatar carrying read/unread\n // (and the thread count). It replaces the old inline Mail toggle so a\n // variable-width indicator no longer ragged-edges the sender titles.\n const ballPos =\n 'ds:absolute ds:top-[calc(var(--spacing-xs)*-1)] ds:end-[calc(var(--spacing-xs)*-1)] ds:z-[1]';\n const ballDot =\n 'ds:block ds:size-[calc(var(--spacing-sm)+var(--spacing-xs))] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--primary)] ds:ring-2 ds:ring-[color:var(--card)] ds:forced-colors:bg-[Highlight]';\n const ballRing =\n 'ds:block ds:size-[calc(var(--spacing-sm)+var(--spacing-xs))] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--card)] ds:border-2 ds:border-[color:color-mix(in_srgb,var(--muted-foreground)_55%,transparent)] ds:forced-colors:border-[CanvasText]';\n const ballNum =\n 'ds:inline-flex ds:items-center ds:justify-center ds:min-w-[calc(var(--spacing-md)+var(--spacing-2xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-2xs))] ds:px-[var(--spacing-2xs)] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--primary)] ds:text-[color:var(--primary-foreground)] ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none ds:ring-2 ds:ring-[color:var(--card)] ds:forced-colors:bg-[Highlight] ds:forced-colors:text-[CanvasText]';\n\n // Interactive ball gets the kit focus ring + pointer cursor (a bare\n // <button> falls back to the browser default outline). The transparent\n // ::before grows the touch target to --min-target-size on coarse pointers\n // (matches IconButton) while the visual ball stays small; dropped at sm+.\n const ballBtn =\n 'ds:cursor-pointer ds:outline-none ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)] ds:forced-colors:focus-visible:outline-[CanvasText] ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:hidden';\n const ballNumbered = !item.read && showThreadCount;\n const ballVisual = item.read ? ballRing : ballNumbered ? ballNum : ballDot;\n const statusBall =\n variant !== 'compact' ? null : onToggleRead ? (\n <button\n type=\"button\"\n onClick={() => onToggleRead(item)}\n aria-label={\n item.read\n ? t('messageCard.markAsUnread', 'Mark as unread')\n : ballNumbered\n ? `${threadCountLabel}, ${t('messageCard.markAsRead', 'Mark as read')}`\n : t('messageCard.markAsRead', 'Mark as read')\n }\n className={`${ballPos} ${ballVisual} ${ballBtn}`}\n >\n {ballNumbered ? (\n <span aria-hidden=\"true\">{item.unreadCount}</span>\n ) : null}\n </button>\n ) : ballNumbered ? (\n <span\n role=\"img\"\n aria-label={threadCountLabel}\n className={`${ballPos} ${ballNum}`}\n >\n <span aria-hidden=\"true\">{item.unreadCount}</span>\n </span>\n ) : (\n <span aria-hidden=\"true\" className={`${ballPos} ${ballVisual}`} />\n );\n\n // Close insets track the card padding so it aligns with the title's first\n // line at either size.\n const closeInset =\n size === 'md'\n ? 'ds:top-[var(--spacing-md)] ds:end-[var(--spacing-md)]'\n : 'ds:top-[var(--spacing-sm)] ds:end-[var(--spacing-sm)]';\n\n return (\n <div\n ref={ref}\n role=\"listitem\"\n data-component=\"message-card\"\n data-component-id={item.id}\n data-read={item.read ? 'true' : 'false'}\n data-leaving={effectiveLeaving ? 'true' : undefined}\n aria-hidden={effectiveLeaving || undefined}\n className={cardVariants({\n variant,\n size,\n state,\n surface: variant === 'compact' ? surface : 'flat',\n className,\n })}\n {...rest}\n >\n {/* Avatar is decorative here — the row's assembled `aria-label`\n already names the sender, so letting Avatar contribute its own\n `role=\"img\"` + `aria-label={name}` would announce the name twice\n per row. `aria-hidden` + `role=\"presentation\"` (spread last, so\n they win over Avatar's internal values) pulls the element out of\n the a11y tree entirely. */}\n {/* Avatar is decorative (the row's aria-label names the sender). The\n status ball overlays its corner; `relative` anchors it. */}\n <span className=\"ds:relative ds:shrink-0\">\n <Avatar\n name={item.sender.name}\n src={item.sender.avatarUrl}\n size={size === 'md' ? 'md' : 'sm'}\n aria-hidden=\"true\"\n role=\"presentation\"\n aria-label={undefined}\n />\n {statusBall}\n </span>\n\n <div className=\"ds:flex-1 ds:min-w-0 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n {variant === 'dashboard' ? (\n <h3 className=\"ds:m-0 ds:flex-1 ds:min-w-0 type-title-item\">\n {senderNode}\n </h3>\n ) : (\n <span className=\"ds:flex-1 ds:min-w-0 type-title-item ds:text-[color:var(--foreground)]\">\n {senderNode}\n </span>\n )}\n {variant === 'dashboard' ? threadCountBadge : null}\n </div>\n\n {item.subject ? (\n <p\n className={[\n 'ds:m-0 type-body-sm ds:text-[color:var(--foreground)] ds:truncate',\n item.read ? 'ds:font-normal' : 'ds:font-semibold',\n ].join(' ')}\n >\n {item.subject}\n </p>\n ) : null}\n\n <p className=\"ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)] ds:[overflow:hidden] ds:[display:-webkit-box] ds:[-webkit-box-orient:vertical] ds:[-webkit-line-clamp:2] ds:break-words\">\n {item.preview}\n </p>\n\n <Timestamp\n value={item.sentAt}\n shape=\"chip\"\n size=\"sm\"\n relativeWindow={12 * 60 * 60 * 1000}\n />\n\n {variant === 'dashboard' && (ctaLabel || dismissLabel) ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {ctaLabel && hasSafeUrl ? (\n <Button\n intent=\"outline\"\n size=\"sm\"\n asChild\n className=\"ds:relative ds:z-[1]\"\n >\n <a\n href={item.url}\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n onActivate?.(item);\n }}\n >\n {ctaLabel}\n </a>\n </Button>\n ) : null}\n {dismissLabel && onDismiss ? (\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={handleDismiss}\n className=\"ds:relative ds:z-[1]\"\n >\n {dismissLabel}\n </Button>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {/* Close — inline-end, hover/focus-revealed. Absolutely positioned so it\n claims no width at rest: the sender row fills the width and there's\n no empty gap when the row isn't hovered. */}\n {variant === 'compact' && onDismiss ? (\n <span\n className={\n 'ds:absolute ds:z-[2] ds:opacity-0 ds:pointer-events-none ds:transition-opacity ds:motion-reduce:transition-none ds:group-hover:opacity-100 ds:group-hover:pointer-events-auto ds:group-focus-within:opacity-100 ds:group-focus-within:pointer-events-auto ' +\n closeInset\n }\n >\n <IconButton\n icon={<X />}\n intent=\"ghost\"\n size=\"sm\"\n aria-label={t('messageCard.dismiss', 'Dismiss message')}\n onClick={handleDismiss}\n />\n </span>\n ) : null}\n </div>\n );\n },\n);\n\nMessageCard.displayName = 'MessageCard';\n"],"names":["cardVariants","cva","stretchedLinkClass","MessageCard","forwardRef","item","variant","surface","size","onActivate","onToggleRead","onDismiss","ctaLabel","dismissLabel","leaving","className","rest","ref","t","i18n","useTranslation","accessibleTime","useMemo","date","isControlledLeaving","isLeaving","setIsLeaving","useState","dismissTimerRef","useRef","effectiveLeaving","prefersReducedMotion","handleDismiss","useCallback","event","raw","ms","state","unreadSuffix","subjectFragment","ariaLabel","hasSafeUrl","isSafeEntityUrl","senderText","jsx","senderNode","showThreadCount","threadCountLabel","threadCountBadge","ballPos","ballDot","ballRing","ballNum","ballBtn","ballNumbered","ballVisual","statusBall","closeInset","jsxs","Avatar","Timestamp","Button","IconButton","X"],"mappings":"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"}
1
+ {"version":3,"file":"message-card-B6SduXJv.js","sources":["../../src/components/message-card/message-card.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { X } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Button } from '../button/button';\nimport { Avatar } from '../avatar/avatar';\nimport { Timestamp } from '../timestamp';\nimport { isSafeEntityUrl } from '../_shared/is-safe-url';\n\n// Back-compat alias — the URL guard now lives in the shared entity-card\n// helper. Existing consumers (and this dir's tests) import isSafeMessageUrl.\nexport { isSafeEntityUrl as isSafeMessageUrl } from '../_shared/is-safe-url';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface MessageSender {\n /** Display name — drives the avatar's deterministic colour + initials. */\n name: string;\n /** Optional avatar image URL. */\n avatarUrl?: string;\n}\n\nexport interface MessageItem {\n /** Unique identifier for the message (or thread). */\n id: string;\n /** Sender identity — avatar + bold display name. */\n sender: MessageSender;\n /** Optional subject / conversation title. Rendered bold when unread. */\n subject?: string;\n /** Last-message preview — rendered as plain text, clamped to two lines. */\n preview: string;\n /** ISO-8601 timestamp of when the message was sent. */\n sentAt: string;\n /** Whether the message has been seen. Unread items get accent styling. */\n read?: boolean;\n /** Optional deep link — when present the card row is an anchor. */\n url?: string;\n /**\n * Count of unread messages inside a thread. Rendered as an end-aligned\n * badge when greater than 1.\n */\n unreadCount?: number;\n}\n\nexport interface MessageCardProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onClick' | 'role' | 'title'>,\n VariantProps<typeof cardVariants> {\n /** The message to render. */\n item: MessageItem;\n /**\n * Layout shape.\n * - `compact` — single-line row with the whole card clickable (used by\n * MessageTray).\n * - `dashboard` — bordered block with explicit CTA and mark-as-read\n * controls (used by dashboards / sidebars).\n */\n variant?: 'compact' | 'dashboard';\n /**\n * Fires when the read/unread status ball (the corner badge on the avatar) is\n * activated. Supply to make the ball an interactive toggle; omit and it\n * renders as a static read-state indicator.\n */\n onToggleRead?: (item: MessageItem) => void;\n /**\n * Row chrome for the `compact` variant (ignored for `dashboard`). `'flat'`\n * (default) — chrome-less row inside a bordered tray. `'elevated'` — own\n * card chrome (border + `--shadow-sm`), matching `AppointmentCard` /\n * `ClinicalNoteCard` for rail feeds (e.g. the Inbox).\n */\n surface?: 'flat' | 'elevated';\n /** Visual density. */\n size?: 'sm' | 'md';\n /** Fires when the row / title is activated. */\n onActivate?: (item: MessageItem) => void;\n /** Fires when the dismiss control is activated. */\n onDismiss?: (item: MessageItem) => void;\n /**\n * Label for the dashboard-variant CTA. Only rendered when `variant` is\n * `'dashboard'` and the item has a `url`.\n */\n ctaLabel?: string;\n /**\n * Label for the dashboard-variant mark-as-read link. Only rendered when\n * `variant` is `'dashboard'` and `onDismiss` is supplied.\n */\n dismissLabel?: string;\n /**\n * External exit-animation control. When supplied the card plays its\n * fade-out when this turns `true` and the consumer owns the subsequent\n * unmount (see MessageTray). If omitted, the card self-manages the\n * exit on internal dismiss.\n */\n leaving?: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst cardVariants = cva(\n [\n 'ds:relative ds:flex ds:gap-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:transition-colors',\n 'ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:slide-in-from-top-2 ds:motion-safe:duration-[var(--animation-duration)]',\n 'ds:data-[leaving=true]:motion-safe:animate-out ds:data-[leaving=true]:motion-safe:fade-out-0 ds:data-[leaving=true]:motion-safe:slide-out-to-top-2',\n 'ds:data-[leaving=true]:motion-safe:fill-mode-forwards',\n 'ds:data-[leaving=true]:pointer-events-none',\n 'ds:motion-reduce:transition-none',\n 'ds:text-start',\n // Compact rows are borderless (flat list — the rail / tray panel is the\n // frame), matching NotificationCard so a mixed inbox feed reads as one\n // flat list; the dashboard variant adds its own card border below.\n // Forced-colors keeps a border on both so rows stay separated in HCM.\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n variant: {\n // Flat rows by default; the accessible (AAA) theme restores a hairline\n // row divider so consecutive rows keep a visible boundary (see the\n // compact + flat compound below).\n compact: 'ds:items-start ds:group',\n dashboard:\n 'ds:flex-col ds:sm:flex-row ds:items-stretch ds:sm:items-start ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)] ds:shadow-[var(--shadow-card)] ds:bg-[color:var(--card)]',\n },\n size: {\n sm: 'ds:p-[var(--spacing-sm)]',\n md: 'ds:p-[var(--spacing-md)]',\n },\n state: {\n unread: '',\n read: 'ds:bg-transparent',\n },\n // Compact-row chrome: flat (tray) vs elevated (own card on a rail).\n // Mirrors AppointmentCard / NotificationCard so a rail feed of mixed\n // cards reads consistently.\n surface: {\n flat: '',\n elevated:\n 'ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)] ds:shadow-[var(--shadow-sm)]',\n },\n },\n compoundVariants: [\n // Compact rows no longer tint the background for unread — the read state\n // is carried by the avatar's corner status ball instead.\n {\n variant: 'compact',\n state: 'unread',\n class: 'ds:hover:bg-[color:var(--muted)]/40',\n },\n {\n variant: 'compact',\n state: 'read',\n class: 'ds:hover:bg-[color:var(--muted)]/40',\n },\n {\n variant: 'dashboard',\n state: 'unread',\n class: 'ds:bg-[color:var(--accent)]/5',\n },\n // The accessible-only row divider. --accessible-edge-width is 0\n // outside the accessible themes. An elevated row has its own edge.\n {\n variant: 'compact',\n surface: 'flat',\n class:\n 'ds:[:where(&)]:border-b-[length:var(--accessible-edge-width,0px)] ds:border-b-[color:var(--card-border)]',\n },\n ],\n defaultVariants: {\n variant: 'compact',\n size: 'sm',\n state: 'read',\n surface: 'flat',\n },\n },\n);\n\nconst stretchedLinkClass = [\n 'ds:focus-visible:outline-none',\n \"ds:after:content-[''] ds:after:absolute ds:after:inset-0 ds:after:rounded-[var(--radius-sm)]\",\n 'ds:after:pointer-events-auto',\n 'ds:focus-visible:after:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:after:outline-solid',\n 'ds:focus-visible:after:outline-[color:var(--ring)]',\n 'ds:focus-visible:after:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:after:outline-[CanvasText]',\n].join(' ');\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const MessageCard = forwardRef<HTMLDivElement, MessageCardProps>(\n (\n {\n item,\n variant = 'compact',\n surface = 'flat',\n size = 'sm',\n onActivate,\n onToggleRead,\n onDismiss,\n ctaLabel,\n dismissLabel,\n leaving,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n\n const accessibleTime = useMemo(() => {\n const date = new Date(item.sentAt);\n if (Number.isNaN(date.getTime())) return '';\n return new Intl.DateTimeFormat(i18n.language, {\n dateStyle: 'medium',\n timeStyle: 'short',\n }).format(date);\n }, [item.sentAt, i18n.language]);\n\n const isControlledLeaving = leaving !== undefined;\n const [isLeaving, setIsLeaving] = useState(false);\n const dismissTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const effectiveLeaving = isControlledLeaving ? leaving : isLeaving;\n\n const prefersReducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const handleDismiss = useCallback(\n (event?: React.MouseEvent) => {\n // The card carries a stretched-link `::after` overlay for the\n // whole-row click target. The dismiss button is rendered above it\n // (z-index), but click events still bubble — stop propagation so the\n // wrapper's navigation does not fire alongside the dismiss action.\n event?.preventDefault();\n event?.stopPropagation();\n if (!onDismiss) return;\n if (isControlledLeaving || prefersReducedMotion) {\n onDismiss(item);\n return;\n }\n setIsLeaving(true);\n if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);\n const raw =\n (typeof window !== 'undefined' &&\n window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration')) ||\n '200ms';\n const ms = raw.trim().endsWith('ms')\n ? parseFloat(raw)\n : parseFloat(raw) * 1000;\n dismissTimerRef.current = setTimeout(\n () => onDismiss(item),\n Number.isFinite(ms) ? ms : 200,\n );\n },\n [onDismiss, item, isControlledLeaving, prefersReducedMotion],\n );\n\n const state = item.read ? 'read' : 'unread';\n\n const unreadSuffix = item.read\n ? ''\n : t('messageCard.unreadSuffix', ', unread');\n const subjectFragment = item.subject\n ? t('messageCard.subjectFragment', {\n subject: item.subject,\n defaultValue: ' — {{subject}}',\n })\n : '';\n const ariaLabel = t('messageCard.itemLabel', {\n sender: item.sender.name,\n subjectFragment,\n time: accessibleTime,\n unreadSuffix,\n defaultValue:\n 'Message from {{sender}}{{subjectFragment}}, {{time}}{{unreadSuffix}}',\n });\n\n const hasSafeUrl = !!item.url && isSafeEntityUrl(item.url);\n\n /* ------- Sender-name rendering (stretched link in compact mode) ------ */\n\n const senderText = (\n <span\n className={[\n 'ds:flex-1 ds:min-w-0 ds:truncate',\n item.read ? 'ds:font-normal' : 'ds:font-semibold',\n ].join(' ')}\n >\n {item.sender.name}\n </span>\n );\n\n let senderNode: ReactNode;\n if (variant === 'compact' && hasSafeUrl && onActivate) {\n senderNode = (\n <a\n href={item.url}\n aria-label={ariaLabel}\n className={stretchedLinkClass + ' ds:contents'}\n onClick={(event) => {\n // Let the browser handle modifier-click (open in new tab,\n // download, etc.) and respect upstream preventDefault.\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n // When the consumer wires `onActivate`, they own routing — stop\n // the browser's default navigation so we don't full-page reload\n // out of an SPA shell or a test iframe.\n event.preventDefault();\n onActivate(item);\n }}\n >\n {senderText}\n </a>\n );\n } else if (variant === 'compact' && onActivate) {\n senderNode = (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n className={\n stretchedLinkClass +\n ' ds:contents ds:bg-transparent ds:border-0 ds:p-0'\n }\n onClick={() => onActivate(item)}\n >\n {senderText}\n </button>\n );\n } else if (variant === 'dashboard' && hasSafeUrl && onActivate) {\n senderNode = (\n <a\n href={item.url}\n className=\"ds:text-[color:var(--foreground)] ds:no-underline ds:hover:underline ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]\"\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n onActivate(item);\n }}\n >\n {senderText}\n </a>\n );\n } else {\n senderNode = senderText;\n }\n\n const showThreadCount =\n typeof item.unreadCount === 'number' && item.unreadCount > 1;\n\n const threadCountLabel = t('messageCard.threadCount', {\n count: item.unreadCount,\n defaultValue_one: '{{count}} new message in thread',\n defaultValue_other: '{{count}} new messages in thread',\n });\n\n // Dashboard variant keeps its inline title-row count badge.\n const threadCountBadge = showThreadCount ? (\n <span\n role=\"img\"\n aria-label={threadCountLabel}\n className=\"ds:relative ds:z-[1] ds:shrink-0 ds:inline-flex ds:items-center ds:justify-center ds:min-w-[calc(var(--spacing-md)+var(--spacing-xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-xs))] ds:ps-[calc(var(--spacing-xs)/1.5)] ds:pe-[calc(var(--spacing-xs)/1.5)] ds:rounded-[var(--radius-full)] ds:border ds:border-[color:color-mix(in_srgb,var(--foreground)_15%,transparent)] ds:bg-[color:var(--accent)] ds:text-[color:var(--accent-foreground)] ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]\"\n >\n {item.unreadCount}\n </span>\n ) : null;\n\n // Compact \"status ball\" — a corner badge on the avatar carrying read/unread\n // (and the thread count). It replaces the old inline Mail toggle so a\n // variable-width indicator no longer ragged-edges the sender titles.\n const ballPos =\n 'ds:absolute ds:top-[calc(var(--spacing-xs)*-1)] ds:end-[calc(var(--spacing-xs)*-1)] ds:z-[1]';\n const ballDot =\n 'ds:block ds:size-[calc(var(--spacing-sm)+var(--spacing-xs))] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--primary)] ds:ring-2 ds:ring-[color:var(--card)] ds:forced-colors:bg-[Highlight]';\n const ballRing =\n 'ds:block ds:size-[calc(var(--spacing-sm)+var(--spacing-xs))] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--card)] ds:border-2 ds:border-[color:color-mix(in_srgb,var(--muted-foreground)_55%,transparent)] ds:forced-colors:border-[CanvasText]';\n const ballNum =\n 'ds:inline-flex ds:items-center ds:justify-center ds:min-w-[calc(var(--spacing-md)+var(--spacing-2xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-2xs))] ds:px-[var(--spacing-2xs)] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--primary)] ds:text-[color:var(--primary-foreground)] ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none ds:ring-2 ds:ring-[color:var(--card)] ds:forced-colors:bg-[Highlight] ds:forced-colors:text-[CanvasText]';\n\n // Interactive ball gets the kit focus ring + pointer cursor (a bare\n // <button> falls back to the browser default outline). The transparent\n // ::before grows the touch target to --min-target-size on coarse pointers\n // (matches IconButton) while the visual ball stays small; dropped at sm+.\n const ballBtn =\n 'ds:cursor-pointer ds:outline-none ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)] ds:forced-colors:focus-visible:outline-[CanvasText] ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:hidden';\n const ballNumbered = !item.read && showThreadCount;\n const ballVisual = item.read ? ballRing : ballNumbered ? ballNum : ballDot;\n const statusBall =\n variant !== 'compact' ? null : onToggleRead ? (\n <button\n type=\"button\"\n onClick={() => onToggleRead(item)}\n aria-label={\n item.read\n ? t('messageCard.markAsUnread', 'Mark as unread')\n : ballNumbered\n ? `${threadCountLabel}, ${t('messageCard.markAsRead', 'Mark as read')}`\n : t('messageCard.markAsRead', 'Mark as read')\n }\n className={`${ballPos} ${ballVisual} ${ballBtn}`}\n >\n {ballNumbered ? (\n <span aria-hidden=\"true\">{item.unreadCount}</span>\n ) : null}\n </button>\n ) : ballNumbered ? (\n <span\n role=\"img\"\n aria-label={threadCountLabel}\n className={`${ballPos} ${ballNum}`}\n >\n <span aria-hidden=\"true\">{item.unreadCount}</span>\n </span>\n ) : (\n <span aria-hidden=\"true\" className={`${ballPos} ${ballVisual}`} />\n );\n\n // Close insets track the card padding so it aligns with the title's first\n // line at either size.\n const closeInset =\n size === 'md'\n ? 'ds:top-[var(--spacing-md)] ds:end-[var(--spacing-md)]'\n : 'ds:top-[var(--spacing-sm)] ds:end-[var(--spacing-sm)]';\n\n return (\n <div\n ref={ref}\n role=\"listitem\"\n data-component=\"message-card\"\n data-component-id={item.id}\n data-read={item.read ? 'true' : 'false'}\n data-leaving={effectiveLeaving ? 'true' : undefined}\n aria-hidden={effectiveLeaving || undefined}\n className={cardVariants({\n variant,\n size,\n state,\n surface: variant === 'compact' ? surface : 'flat',\n className,\n })}\n {...rest}\n >\n {/* Avatar is decorative here — the row's assembled `aria-label`\n already names the sender, so letting Avatar contribute its own\n `role=\"img\"` + `aria-label={name}` would announce the name twice\n per row. `aria-hidden` + `role=\"presentation\"` (spread last, so\n they win over Avatar's internal values) pulls the element out of\n the a11y tree entirely. */}\n {/* Avatar is decorative (the row's aria-label names the sender). The\n status ball overlays its corner; `relative` anchors it. */}\n <span className=\"ds:relative ds:shrink-0\">\n <Avatar\n name={item.sender.name}\n src={item.sender.avatarUrl}\n size={size === 'md' ? 'md' : 'sm'}\n aria-hidden=\"true\"\n role=\"presentation\"\n aria-label={undefined}\n />\n {statusBall}\n </span>\n\n <div className=\"ds:flex-1 ds:min-w-0 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n {variant === 'dashboard' ? (\n <h3 className=\"ds:m-0 ds:flex-1 ds:min-w-0 type-title-item\">\n {senderNode}\n </h3>\n ) : (\n <span className=\"ds:flex-1 ds:min-w-0 type-title-item ds:text-[color:var(--foreground)]\">\n {senderNode}\n </span>\n )}\n {variant === 'dashboard' ? threadCountBadge : null}\n </div>\n\n {item.subject ? (\n <p\n className={[\n 'ds:m-0 type-body-sm ds:text-[color:var(--foreground)] ds:truncate',\n item.read ? 'ds:font-normal' : 'ds:font-semibold',\n ].join(' ')}\n >\n {item.subject}\n </p>\n ) : null}\n\n <p className=\"ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)] ds:[overflow:hidden] ds:[display:-webkit-box] ds:[-webkit-box-orient:vertical] ds:[-webkit-line-clamp:2] ds:break-words\">\n {item.preview}\n </p>\n\n <Timestamp\n value={item.sentAt}\n shape=\"chip\"\n size=\"sm\"\n relativeWindow={12 * 60 * 60 * 1000}\n />\n\n {variant === 'dashboard' && (ctaLabel || dismissLabel) ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {ctaLabel && hasSafeUrl ? (\n <Button\n intent=\"outline\"\n size=\"sm\"\n asChild\n className=\"ds:relative ds:z-[1]\"\n >\n <a\n href={item.url}\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n onActivate?.(item);\n }}\n >\n {ctaLabel}\n </a>\n </Button>\n ) : null}\n {dismissLabel && onDismiss ? (\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={handleDismiss}\n className=\"ds:relative ds:z-[1]\"\n >\n {dismissLabel}\n </Button>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {/* Close — inline-end, hover/focus-revealed. Absolutely positioned so it\n claims no width at rest: the sender row fills the width and there's\n no empty gap when the row isn't hovered. */}\n {variant === 'compact' && onDismiss ? (\n <span\n className={\n 'ds:absolute ds:z-[2] ds:opacity-0 ds:pointer-events-none ds:transition-opacity ds:motion-reduce:transition-none ds:group-hover:opacity-100 ds:group-hover:pointer-events-auto ds:group-focus-within:opacity-100 ds:group-focus-within:pointer-events-auto ' +\n closeInset\n }\n >\n <IconButton\n icon={<X />}\n intent=\"ghost\"\n size=\"sm\"\n aria-label={t('messageCard.dismiss', 'Dismiss message')}\n onClick={handleDismiss}\n />\n </span>\n ) : null}\n </div>\n );\n },\n);\n\nMessageCard.displayName = 'MessageCard';\n"],"names":["cardVariants","cva","stretchedLinkClass","MessageCard","forwardRef","item","variant","surface","size","onActivate","onToggleRead","onDismiss","ctaLabel","dismissLabel","leaving","className","rest","ref","t","i18n","useTranslation","accessibleTime","useMemo","date","isControlledLeaving","isLeaving","setIsLeaving","useState","dismissTimerRef","useRef","effectiveLeaving","prefersReducedMotion","handleDismiss","useCallback","event","raw","ms","state","unreadSuffix","subjectFragment","ariaLabel","hasSafeUrl","isSafeEntityUrl","senderText","jsx","senderNode","showThreadCount","threadCountLabel","threadCountBadge","ballPos","ballDot","ballRing","ballNum","ballBtn","ballNumbered","ballVisual","statusBall","closeInset","jsxs","Avatar","Timestamp","Button","IconButton","X"],"mappings":"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"}
@@ -11,7 +11,7 @@ import { B as L } from "./button-DohK_Ak_.js";
11
11
  import { S as F } from "./separator-CYU_bGFn.js";
12
12
  import { S as y } from "./skeleton-tTWJpvAq.js";
13
13
  import { S as fe } from "./scroll-area-CY5SLYNw.js";
14
- import { M as ve } from "./message-card-CvCnCssc.js";
14
+ import { M as ve } from "./message-card-B6SduXJv.js";
15
15
  import { u as he } from "./registry-DvAUVLHh.js";
16
16
  import { M as V } from "./mail-BqXVF2zH.js";
17
17
  const ye = {
@@ -498,4 +498,4 @@ export {
498
498
  Se as M,
499
499
  ye as m
500
500
  };
501
- //# sourceMappingURL=message-tray-IJYvy6Cf.js.map
501
+ //# sourceMappingURL=message-tray-Cllf-v0G.js.map