@alfadocs/ui-kit-debug 0.38.0 → 0.39.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 (266) hide show
  1. package/dist/_chunks/{accordion-bSU21uTV.js → accordion-9lJSMMsZ.js} +6 -6
  2. package/dist/_chunks/accordion-9lJSMMsZ.js.map +1 -0
  3. package/dist/_chunks/{agenda-tray-By_asPN9.js → agenda-tray-Dyj9ChHC.js} +22 -21
  4. package/dist/_chunks/agenda-tray-Dyj9ChHC.js.map +1 -0
  5. package/dist/_chunks/{bmi-calculator-BRUru9QX.js → bmi-calculator-DnEr513I.js} +2 -2
  6. package/dist/_chunks/{bmi-calculator-BRUru9QX.js.map → bmi-calculator-DnEr513I.js.map} +1 -1
  7. package/dist/_chunks/{booking-DK_BPHnQ.js → booking-4mCw3Mpl.js} +2 -2
  8. package/dist/_chunks/{booking-DK_BPHnQ.js.map → booking-4mCw3Mpl.js.map} +1 -1
  9. package/dist/_chunks/{chart-DnHvmiDX.js → chart-Cbt0_sKv.js} +46 -37
  10. package/dist/_chunks/chart-Cbt0_sKv.js.map +1 -0
  11. package/dist/_chunks/{collapsible-CERONory.js → collapsible-X3oaLPU3.js} +5 -5
  12. package/dist/_chunks/collapsible-X3oaLPU3.js.map +1 -0
  13. package/dist/_chunks/{document-scanner-CdHQ6lTN.js → document-scanner-CqS_klIr.js} +56 -55
  14. package/dist/_chunks/document-scanner-CqS_klIr.js.map +1 -0
  15. package/dist/_chunks/{editable-currency-cell-renderer-DGKuRNVG.js → editable-currency-cell-renderer-DgkCIIcO.js} +2 -2
  16. package/dist/_chunks/{editable-currency-cell-renderer-DGKuRNVG.js.map → editable-currency-cell-renderer-DgkCIIcO.js.map} +1 -1
  17. package/dist/_chunks/{file-upload-CnzRcErt.js → file-upload-BosbPDb1.js} +2 -2
  18. package/dist/_chunks/file-upload-BosbPDb1.js.map +1 -0
  19. package/dist/_chunks/{freemium-paywall-D1N02Oam.js → freemium-paywall-BAk3a6er.js} +7 -7
  20. package/dist/_chunks/{freemium-paywall-D1N02Oam.js.map → freemium-paywall-BAk3a6er.js.map} +1 -1
  21. package/dist/_chunks/header-settings-CBLwUK6t.js +244 -0
  22. package/dist/_chunks/header-settings-CBLwUK6t.js.map +1 -0
  23. package/dist/_chunks/{map-view-vD5pvWs9.js → map-view-qJLybrmN.js} +2 -2
  24. package/dist/_chunks/{map-view-vD5pvWs9.js.map → map-view-qJLybrmN.js.map} +1 -1
  25. package/dist/_chunks/marketplace-app-shell-BlxVizU4.js +296 -0
  26. package/dist/_chunks/marketplace-app-shell-BlxVizU4.js.map +1 -0
  27. package/dist/_chunks/{message-card-BbRhZkDI.js → message-card-DSPw5ghw.js} +20 -19
  28. package/dist/_chunks/message-card-DSPw5ghw.js.map +1 -0
  29. package/dist/_chunks/{message-tray-B762TKuv.js → message-tray-hSQff9u4.js} +3 -3
  30. package/dist/_chunks/message-tray-hSQff9u4.js.map +1 -0
  31. package/dist/_chunks/{notification-card-DMdO4g54.js → notification-card-CObnGdJu.js} +22 -21
  32. package/dist/_chunks/notification-card-CObnGdJu.js.map +1 -0
  33. package/dist/_chunks/{notification-tray-Dl3FTleW.js → notification-tray-BWHDIjgd.js} +2 -2
  34. package/dist/_chunks/{notification-tray-Dl3FTleW.js.map → notification-tray-BWHDIjgd.js.map} +1 -1
  35. package/dist/_chunks/{otp-input-CDTWT5EK.js → otp-input-CMphfBxZ.js} +70 -71
  36. package/dist/_chunks/otp-input-CMphfBxZ.js.map +1 -0
  37. package/dist/_chunks/{patient-shell-Bz3CdO84.js → patient-shell-DF81lALv.js} +36 -35
  38. package/dist/_chunks/{patient-shell-Bz3CdO84.js.map → patient-shell-DF81lALv.js.map} +1 -1
  39. package/dist/_chunks/{payment-form-D5rgnZu7.js → payment-form-Dy3WIIsC.js} +18 -18
  40. package/dist/_chunks/payment-form-Dy3WIIsC.js.map +1 -0
  41. package/dist/_chunks/{pdf-viewer-DvtEHcEP.js → pdf-viewer-Cy6Ul3hZ.js} +2 -2
  42. package/dist/_chunks/pdf-viewer-Cy6Ul3hZ.js.map +1 -0
  43. package/dist/_chunks/{practice-results-C8ciLQap.js → practice-results-C0d4IL5E.js} +2 -2
  44. package/dist/_chunks/{practice-results-C8ciLQap.js.map → practice-results-C0d4IL5E.js.map} +1 -1
  45. package/dist/_chunks/{public-footer.agent-zw1vFin_.js → public-footer.agent-okt8ZRc5.js} +2 -2
  46. package/dist/_chunks/{public-footer.agent-zw1vFin_.js.map → public-footer.agent-okt8ZRc5.js.map} +1 -1
  47. package/dist/_chunks/{reviews-panel-Dow8Dzoa.js → reviews-panel-CPrXu5TX.js} +2 -2
  48. package/dist/_chunks/{reviews-panel-Dow8Dzoa.js.map → reviews-panel-CPrXu5TX.js.map} +1 -1
  49. package/dist/_chunks/{sidebar-BbR8f6oe.js → sidebar-_vJXI9rB.js} +2 -2
  50. package/dist/_chunks/{sidebar-BbR8f6oe.js.map → sidebar-_vJXI9rB.js.map} +1 -1
  51. package/dist/_chunks/sign-document-DId1p-nn.js +315 -0
  52. package/dist/_chunks/sign-document-DId1p-nn.js.map +1 -0
  53. package/dist/_chunks/{signature-capture-C-fF71xI.js → signature-capture-BRzCklg4.js} +27 -24
  54. package/dist/_chunks/signature-capture-BRzCklg4.js.map +1 -0
  55. package/dist/_chunks/{sparkline-DEROcSl0.js → sparkline-DGhCSw8M.js} +55 -46
  56. package/dist/_chunks/sparkline-DGhCSw8M.js.map +1 -0
  57. package/dist/_chunks/{stepper-accordion-BfS6lUB9.js → stepper-accordion-Dki6r9ZE.js} +2 -2
  58. package/dist/_chunks/stepper-accordion-Dki6r9ZE.js.map +1 -0
  59. package/dist/_chunks/{tag-CyoaEmf_.js → tag-CdA0s_VV.js} +16 -16
  60. package/dist/_chunks/tag-CdA0s_VV.js.map +1 -0
  61. package/dist/_chunks/{task-card-BUVMh6HN.js → task-card-CPyQ5AXC.js} +6 -5
  62. package/dist/_chunks/task-card-CPyQ5AXC.js.map +1 -0
  63. package/dist/_chunks/{task-tray-DRK0b0Qb.js → task-tray-B8jFv5FV.js} +36 -35
  64. package/dist/_chunks/task-tray-B8jFv5FV.js.map +1 -0
  65. package/dist/_chunks/{transcript-panel-DyhTpAP7.js → transcript-panel-CR7VY1uw.js} +8 -7
  66. package/dist/_chunks/transcript-panel-CR7VY1uw.js.map +1 -0
  67. package/dist/_chunks/{warning-stack-bDicCvxs.js → warning-stack-DNR3-IbP.js} +17 -16
  68. package/dist/_chunks/warning-stack-DNR3-IbP.js.map +1 -0
  69. package/dist/_chunks/{workflow-map-uSiHbOWQ.js → workflow-map-C3gB0FvB.js} +3 -2
  70. package/dist/_chunks/{workflow-map-uSiHbOWQ.js.map → workflow-map-C3gB0FvB.js.map} +1 -1
  71. package/dist/agent-catalog.json +39 -1
  72. package/dist/brand/product-lockup/product-lockup.d.ts.map +1 -1
  73. package/dist/components/accordion/index.js +1 -1
  74. package/dist/components/agenda-tray/agenda-tray.d.ts.map +1 -1
  75. package/dist/components/agenda-tray/index.js +1 -1
  76. package/dist/components/bmi-calculator/index.js +1 -1
  77. package/dist/components/booking/index.js +1 -1
  78. package/dist/components/chart/chart.d.ts +1 -1
  79. package/dist/components/chart/chart.d.ts.map +1 -1
  80. package/dist/components/chart/index.js +1 -1
  81. package/dist/components/collapsible/index.js +1 -1
  82. package/dist/components/data-table/index.js +1 -1
  83. package/dist/components/document-scanner/document-scanner.d.ts.map +1 -1
  84. package/dist/components/document-scanner/index.js +1 -1
  85. package/dist/components/file-upload/index.js +1 -1
  86. package/dist/components/freemium-paywall/index.js +1 -1
  87. package/dist/components/header-settings/header-settings.agent.d.ts +4 -0
  88. package/dist/components/header-settings/header-settings.agent.d.ts.map +1 -0
  89. package/dist/components/header-settings/header-settings.d.ts +36 -0
  90. package/dist/components/header-settings/header-settings.d.ts.map +1 -0
  91. package/dist/components/header-settings/index.d.ts +2 -0
  92. package/dist/components/header-settings/index.d.ts.map +1 -0
  93. package/dist/components/header-settings/index.js +2 -241
  94. package/dist/components/header-settings/index.js.map +1 -1
  95. package/dist/components/index.d.ts +1 -0
  96. package/dist/components/index.d.ts.map +1 -1
  97. package/dist/components/locale-picker/locale-picker.agent.d.ts +4 -0
  98. package/dist/components/locale-picker/locale-picker.agent.d.ts.map +1 -0
  99. package/dist/components/locale-picker/locale-picker.d.ts +80 -0
  100. package/dist/components/locale-picker/locale-picker.d.ts.map +1 -0
  101. package/dist/components/map-view/index.js +1 -1
  102. package/dist/components/message-card/index.js +1 -1
  103. package/dist/components/message-card/message-card.d.ts.map +1 -1
  104. package/dist/components/message-tray/index.js +1 -1
  105. package/dist/components/notification-card/index.js +1 -1
  106. package/dist/components/notification-card/notification-card.d.ts.map +1 -1
  107. package/dist/components/notification-tray/index.js +1 -1
  108. package/dist/components/otp-input/index.d.ts +1 -1
  109. package/dist/components/otp-input/index.d.ts.map +1 -1
  110. package/dist/components/otp-input/index.js +1 -1
  111. package/dist/components/otp-input/otp-input.d.ts +1 -1
  112. package/dist/components/otp-input/otp-input.d.ts.map +1 -1
  113. package/dist/components/payment-form/index.js +1 -1
  114. package/dist/components/pdf-viewer/index.js +1 -1
  115. package/dist/components/practice-results/index.js +1 -1
  116. package/dist/components/public-footer/index.js +1 -1
  117. package/dist/components/reviews-panel/index.js +1 -1
  118. package/dist/components/sidebar/index.js +1 -1
  119. package/dist/components/sign-document/index.d.ts +4 -0
  120. package/dist/components/sign-document/index.d.ts.map +1 -0
  121. package/dist/components/sign-document/index.js +6 -0
  122. package/dist/components/sign-document/index.js.map +1 -0
  123. package/dist/components/sign-document/sign-document.agent.d.ts +4 -0
  124. package/dist/components/sign-document/sign-document.agent.d.ts.map +1 -0
  125. package/dist/components/sign-document/sign-document.d.ts +47 -0
  126. package/dist/components/sign-document/sign-document.d.ts.map +1 -0
  127. package/dist/components/signature-capture/index.js +1 -1
  128. package/dist/components/signature-capture/signature-capture.d.ts.map +1 -1
  129. package/dist/components/sparkline/index.js +1 -1
  130. package/dist/components/sparkline/sparkline.d.ts +1 -1
  131. package/dist/components/sparkline/sparkline.d.ts.map +1 -1
  132. package/dist/components/stepper-accordion/index.js +1 -1
  133. package/dist/components/tag/index.js +1 -1
  134. package/dist/components/task-card/index.js +1 -1
  135. package/dist/components/task-card/task-card.d.ts.map +1 -1
  136. package/dist/components/task-tray/index.js +1 -1
  137. package/dist/components/task-tray/task-tray.d.ts.map +1 -1
  138. package/dist/components/transcript-panel/index.js +1 -1
  139. package/dist/components/transcript-panel/transcript-panel.d.ts.map +1 -1
  140. package/dist/components/warning-stack/index.js +1 -1
  141. package/dist/components/warning-stack/warning-stack.d.ts.map +1 -1
  142. package/dist/components/workflow/index.js +1 -1
  143. package/dist/components/workflow/workflow-map.d.ts.map +1 -1
  144. package/dist/i18n/locale-meta.d.ts +56 -0
  145. package/dist/i18n/locale-meta.d.ts.map +1 -0
  146. package/dist/i18n/locales/ar.d.ts +22 -0
  147. package/dist/i18n/locales/ar.d.ts.map +1 -1
  148. package/dist/i18n/locales/ar.js +22 -0
  149. package/dist/i18n/locales/ar.js.map +1 -1
  150. package/dist/i18n/locales/de.d.ts +22 -0
  151. package/dist/i18n/locales/de.d.ts.map +1 -1
  152. package/dist/i18n/locales/de.js +22 -0
  153. package/dist/i18n/locales/de.js.map +1 -1
  154. package/dist/i18n/locales/el.d.ts +22 -0
  155. package/dist/i18n/locales/el.d.ts.map +1 -1
  156. package/dist/i18n/locales/el.js +22 -0
  157. package/dist/i18n/locales/el.js.map +1 -1
  158. package/dist/i18n/locales/en.d.ts +22 -0
  159. package/dist/i18n/locales/en.d.ts.map +1 -1
  160. package/dist/i18n/locales/en.js +22 -0
  161. package/dist/i18n/locales/en.js.map +1 -1
  162. package/dist/i18n/locales/es.d.ts +22 -0
  163. package/dist/i18n/locales/es.d.ts.map +1 -1
  164. package/dist/i18n/locales/es.js +22 -0
  165. package/dist/i18n/locales/es.js.map +1 -1
  166. package/dist/i18n/locales/fr.d.ts +22 -0
  167. package/dist/i18n/locales/fr.d.ts.map +1 -1
  168. package/dist/i18n/locales/fr.js +22 -0
  169. package/dist/i18n/locales/fr.js.map +1 -1
  170. package/dist/i18n/locales/hi.d.ts +22 -0
  171. package/dist/i18n/locales/hi.d.ts.map +1 -1
  172. package/dist/i18n/locales/hi.js +22 -0
  173. package/dist/i18n/locales/hi.js.map +1 -1
  174. package/dist/i18n/locales/it.d.ts +22 -0
  175. package/dist/i18n/locales/it.d.ts.map +1 -1
  176. package/dist/i18n/locales/it.js +22 -0
  177. package/dist/i18n/locales/it.js.map +1 -1
  178. package/dist/i18n/locales/ja.d.ts +22 -0
  179. package/dist/i18n/locales/ja.d.ts.map +1 -1
  180. package/dist/i18n/locales/ja.js +22 -0
  181. package/dist/i18n/locales/ja.js.map +1 -1
  182. package/dist/i18n/locales/nl.d.ts +22 -0
  183. package/dist/i18n/locales/nl.d.ts.map +1 -1
  184. package/dist/i18n/locales/nl.js +22 -0
  185. package/dist/i18n/locales/nl.js.map +1 -1
  186. package/dist/i18n/locales/pl.d.ts +22 -0
  187. package/dist/i18n/locales/pl.d.ts.map +1 -1
  188. package/dist/i18n/locales/pl.js +22 -0
  189. package/dist/i18n/locales/pl.js.map +1 -1
  190. package/dist/i18n/locales/pt.d.ts +22 -0
  191. package/dist/i18n/locales/pt.d.ts.map +1 -1
  192. package/dist/i18n/locales/pt.js +22 -0
  193. package/dist/i18n/locales/pt.js.map +1 -1
  194. package/dist/i18n/locales/ro.d.ts +22 -0
  195. package/dist/i18n/locales/ro.d.ts.map +1 -1
  196. package/dist/i18n/locales/ro.js +22 -0
  197. package/dist/i18n/locales/ro.js.map +1 -1
  198. package/dist/i18n/locales/ru.d.ts +22 -0
  199. package/dist/i18n/locales/ru.d.ts.map +1 -1
  200. package/dist/i18n/locales/ru.js +22 -0
  201. package/dist/i18n/locales/ru.js.map +1 -1
  202. package/dist/i18n/locales/sq.d.ts +22 -0
  203. package/dist/i18n/locales/sq.d.ts.map +1 -1
  204. package/dist/i18n/locales/sq.js +22 -0
  205. package/dist/i18n/locales/sq.js.map +1 -1
  206. package/dist/i18n/locales/sv.d.ts +22 -0
  207. package/dist/i18n/locales/sv.d.ts.map +1 -1
  208. package/dist/i18n/locales/sv.js +22 -0
  209. package/dist/i18n/locales/sv.js.map +1 -1
  210. package/dist/i18n/locales/tr.d.ts +22 -0
  211. package/dist/i18n/locales/tr.d.ts.map +1 -1
  212. package/dist/i18n/locales/tr.js +22 -0
  213. package/dist/i18n/locales/tr.js.map +1 -1
  214. package/dist/i18n/locales/zh.d.ts +22 -0
  215. package/dist/i18n/locales/zh.d.ts.map +1 -1
  216. package/dist/i18n/locales/zh.js +22 -0
  217. package/dist/i18n/locales/zh.js.map +1 -1
  218. package/dist/index.js +110 -107
  219. package/dist/index.js.map +1 -1
  220. package/dist/locales/ar.json +22 -0
  221. package/dist/locales/de.json +22 -0
  222. package/dist/locales/el.json +22 -0
  223. package/dist/locales/en.json +22 -0
  224. package/dist/locales/es.json +22 -0
  225. package/dist/locales/fr.json +22 -0
  226. package/dist/locales/hi.json +22 -0
  227. package/dist/locales/it.json +22 -0
  228. package/dist/locales/ja.json +22 -0
  229. package/dist/locales/nl.json +22 -0
  230. package/dist/locales/pl.json +22 -0
  231. package/dist/locales/pt.json +22 -0
  232. package/dist/locales/ro.json +22 -0
  233. package/dist/locales/ru.json +22 -0
  234. package/dist/locales/sq.json +22 -0
  235. package/dist/locales/sv.json +22 -0
  236. package/dist/locales/tr.json +22 -0
  237. package/dist/locales/zh.json +22 -0
  238. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  239. package/dist/patterns/marketplace-app-shell/marketplace-app-shell.d.ts +12 -8
  240. package/dist/patterns/marketplace-app-shell/marketplace-app-shell.d.ts.map +1 -1
  241. package/dist/patterns/patient-shell/index.js +1 -1
  242. package/dist/patterns/patient-shell/patient-shell.d.ts.map +1 -1
  243. package/dist/tokens.css +1 -1
  244. package/package.json +5 -1
  245. package/dist/_chunks/accordion-bSU21uTV.js.map +0 -1
  246. package/dist/_chunks/agenda-tray-By_asPN9.js.map +0 -1
  247. package/dist/_chunks/chart-DnHvmiDX.js.map +0 -1
  248. package/dist/_chunks/collapsible-CERONory.js.map +0 -1
  249. package/dist/_chunks/document-scanner-CdHQ6lTN.js.map +0 -1
  250. package/dist/_chunks/file-upload-CnzRcErt.js.map +0 -1
  251. package/dist/_chunks/marketplace-app-shell-BnClrL2B.js +0 -295
  252. package/dist/_chunks/marketplace-app-shell-BnClrL2B.js.map +0 -1
  253. package/dist/_chunks/message-card-BbRhZkDI.js.map +0 -1
  254. package/dist/_chunks/message-tray-B762TKuv.js.map +0 -1
  255. package/dist/_chunks/notification-card-DMdO4g54.js.map +0 -1
  256. package/dist/_chunks/otp-input-CDTWT5EK.js.map +0 -1
  257. package/dist/_chunks/payment-form-D5rgnZu7.js.map +0 -1
  258. package/dist/_chunks/pdf-viewer-DvtEHcEP.js.map +0 -1
  259. package/dist/_chunks/signature-capture-C-fF71xI.js.map +0 -1
  260. package/dist/_chunks/sparkline-DEROcSl0.js.map +0 -1
  261. package/dist/_chunks/stepper-accordion-BfS6lUB9.js.map +0 -1
  262. package/dist/_chunks/tag-CyoaEmf_.js.map +0 -1
  263. package/dist/_chunks/task-card-BUVMh6HN.js.map +0 -1
  264. package/dist/_chunks/task-tray-DRK0b0Qb.js.map +0 -1
  265. package/dist/_chunks/transcript-panel-DyhTpAP7.js.map +0 -1
  266. package/dist/_chunks/warning-stack-bDicCvxs.js.map +0 -1
