@alfadocs/ui-kit-debug 1.67.0 → 1.68.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 (499) hide show
  1. package/dist/_chunks/{address-fields-CJtu7LQU.js → address-fields-BUPRs3n-.js} +3 -3
  2. package/dist/_chunks/{address-fields-CJtu7LQU.js.map → address-fields-BUPRs3n-.js.map} +1 -1
  3. package/dist/_chunks/{agenda-card-DR9gDdKp.js → agenda-card-BDuvreCe.js} +2 -2
  4. package/dist/_chunks/{agenda-card-DR9gDdKp.js.map → agenda-card-BDuvreCe.js.map} +1 -1
  5. package/dist/_chunks/{agenda-tray-DGB1Zup-.js → agenda-tray-CfwylhWf.js} +3 -3
  6. package/dist/_chunks/{agenda-tray-DGB1Zup-.js.map → agenda-tray-CfwylhWf.js.map} +1 -1
  7. package/dist/_chunks/{ai-credits-exhausted-notice-DfAgfZDF.js → ai-credits-exhausted-notice-Bg8NpW2K.js} +2 -2
  8. package/dist/_chunks/{ai-credits-exhausted-notice-DfAgfZDF.js.map → ai-credits-exhausted-notice-Bg8NpW2K.js.map} +1 -1
  9. package/dist/_chunks/{ai-permission-notice-qsdm4Sx4.js → ai-permission-notice-C00i6VhY.js} +2 -2
  10. package/dist/_chunks/{ai-permission-notice-qsdm4Sx4.js.map → ai-permission-notice-C00i6VhY.js.map} +1 -1
  11. package/dist/_chunks/{ai-prompt-input-DSGSe4LH.js → ai-prompt-input-DzgyoKyk.js} +141 -139
  12. package/dist/_chunks/ai-prompt-input-DzgyoKyk.js.map +1 -0
  13. package/dist/_chunks/{alert-DjsJMGRE.js → alert-9kEwDza3.js} +122 -112
  14. package/dist/_chunks/alert-9kEwDza3.js.map +1 -0
  15. package/dist/_chunks/{alia-sidebar-qe0quZkB.js → alia-sidebar-B06ZSOaF.js} +3 -3
  16. package/dist/_chunks/{alia-sidebar-qe0quZkB.js.map → alia-sidebar-B06ZSOaF.js.map} +1 -1
  17. package/dist/_chunks/{anamnesis-summary-card-CMzBLTiN.js → anamnesis-summary-card-DQ3iE1gD.js} +2 -2
  18. package/dist/_chunks/{anamnesis-summary-card-CMzBLTiN.js.map → anamnesis-summary-card-DQ3iE1gD.js.map} +1 -1
  19. package/dist/_chunks/{anamnesis-summary-rows-BQ_EokKz.js → anamnesis-summary-rows-CNK0fIJk.js} +392 -388
  20. package/dist/_chunks/anamnesis-summary-rows-CNK0fIJk.js.map +1 -0
  21. package/dist/_chunks/{appointment-card-CL32sux-.js → appointment-card-5JMWi9_f.js} +2 -2
  22. package/dist/_chunks/{appointment-card-CL32sux-.js.map → appointment-card-5JMWi9_f.js.map} +1 -1
  23. package/dist/_chunks/{appointment-peek-B5mcDcXt.js → appointment-peek-D5XCfYKu.js} +2 -2
  24. package/dist/_chunks/{appointment-peek-B5mcDcXt.js.map → appointment-peek-D5XCfYKu.js.map} +1 -1
  25. package/dist/_chunks/{appointment-timeline-CCqjORFb.js → appointment-timeline-VFP6HoXT.js} +4 -4
  26. package/dist/_chunks/{appointment-timeline-CCqjORFb.js.map → appointment-timeline-VFP6HoXT.js.map} +1 -1
  27. package/dist/_chunks/{appointment-tray-qtpJt8e0.js → appointment-tray-B3PDER3I.js} +3 -3
  28. package/dist/_chunks/{appointment-tray-qtpJt8e0.js.map → appointment-tray-B3PDER3I.js.map} +1 -1
  29. package/dist/_chunks/{audio-recorder-B11RR-rC.js → audio-recorder-4Ll0pwYK.js} +3 -3
  30. package/dist/_chunks/{audio-recorder-B11RR-rC.js.map → audio-recorder-4Ll0pwYK.js.map} +1 -1
  31. package/dist/_chunks/{auth-form-parts-DwUTH6YN.js → auth-form-parts-B40zvD-a.js} +2 -2
  32. package/dist/_chunks/{auth-form-parts-DwUTH6YN.js.map → auth-form-parts-B40zvD-a.js.map} +1 -1
  33. package/dist/_chunks/avatar-BPiPL7ND.js +199 -0
  34. package/dist/_chunks/avatar-BPiPL7ND.js.map +1 -0
  35. package/dist/_chunks/{balance-badge-cell-DZNthHO1.js → balance-badge-cell-BG3DMly4.js} +4 -4
  36. package/dist/_chunks/{balance-badge-cell-DZNthHO1.js.map → balance-badge-cell-BG3DMly4.js.map} +1 -1
  37. package/dist/_chunks/{bishop-score-CaNTrikJ.js → bishop-score-Df8nF1qg.js} +2 -2
  38. package/dist/_chunks/{bishop-score-CaNTrikJ.js.map → bishop-score-Df8nF1qg.js.map} +1 -1
  39. package/dist/_chunks/{booking-tTVxKPQY.js → booking-B1pDbERi.js} +377 -335
  40. package/dist/_chunks/booking-B1pDbERi.js.map +1 -0
  41. package/dist/_chunks/{calendar-BhN-jisv.js → calendar-BvOM8rG3.js} +2 -2
  42. package/dist/_chunks/{calendar-BhN-jisv.js.map → calendar-BvOM8rG3.js.map} +1 -1
  43. package/dist/_chunks/{calendar-workspace-MRrzcxAy.js → calendar-workspace-CYK1M83j.js} +18 -18
  44. package/dist/_chunks/{calendar-workspace-MRrzcxAy.js.map → calendar-workspace-CYK1M83j.js.map} +1 -1
  45. package/dist/_chunks/{chat-message-fRLZ95O5.js → chat-message-Be-9vIIQ.js} +2 -2
  46. package/dist/_chunks/{chat-message-fRLZ95O5.js.map → chat-message-Be-9vIIQ.js.map} +1 -1
  47. package/dist/_chunks/{clinical-note-card-BnFTIs6x.js → clinical-note-card-Caidqcwa.js} +2 -2
  48. package/dist/_chunks/{clinical-note-card-BnFTIs6x.js.map → clinical-note-card-Caidqcwa.js.map} +1 -1
  49. package/dist/_chunks/{color-picker-BsggJovx.js → color-picker-AcaWuKah.js} +99 -95
  50. package/dist/_chunks/color-picker-AcaWuKah.js.map +1 -0
  51. package/dist/_chunks/{combobox-U5yfO6o0.js → combobox-vF9O-QoG.js} +92 -83
  52. package/dist/_chunks/combobox-vF9O-QoG.js.map +1 -0
  53. package/dist/_chunks/{contact-profile-card-C4-OCshj.js → contact-profile-card-CAwwOqHl.js} +40 -40
  54. package/dist/_chunks/contact-profile-card-CAwwOqHl.js.map +1 -0
  55. package/dist/_chunks/{control-room-rail-DUerqHeo.js → control-room-rail-BB6rCDWI.js} +3 -3
  56. package/dist/_chunks/{control-room-rail-DUerqHeo.js.map → control-room-rail-BB6rCDWI.js.map} +1 -1
  57. package/dist/_chunks/{country-select-DF5Bd_mn.js → country-select-CSE2Zm_s.js} +2 -2
  58. package/dist/_chunks/{country-select-DF5Bd_mn.js.map → country-select-CSE2Zm_s.js.map} +1 -1
  59. package/dist/_chunks/dashboard-grid-7JzaiKnk.js +1487 -0
  60. package/dist/_chunks/dashboard-grid-7JzaiKnk.js.map +1 -0
  61. package/dist/_chunks/{data-table-COoCQ4n_.js → data-table-Cty4-Jht.js} +3 -3
  62. package/dist/_chunks/{data-table-COoCQ4n_.js.map → data-table-Cty4-Jht.js.map} +1 -1
  63. package/dist/_chunks/{dependent-selector-DBr1AhLg.js → dependent-selector-C4kOgO8b.js} +2 -2
  64. package/dist/_chunks/{dependent-selector-DBr1AhLg.js.map → dependent-selector-C4kOgO8b.js.map} +1 -1
  65. package/dist/_chunks/{document-preview-VyQOjFVL.js → document-preview-513f3iPn.js} +4 -4
  66. package/dist/_chunks/{document-preview-VyQOjFVL.js.map → document-preview-513f3iPn.js.map} +1 -1
  67. package/dist/_chunks/{document-scanner-CXH_GYh4.js → document-scanner-Bd3wbzpI.js} +2 -2
  68. package/dist/_chunks/{document-scanner-CXH_GYh4.js.map → document-scanner-Bd3wbzpI.js.map} +1 -1
  69. package/dist/_chunks/{editable-description-ChGNdYY8.js → editable-description-DnAFi360.js} +2 -2
  70. package/dist/_chunks/{editable-description-ChGNdYY8.js.map → editable-description-DnAFi360.js.map} +1 -1
  71. package/dist/_chunks/{entity-summary-Bj-Wxq7Y.js → entity-summary-C2B8yNmc.js} +4 -4
  72. package/dist/_chunks/{entity-summary-Bj-Wxq7Y.js.map → entity-summary-C2B8yNmc.js.map} +1 -1
  73. package/dist/_chunks/{error-summary-PUE5Zxp9.js → error-summary-mGxIyDAY.js} +2 -2
  74. package/dist/_chunks/{error-summary-PUE5Zxp9.js.map → error-summary-mGxIyDAY.js.map} +1 -1
  75. package/dist/_chunks/{face-scheme-DAD-mXzM.js → face-scheme-CSJdRNad.js} +248 -244
  76. package/dist/_chunks/{face-scheme-DAD-mXzM.js.map → face-scheme-CSJdRNad.js.map} +1 -1
  77. package/dist/_chunks/{file-manager-RiV7-OEE.js → file-manager-D4cPnRhL.js} +3 -3
  78. package/dist/_chunks/{file-manager-RiV7-OEE.js.map → file-manager-D4cPnRhL.js.map} +1 -1
  79. package/dist/_chunks/{forgot-password-form-CPOfRE0C.js → forgot-password-form-Dqi7R-NL.js} +4 -4
  80. package/dist/_chunks/{forgot-password-form-CPOfRE0C.js.map → forgot-password-form-Dqi7R-NL.js.map} +1 -1
  81. package/dist/_chunks/format-number-DdzqwMs1.js +13 -0
  82. package/dist/_chunks/format-number-DdzqwMs1.js.map +1 -0
  83. package/dist/_chunks/{freemium-paywall-6DO7noHX.js → freemium-paywall-C73C8Rgd.js} +2 -2
  84. package/dist/_chunks/{freemium-paywall-6DO7noHX.js.map → freemium-paywall-C73C8Rgd.js.map} +1 -1
  85. package/dist/_chunks/{gestational-age-calculator-CZYa2D6m.js → gestational-age-calculator-Du53p8MH.js} +2 -2
  86. package/dist/_chunks/{gestational-age-calculator-CZYa2D6m.js.map → gestational-age-calculator-Du53p8MH.js.map} +1 -1
  87. package/dist/_chunks/{header-settings-BSH9Gk0J.js → header-settings-DlUbvAUx.js} +37 -36
  88. package/dist/_chunks/header-settings-DlUbvAUx.js.map +1 -0
  89. package/dist/_chunks/{heatmap-C1TeC7wT.js → heatmap-DbZIQg14.js} +4 -4
  90. package/dist/_chunks/{heatmap-C1TeC7wT.js.map → heatmap-DbZIQg14.js.map} +1 -1
  91. package/dist/_chunks/{help-me-write-templates-Bw3Q58x-.js → help-me-write-templates-5WkUfvc_.js} +3 -3
  92. package/dist/_chunks/{help-me-write-templates-Bw3Q58x-.js.map → help-me-write-templates-5WkUfvc_.js.map} +1 -1
  93. package/dist/_chunks/{kit-extensions-DWs1UEXb.js → kit-extensions-CYvLL4ee.js} +3 -3
  94. package/dist/_chunks/{kit-extensions-DWs1UEXb.js.map → kit-extensions-CYvLL4ee.js.map} +1 -1
  95. package/dist/_chunks/length-token-DwMnGEYT.js +24 -0
  96. package/dist/_chunks/length-token-DwMnGEYT.js.map +1 -0
  97. package/dist/_chunks/{link-cell-renderer-CtTsvfPY.js → link-cell-renderer-DtIsQWDO.js} +4 -4
  98. package/dist/_chunks/{link-cell-renderer-CtTsvfPY.js.map → link-cell-renderer-DtIsQWDO.js.map} +1 -1
  99. package/dist/_chunks/{login-dev-card-A-CL3mjt.js → login-dev-card-vEL-o5wq.js} +3 -3
  100. package/dist/_chunks/{login-dev-card-A-CL3mjt.js.map → login-dev-card-vEL-o5wq.js.map} +1 -1
  101. package/dist/_chunks/{map-view-BuVfJMEa.js → map-view-CtohteZD.js} +300 -191
  102. package/dist/_chunks/map-view-CtohteZD.js.map +1 -0
  103. package/dist/_chunks/{marketplace-app-shell-DtSX8sYb.js → marketplace-app-shell-CcLQ0Dn-.js} +4 -4
  104. package/dist/_chunks/{marketplace-app-shell-DtSX8sYb.js.map → marketplace-app-shell-CcLQ0Dn-.js.map} +1 -1
  105. package/dist/_chunks/{message-card-A3mJNqfy.js → message-card-C_ksqIYM.js} +2 -2
  106. package/dist/_chunks/{message-card-A3mJNqfy.js.map → message-card-C_ksqIYM.js.map} +1 -1
  107. package/dist/_chunks/{message-tray-Ft6vSr71.js → message-tray-DCoQ4GQb.js} +3 -3
  108. package/dist/_chunks/{message-tray-Ft6vSr71.js.map → message-tray-DCoQ4GQb.js.map} +1 -1
  109. package/dist/_chunks/{multi-select-CMaAQQgb.js → multi-select-BOad3za9.js} +110 -98
  110. package/dist/_chunks/multi-select-BOad3za9.js.map +1 -0
  111. package/dist/_chunks/{muscle-scheme-YoN3rYXV.js → muscle-scheme-C66WlCxG.js} +2 -2
  112. package/dist/_chunks/{muscle-scheme-YoN3rYXV.js.map → muscle-scheme-C66WlCxG.js.map} +1 -1
  113. package/dist/_chunks/{note-timeline-DDqNU46n.js → note-timeline-KzL52MmB.js} +2 -2
  114. package/dist/_chunks/{note-timeline-DDqNU46n.js.map → note-timeline-KzL52MmB.js.map} +1 -1
  115. package/dist/_chunks/{notes-panel-IdsmqRFC.js → notes-panel-BXN46XkF.js} +6 -6
  116. package/dist/_chunks/{notes-panel-IdsmqRFC.js.map → notes-panel-BXN46XkF.js.map} +1 -1
  117. package/dist/_chunks/notice-group-DkYzKyAZ.js +291 -0
  118. package/dist/_chunks/notice-group-DkYzKyAZ.js.map +1 -0
  119. package/dist/_chunks/{notification-tray-BR3seWA7.js → notification-tray-Cp18MW5b.js} +2 -2
  120. package/dist/_chunks/{notification-tray-BR3seWA7.js.map → notification-tray-Cp18MW5b.js.map} +1 -1
  121. package/dist/_chunks/{operator-hero-3_RG4Dkj.js → operator-hero-6aAIQaFZ.js} +83 -66
  122. package/dist/_chunks/operator-hero-6aAIQaFZ.js.map +1 -0
  123. package/dist/_chunks/{optical-prescription-CxfMsbxi.js → optical-prescription-ulXnDbBe.js} +525 -509
  124. package/dist/_chunks/optical-prescription-ulXnDbBe.js.map +1 -0
  125. package/dist/_chunks/panel-header-CbtlTe85.js +190 -0
  126. package/dist/_chunks/panel-header-CbtlTe85.js.map +1 -0
  127. package/dist/_chunks/{panel-subview-yP4qIbKS.js → panel-subview-BPU7220K.js} +2 -2
  128. package/dist/_chunks/{panel-subview-yP4qIbKS.js.map → panel-subview-BPU7220K.js.map} +1 -1
  129. package/dist/_chunks/{patient-details-C-EWQTms.js → patient-details-C4Dyo7Ck.js} +4 -4
  130. package/dist/_chunks/{patient-details-C-EWQTms.js.map → patient-details-C4Dyo7Ck.js.map} +1 -1
  131. package/dist/_chunks/{patient-field-row-lY-Tb5Mo.js → patient-field-row-DROvUkFu.js} +4 -4
  132. package/dist/_chunks/{patient-field-row-lY-Tb5Mo.js.map → patient-field-row-DROvUkFu.js.map} +1 -1
  133. package/dist/_chunks/{patient-search-DpAKidZ5.js → patient-search-BADdx3M1.js} +2 -2
  134. package/dist/_chunks/{patient-search-DpAKidZ5.js.map → patient-search-BADdx3M1.js.map} +1 -1
  135. package/dist/_chunks/{patient-summary-card-Bpto_VCD.js → patient-summary-card-CAimxbuI.js} +4 -4
  136. package/dist/_chunks/{patient-summary-card-Bpto_VCD.js.map → patient-summary-card-CAimxbuI.js.map} +1 -1
  137. package/dist/_chunks/{payment-automation-upsell-BQ307qEX.js → payment-automation-upsell-CiwF5UrC.js} +2 -2
  138. package/dist/_chunks/{payment-automation-upsell-BQ307qEX.js.map → payment-automation-upsell-CiwF5UrC.js.map} +1 -1
  139. package/dist/_chunks/{payment-form-XKtinW8r.js → payment-form-PBuh8PIa.js} +2 -2
  140. package/dist/_chunks/{payment-form-XKtinW8r.js.map → payment-form-PBuh8PIa.js.map} +1 -1
  141. package/dist/_chunks/{pdf-viewer-BvoVMjH4.js → pdf-viewer-gAsNUsA8.js} +2 -2
  142. package/dist/_chunks/{pdf-viewer-BvoVMjH4.js.map → pdf-viewer-gAsNUsA8.js.map} +1 -1
  143. package/dist/_chunks/{periodontal-risk-chart-CPy7CNFe.js → periodontal-risk-chart-B7S9OmPC.js} +97 -89
  144. package/dist/_chunks/periodontal-risk-chart-B7S9OmPC.js.map +1 -0
  145. package/dist/_chunks/practice-profile-hero-qfrsFQI_.js +236 -0
  146. package/dist/_chunks/practice-profile-hero-qfrsFQI_.js.map +1 -0
  147. package/dist/_chunks/{practice-results-BrUDDMXC.js → practice-results-BzThnpnm.js} +328 -298
  148. package/dist/_chunks/practice-results-BzThnpnm.js.map +1 -0
  149. package/dist/_chunks/{pregnancy-dating-B8wo4l_r.js → pregnancy-dating-EFcFUJkQ.js} +2 -2
  150. package/dist/_chunks/{pregnancy-dating-B8wo4l_r.js.map → pregnancy-dating-EFcFUJkQ.js.map} +1 -1
  151. package/dist/_chunks/{privacy-mask-Ch7743uk.js → privacy-mask-CCz9zuIh.js} +2 -2
  152. package/dist/_chunks/{privacy-mask-Ch7743uk.js.map → privacy-mask-CCz9zuIh.js.map} +1 -1
  153. package/dist/_chunks/{product-hub-panel-C_ZosrBt.js → product-hub-panel-YuFbNPlT.js} +2 -2
  154. package/dist/_chunks/{product-hub-panel-C_ZosrBt.js.map → product-hub-panel-YuFbNPlT.js.map} +1 -1
  155. package/dist/_chunks/progress-notice-DiHWZ8Ms.js +279 -0
  156. package/dist/_chunks/progress-notice-DiHWZ8Ms.js.map +1 -0
  157. package/dist/_chunks/{province-select-Bd20Z9Br.js → province-select-CDjs5obD.js} +2 -2
  158. package/dist/_chunks/{province-select-Bd20Z9Br.js.map → province-select-CDjs5obD.js.map} +1 -1
  159. package/dist/_chunks/{radiograph-panel.agent-8Ewv8-d7.js → radiograph-panel.agent-4UllIoTQ.js} +2 -2
  160. package/dist/_chunks/{radiograph-panel.agent-8Ewv8-d7.js.map → radiograph-panel.agent-4UllIoTQ.js.map} +1 -1
  161. package/dist/_chunks/{rating-C1Vrmpsi.js → rating-CGYpg5dj.js} +43 -44
  162. package/dist/_chunks/rating-CGYpg5dj.js.map +1 -0
  163. package/dist/_chunks/{registration-form-BxwqUZzk.js → registration-form-1B0PTDal.js} +4 -4
  164. package/dist/_chunks/{registration-form-BxwqUZzk.js.map → registration-form-1B0PTDal.js.map} +1 -1
  165. package/dist/_chunks/{reviews-panel-AvsVgtJu.js → reviews-panel-CosDZyow.js} +29 -7
  166. package/dist/_chunks/reviews-panel-CosDZyow.js.map +1 -0
  167. package/dist/_chunks/{rich-text-editor-aCIoptbg.js → rich-text-editor-56dSsyZI.js} +3 -3
  168. package/dist/_chunks/{rich-text-editor-aCIoptbg.js.map → rich-text-editor-56dSsyZI.js.map} +1 -1
  169. package/dist/_chunks/{select-k4gBdS8N.js → select-4S-eYZUf.js} +244 -214
  170. package/dist/_chunks/select-4S-eYZUf.js.map +1 -0
  171. package/dist/_chunks/{sign-document-D1P1nUQA.js → sign-document-BiOTs1P4.js} +2 -2
  172. package/dist/_chunks/{sign-document-D1P1nUQA.js.map → sign-document-BiOTs1P4.js.map} +1 -1
  173. package/dist/_chunks/{signature-request-3u6TvRt2.js → signature-request-DAmNj_uq.js} +5 -5
  174. package/dist/_chunks/{signature-request-3u6TvRt2.js.map → signature-request-DAmNj_uq.js.map} +1 -1
  175. package/dist/_chunks/skeleton-tTWJpvAq.js +415 -0
  176. package/dist/_chunks/skeleton-tTWJpvAq.js.map +1 -0
  177. package/dist/_chunks/{slot-grid-dj5f6R2w.js → slot-grid-D_gix9mJ.js} +2 -2
  178. package/dist/_chunks/{slot-grid-dj5f6R2w.js.map → slot-grid-D_gix9mJ.js.map} +1 -1
  179. package/dist/_chunks/{tabs-2x3L13jn.js → tabs-BTj-2qMZ.js} +2 -2
  180. package/dist/_chunks/{tabs-2x3L13jn.js.map → tabs-BTj-2qMZ.js.map} +1 -1
  181. package/dist/_chunks/{task-card-BS7Uqevr.js → task-card-Ci2XbLmq.js} +2 -2
  182. package/dist/_chunks/{task-card-BS7Uqevr.js.map → task-card-Ci2XbLmq.js.map} +1 -1
  183. package/dist/_chunks/{task-editor-Bb5MMcid.js → task-editor-BomyxGoZ.js} +8 -8
  184. package/dist/_chunks/{task-editor-Bb5MMcid.js.map → task-editor-BomyxGoZ.js.map} +1 -1
  185. package/dist/_chunks/{task-tray-eQU4KJcA.js → task-tray-Dnc72nl-.js} +3 -3
  186. package/dist/_chunks/{task-tray-eQU4KJcA.js.map → task-tray-Dnc72nl-.js.map} +1 -1
  187. package/dist/_chunks/{tasks-panel-BOb57Ysw.js → tasks-panel-ATz9JDy8.js} +6 -6
  188. package/dist/_chunks/{tasks-panel-BOb57Ysw.js.map → tasks-panel-ATz9JDy8.js.map} +1 -1
  189. package/dist/_chunks/{theme-toggle-Ctb77x6O.js → theme-toggle-DT_Jn4DC.js} +147 -138
  190. package/dist/_chunks/theme-toggle-DT_Jn4DC.js.map +1 -0
  191. package/dist/_chunks/{timeline-DEIuHrWz.js → timeline-wUuTDFY_.js} +2 -2
  192. package/dist/_chunks/{timeline-DEIuHrWz.js.map → timeline-wUuTDFY_.js.map} +1 -1
  193. package/dist/_chunks/{tool-rail-C-03rH2I.js → tool-rail-C-M3eVdY.js} +2 -2
  194. package/dist/_chunks/{tool-rail-C-03rH2I.js.map → tool-rail-C-M3eVdY.js.map} +1 -1
  195. package/dist/_chunks/{transcript-panel-XudW5l6l.js → transcript-panel-CoHHpcFg.js} +2 -2
  196. package/dist/_chunks/{transcript-panel-XudW5l6l.js.map → transcript-panel-CoHHpcFg.js.map} +1 -1
  197. package/dist/_chunks/{treatment-receipt-Cpm8tqQN.js → treatment-receipt-pFqWFyD_.js} +2 -2
  198. package/dist/_chunks/{treatment-receipt-Cpm8tqQN.js.map → treatment-receipt-pFqWFyD_.js.map} +1 -1
  199. package/dist/_chunks/{unit-converter-BPZ0Ldkb.js → unit-converter-CIoTmCmP.js} +2 -2
  200. package/dist/_chunks/{unit-converter-BPZ0Ldkb.js.map → unit-converter-CIoTmCmP.js.map} +1 -1
  201. package/dist/_chunks/{use-appointment-details-read-CVSPoP5j.js → use-appointment-details-read-CUGfE0hV.js} +12 -12
  202. package/dist/_chunks/{use-appointment-details-read-CVSPoP5j.js.map → use-appointment-details-read-CUGfE0hV.js.map} +1 -1
  203. package/dist/_chunks/use-dismissed-CTOWqA0e.js +177 -0
  204. package/dist/_chunks/use-dismissed-CTOWqA0e.js.map +1 -0
  205. package/dist/_chunks/{voice-control-panel-BJIEbDq6.js → voice-control-panel-B8Lrk0C4.js} +4 -4
  206. package/dist/_chunks/{voice-control-panel-BJIEbDq6.js.map → voice-control-panel-B8Lrk0C4.js.map} +1 -1
  207. package/dist/_chunks/{warning-stack-BdY-0bd3.js → warning-stack-BhHUmRiD.js} +2 -2
  208. package/dist/_chunks/{warning-stack-BdY-0bd3.js.map → warning-stack-BhHUmRiD.js.map} +1 -1
  209. package/dist/_chunks/{workflow-map-CYbRD9ek.js → workflow-map-ln4_OG8A.js} +2 -2
  210. package/dist/_chunks/{workflow-map-CYbRD9ek.js.map → workflow-map-ln4_OG8A.js.map} +1 -1
  211. package/dist/agent-catalog.json +172 -4
  212. package/dist/agent-i18n/en.json +25 -1
  213. package/dist/components/_shared/format-number.d.ts +20 -0
  214. package/dist/components/_shared/format-number.d.ts.map +1 -0
  215. package/dist/components/_shared/length-token.d.ts +12 -0
  216. package/dist/components/_shared/length-token.d.ts.map +1 -0
  217. package/dist/components/_shared/option.d.ts +1 -0
  218. package/dist/components/_shared/option.d.ts.map +1 -1
  219. package/dist/components/address-fields/index.js +1 -1
  220. package/dist/components/agenda-card/index.js +1 -1
  221. package/dist/components/agenda-tray/index.js +1 -1
  222. package/dist/components/ai-credits-notice/index.js +1 -1
  223. package/dist/components/ai-permission-notice/index.js +1 -1
  224. package/dist/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
  225. package/dist/components/ai-prompt-input/index.js +1 -1
  226. package/dist/components/alert/alert.d.ts +26 -0
  227. package/dist/components/alert/alert.d.ts.map +1 -1
  228. package/dist/components/alert/index.js +1 -1
  229. package/dist/components/anamnesis-summary-card/index.js +1 -1
  230. package/dist/components/appointment-card/index.js +2 -2
  231. package/dist/components/appointment-details-panel/index.js +1 -1
  232. package/dist/components/appointment-peek/index.js +1 -1
  233. package/dist/components/appointment-timeline/index.js +1 -1
  234. package/dist/components/audio-recorder/index.js +1 -1
  235. package/dist/components/avatar/avatar.d.ts +2 -0
  236. package/dist/components/avatar/avatar.d.ts.map +1 -1
  237. package/dist/components/avatar/index.js +1 -1
  238. package/dist/components/bishop-score/index.js +1 -1
  239. package/dist/components/booking/booking.d.ts.map +1 -1
  240. package/dist/components/booking/details-form.d.ts.map +1 -1
  241. package/dist/components/booking/index.js +1 -1
  242. package/dist/components/calendar/index.js +1 -1
  243. package/dist/components/chat-message/index.js +1 -1
  244. package/dist/components/clinical-note-card/index.js +1 -1
  245. package/dist/components/color-picker/color-picker.d.ts.map +1 -1
  246. package/dist/components/color-picker/index.js +1 -1
  247. package/dist/components/combobox/combobox.d.ts.map +1 -1
  248. package/dist/components/combobox/index.js +1 -1
  249. package/dist/components/contact-profile-card/index.js +1 -1
  250. package/dist/components/control-room-rail/index.js +1 -1
  251. package/dist/components/country-select/index.js +1 -1
  252. package/dist/components/dashboard-grid/dashboard-grid.agent.d.ts.map +1 -1
  253. package/dist/components/dashboard-grid/dashboard-grid.d.ts +20 -1
  254. package/dist/components/dashboard-grid/dashboard-grid.d.ts.map +1 -1
  255. package/dist/components/dashboard-grid/index.js +1 -1
  256. package/dist/components/data-table/index.js +2 -2
  257. package/dist/components/dependent-selector/index.js +1 -1
  258. package/dist/components/document-preview/index.js +1 -1
  259. package/dist/components/document-scanner/index.js +1 -1
  260. package/dist/components/editable-description/index.js +1 -1
  261. package/dist/components/entity-summary/index.js +1 -1
  262. package/dist/components/error-summary/index.js +1 -1
  263. package/dist/components/face-scheme/face-scheme.d.ts.map +1 -1
  264. package/dist/components/face-scheme/index.js +1 -1
  265. package/dist/components/file-manager/index.js +1 -1
  266. package/dist/components/freemium-paywall/index.js +1 -1
  267. package/dist/components/gestational-age-calculator/index.js +1 -1
  268. package/dist/components/header-settings/header-settings.d.ts.map +1 -1
  269. package/dist/components/header-settings/index.js +1 -1
  270. package/dist/components/heatmap/index.js +1 -1
  271. package/dist/components/index.d.ts +4 -2
  272. package/dist/components/index.d.ts.map +1 -1
  273. package/dist/components/map-view/index.d.ts +1 -1
  274. package/dist/components/map-view/index.d.ts.map +1 -1
  275. package/dist/components/map-view/index.js +1 -1
  276. package/dist/components/map-view/map-view.d.ts +51 -0
  277. package/dist/components/map-view/map-view.d.ts.map +1 -1
  278. package/dist/components/message-card/index.js +1 -1
  279. package/dist/components/message-tray/index.js +1 -1
  280. package/dist/components/multi-select/index.js +1 -1
  281. package/dist/components/multi-select/multi-select.d.ts.map +1 -1
  282. package/dist/components/muscle-scheme/index.js +1 -1
  283. package/dist/components/note-timeline/index.js +1 -1
  284. package/dist/components/notes-panel/index.js +1 -1
  285. package/dist/components/notice-group/index.d.ts +3 -0
  286. package/dist/components/notice-group/index.d.ts.map +1 -0
  287. package/dist/components/notice-group/index.js +6 -0
  288. package/dist/components/notice-group/index.js.map +1 -0
  289. package/dist/components/notice-group/notice-group.agent.d.ts +4 -0
  290. package/dist/components/notice-group/notice-group.agent.d.ts.map +1 -0
  291. package/dist/components/notice-group/notice-group.d.ts +43 -0
  292. package/dist/components/notice-group/notice-group.d.ts.map +1 -0
  293. package/dist/components/notification-tray/index.js +1 -1
  294. package/dist/components/operator-hero/index.js +1 -1
  295. package/dist/components/operator-hero/operator-hero.d.ts.map +1 -1
  296. package/dist/components/optical-prescription/index.js +1 -1
  297. package/dist/components/optical-prescription/optical-prescription-data.d.ts +8 -8
  298. package/dist/components/optical-prescription/optical-prescription-data.d.ts.map +1 -1
  299. package/dist/components/optical-prescription/optical-prescription.d.ts.map +1 -1
  300. package/dist/components/panel-header/index.js +1 -1
  301. package/dist/components/panel-header/panel-header.d.ts +10 -0
  302. package/dist/components/panel-header/panel-header.d.ts.map +1 -1
  303. package/dist/components/panel-subview/index.js +1 -1
  304. package/dist/components/patient-details/index.js +1 -1
  305. package/dist/components/patient-search/index.js +1 -1
  306. package/dist/components/patient-summary-card/index.js +1 -1
  307. package/dist/components/patient-table/index.js +1 -1
  308. package/dist/components/payment-form/index.js +1 -1
  309. package/dist/components/pdf-viewer/index.js +1 -1
  310. package/dist/components/periodontal-risk-chart/index.js +1 -1
  311. package/dist/components/periodontal-risk-chart/periodontal-risk-chart.d.ts.map +1 -1
  312. package/dist/components/practice-profile-hero/index.js +1 -1
  313. package/dist/components/practice-profile-hero/practice-profile-hero.d.ts +4 -1
  314. package/dist/components/practice-profile-hero/practice-profile-hero.d.ts.map +1 -1
  315. package/dist/components/practice-results/index.js +1 -1
  316. package/dist/components/practice-results/practice-results.d.ts +10 -2
  317. package/dist/components/practice-results/practice-results.d.ts.map +1 -1
  318. package/dist/components/pregnancy-dating/index.js +1 -1
  319. package/dist/components/product-hub-tray/index.js +1 -1
  320. package/dist/components/progress-notice/index.d.ts +3 -0
  321. package/dist/components/progress-notice/index.d.ts.map +1 -0
  322. package/dist/components/progress-notice/index.js +6 -0
  323. package/dist/components/progress-notice/index.js.map +1 -0
  324. package/dist/components/progress-notice/progress-notice.agent.d.ts +4 -0
  325. package/dist/components/progress-notice/progress-notice.agent.d.ts.map +1 -0
  326. package/dist/components/progress-notice/progress-notice.d.ts +81 -0
  327. package/dist/components/progress-notice/progress-notice.d.ts.map +1 -0
  328. package/dist/components/province-select/index.js +1 -1
  329. package/dist/components/radiograph-panel/index.js +1 -1
  330. package/dist/components/rating/index.js +1 -1
  331. package/dist/components/rating/rating.d.ts.map +1 -1
  332. package/dist/components/reviews-panel/index.js +1 -1
  333. package/dist/components/reviews-panel/reviews-panel.d.ts.map +1 -1
  334. package/dist/components/rich-text-editor/index.js +2 -2
  335. package/dist/components/select/index.js +1 -1
  336. package/dist/components/select/select.d.ts +6 -0
  337. package/dist/components/select/select.d.ts.map +1 -1
  338. package/dist/components/sign-document/index.js +1 -1
  339. package/dist/components/skeleton/index.d.ts +1 -1
  340. package/dist/components/skeleton/index.d.ts.map +1 -1
  341. package/dist/components/skeleton/index.js +1 -1
  342. package/dist/components/skeleton/skeleton.d.ts +41 -1
  343. package/dist/components/skeleton/skeleton.d.ts.map +1 -1
  344. package/dist/components/skeleton-scheme/index.js +1 -1
  345. package/dist/components/slot-grid/index.js +1 -1
  346. package/dist/components/tabs/index.js +1 -1
  347. package/dist/components/task-card/index.js +1 -1
  348. package/dist/components/task-editor/index.js +1 -1
  349. package/dist/components/task-tray/index.js +1 -1
  350. package/dist/components/tasks-panel/index.js +1 -1
  351. package/dist/components/theme-toggle/index.js +1 -1
  352. package/dist/components/theme-toggle/theme-toggle.d.ts.map +1 -1
  353. package/dist/components/timeline/index.js +1 -1
  354. package/dist/components/tool-rail/index.js +1 -1
  355. package/dist/components/transcript-panel/index.js +1 -1
  356. package/dist/components/treatment-receipt/index.js +1 -1
  357. package/dist/components/unit-converter/index.js +1 -1
  358. package/dist/components/voice-control-panel/index.js +1 -1
  359. package/dist/components/warning-stack/index.js +1 -1
  360. package/dist/components/workflow/index.js +1 -1
  361. package/dist/hooks/index.d.ts +1 -0
  362. package/dist/hooks/index.d.ts.map +1 -1
  363. package/dist/hooks/index.js +81 -76
  364. package/dist/hooks/index.js.map +1 -1
  365. package/dist/hooks/use-dismissed.d.ts +58 -0
  366. package/dist/hooks/use-dismissed.d.ts.map +1 -0
  367. package/dist/i18n/locales/ar.d.ts +22 -0
  368. package/dist/i18n/locales/ar.d.ts.map +1 -1
  369. package/dist/i18n/locales/ar.js +22 -0
  370. package/dist/i18n/locales/ar.js.map +1 -1
  371. package/dist/i18n/locales/de.d.ts +22 -0
  372. package/dist/i18n/locales/de.d.ts.map +1 -1
  373. package/dist/i18n/locales/de.js +22 -0
  374. package/dist/i18n/locales/de.js.map +1 -1
  375. package/dist/i18n/locales/el.d.ts +22 -0
  376. package/dist/i18n/locales/el.d.ts.map +1 -1
  377. package/dist/i18n/locales/el.js +22 -0
  378. package/dist/i18n/locales/el.js.map +1 -1
  379. package/dist/i18n/locales/en.d.ts +22 -0
  380. package/dist/i18n/locales/en.d.ts.map +1 -1
  381. package/dist/i18n/locales/en.js +22 -0
  382. package/dist/i18n/locales/en.js.map +1 -1
  383. package/dist/i18n/locales/es.d.ts +22 -0
  384. package/dist/i18n/locales/es.d.ts.map +1 -1
  385. package/dist/i18n/locales/es.js +22 -0
  386. package/dist/i18n/locales/es.js.map +1 -1
  387. package/dist/i18n/locales/fr.d.ts +22 -0
  388. package/dist/i18n/locales/fr.d.ts.map +1 -1
  389. package/dist/i18n/locales/fr.js +22 -0
  390. package/dist/i18n/locales/fr.js.map +1 -1
  391. package/dist/i18n/locales/hi.d.ts +22 -0
  392. package/dist/i18n/locales/hi.d.ts.map +1 -1
  393. package/dist/i18n/locales/hi.js +22 -0
  394. package/dist/i18n/locales/hi.js.map +1 -1
  395. package/dist/i18n/locales/it.d.ts +22 -0
  396. package/dist/i18n/locales/it.d.ts.map +1 -1
  397. package/dist/i18n/locales/it.js +22 -0
  398. package/dist/i18n/locales/it.js.map +1 -1
  399. package/dist/i18n/locales/ja.d.ts +22 -0
  400. package/dist/i18n/locales/ja.d.ts.map +1 -1
  401. package/dist/i18n/locales/ja.js +22 -0
  402. package/dist/i18n/locales/ja.js.map +1 -1
  403. package/dist/i18n/locales/nl.d.ts +22 -0
  404. package/dist/i18n/locales/nl.d.ts.map +1 -1
  405. package/dist/i18n/locales/nl.js +22 -0
  406. package/dist/i18n/locales/nl.js.map +1 -1
  407. package/dist/i18n/locales/pl.d.ts +22 -0
  408. package/dist/i18n/locales/pl.d.ts.map +1 -1
  409. package/dist/i18n/locales/pl.js +22 -0
  410. package/dist/i18n/locales/pl.js.map +1 -1
  411. package/dist/i18n/locales/pt.d.ts +22 -0
  412. package/dist/i18n/locales/pt.d.ts.map +1 -1
  413. package/dist/i18n/locales/pt.js +22 -0
  414. package/dist/i18n/locales/pt.js.map +1 -1
  415. package/dist/i18n/locales/ro.d.ts +22 -0
  416. package/dist/i18n/locales/ro.d.ts.map +1 -1
  417. package/dist/i18n/locales/ro.js +22 -0
  418. package/dist/i18n/locales/ro.js.map +1 -1
  419. package/dist/i18n/locales/ru.d.ts +22 -0
  420. package/dist/i18n/locales/ru.d.ts.map +1 -1
  421. package/dist/i18n/locales/ru.js +22 -0
  422. package/dist/i18n/locales/ru.js.map +1 -1
  423. package/dist/i18n/locales/sq.d.ts +22 -0
  424. package/dist/i18n/locales/sq.d.ts.map +1 -1
  425. package/dist/i18n/locales/sq.js +22 -0
  426. package/dist/i18n/locales/sq.js.map +1 -1
  427. package/dist/i18n/locales/sv.d.ts +22 -0
  428. package/dist/i18n/locales/sv.d.ts.map +1 -1
  429. package/dist/i18n/locales/sv.js +22 -0
  430. package/dist/i18n/locales/sv.js.map +1 -1
  431. package/dist/i18n/locales/tr.d.ts +22 -0
  432. package/dist/i18n/locales/tr.d.ts.map +1 -1
  433. package/dist/i18n/locales/tr.js +22 -0
  434. package/dist/i18n/locales/tr.js.map +1 -1
  435. package/dist/i18n/locales/zh.d.ts +22 -0
  436. package/dist/i18n/locales/zh.d.ts.map +1 -1
  437. package/dist/i18n/locales/zh.js +22 -0
  438. package/dist/i18n/locales/zh.js.map +1 -1
  439. package/dist/index.js +1194 -1183
  440. package/dist/index.js.map +1 -1
  441. package/dist/locales/ar.json +22 -0
  442. package/dist/locales/de.json +22 -0
  443. package/dist/locales/el.json +22 -0
  444. package/dist/locales/en.json +22 -0
  445. package/dist/locales/es.json +22 -0
  446. package/dist/locales/fr.json +22 -0
  447. package/dist/locales/hi.json +22 -0
  448. package/dist/locales/it.json +22 -0
  449. package/dist/locales/ja.json +22 -0
  450. package/dist/locales/nl.json +22 -0
  451. package/dist/locales/pl.json +22 -0
  452. package/dist/locales/pt.json +22 -0
  453. package/dist/locales/ro.json +22 -0
  454. package/dist/locales/ru.json +22 -0
  455. package/dist/locales/sq.json +22 -0
  456. package/dist/locales/sv.json +22 -0
  457. package/dist/locales/tr.json +22 -0
  458. package/dist/locales/zh.json +22 -0
  459. package/dist/patterns/alia-assistant/index.js +1 -1
  460. package/dist/patterns/anamnesis/anamnesis-export-pdf.d.ts.map +1 -1
  461. package/dist/patterns/anamnesis/index.js +1 -1
  462. package/dist/patterns/calendar/index.js +1 -1
  463. package/dist/patterns/forgot-password-form/index.js +1 -1
  464. package/dist/patterns/help-me-write-templates/index.js +2 -2
  465. package/dist/patterns/login-form/index.js +1 -1
  466. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  467. package/dist/patterns/payment-automation-upsell/index.js +1 -1
  468. package/dist/patterns/registration-form/index.js +1 -1
  469. package/dist/patterns/signature-request/index.js +1 -1
  470. package/dist/tokens.css +1 -1
  471. package/package.json +9 -1
  472. package/dist/_chunks/ai-prompt-input-DSGSe4LH.js.map +0 -1
  473. package/dist/_chunks/alert-DjsJMGRE.js.map +0 -1
  474. package/dist/_chunks/anamnesis-summary-rows-BQ_EokKz.js.map +0 -1
  475. package/dist/_chunks/avatar-WZY3eGE7.js +0 -123
  476. package/dist/_chunks/avatar-WZY3eGE7.js.map +0 -1
  477. package/dist/_chunks/booking-tTVxKPQY.js.map +0 -1
  478. package/dist/_chunks/color-picker-BsggJovx.js.map +0 -1
  479. package/dist/_chunks/combobox-U5yfO6o0.js.map +0 -1
  480. package/dist/_chunks/contact-profile-card-C4-OCshj.js.map +0 -1
  481. package/dist/_chunks/dashboard-grid-B2MB7SRS.js +0 -1428
  482. package/dist/_chunks/dashboard-grid-B2MB7SRS.js.map +0 -1
  483. package/dist/_chunks/header-settings-BSH9Gk0J.js.map +0 -1
  484. package/dist/_chunks/map-view-BuVfJMEa.js.map +0 -1
  485. package/dist/_chunks/multi-select-CMaAQQgb.js.map +0 -1
  486. package/dist/_chunks/operator-hero-3_RG4Dkj.js.map +0 -1
  487. package/dist/_chunks/optical-prescription-CxfMsbxi.js.map +0 -1
  488. package/dist/_chunks/panel-header-BJkaUwnl.js +0 -128
  489. package/dist/_chunks/panel-header-BJkaUwnl.js.map +0 -1
  490. package/dist/_chunks/periodontal-risk-chart-CPy7CNFe.js.map +0 -1
  491. package/dist/_chunks/practice-profile-hero-Dfc0F60y.js +0 -193
  492. package/dist/_chunks/practice-profile-hero-Dfc0F60y.js.map +0 -1
  493. package/dist/_chunks/practice-results-BrUDDMXC.js.map +0 -1
  494. package/dist/_chunks/rating-C1Vrmpsi.js.map +0 -1
  495. package/dist/_chunks/reviews-panel-AvsVgtJu.js.map +0 -1
  496. package/dist/_chunks/select-k4gBdS8N.js.map +0 -1
  497. package/dist/_chunks/skeleton-B1KTdJ4N.js +0 -116
  498. package/dist/_chunks/skeleton-B1KTdJ4N.js.map +0 -1
  499. package/dist/_chunks/theme-toggle-Ctb77x6O.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map-view-CtohteZD.js","sources":["../../src/components/map-view/map-view.agent.ts","../../src/components/map-view/map-view.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — MapView. */\n/* */\n/* Read-safety actions on the kit's Google Maps wrapper. State is the */\n/* current centre / zoom / selected marker; actions pan, zoom, and */\n/* select markers programmatically. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { MapViewHandle, MapLatLng } from './map-view';\n\nexport const mapViewAgent: AgentAdapter<MapViewHandle> = {\n id: 'map-view',\n // pan → scroll (viewport move); set_zoom → set_value; select_marker → pick\n // (NON-persisting marker focus, no value state slot).\n capabilities: ['scroll', 'set_value', 'pick'],\n // Every action routes through the imperative bridge, which only exists\n // once the map has loaded: consent granted (the default is\n // `consentGranted={false}`) and Google Maps finished loading. Until then\n // all three actions are silent no-ops. `consentGranted` says whether the\n // gate is passed, and a null `center` after it means the map is still\n // loading. `center` / `zoom` are read off the live\n // map because Google clamps zoom and animates pans, so requested is not\n // applied; `selectedMarkerId` is the only confirmation the host accepted\n // a `select_marker` proposal.\n //\n // A9: marker ids only (`MapMarker.id` is a stable opaque id). Never\n // `MapMarker.label`, never the `address` prop (consumer-supplied free\n // text, PII in any patient-address deployment), never `apiKey`.\n state: {\n consentGranted: {\n type: 'boolean',\n descriptionKey: 'ui.agent.mapView.state.consentGranted',\n description:\n 'True when the GDPR consent gate has been passed. Read this FIRST: while it is false every action is a silent no-op against a placeholder, and nothing else in the surface says so. When it is true but `center` is still null, Google Maps is loading; wait for `center` before acting.',\n read: (handle) => handle.isConsentGranted(),\n },\n markerCount: {\n type: 'number',\n descriptionKey: 'ui.agent.mapView.state.markerCount',\n description:\n 'Number of markers the consumer passed. Zero means there is nothing for `select_marker` to select. A count only — no ids, labels or positions.',\n read: (handle) => handle.getMarkerCount(),\n },\n selectedMarkerId: {\n type: 'string | null',\n descriptionKey: 'ui.agent.mapView.state.selectedMarkerId',\n description:\n 'Id of the marker the host currently holds as selected, or null. Selection is fully controlled by the consumer, so `select_marker` only proposes — this slot is the only way to see whether the proposal was accepted.',\n read: (handle) => handle.getSelectedMarkerId(),\n },\n center: {\n type: '{ lat: number; lng: number } | null',\n descriptionKey: 'ui.agent.mapView.state.center',\n description:\n 'Live map centre in lat/lng, or null until the map has loaded (consent not granted, or Google Maps still loading). The read-back for `pan_to`, and the sign that the map is ready.',\n read: (handle) => handle.getCenter(),\n },\n zoom: {\n type: 'number | null',\n descriptionKey: 'ui.agent.mapView.state.zoom',\n description:\n \"Live zoom level, or null until the map has loaded. Google clamps zoom to the map type's range, so this is not necessarily the value last passed to `set_zoom`.\",\n read: (handle) => handle.getZoom(),\n },\n },\n actions: {\n pan_to: {\n // Ephemeral viewport move, no data loss → read.\n safety: 'read',\n argsType: '{ position: { lat: number; lng: number } }',\n argsSchema: {\n type: 'object',\n properties: {\n position: {\n type: 'object',\n properties: {\n lat: { type: 'number', description: 'Latitude in degrees.' },\n lng: { type: 'number', description: 'Longitude in degrees.' },\n },\n required: ['lat', 'lng'],\n },\n },\n required: ['position'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.mapView.actions.panTo',\n description:\n 'Pan the map to a new centre without changing zoom. Read the `center` slot back to confirm — Google animates the pan, so the applied centre settles after the call.',\n errors: [\n 'Silent no-op until the map has loaded: while `consentGranted` is false (only the consent placeholder shows) or while `center` is still null (Google Maps is loading).',\n ],\n invoke: (handle, args: { position: MapLatLng }) => {\n handle.panTo(args.position);\n },\n },\n set_zoom: {\n // Ephemeral viewport zoom, no data loss → read.\n safety: 'read',\n argsType: '{ zoom: number }',\n argsSchema: {\n type: 'object',\n properties: {\n zoom: {\n type: 'number',\n description: 'Zoom level, typical range 1–20.',\n },\n },\n required: ['zoom'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.mapView.actions.setZoom',\n description:\n 'Set the map zoom level (typical range 1–20). Read the `zoom` slot back — Google clamps the request to the map type’s supported range, so requested and applied can differ.',\n errors: [\n 'Silent no-op until the map has loaded: while `consentGranted` is false (only the consent placeholder shows) or while `center` is still null (Google Maps is loading).',\n \"Requested zoom is clamped to the map type's range; `zoom` reports what was actually applied.\",\n ],\n invoke: (handle, args: { zoom: number }) => {\n handle.setZoom(args.zoom);\n },\n },\n select_marker: {\n // Ephemeral marker focus, no data loss → read.\n safety: 'read',\n argsType: '{ id: string | null }',\n argsSchema: {\n type: 'object',\n properties: {\n id: {\n type: ['string', 'null'],\n description: 'Marker id to select, or null to clear the selection.',\n },\n },\n required: ['id'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.mapView.actions.selectMarker',\n description:\n \"Propose a marker selection by id, or pass null to clear it. Fires the host's `onMarkerClick`; selection is controlled by the host, so read the `selectedMarkerId` slot back to see whether it accepted.\",\n errors: [\n 'Silent no-op until the map has loaded: while `consentGranted` is false (only the consent placeholder shows) or while `center` is still null (Google Maps is loading).',\n 'The host owns `selectedMarkerId` and may ignore the proposal; `selectedMarkerId` is unchanged when it does.',\n ],\n invoke: (handle, args: { id: string | null }) => {\n handle.selectMarker(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'map-view',\n description: 'Marks the element as a kit MapView.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* MapView — kit wrapper over @vis.gl/react-google-maps. */\n/* */\n/* - Loads the Google Maps JS API on demand via the library's */\n/* `APIProvider`; consumer supplies the key (no kit-side cache). */\n/* - Defaults to a CONSENT-GATED placeholder (`consentGranted={false}`) */\n/* so the third-party load never happens before the consumer flips */\n/* the opt-in. GDPR-safe by default. */\n/* - Theme-reactive: the Google Maps `styles` JSON re-resolves on every */\n/* `documentElement.class` mutation (same pattern as Sparkline). */\n/* Consumers may pass `mapId` to switch to a cloud-styled map */\n/* instead, in which case `styles` is ignored. */\n/* - `data-component=\"map-view\"` lives on the outer span; the inner */\n/* `<Map>` mounts inside it. */\n/* ------------------------------------------------------------------ */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\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 { MapPin, ExternalLink } from 'lucide-react';\nimport {\n APIProvider,\n Map as GoogleMap,\n AdvancedMarker,\n Marker,\n Pin,\n useApiIsLoaded,\n useMap,\n useMapsLibrary,\n} from '@vis.gl/react-google-maps';\nimport { Button } from '../button';\nimport { Skeleton } from '../skeleton';\nimport { VisuallyHidden } from '../visually-hidden';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { mapViewAgent } from './map-view.agent';\nimport { lengthTokenPx } from '../_shared/length-token';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface MapLatLng {\n lat: number;\n lng: number;\n}\n\n/**\n * A point to fit the camera to. `id` is its identity (a result id): it\n * decides whether a new set only added points to the old one. Without\n * it the coordinates stand in, so two results at one address count as\n * one.\n */\nexport interface MapFitPoint extends MapLatLng {\n id?: string;\n}\n\nexport interface MapMarker {\n /** Stable id — used for keyed re-rendering and `onMarkerClick`. */\n id: string;\n /** Position in lat/lng. */\n position: MapLatLng;\n /** Optional accessible label — falls back to the id. */\n label?: string;\n}\n\nexport interface MapViewHandle {\n /** Pan the map to a new centre without changing zoom. */\n panTo: (position: MapLatLng) => void;\n /** Set zoom (typical range 1–20). */\n setZoom: (zoom: number) => void;\n /** Programmatically select a marker (fires `onMarkerClick`). */\n selectMarker: (id: string | null) => void;\n /* ---- read-back ------------------------------------------------- */\n /**\n * True once the consent gate has been passed. The map may still be\n * loading: the three actions above stay silent no-ops until\n * `getCenter` returns a value.\n */\n isConsentGranted: () => boolean;\n /** Live map centre, or `null` until the map has loaded. */\n getCenter: () => MapLatLng | null;\n /**\n * Live zoom level, or `null` until the map has loaded.\n * Google clamps to the map type's range, so this is not necessarily\n * the value last passed to `setZoom`.\n */\n getZoom: () => number | null;\n /**\n * The controlled `selectedMarkerId` prop as the host currently holds\n * it. `selectMarker` only proposes a selection — the host is free to\n * ignore it, and this is the only way to see whether it did.\n */\n getSelectedMarkerId: () => string | null;\n /** Number of markers passed to the component. Count only, no ids. */\n getMarkerCount: () => number;\n}\n\n/**\n * The slice of `MapViewHandle` that needs a live `google.maps.Map`.\n * Built inside the `APIProvider` subtree by `MapImperativeBridge`; the\n * outer component composes it with the props-derived getters, and holds\n * `null` whenever the subtree is unmounted.\n */\ntype MapBridgeHandle = Pick<\n MapViewHandle,\n 'panTo' | 'setZoom' | 'selectMarker' | 'getCenter' | 'getZoom'\n> & {\n /** Set centre and zoom in one step, never animated. Internal. */\n jumpTo: (center: MapLatLng, zoom: number) => void;\n};\n\nexport interface MapViewProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onClick'>,\n VariantProps<typeof mapViewVariants> {\n /** Opaque instance id — emitted as `data-component-id`. */\n id?: string;\n /** Google Maps JS API key. Consumer-owned; never cached by the kit. */\n apiKey: string;\n /** Map centre (lat/lng). Required so the consent placeholder can also use it. */\n center: MapLatLng;\n /** Initial zoom. Default 15 (city-block detail, matches booking site). */\n zoom?: number;\n /**\n * Markers to render. The first marker auto-selects when no\n * `selectedMarkerId` is given.\n */\n markers?: MapMarker[];\n /** Controlled selection — fires `onMarkerClick` with the new id (or null on map click). */\n selectedMarkerId?: string | null;\n /** Fires when a marker is clicked, or `null` when the map background is clicked. */\n onMarkerClick?: (id: string | null) => void;\n /**\n * GDPR consent gate. When `false` (default) the component renders a\n * placeholder with a translated CTA — the Maps JS API is **not**\n * loaded. Flip to `true` once the consumer has captured opt-in.\n */\n consentGranted?: boolean;\n /** Fires when the consumer clicks the \"Load map\" CTA in the placeholder. */\n onConsentRequest?: () => void;\n /**\n * Optional address string shown in the consent placeholder so the\n * surface is useful before the map loads. Also used to build the\n * fallback \"Open in Google Maps\" link target.\n */\n address?: string;\n /**\n * Cloud-styled-map id. When set, takes precedence over the JSON\n * `styles` array and disables the theme-bridge re-fire. Use when\n * you've provisioned a styled map in Google Cloud Console.\n */\n mapId?: string;\n /**\n * Override the consent-placeholder description text. The default\n * (`t('mapView.consentDescription')`) is a generic IP-disclosure\n * line. Consumers operating under specific GDPR / ePrivacy\n * disclosures (jurisdiction, named controller, policy link) should\n * supply their own text via this prop. Pass any `ReactNode` — a\n * paragraph, a localised `<Trans>` instance, etc.\n */\n consentDescription?: ReactNode;\n /**\n * Replace the kit-rendered \"Load map\" button with custom CTA chrome.\n * Use when the consent dialog needs a policy link, a specific\n * jurisdiction phrasing, or a different surface (Tooltip-wrapped\n * button, link to a settings page, etc.). When omitted the kit\n * renders its own `<Button>` — that button calls `onConsentRequest`\n * if provided, otherwise flips MapView's internal opt-in state so\n * the map loads inline.\n */\n consentCta?: ReactNode;\n /**\n * Visual surface. Default `bordered` (current behaviour: 1px\n * `--border` outline + `--radius-md`). `elevated` replaces the\n * border with `--shadow-card`, matching `<Card variant=\"elevated\">`.\n * `bare` drops both — map is flush against the page canvas.\n */\n surface?: 'bordered' | 'elevated' | 'bare';\n /** Accessible label for the map region. Falls back to `t('mapView.label')`. */\n ariaLabel?: string;\n /**\n * Points the camera fits into view, with a margin, once the map has\n * loaded, and again whenever `fitKey` changes. Use it to show every pin\n * of a result list without the patient moving the map.\n *\n * - One point (or several at the same place) centres on it at\n * `fitMaxZoom`.\n * - No points: no fit, the camera shows `center` / `zoom`. If the\n * points run out after a fit, or the prop is removed, the camera\n * goes back there in one step.\n * - Between key changes nothing refits, so a map the patient has\n * panned or zoomed stays where they left it.\n * - A key change that only adds points (a \"load more\": every fitted\n * point is still there, compared by `id`) refits only if the patient\n * has not moved the map. Any other change refits. Give each point the\n * `id` of its result: two results can share an address.\n * - The camera is set in one step, never animated.\n * - While there are points to fit, the fit owns the camera: later\n * changes to `center` or `zoom` do not move it.\n */\n fitToPoints?: MapFitPoint[];\n /**\n * Identity of the fitted set: the camera refits only when this\n * changes. Pass the ids of the listed results, so re-sorting the same\n * results does not refit. Defaults to the points themselves, in any\n * order.\n */\n fitKey?: string;\n /**\n * The closest a fit may zoom in, so one result does not open at street\n * level. Default 15.\n */\n fitMaxZoom?: number;\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst mapViewVariants = cva(\n ['ds:relative ds:overflow-hidden ds:block', 'ds:bg-[var(--muted)]'].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:[--map-block-size:14rem]',\n md: 'ds:[--map-block-size:20rem]',\n lg: 'ds:[--map-block-size:28rem]',\n // `fill` defers sizing to the parent. The outer takes\n // `block-size: 100%` so the inner (also 100%) has something\n // to inherit from. Use inside a viewport-locked column —\n // `<PracticeResults variant=\"map-first\">` wires this through\n // automatically; standalone consumers must give the parent\n // a constrained block-size or the map collapses to 0.\n fill: 'ds:[block-size:100%]',\n },\n surface: {\n bordered:\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n elevated:\n 'ds:rounded-[var(--radius-md)] ds:shadow-[var(--shadow-card)] ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)]',\n bare: 'ds:rounded-none ds:border-0',\n },\n },\n defaultVariants: { size: 'md', surface: 'bordered' },\n },\n);\n\n// Inner block-size: percentage when `size=\"fill\"`, rem-token otherwise.\n// Splitting this out (instead of compound-variants) keeps the size\n// switch readable and avoids enumerating every (size × surface) pair.\nconst innerSurfaceVariants = cva('ds:block ds:inline-size-full', {\n variants: {\n size: {\n sm: 'ds:[block-size:var(--map-block-size)]',\n md: 'ds:[block-size:var(--map-block-size)]',\n lg: 'ds:[block-size:var(--map-block-size)]',\n fill: 'ds:[block-size:100%]',\n },\n },\n defaultVariants: { size: 'md' },\n});\n\nconst consentChromeVariants = cva(\n [\n 'ds:absolute ds:inset-0',\n 'ds:flex ds:flex-col ds:items-center ds:justify-center',\n 'ds:gap-[var(--spacing-sm)]',\n 'ds:p-[var(--spacing-md)]',\n 'ds:bg-[var(--muted)] ds:text-[var(--foreground)]',\n 'ds:text-center',\n ].join(' '),\n);\n\nconst consentTitleVariants = cva('type-heading-3 ds:m-0');\n\nconst consentDescriptionVariants = cva(\n 'type-body-sm ds:text-[var(--muted-foreground)] ds:[max-inline-size:28rem] ds:m-0',\n);\n\n/* ------------------------------------------------------------------ */\n/* Inner imperative bridge */\n/* */\n/* `useMap()` only resolves inside the APIProvider tree, so the */\n/* imperative actions live in a tiny inner component that the outer */\n/* `MapView` mounts conditionally. It exposes the `panTo` / `setZoom` */\n/* etc. to the forwardRef via a `useImperativeHandle` callback prop. */\n/* ------------------------------------------------------------------ */\n\ninterface MapImperativeBridgeProps {\n /** Called with the live handle on mount, and with `null` on unmount. */\n onHandleReady: (handle: MapBridgeHandle | null) => void;\n onMarkerSelect: (id: string | null) => void;\n}\n\nfunction MapImperativeBridge({\n onHandleReady,\n onMarkerSelect,\n}: MapImperativeBridgeProps): null {\n const map = useMap();\n useEffect(() => {\n if (!map) return;\n onHandleReady({\n panTo: (position) => map.panTo(position),\n setZoom: (zoom) => map.setZoom(zoom),\n jumpTo: (center, zoom) => map.moveCamera({ center, zoom }),\n selectMarker: (id) => onMarkerSelect(id),\n // Read straight off the live map: Google clamps `setZoom` to the\n // map type's range and animates `panTo`, so requested and applied\n // are not the same value.\n getCenter: () => map.getCenter()?.toJSON() ?? null,\n getZoom: () => map.getZoom() ?? null,\n });\n // Drop the handle when the subtree unmounts (consent revoked, or the\n // component tears down) so the outer getters answer `null` instead of\n // reporting a dead map's last known position.\n return () => onHandleReady(null);\n }, [map, onHandleReady, onMarkerSelect]);\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Fit to points */\n/* */\n/* Lives inside <GoogleMap>, so it only runs once the `maps` library */\n/* has arrived and `useMap()` holds a real map: the load-race rule */\n/* below applies to it too. The camera is computed here (Web Mercator) */\n/* and set in one step, rather than through fitBounds: fitBounds takes */\n/* no zoom limit, and capping it afterwards needs an `idle` event that */\n/* Google may never send when the view does not change, so the cap */\n/* could fire on the patient's next zoom instead. Setting the camera */\n/* directly is synchronous and never animates (reduced motion). */\n/* */\n/* A map in a hidden column or a sheet still opening has no size yet, */\n/* so the fit waits for the map to be laid out. */\n/* ------------------------------------------------------------------ */\n\n/** Google's world is 256px wide at zoom 0. */\nconst WORLD_PX = 256;\n\nconst toRadians = (degrees: number): number => (degrees * Math.PI) / 180;\n\n/** Web Mercator y of a latitude: the world spans -π..π. */\nfunction mercatorY(lat: number): number {\n const sin = Math.min(Math.max(Math.sin(toRadians(lat)), -0.9999), 0.9999);\n return Math.log((1 + sin) / (1 - sin)) / 2;\n}\n\nconst latitudeOf = (y: number): number =>\n (Math.atan(Math.sinh(y)) * 180) / Math.PI;\n\n/** The box round `points` (not antimeridian-aware: the kit maps Europe). */\nfunction boundsOfPoints(points: MapLatLng[]): google.maps.LatLngBoundsLiteral {\n let north = -90;\n let south = 90;\n let east = -180;\n let west = 180;\n for (const { lat, lng } of points) {\n north = Math.max(north, lat);\n south = Math.min(south, lat);\n east = Math.max(east, lng);\n west = Math.min(west, lng);\n }\n return { north, south, east, west };\n}\n\n/**\n * The centre and the closest whole zoom that shows every point inside a\n * `width` x `height` map, `padding` px in from each edge, no closer than\n * `maxZoom`. Exported for tests.\n */\nexport function cameraForPoints(\n points: MapLatLng[],\n width: number,\n height: number,\n padding: number,\n maxZoom: number,\n): { center: MapLatLng; zoom: number } {\n const { north, south, east, west } = boundsOfPoints(points);\n if (north === south && east === west) {\n return { center: { lat: north, lng: east }, zoom: maxZoom };\n }\n const top = mercatorY(north);\n const bottom = mercatorY(south);\n const center = {\n lat: latitudeOf((top + bottom) / 2),\n lng: (east + west) / 2,\n };\n const fit = (px: number, fraction: number): number =>\n fraction > 0 ? Math.log2(Math.max(px, 1) / WORLD_PX / fraction) : maxZoom;\n const zoom = Math.min(\n fit(width - 2 * padding, (east - west) / 360),\n fit(height - 2 * padding, (top - bottom) / (2 * Math.PI)),\n maxZoom,\n );\n return { center, zoom: Math.max(0, Math.floor(zoom)) };\n}\n\n/** A fit point's identity: its id, or else its coordinates. */\nconst pointKey = ({ id, lat, lng }: MapFitPoint): string =>\n id != null ? `id:${id}` : `at:${lat},${lng}`;\n\ninterface MapFitterProps {\n points: MapFitPoint[];\n fitKey: string;\n maxZoom: number;\n}\n\nfunction MapFitter({ points, fitKey, maxZoom }: MapFitterProps): null {\n const map = useMap();\n const fitted = useRef<{\n map: google.maps.Map;\n key: string;\n points: Set<string>;\n } | null>(null);\n // Whether the patient has panned or zoomed since the last fit: any\n // camera the kit did not set counts. Comparing with the camera the kit\n // last set (rather than flagging the kit's own call) holds whether\n // Google reports the change at once or later, and catches keyboard and\n // control-button pans, which fire no `dragstart`.\n const userMoved = useRef(false);\n const ownCamera = useRef<{ center: MapLatLng; zoom: number } | null>(null);\n\n useEffect(() => {\n if (!map) return undefined;\n const check = (): void => {\n const own = ownCamera.current;\n const center = map.getCenter()?.toJSON();\n const zoom = map.getZoom();\n const same =\n own != null &&\n zoom === own.zoom &&\n center != null &&\n Math.abs(center.lat - own.center.lat) < 1e-6 &&\n Math.abs(center.lng - own.center.lng) < 1e-6;\n if (!same) userMoved.current = true;\n };\n const listeners = [\n map.addListener('dragstart', () => {\n userMoved.current = true;\n }),\n map.addListener('center_changed', check),\n map.addListener('zoom_changed', check),\n ];\n return () => listeners.forEach((listener) => listener.remove());\n }, [map]);\n\n useEffect(() => {\n if (!map) return undefined;\n const last = fitted.current?.map === map ? fitted.current : null;\n if (last?.key === fitKey) return undefined;\n const keys = new Set(points.map(pointKey));\n const moveCamera = (center: MapLatLng, zoom: number): void => {\n ownCamera.current = { center, zoom };\n // One step, never animated.\n map.moveCamera({ center, zoom });\n userMoved.current = false;\n };\n\n if (points.length === 0) {\n // Nothing to fit. MapView returns the camera to center/zoom when\n // fitting ends. Recording the empty set means the same results\n // coming back later count as a change and fit again.\n fitted.current = { map, key: fitKey, points: keys };\n return undefined;\n }\n\n // More of the same results (\"load more\"): every point already fitted\n // is still listed, by identity. If the patient has moved the map,\n // their view wins. A result replaced by another at the same address\n // is a different id, so that set refits.\n const grewOnly =\n last != null &&\n last.points.size > 0 &&\n [...last.points].every((point) => keys.has(point));\n if (grewOnly && userMoved.current) {\n fitted.current = { map, key: fitKey, points: keys };\n return undefined;\n }\n\n const div = map.getDiv();\n // Only a fake map has no element; there is nothing to measure.\n if (!(div instanceof Element)) return undefined;\n const fit = (): void => {\n fitted.current = { map, key: fitKey, points: keys };\n // Never more than a quarter of either side, so a small map still\n // has room to fit the points rather than zooming out to the world.\n const padding = Math.min(\n lengthTokenPx('--spacing-2xl', div, 48),\n div.clientWidth / 4,\n div.clientHeight / 4,\n );\n const { center, zoom } = cameraForPoints(\n points,\n div.clientWidth,\n div.clientHeight,\n padding,\n maxZoom,\n );\n moveCamera(center, zoom);\n };\n const laidOut = (): boolean => div.clientWidth > 0 && div.clientHeight > 0;\n if (laidOut() || typeof ResizeObserver === 'undefined') {\n fit();\n return undefined;\n }\n const observer = new ResizeObserver(() => {\n if (!laidOut()) return;\n observer.disconnect();\n fit();\n });\n observer.observe(div);\n return () => observer.disconnect();\n }, [map, fitKey, points, maxZoom]);\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Library gates */\n/* */\n/* APIProvider reports LOADED as soon as `google.maps.importLibrary` */\n/* exists when another loader installed it (Google's bootstrap, a host */\n/* Places loader), before the `maps` library itself has arrived. <Map> */\n/* would then run `new google.maps.Map` and throw, taking the host's */\n/* React tree down. The map waits for `maps`, and the markers for */\n/* `marker`, whoever loaded the API. Before the API loads, <Map> only */\n/* renders its empty container, and once a constructor exists nothing */\n/* can throw, so both pass straight through as they always did. */\n/* ------------------------------------------------------------------ */\n\ntype GoogleMapsGlobal = {\n google?: { maps?: { Map?: unknown; Marker?: unknown } };\n};\nconst hasConstructor = (name: 'Map' | 'Marker'): boolean =>\n typeof (globalThis as GoogleMapsGlobal).google?.maps?.[name] === 'function';\n\n/** What the map area shows while Google's map library is on its way.\n * Exported for its story; not part of the public API. */\nexport function MapViewLoading(): ReactNode {\n const { t } = useTranslation('ui');\n return (\n <div\n role=\"status\"\n data-testid=\"map-view-loading\"\n className=\"ds:[inline-size:100%] ds:[block-size:100%]\"\n >\n <Skeleton variant=\"rectangular\" width=\"100%\" height=\"100%\" />\n <VisuallyHidden>{t('common.loading')}</VisuallyHidden>\n </div>\n );\n}\n\nfunction MapsLibraryGate({ children }: { children: ReactNode }): ReactNode {\n const apiIsLoaded = useApiIsLoaded();\n const maps = useMapsLibrary('maps');\n if (maps || !apiIsLoaded || hasConstructor('Map')) return children;\n return <MapViewLoading />;\n}\n\nfunction MarkerLibraryGate({ children }: { children: ReactNode }): ReactNode {\n const marker = useMapsLibrary('marker');\n return marker || hasConstructor('Marker') ? children : null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Consent placeholder */\n/* ------------------------------------------------------------------ */\n\ninterface ConsentPlaceholderProps {\n address: string | undefined;\n description: ReactNode;\n /**\n * Click handler for the \"Load map\" button. Always rendered. When the\n * consumer provides `onConsentRequest` it owns the state transition\n * (typically: open a GDPR dialog, then flip `consentGranted` to true\n * after acceptance). When omitted, the kit's `MapView` falls back to\n * its own internal opt-in toggle — clicking grants consent for this\n * MapView instance only, no consumer plumbing required. This default\n * fixes a regression where the button was conditionally rendered and\n * any consumer omitting `onConsentRequest` left the patient with no\n * way to load the map (booking-website 0.31.0 hit this).\n */\n onLoadMap: () => void;\n openInGoogleMapsHref: string;\n /**\n * Custom CTA — replaces the kit-rendered `<Button>` when the consumer\n * needs a different surface (e.g. a Tooltip-wrapped button with a\n * policy link). The kit's button is still the recommended path; this\n * slot exists for consumers operating under specific compliance UX\n * requirements (jurisdiction, named controller, policy link). Pass\n * any `ReactNode`.\n */\n consentCta: ReactNode | undefined;\n}\n\nfunction ConsentPlaceholder({\n address,\n description,\n onLoadMap,\n openInGoogleMapsHref,\n consentCta,\n}: ConsentPlaceholderProps): ReactNode {\n const { t } = useTranslation('ui');\n return (\n <div className={consentChromeVariants()} data-testid=\"map-view-consent\">\n <MapPin\n aria-hidden=\"true\"\n className=\"ds:size-6 ds:text-[var(--muted-foreground)]\"\n />\n <p className={consentTitleVariants()}>{t('mapView.consentTitle')}</p>\n {address ? (\n <p\n className={consentDescriptionVariants()}\n data-testid=\"map-view-address\"\n >\n {address}\n </p>\n ) : null}\n <p className={consentDescriptionVariants()}>{description}</p>\n <div className=\"ds:flex ds:gap-[var(--spacing-sm)] ds:flex-wrap ds:items-center ds:justify-center\">\n {consentCta ?? (\n <Button\n type=\"button\"\n intent=\"primary\"\n size=\"sm\"\n onClick={onLoadMap}\n data-testid=\"map-view-load-cta\"\n >\n {t('mapView.consentCta')}\n </Button>\n )}\n <a\n href={openInGoogleMapsHref}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)] ds:text-[var(--primary)] ds:underline ds:underline-offset-2\"\n >\n {t('mapView.openInGoogleMaps')}\n <ExternalLink aria-hidden=\"true\" className=\"ds:size-3\" />\n </a>\n </div>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* MapView */\n/* ------------------------------------------------------------------ */\n\nexport const MapView = forwardRef<MapViewHandle, MapViewProps>(\n (\n {\n id,\n apiKey,\n center,\n zoom = 15,\n markers,\n selectedMarkerId,\n onMarkerClick,\n consentGranted = false,\n onConsentRequest,\n address,\n consentDescription,\n consentCta,\n mapId,\n size,\n surface,\n ariaLabel,\n fitToPoints,\n fitKey,\n fitMaxZoom = 15,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const fitPoints = useMemo(() => fitToPoints ?? [], [fitToPoints]);\n // Identity and place: a result that keeps its id but moves (a\n // corrected address) still refits. \"Only grew\" uses identity alone.\n const resolvedFitKey = useMemo(\n () =>\n fitKey ??\n fitPoints\n .map((point) => `${pointKey(point)}@${point.lat},${point.lng}`)\n .sort()\n .join('|'),\n [fitKey, fitPoints],\n );\n // While there are points, the fit owns the camera (see `fitToPoints`).\n const fitting = fitPoints.length > 0;\n const wasFitting = useRef(fitting);\n const rawId = useId();\n const instanceId = useMemo(\n () => `map-${rawId.replace(/[^a-zA-Z0-9-_]/g, '')}`,\n [rawId],\n );\n\n // Reduced-motion gating. Google's own pan / zoom animations\n // happen inside the Maps JS API and the kit can't reach into\n // those — but the kit's own programmatic `panTo` calls (triggered\n // by prop changes via the controlled-sync effect below) can be\n // suppressed. When `prefers-reduced-motion: reduce` is set, we\n // skip the synthetic `panTo` so the consumer's prop change\n // results in a hard recenter rather than an animated glide.\n const [reducedMotion, setReducedMotion] = useState(false);\n useEffect(() => {\n if (typeof window === 'undefined') return undefined;\n const mql = window.matchMedia('(prefers-reduced-motion: reduce)');\n const sync = (): void => setReducedMotion(mql.matches);\n sync();\n mql.addEventListener('change', sync);\n return () => mql.removeEventListener('change', sync);\n }, []);\n\n // The \"Open in Google Maps\" fallback link — works without any\n // third-party script load. Uses the modern `?api=1&query=…` form\n // which the booking site already employs.\n const openInGoogleMapsHref = useMemo(() => {\n const query = address\n ? encodeURIComponent(address)\n : `${center.lat},${center.lng}`;\n return `https://www.google.com/maps/search/?api=1&query=${query}`;\n }, [address, center.lat, center.lng]);\n\n // 0.33.5: removed the kit's `getGoogleMapsTheme()` JSON-styles\n // override. Previously, when `mapId` was absent the kit painted\n // water / roads / landscape with kit tokens — a calm muted-grey\n // palette that diverged from the standard Google Maps appearance\n // users expect in every other maps surface they touch. Google's\n // default (blue water, beige land, named-road colours) is more\n // familiar and reads as a \"real map\" rather than a stylised one.\n //\n // Consumers wanting brand-themed colours opt in via `mapId` and\n // configure the palette in Google Cloud Console — that's the\n // Google-recommended path. The `getGoogleMapsTheme` export stays\n // in `src/tokens/google-maps-theme.ts` so consumers wanting the\n // old behaviour can apply the styles themselves, but the kit\n // does NOT install them by default any more.\n //\n // Side benefit: dropped the MutationObserver that previously\n // watched documentElement.class for theme switches — no more\n // observer churn on every theme toggle.\n\n // Imperative handle plumbing — populated by the inner bridge once\n // the APIProvider tree resolves a `Map` instance.\n const handleRef = useRef<MapBridgeHandle | null>(null);\n const onHandleReady = useCallback((handle: MapBridgeHandle | null) => {\n handleRef.current = handle;\n }, []);\n\n // Read in the OUTER component, not through `handleRef` — these three\n // must still answer when the map subtree is unmounted, which is\n // exactly the situation an agent needs explaining. Assigned during\n // render, below, once `effectiveConsent` exists.\n const consentRef = useRef(false);\n const selectedMarkerIdRef = useRef<string | null>(null);\n const markerCountRef = useRef(0);\n\n const buildHandle = useCallback(\n (): MapViewHandle => ({\n panTo: (position) => handleRef.current?.panTo(position),\n setZoom: (z) => handleRef.current?.setZoom(z),\n selectMarker: (markerId) => handleRef.current?.selectMarker(markerId),\n // Without `isConsentGranted` an agent has no way to learn that\n // its pan / zoom / select was swallowed by the GDPR gate rather\n // than applied: under the default (`consentGranted={false}`) the\n // whole Maps subtree is unmounted and every action optional-chains\n // into nothing.\n isConsentGranted: () => consentRef.current,\n getCenter: () => handleRef.current?.getCenter() ?? null,\n getZoom: () => handleRef.current?.getZoom() ?? null,\n getSelectedMarkerId: () => selectedMarkerIdRef.current,\n getMarkerCount: () => markerCountRef.current,\n }),\n [],\n );\n useImperativeHandle(ref, buildHandle, [buildHandle]);\n\n const agentHandle = useMemo<MapViewHandle>(\n () => buildHandle(),\n [buildHandle],\n );\n useAgentRegistration(mapViewAgent, agentHandle, id);\n\n // Controlled-feeling propagation: vis.gl's `<Map>` reads `center`\n // and `zoom` as initial values only (via `defaultCenter` /\n // `defaultZoom`). To honour the documented \"live prop\" contract\n // we shim post-mount sync through the imperative bridge — a\n // parent that swaps offices by changing `center` re-centres the\n // map. User drag does NOT trigger this because the prop doesn't\n // change on user gesture, so the effect doesn't fire and the\n // map stays where the user left it.\n //\n // While fitting, the fit owns the camera and both syncs stand down.\n // `fitting` is a dependency, so when fitting ends (the points run out\n // or `fitToPoints` is removed) the camera returns to `center` / `zoom`\n // even if neither changed. That return is one step, not animated, so\n // it applies under reduced motion too.\n useEffect(() => {\n const fitEnded = wasFitting.current && !fitting;\n wasFitting.current = fitting;\n if (fitting) return;\n if (fitEnded) {\n handleRef.current?.jumpTo(center, zoom);\n return;\n }\n // Skip the animated pan under reduced-motion preference; the\n // map will still recentre on the next render via the agent\n // handle's `panTo`, but Google's own glide animation runs\n // either way (kit can't reach inside it). At least the kit's\n // own initiated pan is gated.\n if (reducedMotion) return;\n handleRef.current?.panTo(center);\n // Including `center` (the object reference) instead of\n // `center.lat`/`center.lng` would fire on every parent render\n // even when the coordinates are identical, fighting user drag.\n // `zoom` is read only when fitting ends; its own sync is below.\n // The destructured deps are intentional.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [center.lat, center.lng, reducedMotion, fitting]);\n useEffect(() => {\n if (fitting) return;\n handleRef.current?.setZoom(zoom);\n }, [zoom, fitting]);\n\n // Internal opt-in fallback. The `consentGranted` prop is the\n // controlled path — consumer flips it after capturing GDPR\n // acceptance through their own dialog and re-renders. When the\n // consumer omits `onConsentRequest` they're opting out of that\n // workflow, so the kit needs a sensible default click handler on\n // the placeholder's button. `internalConsent` tracks that opt-in\n // for this instance only; the map renders when either signal is\n // truthy. The 0.31.0 regression was conditionally rendering the\n // button on `onConsentRequest` — patients of consumers without the\n // hook saw the placeholder with no way to proceed.\n const [internalConsent, setInternalConsent] = useState(false);\n const effectiveConsent = consentGranted || internalConsent;\n // Mirror the three props-derived agent state slots. Assigned during\n // render so a read immediately after a prop change sees the settled\n // value. Ids and a count only — never `MapMarker.label`, never the\n // `address` prop (consumer-supplied free text, PII in any\n // patient-address deployment), never `apiKey`.\n consentRef.current = effectiveConsent;\n selectedMarkerIdRef.current = selectedMarkerId ?? null;\n markerCountRef.current = (markers ?? []).length;\n const handleLoadMap = useCallback(() => {\n if (onConsentRequest) {\n onConsentRequest();\n // The consumer typically flips `consentGranted` to true on the\n // next render. Flip the internal state too so the map still\n // loads if the consumer forgets to update its prop (the\n // common-case footgun this fallback exists to defuse).\n setInternalConsent(true);\n return;\n }\n setInternalConsent(true);\n }, [onConsentRequest]);\n\n return (\n <div\n className={mapViewVariants({ size, surface, className })}\n data-component=\"map-view\"\n data-component-id={id ?? instanceId}\n role=\"region\"\n aria-label={ariaLabel ?? t('mapView.label')}\n {...rest}\n >\n <div className={innerSurfaceVariants({ size })}>\n {effectiveConsent ? (\n <APIProvider\n apiKey={apiKey}\n // Pull the active i18next locale through so map UI text\n // (zoom controls, attribution) localises to match the\n // surrounding kit chrome.\n language={i18n.language}\n >\n <MapsLibraryGate>\n <GoogleMap\n defaultCenter={center}\n defaultZoom={zoom}\n mapId={mapId}\n gestureHandling=\"cooperative\"\n disableDefaultUI={false}\n onClick={() => onMarkerClick?.(null)}\n // `<Map>` reads its own bounding rect for tile sizing.\n // Without explicit dimensions it collapses to 0×0, so\n // we pass kit-class sizing through `className` — vis.gl\n // forwards `className` straight to the rendered root.\n className=\"ds:[inline-size:100%] ds:[block-size:100%]\"\n >\n <MapImperativeBridge\n onHandleReady={onHandleReady}\n onMarkerSelect={(markerId) => onMarkerClick?.(markerId)}\n />\n {fitToPoints ? (\n <MapFitter\n points={fitPoints}\n fitKey={resolvedFitKey}\n maxZoom={fitMaxZoom}\n />\n ) : null}\n <MarkerLibraryGate>\n {(markers ?? []).map((marker) => {\n // Selection state is exposed to the consumer via\n // `data-selected` on the marker root so consumers can\n // style their own InfoWindow / sidebar highlight from\n // it. The kit does NOT swap the Pin's fill colour on\n // selection — `--accent` (magenta-500 in light theme)\n // fails AA on white per 05-accessibility.mdx, and the\n // alternative tokens that pass (`--info`, `--success`)\n // carry semantic baggage. Visual selection state is\n // the consumer's call.\n const isSelected =\n selectedMarkerId != null &&\n selectedMarkerId === marker.id;\n const accessibleLabel = t('mapView.markerLabel', {\n label: marker.label ?? marker.id,\n });\n // Pin implementation switches on whether the\n // consumer supplied `mapId`. Google's\n // AdvancedMarkerElement requires the Map instance to\n // be initialised with a valid Map ID — without one\n // the API logs an error (\"La mappa è stata\n // inizializzata senza un ID mappa valido\") and any\n // AdvancedMarker rendered against that map fails to\n // appear. Cloud Map IDs are an opt-in feature; many\n // consumers (booking-website env without\n // GOOGLE_MAPS_MAP_ID, the OSS demo, etc.) legitimately\n // omit it.\n //\n // Fall back to the classic <Marker> (a thin wrapper\n // around google.maps.Marker) when mapId is absent.\n // Google has formally deprecated google.maps.Marker\n // but it still renders cleanly and produces no\n // console errors; the only loss is the brand-tinted\n // <Pin> chrome (which Marker doesn't accept as a\n // child). When a consumer wants the styled pin they\n // can opt back in by supplying `mapId`.\n if (mapId) {\n return (\n <AdvancedMarker\n key={marker.id}\n position={marker.position}\n // `title` becomes the HTML `title` attribute on\n // Google's marker wrapper — that's a tooltip, not\n // a reliable accessible name. The wrapper also\n // receives `aria-label` which Google honours as\n // the SR-announced name. Both are set so sighted\n // hover tooltips and SR labels stay aligned.\n title={accessibleLabel}\n aria-label={accessibleLabel}\n data-selected={isSelected ? 'true' : 'false'}\n onClick={() => onMarkerClick?.(marker.id)}\n >\n <Pin\n background={'var(--primary)'}\n borderColor={'var(--primary)'}\n glyphColor={'var(--primary-foreground)'}\n />\n </AdvancedMarker>\n );\n }\n return (\n <Marker\n key={marker.id}\n position={marker.position}\n title={accessibleLabel}\n onClick={() => onMarkerClick?.(marker.id)}\n />\n );\n })}\n </MarkerLibraryGate>\n </GoogleMap>\n </MapsLibraryGate>\n </APIProvider>\n ) : (\n <ConsentPlaceholder\n address={address}\n description={\n consentDescription ?? t('mapView.consentDescription')\n }\n onLoadMap={handleLoadMap}\n consentCta={consentCta}\n openInGoogleMapsHref={openInGoogleMapsHref}\n />\n )}\n </div>\n </div>\n );\n },\n);\nMapView.displayName = 'MapView';\n"],"names":["mapViewAgent","handle","args","mapViewVariants","cva","innerSurfaceVariants","consentChromeVariants","consentTitleVariants","consentDescriptionVariants","MapImperativeBridge","onHandleReady","onMarkerSelect","map","useMap","useEffect","position","zoom","center","id","_a","WORLD_PX","toRadians","degrees","mercatorY","lat","sin","latitudeOf","y","boundsOfPoints","points","north","south","east","west","lng","cameraForPoints","width","height","padding","maxZoom","top","bottom","fit","px","fraction","pointKey","MapFitter","fitKey","fitted","useRef","userMoved","ownCamera","check","own","listeners","listener","last","keys","moveCamera","point","div","lengthTokenPx","laidOut","observer","hasConstructor","name","_b","MapViewLoading","t","useTranslation","jsxs","jsx","Skeleton","VisuallyHidden","MapsLibraryGate","children","apiIsLoaded","useApiIsLoaded","useMapsLibrary","MarkerLibraryGate","ConsentPlaceholder","address","description","onLoadMap","openInGoogleMapsHref","consentCta","MapPin","Button","ExternalLink","MapView","forwardRef","apiKey","markers","selectedMarkerId","onMarkerClick","consentGranted","onConsentRequest","consentDescription","mapId","size","surface","ariaLabel","fitToPoints","fitMaxZoom","className","rest","ref","i18n","fitPoints","useMemo","resolvedFitKey","fitting","wasFitting","rawId","useId","instanceId","reducedMotion","setReducedMotion","useState","mql","sync","handleRef","useCallback","consentRef","selectedMarkerIdRef","markerCountRef","buildHandle","z","markerId","useImperativeHandle","agentHandle","useAgentRegistration","fitEnded","internalConsent","setInternalConsent","effectiveConsent","handleLoadMap","APIProvider","GoogleMap","marker","isSelected","accessibleLabel","AdvancedMarker","Pin","Marker"],"mappings":"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"}
@@ -3,13 +3,13 @@ import { forwardRef as V, useState as ve, useCallback as ge, useEffect as K, use
3
3
  import { useTranslation as B, Trans as xe } from "react-i18next";
4
4
  import { c as p } from "./index-D2ZczOXr.js";
5
5
  import { A as q } from "./app-frame-DUPEwu4E.js";
6
- import { A as F } from "./avatar-WZY3eGE7.js";
7
- import { A as be } from "./alert-DjsJMGRE.js";
6
+ import { A as F } from "./avatar-BPiPL7ND.js";
7
+ import { A as be } from "./alert-9kEwDza3.js";
8
8
  import { C as U } from "./card-BA4Ig_kn.js";
9
9
  import { D as u } from "./dropdown-menu-D1we7oAY.js";
10
10
  import { T as ke } from "./tab-bar-BEODTG6k.js";
11
11
  import { a as Y, H as we, g as Ne, f as G, e as ye, c as Se, d as Ce } from "./header-_TppWBpK.js";
12
- import { H as Ae } from "./header-settings-BSH9Gk0J.js";
12
+ import { H as Ae } from "./header-settings-DlUbvAUx.js";
13
13
  import { S as Te } from "./sign-in-with-alfadocs-button-CIv0GgeA.js";
14
14
  import { S as Ee, a as ee, v as ze, h as Ie, c as Me, r as Le, b as He, l as Ve, m as Be, k as Re, j as J } from "./sidebar-BS24EnYd.js";
15
15
  import { N as De } from "./navigation-dismiss-B1mcW1CT.js";
@@ -656,4 +656,4 @@ export {
656
656
  na as M,
657
657
  y as P
658
658
  };
659
- //# sourceMappingURL=marketplace-app-shell-DtSX8sYb.js.map
659
+ //# sourceMappingURL=marketplace-app-shell-CcLQ0Dn-.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace-app-shell-DtSX8sYb.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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"}
1
+ {"version":3,"file":"marketplace-app-shell-CcLQ0Dn-.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-C_1TgRiK.js";
6
6
  import { B as V } from "./button-D-MQxsA_.js";
7
- import { A as rs } from "./avatar-WZY3eGE7.js";
7
+ import { A as rs } from "./avatar-BPiPL7ND.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-A3mJNqfy.js.map
327
+ //# sourceMappingURL=message-card-C_ksqIYM.js.map