@@ -1,12 +1,12 @@
1
- import { jsxs as x, jsx as A } from "react/jsx-runtime";
2
- import { forwardRef as ee, useId as te, useRef as R, useState as se, useEffect as re, useCallback as L, useMemo as ae } from "react";
3
- import { c as N } from "./index-D2ZczOXr.js";
4
- import { useTranslation as oe } from "react-i18next";
5
- import { u as ie } from "./use-controllable-state-BiY4xTzM.js";
6
- import { u as ne } from "./use-web-otp-D_utzp6S.js";
7
- import { u as ce } from "./form-field-context-B3APVHKx.js";
8
- import { u as ue } from "./registry-nPAVE19X.js";
9
- const le = {
1
+ import { jsxs as x, jsx as R } from "react/jsx-runtime";
2
+ import { forwardRef as ee, useId as te, useRef as M, useState as se, useEffect as re, useCallback as N, useMemo as ae, useImperativeHandle as oe } from "react";
3
+ import { c as O } from "./index-D2ZczOXr.js";
4
+ import { useTranslation as ie } from "react-i18next";
5
+ import { u as ne } from "./use-controllable-state-BiY4xTzM.js";
6
+ import { u as ce } from "./use-web-otp-D_utzp6S.js";
7
+ import { u as ue } from "./form-field-context-B3APVHKx.js";
8
+ import { u as le } from "./registry-nPAVE19X.js";
9
+ const de = {
10
10
  id: "otp-input",
11
11
  capabilities: ["edit_inline", "submit"],
12
12
  state: {
@@ -62,7 +62,7 @@ const le = {
62
62
  description: "Sourced from the id prop."
63
63
  }
64
64
  }
65
- }, de = N("ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]"), pe = N(
65
+ }, pe = O("ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]"), fe = O(
66
66
  [
67
67
  "ds:w-[var(--min-target-size)] ds:h-[var(--min-target-size)]",
68
68
  "ds:rounded-[var(--radius-sm)]",
@@ -83,77 +83,77 @@ const le = {
83
83
  defaultVariants: { tone: "default" }
84
84
  }
85
85
  );
86
- function M(e) {
86
+ function F(e) {
87
87
  return e.replace(/[\u0660-\u0669]/g, (a) => String(a.charCodeAt(0) - 1632)).replace(/[\u06F0-\u06F9]/g, (a) => String(a.charCodeAt(0) - 1776));
88
88
  }
89
89
  function y(e, a) {
90
- return M(e).replace(/\D/g, "").slice(0, a);
90
+ return F(e).replace(/\D/g, "").slice(0, a);
91
91
  }
92
- function fe(e, a) {
92
+ function me(e, a) {
93
93
  const m = y(e, a), l = new Array(a).fill("");
94
94
  for (let n = 0; n < m.length; n += 1)
95
95
  l[n] = m[n];
96
96
  return l;
97
97
  }
98
- const me = ee(
98
+ const ve = ee(
99
99
  ({
100
100
  length: e = 6,
101
101
  value: a,
102
102
  defaultValue: m,
103
103
  onChange: l,
104
104
  onComplete: n,
105
- disabled: O,
106
- error: S,
105
+ disabled: S,
106
+ error: H,
107
107
  label: w,
108
- id: F,
108
+ id: K,
109
109
  className: $,
110
110
  webOtp: j = !1
111
111
  }, z) => {
112
- const { t: H } = oe(), b = ce(), W = te(), K = w ? W : void 0, [_, C] = ie({
112
+ const { t: W } = ie(), v = ue(), _ = te(), C = w ? _ : void 0, [q, P] = ne({
113
113
  value: a,
114
114
  defaultValue: y(m ?? "", e)
115
- }), p = y(_ ?? "", e), q = fe(p, e), v = b.disabled || !!O, P = b.invalid || !!S, G = P ? "error" : "default", B = R([]), I = R(p.length === e), d = R(p);
115
+ }), p = y(q ?? "", e), G = me(p, e), b = v.disabled || !!S, B = v.invalid || !!H, J = B ? "error" : "default", E = M([]), I = M(p.length === e), d = M(p);
116
116
  d.current = p;
117
- const J = () => {
117
+ const Q = () => {
118
118
  const s = p.length;
119
119
  return s >= e ? e - 1 : s;
120
- }, [f, h] = se(J);
120
+ }, [f, h] = se(Q);
121
121
  re(() => {
122
122
  f >= e && h(e - 1);
123
123
  }, [f, e]);
124
- const c = L(
124
+ const c = N(
125
125
  (s) => {
126
126
  const t = Math.max(0, Math.min(e - 1, s));
127
127
  h(t);
128
- const r = B.current[t];
128
+ const r = E.current[t];
129
129
  r && (r.focus(), r.select());
130
130
  },
131
131
  [e]
132
- ), u = L(
132
+ ), u = N(
133
133
  (s) => {
134
134
  const t = y(s, e);
135
- C(t), d.current = t, l == null || l(t), t.length === e ? I.current || (I.current = !0, n == null || n(t)) : I.current = !1;
135
+ P(t), d.current = t, l == null || l(t), t.length === e ? I.current || (I.current = !0, n == null || n(t)) : I.current = !1;
136
136
  },
137
- [C, e, l, n]
137
+ [P, e, l, n]
138
138
  );
139
- ne({
140
- enabled: j && !v,
139
+ ce({
140
+ enabled: j && !b,
141
141
  onCode: u
142
142
  });
143
- const Q = (s) => (t) => {
144
- const r = t.target.value, o = M(r).replace(/\D/g, ""), i = d.current;
143
+ const U = (s) => (t) => {
144
+ const r = t.target.value, o = F(r).replace(/\D/g, ""), i = d.current;
145
145
  if (o.length === 0) {
146
146
  if (r === "" && s < i.length) {
147
- const T = i.slice(0, s) + i.slice(s + 1);
148
- u(T);
147
+ const A = i.slice(0, s) + i.slice(s + 1);
148
+ u(A);
149
149
  }
150
150
  return;
151
151
  }
152
- const g = i.slice(0, s), k = i.slice(s + o.length), V = (g + o + k).slice(0, e);
153
- u(V);
154
- const D = Math.min(s + o.length, e - 1);
155
- c(D);
156
- }, U = (s) => (t) => {
152
+ const g = i.slice(0, s), V = i.slice(s + o.length), D = (g + o + V).slice(0, e);
153
+ u(D);
154
+ const T = Math.min(s + o.length, e - 1);
155
+ c(T);
156
+ }, X = (s) => (t) => {
157
157
  const r = d.current;
158
158
  if (t.key === "Backspace") {
159
159
  if (r[s]) {
@@ -182,17 +182,17 @@ const me = ee(
182
182
  return;
183
183
  }
184
184
  t.key === "End" && (t.preventDefault(), c(e - 1));
185
- }, X = (s) => (t) => {
186
- const o = t.clipboardData.getData("text").replace(/\s+/g, ""), i = M(o);
185
+ }, Y = (s) => (t) => {
186
+ const o = t.clipboardData.getData("text").replace(/\s+/g, ""), i = F(o);
187
187
  if (!/^[0-9]+$/.test(i)) return;
188
188
  t.preventDefault();
189
- const g = d.current, k = g.slice(0, s), V = g.slice(s + i.length), D = (k + i + V).slice(0, e);
190
- u(D);
191
- const T = Math.min(s + i.length, e - 1);
192
- c(T);
193
- }, Y = (s) => (t) => {
189
+ const g = d.current, V = g.slice(0, s), D = g.slice(s + i.length), T = (V + i + D).slice(0, e);
190
+ u(T);
191
+ const A = Math.min(s + i.length, e - 1);
192
+ c(A);
193
+ }, Z = (s) => (t) => {
194
194
  h(s), t.currentTarget.select();
195
- }, E = b.id, Z = ae(
195
+ }, L = v.id, k = ae(
196
196
  () => ({
197
197
  getValue: () => d.current,
198
198
  setValue: (s) => u(s),
@@ -202,55 +202,54 @@ const me = ee(
202
202
  }),
203
203
  [u, c, f, e]
204
204
  );
205
- return ue(le, Z, F), /* @__PURE__ */ x("div", { className: de({ className: $ }), children: [
206
- w ? /* @__PURE__ */ A(
205
+ return le(de, k, K), oe(z, () => k, [k]), /* @__PURE__ */ x("div", { className: pe({ className: $ }), children: [
206
+ w ? /* @__PURE__ */ R(
207
207
  "label",
208
208
  {
209
- id: K,
210
- htmlFor: `${E}-0`,
209
+ id: C,
210
+ htmlFor: `${L}-0`,
211
211
  className: "type-label ds:text-foreground",
212
212
  children: w
213
213
  }
214
214
  ) : null,
215
- /* @__PURE__ */ A(
215
+ /* @__PURE__ */ R(
216
216
  "div",
217
217
  {
218
- ref: z,
219
218
  role: "group",
220
219
  dir: "ltr",
221
- "aria-labelledby": K,
222
- "aria-invalid": P || void 0,
223
- "aria-describedby": b.describedBy || void 0,
224
- "aria-disabled": v || void 0,
220
+ "aria-labelledby": C,
221
+ "aria-invalid": B || void 0,
222
+ "aria-describedby": v.describedBy || void 0,
223
+ "aria-disabled": b || void 0,
225
224
  "data-component": "otp-input",
226
- "data-component-id": F,
225
+ "data-component-id": K,
227
226
  className: "ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]",
228
- children: q.map((s, t) => {
229
- const r = !v && t === f;
230
- return /* @__PURE__ */ A(
227
+ children: G.map((s, t) => {
228
+ const r = !b && t === f;
229
+ return /* @__PURE__ */ R(
231
230
  "input",
232
231
  {
233
232
  ref: (o) => {
234
- B.current[t] = o;
233
+ E.current[t] = o;
235
234
  },
236
- id: `${E}-${t}`,
235
+ id: `${L}-${t}`,
237
236
  type: "text",
238
237
  inputMode: "numeric",
239
238
  pattern: "[0-9]*",
240
239
  autoComplete: t === 0 ? "one-time-code" : "off",
241
240
  maxLength: 1,
242
241
  value: s,
243
- disabled: v,
242
+ disabled: b,
244
243
  tabIndex: r ? 0 : -1,
245
- "aria-label": H("inputs.otp.digitLabel", {
244
+ "aria-label": W("inputs.otp.digitLabel", {
246
245
  current: t + 1,
247
246
  total: e
248
247
  }),
249
- onChange: Q(t),
250
- onKeyDown: U(t),
251
- onPaste: X(t),
252
- onFocus: Y(t),
253
- className: pe({ tone: G })
248
+ onChange: U(t),
249
+ onKeyDown: X(t),
250
+ onPaste: Y(t),
251
+ onFocus: Z(t),
252
+ className: fe({ tone: J })
254
253
  },
255
254
  t
256
255
  );
@@ -260,8 +259,8 @@ const me = ee(
260
259
  ] });
261
260
  }
262
261
  );
263
- me.displayName = "OTPInput";
262
+ ve.displayName = "OTPInput";
264
263
  export {
265
- me as O
264
+ ve as O
266
265
  };
267
- //# sourceMappingURL=otp-input-CDTWT5EK.js.map
266
+ //# sourceMappingURL=otp-input-CMphfBxZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otp-input-CMphfBxZ.js","sources":["../../src/components/otp-input/otp-input.agent.ts","../../src/components/otp-input/otp-input.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — OTPInput. */\n/* */\n/* See `src/docs/26-agent-readiness.mdx` for the contract. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { OTPInputHandle } from './otp-input';\n\nexport const otpInputAgent: AgentAdapter<OTPInputHandle> = {\n id: 'otp-input',\n capabilities: ['edit_inline', 'submit'],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.otpInput.state.value',\n description: 'Current digits entered, packed into a single string.',\n read: (handle) => handle.getValue(),\n },\n isComplete: {\n type: 'boolean',\n descriptionKey: 'ui.agent.otpInput.state.isComplete',\n description: 'Whether all required digits have been entered.',\n read: (handle) => handle.isComplete(),\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: string }',\n descriptionKey: 'ui.agent.otpInput.actions.setValue',\n description: 'Replace the entered digits.',\n invoke: (handle, args: { value: string }) => {\n handle.setValue(args.value);\n },\n },\n clear: {\n safety: 'destructive',\n descriptionKey: 'ui.agent.otpInput.actions.clear',\n description: 'Empty all digit cells. Loses any typed value.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n focus: {\n safety: 'read',\n descriptionKey: 'ui.agent.otpInput.actions.focus',\n description: 'Move keyboard focus to the active digit cell.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'otp-input',\n description:\n 'Marks the OTPInput wrapper. Completion is observable via state.isComplete; the host onComplete callback fires once when all digits are filled.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type ClipboardEvent,\n type FocusEvent,\n type KeyboardEvent,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { useWebOtp } from '../../hooks/use-web-otp';\nimport { useFormField } from '../form-field/form-field-context';\nimport { useAgentRegistration } from '../../agent';\nimport { otpInputAgent } from './otp-input.agent';\n\n/** Agent-readiness curated handle for OTPInput. */\nexport interface OTPInputHandle {\n getValue: () => string;\n setValue: (value: string) => void;\n clear: () => void;\n focus: () => void;\n isComplete: () => boolean;\n}\n\nconst wrapperVariants = cva('ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]');\n\nconst boxVariants = cva(\n [\n 'ds:w-[var(--min-target-size)] ds:h-[var(--min-target-size)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:border ds:bg-input ds:text-foreground ds:text-center ds:font-medium ds:text-[length:var(--font-size-lg)]',\n 'ds:shadow-[var(--shadow-input)]',\n 'ds:transition-[colors,box-shadow] ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:disabled:cursor-not-allowed ds:disabled:opacity-50',\n ].join(' '),\n {\n variants: {\n tone: {\n default: 'ds:border-border',\n error: 'ds:border-destructive',\n },\n },\n defaultVariants: { tone: 'default' },\n },\n);\n\nexport interface OTPInputProps {\n length?: 4 | 6 | 8;\n value?: string;\n defaultValue?: string;\n onChange?: (value: string) => void;\n onComplete?: (code: string) => void;\n disabled?: boolean;\n error?: boolean;\n label?: string;\n /** Stable id, used to address this instance from the agent runtime. */\n id?: string;\n className?: string;\n /**\n * Opt into Chrome-Android's WebOTP API for one-tap SMS autofill. When\n * the browser surfaces a matching SMS-bound credential, the kit spreads\n * the code across every digit box and fires `onComplete` automatically.\n *\n * Falls back silently to manual entry on Firefox / desktop / iOS — those\n * platforms either don't ship the API at all or rely on the\n * `autocomplete=\"one-time-code\"` QuickType heuristic the kit already\n * applies to the first input.\n *\n * Prerequisites the prop can't enforce: page must be HTTPS, and the SMS\n * body must end with `@<origin> #<code>` on its last line (Chrome's\n * spec — without it the browser refuses to surface the message).\n * Default `false` so the listener stays opt-in.\n */\n webOtp?: boolean;\n}\n\nfunction normaliseDigits(str: string): string {\n return str\n .replace(/[\\u0660-\\u0669]/g, (c) => String(c.charCodeAt(0) - 0x0660))\n .replace(/[\\u06F0-\\u06F9]/g, (c) => String(c.charCodeAt(0) - 0x06f0));\n}\n\nfunction packValue(value: string, length: number): string {\n return normaliseDigits(value).replace(/\\D/g, '').slice(0, length);\n}\n\nfunction valueToArray(value: string, length: number): string[] {\n const packed = packValue(value, length);\n const arr = new Array<string>(length).fill('');\n for (let i = 0; i < packed.length; i += 1) {\n arr[i] = packed[i];\n }\n return arr;\n}\n\nexport const OTPInput = forwardRef<OTPInputHandle, OTPInputProps>(\n (\n {\n length = 6,\n value,\n defaultValue,\n onChange,\n onComplete,\n disabled,\n error,\n label,\n id,\n className,\n webOtp = false,\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const ctx = useFormField();\n const generatedLabelId = useId();\n const labelId = label ? generatedLabelId : undefined;\n\n const [internalValueRaw, setInternalValue] = useControllableState<string>({\n value,\n defaultValue: packValue(defaultValue ?? '', length),\n });\n const currentValue = packValue(internalValueRaw ?? '', length);\n const digits = valueToArray(currentValue, length);\n\n const effectiveDisabled = ctx.disabled || Boolean(disabled);\n const effectiveError = ctx.invalid || Boolean(error);\n const effectiveTone = effectiveError ? 'error' : 'default';\n\n const inputsRef = useRef<Array<HTMLInputElement | null>>([]);\n const completedRef = useRef(currentValue.length === length);\n const valueRef = useRef(currentValue);\n valueRef.current = currentValue;\n\n const computeInitialIndex = () => {\n const firstEmpty = currentValue.length;\n if (firstEmpty >= length) return length - 1;\n return firstEmpty;\n };\n const [activeIndex, setActiveIndex] = useState<number>(computeInitialIndex);\n\n useEffect(() => {\n if (activeIndex >= length) setActiveIndex(length - 1);\n }, [activeIndex, length]);\n\n const focusBox = useCallback(\n (index: number) => {\n const clamped = Math.max(0, Math.min(length - 1, index));\n setActiveIndex(clamped);\n const node = inputsRef.current[clamped];\n if (node) {\n node.focus();\n node.select();\n }\n },\n [length],\n );\n\n const commit = useCallback(\n (next: string) => {\n const packed = packValue(next, length);\n setInternalValue(packed);\n valueRef.current = packed;\n onChange?.(packed);\n if (packed.length === length) {\n if (!completedRef.current) {\n completedRef.current = true;\n onComplete?.(packed);\n }\n } else {\n completedRef.current = false;\n }\n },\n [setInternalValue, length, onChange, onComplete],\n );\n\n // WebOTP one-tap autofill. The hook silently no-ops when the API is\n // unavailable (Firefox / Safari / desktop Chromium) — `commit()` is\n // the same path manual entry takes, so `onChange` + `onComplete` fire\n // identically whether the digits arrived via SMS, paste, or typing.\n useWebOtp({\n enabled: webOtp && !effectiveDisabled,\n onCode: commit,\n });\n\n const handleChange =\n (index: number) => (event: ChangeEvent<HTMLInputElement>) => {\n const raw = event.target.value;\n const norm = normaliseDigits(raw).replace(/\\D/g, '');\n const current = valueRef.current;\n\n if (norm.length === 0) {\n if (raw === '' && index < current.length) {\n const newValue = current.slice(0, index) + current.slice(index + 1);\n commit(newValue);\n }\n return;\n }\n\n const before = current.slice(0, index);\n const after = current.slice(index + norm.length);\n const newValue = (before + norm + after).slice(0, length);\n commit(newValue);\n\n const focusTarget = Math.min(index + norm.length, length - 1);\n focusBox(focusTarget);\n };\n\n const handleKeyDown =\n (index: number) => (event: KeyboardEvent<HTMLInputElement>) => {\n const current = valueRef.current;\n if (event.key === 'Backspace') {\n if (current[index]) {\n event.preventDefault();\n const newValue = current.slice(0, index) + current.slice(index + 1);\n commit(newValue);\n return;\n }\n if (index > 0) {\n event.preventDefault();\n const newValue = current.slice(0, index - 1) + current.slice(index);\n commit(newValue);\n focusBox(index - 1);\n }\n return;\n }\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n if (index > 0) focusBox(index - 1);\n return;\n }\n if (event.key === 'ArrowRight') {\n event.preventDefault();\n if (index < length - 1) focusBox(index + 1);\n return;\n }\n if (event.key === 'Home') {\n event.preventDefault();\n focusBox(0);\n return;\n }\n if (event.key === 'End') {\n event.preventDefault();\n focusBox(length - 1);\n }\n };\n\n const handlePaste =\n (index: number) => (event: ClipboardEvent<HTMLInputElement>) => {\n const text = event.clipboardData.getData('text');\n const stripped = text.replace(/\\s+/g, '');\n const norm = normaliseDigits(stripped);\n if (!/^[0-9]+$/.test(norm)) return;\n event.preventDefault();\n const current = valueRef.current;\n const before = current.slice(0, index);\n const after = current.slice(index + norm.length);\n const newValue = (before + norm + after).slice(0, length);\n commit(newValue);\n const focusTarget = Math.min(index + norm.length, length - 1);\n focusBox(focusTarget);\n };\n\n const handleFocus =\n (index: number) => (event: FocusEvent<HTMLInputElement>) => {\n setActiveIndex(index);\n event.currentTarget.select();\n };\n\n const baseId = ctx.id;\n\n const agentHandle = useMemo<OTPInputHandle>(\n () => ({\n getValue: () => valueRef.current,\n setValue: (next) => commit(next),\n clear: () => commit(''),\n focus: () => focusBox(activeIndex),\n isComplete: () => valueRef.current.length === length,\n }),\n [commit, focusBox, activeIndex, length],\n );\n useAgentRegistration(otpInputAgent, agentHandle, id);\n // Expose the same imperative handle to React refs so consumers can\n // focus / read / clear the field (e.g. focus the boxes on a step change).\n useImperativeHandle(ref, () => agentHandle, [agentHandle]);\n\n return (\n <div className={wrapperVariants({ className })}>\n {label ? (\n <label\n id={labelId}\n htmlFor={`${baseId}-0`}\n className=\"type-label ds:text-foreground\"\n >\n {label}\n </label>\n ) : null}\n {/* eslint-disable-next-line jsx-a11y/role-supports-aria-props -- aria-invalid is a global ARIA state; conveys group-level validation */}\n <div\n role=\"group\"\n dir=\"ltr\"\n aria-labelledby={labelId}\n aria-invalid={effectiveError || undefined}\n aria-describedby={ctx.describedBy || undefined}\n aria-disabled={effectiveDisabled || undefined}\n data-component=\"otp-input\"\n data-component-id={id}\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\"\n >\n {digits.map((digit, index) => {\n const isTabbable = !effectiveDisabled && index === activeIndex;\n return (\n <input\n key={index}\n ref={(node) => {\n inputsRef.current[index] = node;\n }}\n id={`${baseId}-${index}`}\n type=\"text\"\n inputMode=\"numeric\"\n pattern=\"[0-9]*\"\n autoComplete={index === 0 ? 'one-time-code' : 'off'}\n maxLength={1}\n value={digit}\n disabled={effectiveDisabled}\n tabIndex={isTabbable ? 0 : -1}\n aria-label={t('inputs.otp.digitLabel', {\n current: index + 1,\n total: length,\n })}\n onChange={handleChange(index)}\n onKeyDown={handleKeyDown(index)}\n onPaste={handlePaste(index)}\n onFocus={handleFocus(index)}\n className={boxVariants({ tone: effectiveTone })}\n />\n );\n })}\n </div>\n </div>\n );\n },\n);\n\nOTPInput.displayName = 'OTPInput';\n"],"names":["otpInputAgent","handle","args","wrapperVariants","cva","boxVariants","normaliseDigits","str","c","packValue","value","length","valueToArray","packed","arr","i","OTPInput","forwardRef","defaultValue","onChange","onComplete","disabled","error","label","id","className","webOtp","ref","t","useTranslation","ctx","useFormField","generatedLabelId","useId","labelId","internalValueRaw","setInternalValue","useControllableState","currentValue","digits","effectiveDisabled","effectiveError","effectiveTone","inputsRef","useRef","completedRef","valueRef","computeInitialIndex","firstEmpty","activeIndex","setActiveIndex","useState","useEffect","focusBox","useCallback","index","clamped","node","commit","next","useWebOtp","handleChange","event","raw","norm","current","newValue","before","after","focusTarget","handleKeyDown","handlePaste","stripped","handleFocus","baseId","agentHandle","useMemo","useAgentRegistration","useImperativeHandle","jsx","digit","isTabbable"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import { jsx as e, jsxs as n } from "react/jsx-runtime";
2
- import { forwardRef as w, useState as k } from "react";
2
+ import { forwardRef as k, useState as w } from "react";
3
3
  import { useTranslation as m } from "react-i18next";
4
4
  import { A } from "./app-frame-BYx1gcV7.js";
5
- import { I as H } from "./icon-button-CKEOrN37.js";
5
+ import { I as C } from "./icon-button-CKEOrN37.js";
6
6
  import { D as i } from "./dropdown-menu-BC5ZdOMo.js";
7
- import { H as x, g as C, f as B, e as M, a as N, c as T, d as O } from "./header-CTZWX-tm.js";
7
+ import { H, g as x, f as N, e as B, a as M, c as T, d as O } from "./header-CTZWX-tm.js";
8
8
  import { L as P } from "./logo-yituK7sE.js";
9
- import { S as W, a as j, h as R, j as _, k as z, i as D } from "./sidebar-BbR8f6oe.js";
9
+ import { S as W, a as j, h as R, j as _, k as z, i as D } from "./sidebar-_vJXI9rB.js";
10
10
  import { T as E } from "./theme-root-BOO73p5t.js";
11
11
  import { a as q } from "./tooltip-DvmfrNvB.js";
12
12
  import { u as F } from "./use-theme-C2dHKUAN.js";
@@ -25,31 +25,31 @@ const K = [
25
25
  ["path", { d: "m3 21 7-7", key: "tjx5ai" }],
26
26
  ["path", { d: "M9 21H3v-6", key: "wtvkvv" }]
27
27
  ], Q = G("maximize-2", K);
28
- function V(r) {
29
- return r > 99 ? "99+" : String(r);
28
+ function V(a) {
29
+ return a > 99 ? "99+" : String(a);
30
30
  }
31
- function X(r) {
32
- if (r.startsWith("/") || r.startsWith("#") || r.startsWith("?"))
31
+ function X(a) {
32
+ if (a.startsWith("/") || a.startsWith("#") || a.startsWith("?"))
33
33
  return !0;
34
34
  try {
35
- const t = new URL(r, window.location.origin);
35
+ const t = new URL(a, window.location.origin);
36
36
  return t.protocol === "http:" || t.protocol === "https:";
37
37
  } catch {
38
38
  return !1;
39
39
  }
40
40
  }
41
41
  function Y({
42
- logoutHref: r,
42
+ logoutHref: a,
43
43
  onToggleFullscreen: t
44
44
  }) {
45
- const { t: a } = m();
45
+ const { t: r } = m();
46
46
  return /* @__PURE__ */ n(i.Root, { children: [
47
47
  /* @__PURE__ */ e(i.Trigger, { asChild: !0, children: /* @__PURE__ */ e(
48
- H,
48
+ C,
49
49
  {
50
50
  icon: /* @__PURE__ */ e(U, { "aria-hidden": "true" }),
51
- "aria-label": a("patientShell.settings.triggerAria"),
52
- tooltip: a("patientShell.settings.triggerAria"),
51
+ "aria-label": r("patientShell.settings.triggerAria"),
52
+ tooltip: r("patientShell.settings.triggerAria"),
53
53
  "data-testid": "patient-shell-settings-trigger"
54
54
  }
55
55
  ) }),
@@ -60,7 +60,7 @@ function Y({
60
60
  startIcon: /* @__PURE__ */ e(Q, { "aria-hidden": "true" }),
61
61
  onSelect: t,
62
62
  "data-testid": "patient-shell-fullscreen",
63
- children: a("patientShell.settings.fullscreen")
63
+ children: r("patientShell.settings.fullscreen")
64
64
  }
65
65
  ),
66
66
  /* @__PURE__ */ e(i.Separator, {}),
@@ -69,18 +69,18 @@ function Y({
69
69
  {
70
70
  startIcon: /* @__PURE__ */ e(J, { "aria-hidden": "true" }),
71
71
  onSelect: () => {
72
- typeof window > "u" || X(r) && window.location.assign(r);
72
+ typeof window > "u" || X(a) && window.location.assign(a);
73
73
  },
74
74
  "data-testid": "patient-shell-logout",
75
- children: a("patientShell.settings.logout")
75
+ children: r("patientShell.settings.logout")
76
76
  }
77
77
  )
78
78
  ] })
79
79
  ] });
80
80
  }
81
- function Z({ menuItems: r }) {
82
- return /* @__PURE__ */ e(j, { children: r.map((t) => {
83
- const a = typeof t.badgeCount == "number" && t.badgeCount > 0 ? t.badgeCount : void 0;
81
+ function Z({ menuItems: a }) {
82
+ return /* @__PURE__ */ e(j, { children: a.map((t) => {
83
+ const r = typeof t.badgeCount == "number" && t.badgeCount > 0 ? t.badgeCount : void 0;
84
84
  return /* @__PURE__ */ n(
85
85
  R,
86
86
  {
@@ -90,18 +90,18 @@ function Z({ menuItems: r }) {
90
90
  children: [
91
91
  t.icon ? /* @__PURE__ */ e(_, { children: t.icon }) : null,
92
92
  /* @__PURE__ */ e(z, { children: t.label }),
93
- a !== void 0 ? /* @__PURE__ */ e(D, { children: V(a) }) : null
93
+ r !== void 0 ? /* @__PURE__ */ e(D, { children: V(r) }) : null
94
94
  ]
95
95
  },
96
96
  t.id
97
97
  );
98
98
  }) });
99
99
  }
100
- const $ = w(
100
+ const $ = k(
101
101
  ({
102
- menuItems: r,
102
+ menuItems: a,
103
103
  logoutHref: t,
104
- onToggleFullscreen: a,
104
+ onToggleFullscreen: r,
105
105
  brandLogo: p,
106
106
  brandHref: u = "/",
107
107
  mainAriaLabel: f,
@@ -114,20 +114,21 @@ const $ = w(
114
114
  userName: ee,
115
115
  userAvatarSrc: te
116
116
  }, s) => {
117
- const { t: d } = m(), { theme: S, accessibility: b, resolvedTheme: l } = F(), v = S !== "system" || b !== "system", y = l.startsWith("dark") ? "dark" : "light", I = l.endsWith("-accessible"), [L, c] = k(!1), h = /* @__PURE__ */ e(q, { children: /* @__PURE__ */ e(
117
+ const { t: l } = m(), { theme: b, accessibility: S, resolvedTheme: d } = F(), v = b !== "system" || S !== "system", y = d.startsWith("dark") ? "dark" : "light", I = d.endsWith("-accessible"), [L, c] = w(!1), h = /* @__PURE__ */ e(q, { children: /* @__PURE__ */ e(
118
118
  A,
119
119
  {
120
120
  mainAriaLabel: f,
121
- header: /* @__PURE__ */ n(x, { children: [
122
- /* @__PURE__ */ n(C, { children: [
123
- /* @__PURE__ */ e(B, { href: "#main-content" }),
124
- /* @__PURE__ */ e(M, { onMenuOpen: () => c(!0) }),
121
+ mainClassName: "ds:bg-[color:var(--app-shell-background)]",
122
+ header: /* @__PURE__ */ n(H, { children: [
123
+ /* @__PURE__ */ n(x, { children: [
124
+ /* @__PURE__ */ e(N, { href: "#main-content" }),
125
+ /* @__PURE__ */ e(B, { onMenuOpen: () => c(!0) }),
125
126
  /* @__PURE__ */ e(
126
- N,
127
+ M,
127
128
  {
128
129
  logo: p ?? /* @__PURE__ */ e(P, { variant: "monochrome", size: "md", decorative: !0 }),
129
130
  href: u,
130
- "aria-label": d("patientShell.brand.homeAria")
131
+ "aria-label": l("patientShell.brand.homeAria")
131
132
  }
132
133
  )
133
134
  ] }),
@@ -136,7 +137,7 @@ const $ = w(
136
137
  Y,
137
138
  {
138
139
  logoutHref: t,
139
- onToggleFullscreen: a
140
+ onToggleFullscreen: r
140
141
  }
141
142
  ) })
142
143
  ] }),
@@ -146,9 +147,9 @@ const $ = w(
146
147
  ...o !== void 0 ? { state: o } : { defaultState: "expanded" },
147
148
  open: L,
148
149
  onOpenChange: c,
149
- "aria-label": d("patientShell.sidebar.panelLabel"),
150
+ "aria-label": l("patientShell.sidebar.panelLabel"),
150
151
  "data-testid": "patient-shell-sidebar",
151
- children: /* @__PURE__ */ e(Z, { menuItems: r })
152
+ children: /* @__PURE__ */ e(Z, { menuItems: a })
152
153
  }
153
154
  ),
154
155
  children: g
@@ -170,4 +171,4 @@ $.displayName = "PatientShell";
170
171
  export {
171
172
  $ as P
172
173
  };
173
- //# sourceMappingURL=patient-shell-Bz3CdO84.js.map
174
+ //# sourceMappingURL=patient-shell-DF81lALv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"patient-shell-Bz3CdO84.js","sources":["../../node_modules/lucide-react/dist/esm/icons/maximize-2.js","../../src/patterns/patient-shell/patient-shell.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 3h6v6\", key: \"1q9fwt\" }],\n [\"path\", { d: \"m21 3-7 7\", key: \"1l2asr\" }],\n [\"path\", { d: \"m3 21 7-7\", key: \"tjx5ai\" }],\n [\"path\", { d: \"M9 21H3v-6\", key: \"wtvkvv\" }]\n];\nconst Maximize2 = createLucideIcon(\"maximize-2\", __iconNode);\n\nexport { __iconNode, Maximize2 as default };\n//# sourceMappingURL=maximize-2.js.map\n","/**\n * Patient Shell — the chrome for AlfaDocs's patient-facing users\n * (patients managing their own appointments and records).\n *\n * Deliberately flatter than the clinician `AppFrame` composition: no\n * command palette, no favourites, no practice/chain affordances, no\n * Alia, no privacy lock. Mirrors the legacy `_header.html.twig`\n * `app.user.type == 'patient'` branch and the `knp_menu_render('pcp')`\n * flat nav menu.\n *\n * Unlike most patterns in this folder, PatientShell exports a runtime\n * component because the consuming patient-portal app mounts it in\n * production — the exports are surfaced via `src/patterns/index.ts`\n * and included in the library bundle.\n */\nimport { forwardRef, useState, type ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { LogOut, Maximize2, Settings as SettingsIcon } from 'lucide-react';\n\nimport { AppFrame } from '../../components/app-frame';\nimport { IconButton } from '../../components/button';\nimport { DropdownMenu } from '../../components/dropdown-menu';\nimport {\n Header,\n HeaderBrand,\n HeaderCenter,\n HeaderEnd,\n HeaderMenuButton,\n HeaderSkipLink,\n HeaderStart,\n} from '../../components/header';\nimport { Logo } from '../../components/logo';\nimport {\n Sidebar,\n SidebarBody,\n SidebarItem,\n SidebarItemBadge,\n SidebarItemIcon,\n SidebarItemLabel,\n type SidebarMode,\n} from '../../components/sidebar';\nimport { ThemeRoot } from '../../components/theme-root';\nimport { TooltipProvider } from '../../components/tooltip';\nimport { useTheme } from '../../hooks/use-theme';\n\n/* ------------------------------------------------------------------ */\n/* Public API */\n/* ------------------------------------------------------------------ */\n\nexport interface PatientNavItem {\n id: string;\n /** Pre-translated label — patients' nav labels are emitted already\n * translated by the consuming app's backend (legacy `knp_menu`). */\n label: string;\n href: string;\n /** Optional leading icon. Pass a lucide-react or equivalent element. */\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\nexport interface PatientShellProps {\n /** Patient's display name. Used as the avatar fallback by consumers\n * that read the name through a slot; not rendered inside this shell\n * today because the legacy patient chrome carries no profile pill. */\n userName: string;\n /** Optional avatar URL. Reserved for future profile-pill surfaces;\n * no visible effect today. */\n userAvatarSrc?: string;\n /** Flat nav items rendered in the sidebar, in order. */\n menuItems: PatientNavItem[];\n /** URL the \"Logout\" action navigates to — typically `/logout`. */\n logoutHref: string;\n /** Fires when the user toggles fullscreen from the settings menu. */\n onToggleFullscreen?: () => void;\n /** Optional brand logo. Defaults to\n * `<Logo variant=\"monochrome\" size=\"md\" decorative />`. */\n brandLogo?: ReactNode;\n /** Link target for the brand — typically the patient dashboard. */\n brandHref?: string;\n /** Override the accessible name of the `<main>` landmark. */\n mainAriaLabel?: string;\n /**\n * Force the sidebar into a specific mode. Consuming apps typically\n * flip to `'overlay'` on narrow viewports and leave this undefined\n * elsewhere (the sidebar then defaults to `'expanded'`).\n */\n sidebarState?: SidebarMode;\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\n/**\n * Guard against `javascript:` and other non-navigation schemes before\n * handing the URL to `window.location.assign`. A consuming app that lets\n * attacker-controlled input reach `logoutHref` would otherwise execute\n * script. Allow only relative paths, hash fragments, and `http(s)` URLs.\n */\nfunction isSafeLogoutHref(href: string): boolean {\n if (href.startsWith('/') || href.startsWith('#') || href.startsWith('?')) {\n return true;\n }\n try {\n const url = new URL(href, window.location.origin);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nfunction SettingsMenu({\n logoutHref,\n onToggleFullscreen,\n}: {\n logoutHref: string;\n onToggleFullscreen?: () => void;\n}) {\n const { t } = useTranslation();\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <IconButton\n icon={<SettingsIcon aria-hidden=\"true\" />}\n aria-label={t('patientShell.settings.triggerAria')}\n tooltip={t('patientShell.settings.triggerAria')}\n data-testid=\"patient-shell-settings-trigger\"\n />\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item\n startIcon={<Maximize2 aria-hidden=\"true\" />}\n onSelect={onToggleFullscreen}\n data-testid=\"patient-shell-fullscreen\"\n >\n {t('patientShell.settings.fullscreen')}\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n startIcon={<LogOut aria-hidden=\"true\" />}\n onSelect={() => {\n if (typeof window === 'undefined') return;\n if (!isSafeLogoutHref(logoutHref)) return;\n window.location.assign(logoutHref);\n }}\n data-testid=\"patient-shell-logout\"\n >\n {t('patientShell.settings.logout')}\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\nfunction PatientSidebarNav({ menuItems }: { menuItems: PatientNavItem[] }) {\n return (\n <SidebarBody>\n {menuItems.map((item) => {\n const badge =\n typeof item.badgeCount === 'number' && item.badgeCount > 0\n ? item.badgeCount\n : undefined;\n return (\n <SidebarItem\n key={item.id}\n href={item.href}\n aria-label={item.label}\n isActive={item.isActive}\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 </SidebarItem>\n );\n })}\n </SidebarBody>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nexport const PatientShell = forwardRef<HTMLDivElement, PatientShellProps>(\n (\n {\n menuItems,\n logoutHref,\n onToggleFullscreen,\n brandLogo,\n brandHref = '/',\n mainAriaLabel,\n sidebarState,\n children,\n // `userName` and `userAvatarSrc` are declared on the public API\n // for forward-compatibility (future profile-pill work) — they are\n // intentionally unused today because the legacy patient chrome\n // carries no profile pill.\n userName: _userName,\n userAvatarSrc: _userAvatarSrc,\n },\n ref,\n ) => {\n const { t } = useTranslation();\n // Only wrap children in a nested <ThemeRoot> when the user has\n // explicitly chosen a theme via the hook (e.g., through an in-app\n // toggle). Otherwise we let the outer cascade win — wrapping with\n // the hook's default `resolvedTheme = 'light'` would clobber a\n // consuming app's `<html>` theme class (or Storybook's decorator)\n // for every child rendered inside the shell.\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 // Narrow-viewport overlay: `HeaderMenuButton` only renders below the\n // `md` breakpoint, and toggling opens the Sidebar's overlay Dialog.\n const [sidebarOpen, setSidebarOpen] = useState(false);\n\n const resolvedLogo = brandLogo ?? (\n <Logo variant=\"monochrome\" size=\"md\" decorative />\n );\n\n const shell = (\n <TooltipProvider>\n <AppFrame\n mainAriaLabel={mainAriaLabel}\n header={\n <Header>\n <HeaderStart>\n <HeaderSkipLink href=\"#main-content\" />\n <HeaderMenuButton onMenuOpen={() => setSidebarOpen(true)} />\n <HeaderBrand\n logo={resolvedLogo}\n href={brandHref}\n aria-label={t('patientShell.brand.homeAria')}\n />\n </HeaderStart>\n <HeaderCenter />\n <HeaderEnd>\n <SettingsMenu\n logoutHref={logoutHref}\n onToggleFullscreen={onToggleFullscreen}\n />\n </HeaderEnd>\n </Header>\n }\n sidebar={\n <Sidebar\n {...(sidebarState !== undefined\n ? { state: sidebarState }\n : { defaultState: 'expanded' as const })}\n open={sidebarOpen}\n onOpenChange={setSidebarOpen}\n aria-label={t('patientShell.sidebar.panelLabel')}\n data-testid=\"patient-shell-sidebar\"\n >\n <PatientSidebarNav menuItems={menuItems} />\n </Sidebar>\n }\n >\n {children}\n </AppFrame>\n </TooltipProvider>\n );\n\n if (!hasExplicitOverride) {\n // Pass-through wrapper preserves the ref contract without altering\n // the token cascade.\n return (\n <div ref={ref as never} className=\"ds:contents\">\n {shell}\n </div>\n );\n }\n\n return (\n <ThemeRoot\n ref={ref}\n theme={themeBase}\n accessible={themeAccessible}\n className=\"ds:contents\"\n >\n {shell}\n </ThemeRoot>\n );\n },\n);\n\nPatientShell.displayName = 'PatientShell';\n"],"names":["__iconNode","Maximize2","createLucideIcon","formatBadgeCount","count","isSafeLogoutHref","href","url","SettingsMenu","logoutHref","onToggleFullscreen","t","useTranslation","jsxs","DropdownMenu","jsx","IconButton","SettingsIcon","LogOut","PatientSidebarNav","menuItems","SidebarBody","item","badge","SidebarItem","SidebarItemIcon","SidebarItemLabel","SidebarItemBadge","PatientShell","forwardRef","brandLogo","brandHref","mainAriaLabel","sidebarState","children","_userName","_userAvatarSrc","ref","themePref","accessibility","resolvedTheme","useTheme","hasExplicitOverride","themeBase","themeAccessible","sidebarOpen","setSidebarOpen","useState","shell","TooltipProvider","AppFrame","Header","HeaderStart","HeaderSkipLink","HeaderMenuButton","HeaderBrand","Logo","HeaderCenter","HeaderEnd","Sidebar","ThemeRoot"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"patient-shell-DF81lALv.js","sources":["../../node_modules/lucide-react/dist/esm/icons/maximize-2.js","../../src/patterns/patient-shell/patient-shell.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 3h6v6\", key: \"1q9fwt\" }],\n [\"path\", { d: \"m21 3-7 7\", key: \"1l2asr\" }],\n [\"path\", { d: \"m3 21 7-7\", key: \"tjx5ai\" }],\n [\"path\", { d: \"M9 21H3v-6\", key: \"wtvkvv\" }]\n];\nconst Maximize2 = createLucideIcon(\"maximize-2\", __iconNode);\n\nexport { __iconNode, Maximize2 as default };\n//# sourceMappingURL=maximize-2.js.map\n","/**\n * Patient Shell — the chrome for AlfaDocs's patient-facing users\n * (patients managing their own appointments and records).\n *\n * Deliberately flatter than the clinician `AppFrame` composition: no\n * command palette, no favourites, no practice/chain affordances, no\n * Alia, no privacy lock. Mirrors the legacy `_header.html.twig`\n * `app.user.type == 'patient'` branch and the `knp_menu_render('pcp')`\n * flat nav menu.\n *\n * Unlike most patterns in this folder, PatientShell exports a runtime\n * component because the consuming patient-portal app mounts it in\n * production — the exports are surfaced via `src/patterns/index.ts`\n * and included in the library bundle.\n */\nimport { forwardRef, useState, type ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { LogOut, Maximize2, Settings as SettingsIcon } from 'lucide-react';\n\nimport { AppFrame } from '../../components/app-frame';\nimport { IconButton } from '../../components/button';\nimport { DropdownMenu } from '../../components/dropdown-menu';\nimport {\n Header,\n HeaderBrand,\n HeaderCenter,\n HeaderEnd,\n HeaderMenuButton,\n HeaderSkipLink,\n HeaderStart,\n} from '../../components/header';\nimport { Logo } from '../../components/logo';\nimport {\n Sidebar,\n SidebarBody,\n SidebarItem,\n SidebarItemBadge,\n SidebarItemIcon,\n SidebarItemLabel,\n type SidebarMode,\n} from '../../components/sidebar';\nimport { ThemeRoot } from '../../components/theme-root';\nimport { TooltipProvider } from '../../components/tooltip';\nimport { useTheme } from '../../hooks/use-theme';\n\n/* ------------------------------------------------------------------ */\n/* Public API */\n/* ------------------------------------------------------------------ */\n\nexport interface PatientNavItem {\n id: string;\n /** Pre-translated label — patients' nav labels are emitted already\n * translated by the consuming app's backend (legacy `knp_menu`). */\n label: string;\n href: string;\n /** Optional leading icon. Pass a lucide-react or equivalent element. */\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\nexport interface PatientShellProps {\n /** Patient's display name. Used as the avatar fallback by consumers\n * that read the name through a slot; not rendered inside this shell\n * today because the legacy patient chrome carries no profile pill. */\n userName: string;\n /** Optional avatar URL. Reserved for future profile-pill surfaces;\n * no visible effect today. */\n userAvatarSrc?: string;\n /** Flat nav items rendered in the sidebar, in order. */\n menuItems: PatientNavItem[];\n /** URL the \"Logout\" action navigates to — typically `/logout`. */\n logoutHref: string;\n /** Fires when the user toggles fullscreen from the settings menu. */\n onToggleFullscreen?: () => void;\n /** Optional brand logo. Defaults to\n * `<Logo variant=\"monochrome\" size=\"md\" decorative />`. */\n brandLogo?: ReactNode;\n /** Link target for the brand — typically the patient dashboard. */\n brandHref?: string;\n /** Override the accessible name of the `<main>` landmark. */\n mainAriaLabel?: string;\n /**\n * Force the sidebar into a specific mode. Consuming apps typically\n * flip to `'overlay'` on narrow viewports and leave this undefined\n * elsewhere (the sidebar then defaults to `'expanded'`).\n */\n sidebarState?: SidebarMode;\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\n/**\n * Guard against `javascript:` and other non-navigation schemes before\n * handing the URL to `window.location.assign`. A consuming app that lets\n * attacker-controlled input reach `logoutHref` would otherwise execute\n * script. Allow only relative paths, hash fragments, and `http(s)` URLs.\n */\nfunction isSafeLogoutHref(href: string): boolean {\n if (href.startsWith('/') || href.startsWith('#') || href.startsWith('?')) {\n return true;\n }\n try {\n const url = new URL(href, window.location.origin);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nfunction SettingsMenu({\n logoutHref,\n onToggleFullscreen,\n}: {\n logoutHref: string;\n onToggleFullscreen?: () => void;\n}) {\n const { t } = useTranslation();\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <IconButton\n icon={<SettingsIcon aria-hidden=\"true\" />}\n aria-label={t('patientShell.settings.triggerAria')}\n tooltip={t('patientShell.settings.triggerAria')}\n data-testid=\"patient-shell-settings-trigger\"\n />\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item\n startIcon={<Maximize2 aria-hidden=\"true\" />}\n onSelect={onToggleFullscreen}\n data-testid=\"patient-shell-fullscreen\"\n >\n {t('patientShell.settings.fullscreen')}\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n startIcon={<LogOut aria-hidden=\"true\" />}\n onSelect={() => {\n if (typeof window === 'undefined') return;\n if (!isSafeLogoutHref(logoutHref)) return;\n window.location.assign(logoutHref);\n }}\n data-testid=\"patient-shell-logout\"\n >\n {t('patientShell.settings.logout')}\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\nfunction PatientSidebarNav({ menuItems }: { menuItems: PatientNavItem[] }) {\n return (\n <SidebarBody>\n {menuItems.map((item) => {\n const badge =\n typeof item.badgeCount === 'number' && item.badgeCount > 0\n ? item.badgeCount\n : undefined;\n return (\n <SidebarItem\n key={item.id}\n href={item.href}\n aria-label={item.label}\n isActive={item.isActive}\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 </SidebarItem>\n );\n })}\n </SidebarBody>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nexport const PatientShell = forwardRef<HTMLDivElement, PatientShellProps>(\n (\n {\n menuItems,\n logoutHref,\n onToggleFullscreen,\n brandLogo,\n brandHref = '/',\n mainAriaLabel,\n sidebarState,\n children,\n // `userName` and `userAvatarSrc` are declared on the public API\n // for forward-compatibility (future profile-pill work) — they are\n // intentionally unused today because the legacy patient chrome\n // carries no profile pill.\n userName: _userName,\n userAvatarSrc: _userAvatarSrc,\n },\n ref,\n ) => {\n const { t } = useTranslation();\n // Only wrap children in a nested <ThemeRoot> when the user has\n // explicitly chosen a theme via the hook (e.g., through an in-app\n // toggle). Otherwise we let the outer cascade win — wrapping with\n // the hook's default `resolvedTheme = 'light'` would clobber a\n // consuming app's `<html>` theme class (or Storybook's decorator)\n // for every child rendered inside the shell.\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 // Narrow-viewport overlay: `HeaderMenuButton` only renders below the\n // `md` breakpoint, and toggling opens the Sidebar's overlay Dialog.\n const [sidebarOpen, setSidebarOpen] = useState(false);\n\n const resolvedLogo = brandLogo ?? (\n <Logo variant=\"monochrome\" size=\"md\" decorative />\n );\n\n const shell = (\n <TooltipProvider>\n <AppFrame\n mainAriaLabel={mainAriaLabel}\n mainClassName=\"ds:bg-[color:var(--app-shell-background)]\"\n header={\n <Header>\n <HeaderStart>\n <HeaderSkipLink href=\"#main-content\" />\n <HeaderMenuButton onMenuOpen={() => setSidebarOpen(true)} />\n <HeaderBrand\n logo={resolvedLogo}\n href={brandHref}\n aria-label={t('patientShell.brand.homeAria')}\n />\n </HeaderStart>\n <HeaderCenter />\n <HeaderEnd>\n <SettingsMenu\n logoutHref={logoutHref}\n onToggleFullscreen={onToggleFullscreen}\n />\n </HeaderEnd>\n </Header>\n }\n sidebar={\n <Sidebar\n {...(sidebarState !== undefined\n ? { state: sidebarState }\n : { defaultState: 'expanded' as const })}\n open={sidebarOpen}\n onOpenChange={setSidebarOpen}\n aria-label={t('patientShell.sidebar.panelLabel')}\n data-testid=\"patient-shell-sidebar\"\n >\n <PatientSidebarNav menuItems={menuItems} />\n </Sidebar>\n }\n >\n {children}\n </AppFrame>\n </TooltipProvider>\n );\n\n if (!hasExplicitOverride) {\n // Pass-through wrapper preserves the ref contract without altering\n // the token cascade.\n return (\n <div ref={ref} className=\"ds:contents\">\n {shell}\n </div>\n );\n }\n\n return (\n <ThemeRoot\n ref={ref}\n theme={themeBase}\n accessible={themeAccessible}\n className=\"ds:contents\"\n >\n {shell}\n </ThemeRoot>\n );\n },\n);\n\nPatientShell.displayName = 'PatientShell';\n"],"names":["__iconNode","Maximize2","createLucideIcon","formatBadgeCount","count","isSafeLogoutHref","href","url","SettingsMenu","logoutHref","onToggleFullscreen","t","useTranslation","jsxs","DropdownMenu","jsx","IconButton","SettingsIcon","LogOut","PatientSidebarNav","menuItems","SidebarBody","item","badge","SidebarItem","SidebarItemIcon","SidebarItemLabel","SidebarItemBadge","PatientShell","forwardRef","brandLogo","brandHref","mainAriaLabel","sidebarState","children","_userName","_userAvatarSrc","ref","themePref","accessibility","resolvedTheme","useTheme","hasExplicitOverride","themeBase","themeAccessible","sidebarOpen","setSidebarOpen","useState","shell","TooltipProvider","AppFrame","Header","HeaderStart","HeaderSkipLink","HeaderMenuButton","HeaderBrand","Logo","HeaderCenter","HeaderEnd","Sidebar","ThemeRoot"],"mappings":"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","x_google_ignoreList":[0]}