@burtson-labs/ui 0.13.1 → 0.14.1

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 (460) hide show
  1. package/LICENSES/DEPENDENCIES.txt +2745 -0
  2. package/LICENSES/Radix-MIT.txt +21 -0
  3. package/LICENSES/cmdk-MIT.txt +21 -0
  4. package/LICENSES/overrides/react-remove-scroll-bar.txt +26 -0
  5. package/LICENSES/shadcn-MIT.txt +21 -0
  6. package/README.md +20 -12
  7. package/THIRD_PARTY_NOTICES.md +15 -3
  8. package/dist/components/accordion.d.ts +4 -4
  9. package/dist/components/accordion.js +22 -18
  10. package/dist/components/accordion.js.map +1 -1
  11. package/dist/components/alert-dialog.d.ts +13 -11
  12. package/dist/components/alert-dialog.js +41 -31
  13. package/dist/components/alert-dialog.js.map +1 -1
  14. package/dist/components/alert.d.ts +5 -3
  15. package/dist/components/alert.js +12 -7
  16. package/dist/components/alert.js.map +1 -1
  17. package/dist/components/app-shell.d.ts +7 -6
  18. package/dist/components/app-shell.js +22 -14
  19. package/dist/components/app-shell.js.map +1 -1
  20. package/dist/components/attachment.d.ts +3 -3
  21. package/dist/components/attachment.js +11 -7
  22. package/dist/components/attachment.js.map +1 -1
  23. package/dist/components/audio-player.d.ts +2 -2
  24. package/dist/components/audio-player.js +9 -6
  25. package/dist/components/audio-player.js.map +1 -1
  26. package/dist/components/avatar.d.ts +4 -4
  27. package/dist/components/avatar.js +16 -12
  28. package/dist/components/avatar.js.map +1 -1
  29. package/dist/components/badge.d.ts +1 -1
  30. package/dist/components/badge.js +15 -13
  31. package/dist/components/badge.js.map +1 -1
  32. package/dist/components/breadcrumb.d.ts +8 -8
  33. package/dist/components/breadcrumb.js +27 -20
  34. package/dist/components/breadcrumb.js.map +1 -1
  35. package/dist/components/button.d.ts +9 -2
  36. package/dist/components/button.js +15 -6
  37. package/dist/components/button.js.map +1 -1
  38. package/dist/components/card.d.ts +9 -9
  39. package/dist/components/card.js +33 -23
  40. package/dist/components/card.js.map +1 -1
  41. package/dist/components/chat-history.d.ts +1 -1
  42. package/dist/components/chat-history.js +11 -9
  43. package/dist/components/chat-history.js.map +1 -1
  44. package/dist/components/chat-layout.d.ts +1 -1
  45. package/dist/components/chat-layout.js +8 -3
  46. package/dist/components/chat-layout.js.map +1 -1
  47. package/dist/components/checkbox-card.d.ts +3 -3
  48. package/dist/components/checkbox-card.js +12 -10
  49. package/dist/components/checkbox-card.js.map +1 -1
  50. package/dist/components/checkbox.d.ts +24 -3
  51. package/dist/components/checkbox.js +52 -9
  52. package/dist/components/checkbox.js.map +1 -1
  53. package/dist/components/collapsible.d.ts +3 -3
  54. package/dist/components/collapsible.js +14 -11
  55. package/dist/components/collapsible.js.map +1 -1
  56. package/dist/components/combobox.d.ts +14 -4
  57. package/dist/components/combobox.js +19 -8
  58. package/dist/components/combobox.js.map +1 -1
  59. package/dist/components/command.d.ts +68 -12
  60. package/dist/components/command.js +48 -34
  61. package/dist/components/command.js.map +1 -1
  62. package/dist/components/composer.d.ts +2 -2
  63. package/dist/components/composer.js +10 -7
  64. package/dist/components/composer.js.map +1 -1
  65. package/dist/components/connection-status.d.ts +3 -3
  66. package/dist/components/connection-status.js +19 -14
  67. package/dist/components/connection-status.js.map +1 -1
  68. package/dist/components/context-menu.d.ts +15 -14
  69. package/dist/components/context-menu.js +52 -41
  70. package/dist/components/context-menu.js.map +1 -1
  71. package/dist/components/conversation.d.ts +1 -1
  72. package/dist/components/conversation.js +7 -5
  73. package/dist/components/conversation.js.map +1 -1
  74. package/dist/components/copy-button.d.ts +1 -1
  75. package/dist/components/copy-button.js +4 -2
  76. package/dist/components/copy-button.js.map +1 -1
  77. package/dist/components/data-table.d.ts +7 -2
  78. package/dist/components/data-table.js +17 -42
  79. package/dist/components/data-table.js.map +1 -1
  80. package/dist/components/dialog.d.ts +19 -10
  81. package/dist/components/dialog.js +50 -33
  82. package/dist/components/dialog.js.map +1 -1
  83. package/dist/components/dropdown-menu.d.ts +15 -14
  84. package/dist/components/dropdown-menu.js +52 -41
  85. package/dist/components/dropdown-menu.js.map +1 -1
  86. package/dist/components/editor-tabs.d.ts +1 -1
  87. package/dist/components/editor-tabs.js +7 -5
  88. package/dist/components/editor-tabs.js.map +1 -1
  89. package/dist/components/empty-state.d.ts +5 -5
  90. package/dist/components/empty-state.js +17 -11
  91. package/dist/components/empty-state.js.map +1 -1
  92. package/dist/components/error-summary.d.ts +21 -0
  93. package/dist/components/error-summary.js +62 -0
  94. package/dist/components/error-summary.js.map +1 -0
  95. package/dist/components/field.d.ts +66 -7
  96. package/dist/components/field.js +152 -20
  97. package/dist/components/field.js.map +1 -1
  98. package/dist/components/form-actions.d.ts +18 -0
  99. package/dist/components/form-actions.js +30 -0
  100. package/dist/components/form-actions.js.map +1 -0
  101. package/dist/components/icon-button.d.ts +3 -1
  102. package/dist/components/icon-button.js +6 -3
  103. package/dist/components/icon-button.js.map +1 -1
  104. package/dist/components/input.d.ts +42 -7
  105. package/dist/components/input.js +54 -10
  106. package/dist/components/input.js.map +1 -1
  107. package/dist/components/kbd.d.ts +2 -2
  108. package/dist/components/kbd.js +8 -5
  109. package/dist/components/kbd.js.map +1 -1
  110. package/dist/components/label.d.ts +7 -2
  111. package/dist/components/label.js +14 -7
  112. package/dist/components/label.js.map +1 -1
  113. package/dist/components/markdown.d.ts +4 -3
  114. package/dist/components/markdown.js +8 -6
  115. package/dist/components/markdown.js.map +1 -1
  116. package/dist/components/menubar.d.ts +17 -15
  117. package/dist/components/menubar.js +58 -45
  118. package/dist/components/menubar.js.map +1 -1
  119. package/dist/components/message-actions.d.ts +3 -3
  120. package/dist/components/message-actions.js +16 -12
  121. package/dist/components/message-actions.js.map +1 -1
  122. package/dist/components/message.d.ts +1 -1
  123. package/dist/components/message.js +6 -3
  124. package/dist/components/message.js.map +1 -1
  125. package/dist/components/mobile-nav.d.ts +1 -1
  126. package/dist/components/mobile-nav.js +7 -5
  127. package/dist/components/mobile-nav.js.map +1 -1
  128. package/dist/components/native-select.d.ts +16 -0
  129. package/dist/components/native-select.js +33 -0
  130. package/dist/components/native-select.js.map +1 -0
  131. package/dist/components/navigation-menu.d.ts +13 -12
  132. package/dist/components/navigation-menu.js +43 -33
  133. package/dist/components/navigation-menu.js.map +1 -1
  134. package/dist/components/number-input.d.ts +23 -0
  135. package/dist/components/number-input.js +45 -0
  136. package/dist/components/number-input.js.map +1 -0
  137. package/dist/components/onboarding-checklist.d.ts +1 -1
  138. package/dist/components/onboarding-checklist.js +5 -3
  139. package/dist/components/onboarding-checklist.js.map +1 -1
  140. package/dist/components/page-header.d.ts +7 -6
  141. package/dist/components/page-header.js +23 -15
  142. package/dist/components/page-header.js.map +1 -1
  143. package/dist/components/pagination.d.ts +1 -1
  144. package/dist/components/pagination.js +4 -2
  145. package/dist/components/pagination.js.map +1 -1
  146. package/dist/components/popover.d.ts +14 -11
  147. package/dist/components/popover.js +30 -23
  148. package/dist/components/popover.js.map +1 -1
  149. package/dist/components/progress.d.ts +2 -2
  150. package/dist/components/progress.js +11 -9
  151. package/dist/components/progress.js.map +1 -1
  152. package/dist/components/radio-group.d.ts +23 -4
  153. package/dist/components/radio-group.js +56 -14
  154. package/dist/components/radio-group.js.map +1 -1
  155. package/dist/components/reasoning.d.ts +3 -3
  156. package/dist/components/reasoning.js +14 -11
  157. package/dist/components/reasoning.js.map +1 -1
  158. package/dist/components/resizable.js +1 -0
  159. package/dist/components/resizable.js.map +1 -1
  160. package/dist/components/scroll-area.d.ts +4 -3
  161. package/dist/components/scroll-area.js +18 -14
  162. package/dist/components/scroll-area.js.map +1 -1
  163. package/dist/components/secret-input.d.ts +3 -2
  164. package/dist/components/secret-input.js +7 -4
  165. package/dist/components/secret-input.js.map +1 -1
  166. package/dist/components/select.d.ts +12 -7
  167. package/dist/components/select.js +42 -35
  168. package/dist/components/select.js.map +1 -1
  169. package/dist/components/separator.d.ts +2 -2
  170. package/dist/components/separator.js +8 -6
  171. package/dist/components/separator.js.map +1 -1
  172. package/dist/components/sheet.d.ts +11 -9
  173. package/dist/components/sheet.js +41 -29
  174. package/dist/components/sheet.js.map +1 -1
  175. package/dist/components/skeleton.d.ts +2 -1
  176. package/dist/components/skeleton.js +7 -4
  177. package/dist/components/skeleton.js.map +1 -1
  178. package/dist/components/slider.d.ts +10 -6
  179. package/dist/components/slider.js +16 -7
  180. package/dist/components/slider.js.map +1 -1
  181. package/dist/components/source.d.ts +2 -2
  182. package/dist/components/source.js +10 -7
  183. package/dist/components/source.js.map +1 -1
  184. package/dist/components/spinner.d.ts +4 -2
  185. package/dist/components/spinner.js +5 -3
  186. package/dist/components/spinner.js.map +1 -1
  187. package/dist/components/stat-card.d.ts +27 -2
  188. package/dist/components/stat-card.js +70 -9
  189. package/dist/components/stat-card.js.map +1 -1
  190. package/dist/components/status.d.ts +7 -6
  191. package/dist/components/status.js +12 -5
  192. package/dist/components/status.js.map +1 -1
  193. package/dist/components/steps.d.ts +1 -1
  194. package/dist/components/steps.js +5 -3
  195. package/dist/components/steps.js.map +1 -1
  196. package/dist/components/switch.d.ts +47 -3
  197. package/dist/components/switch.js +89 -11
  198. package/dist/components/switch.js.map +1 -1
  199. package/dist/components/table.d.ts +29 -12
  200. package/dist/components/table.js +80 -34
  201. package/dist/components/table.js.map +1 -1
  202. package/dist/components/tabs.d.ts +10 -5
  203. package/dist/components/tabs.js +29 -19
  204. package/dist/components/tabs.js.map +1 -1
  205. package/dist/components/textarea.d.ts +6 -1
  206. package/dist/components/textarea.js +4 -3
  207. package/dist/components/textarea.js.map +1 -1
  208. package/dist/components/toast.d.ts +11 -7
  209. package/dist/components/toast.js +37 -27
  210. package/dist/components/toast.js.map +1 -1
  211. package/dist/components/toaster.d.ts +4 -2
  212. package/dist/components/toaster.js +7 -2
  213. package/dist/components/toaster.js.map +1 -1
  214. package/dist/components/tool-call.d.ts +2 -2
  215. package/dist/components/tool-call.js +15 -12
  216. package/dist/components/tool-call.js.map +1 -1
  217. package/dist/components/toolbar.d.ts +9 -4
  218. package/dist/components/toolbar.js +15 -9
  219. package/dist/components/toolbar.js.map +1 -1
  220. package/dist/components/tooltip.d.ts +4 -3
  221. package/dist/components/tooltip.js +17 -13
  222. package/dist/components/tooltip.js.map +1 -1
  223. package/dist/components/tour.js +10 -8
  224. package/dist/components/tour.js.map +1 -1
  225. package/dist/components/tree-view.d.ts +1 -1
  226. package/dist/components/tree-view.js +10 -5
  227. package/dist/components/tree-view.js.map +1 -1
  228. package/dist/components/voice-recorder.d.ts +1 -1
  229. package/dist/components/voice-recorder.js +5 -2
  230. package/dist/components/voice-recorder.js.map +1 -1
  231. package/dist/index.d.ts +6 -1
  232. package/dist/index.js +17 -12
  233. package/dist/lib/media.d.ts +18 -0
  234. package/dist/lib/media.js +34 -0
  235. package/dist/lib/media.js.map +1 -0
  236. package/dist/lib/utils.d.ts +32 -0
  237. package/dist/lib/utils.js +33 -1
  238. package/dist/lib/utils.js.map +1 -1
  239. package/dist/mui/index.js +20 -8
  240. package/dist/mui/index.js.map +1 -1
  241. package/dist/primitives/vendor/cmdk/command-score.d.ts +1 -0
  242. package/dist/primitives/vendor/cmdk/command-score.js +64 -0
  243. package/dist/primitives/vendor/cmdk/command-score.js.map +1 -0
  244. package/dist/primitives/vendor/cmdk/index.d.ts +384 -0
  245. package/dist/primitives/vendor/cmdk/index.js +687 -0
  246. package/dist/primitives/vendor/cmdk/index.js.map +1 -0
  247. package/dist/primitives/vendor/radix/number/index.d.ts +1 -0
  248. package/dist/primitives/vendor/radix/number/number.d.ts +2 -0
  249. package/dist/primitives/vendor/radix/number/number.js +9 -0
  250. package/dist/primitives/vendor/radix/number/number.js.map +1 -0
  251. package/dist/primitives/vendor/radix/primitive/index.d.ts +2 -0
  252. package/dist/primitives/vendor/radix/primitive/is-development.d.ts +1 -0
  253. package/dist/primitives/vendor/radix/primitive/is-development.js +7 -0
  254. package/dist/primitives/vendor/radix/primitive/is-development.js.map +1 -0
  255. package/dist/primitives/vendor/radix/primitive/primitive.d.ts +14 -0
  256. package/dist/primitives/vendor/radix/primitive/primitive.js +12 -0
  257. package/dist/primitives/vendor/radix/primitive/primitive.js.map +1 -0
  258. package/dist/primitives/vendor/radix/primitive/types.d.ts +5 -0
  259. package/dist/primitives/vendor/radix/react-accordion/accordion.d.ts +112 -0
  260. package/dist/primitives/vendor/radix/react-accordion/accordion.js +266 -0
  261. package/dist/primitives/vendor/radix/react-accordion/accordion.js.map +1 -0
  262. package/dist/primitives/vendor/radix/react-accordion/index.d.ts +2 -0
  263. package/dist/primitives/vendor/radix/react-alert-dialog/alert-dialog.d.ts +49 -0
  264. package/dist/primitives/vendor/radix/react-alert-dialog/alert-dialog.js +122 -0
  265. package/dist/primitives/vendor/radix/react-alert-dialog/alert-dialog.js.map +1 -0
  266. package/dist/primitives/vendor/radix/react-alert-dialog/index.d.ts +2 -0
  267. package/dist/primitives/vendor/radix/react-arrow/arrow.d.ts +9 -0
  268. package/dist/primitives/vendor/radix/react-arrow/arrow.js +22 -0
  269. package/dist/primitives/vendor/radix/react-arrow/arrow.js.map +1 -0
  270. package/dist/primitives/vendor/radix/react-arrow/index.d.ts +2 -0
  271. package/dist/primitives/vendor/radix/react-avatar/avatar.d.ts +19 -0
  272. package/dist/primitives/vendor/radix/react-avatar/avatar.js +132 -0
  273. package/dist/primitives/vendor/radix/react-avatar/avatar.js.map +1 -0
  274. package/dist/primitives/vendor/radix/react-avatar/index.d.ts +2 -0
  275. package/dist/primitives/vendor/radix/react-checkbox/checkbox.d.ts +47 -0
  276. package/dist/primitives/vendor/radix/react-checkbox/checkbox.js +197 -0
  277. package/dist/primitives/vendor/radix/react-checkbox/checkbox.js.map +1 -0
  278. package/dist/primitives/vendor/radix/react-checkbox/index.d.ts +2 -0
  279. package/dist/primitives/vendor/radix/react-collapsible/collapsible.d.ts +31 -0
  280. package/dist/primitives/vendor/radix/react-collapsible/collapsible.js +133 -0
  281. package/dist/primitives/vendor/radix/react-collapsible/collapsible.js.map +1 -0
  282. package/dist/primitives/vendor/radix/react-collapsible/index.d.ts +2 -0
  283. package/dist/primitives/vendor/radix/react-collection/collection-legacy.d.ts +21 -0
  284. package/dist/primitives/vendor/radix/react-collection/collection-legacy.js +84 -0
  285. package/dist/primitives/vendor/radix/react-collection/collection-legacy.js.map +1 -0
  286. package/dist/primitives/vendor/radix/react-collection/collection.d.ts +32 -0
  287. package/dist/primitives/vendor/radix/react-collection/index.d.ts +4 -0
  288. package/dist/primitives/vendor/radix/react-collection/ordered-dictionary.d.ts +51 -0
  289. package/dist/primitives/vendor/radix/react-compose-refs/compose-refs.d.ts +13 -0
  290. package/dist/primitives/vendor/radix/react-compose-refs/compose-refs.js +43 -0
  291. package/dist/primitives/vendor/radix/react-compose-refs/compose-refs.js.map +1 -0
  292. package/dist/primitives/vendor/radix/react-compose-refs/index.d.ts +1 -0
  293. package/dist/primitives/vendor/radix/react-context/create-context.d.ts +45 -0
  294. package/dist/primitives/vendor/radix/react-context/create-context.js +74 -0
  295. package/dist/primitives/vendor/radix/react-context/create-context.js.map +1 -0
  296. package/dist/primitives/vendor/radix/react-context/index.d.ts +2 -0
  297. package/dist/primitives/vendor/radix/react-context-menu/context-menu.d.ts +95 -0
  298. package/dist/primitives/vendor/radix/react-context-menu/context-menu.js +279 -0
  299. package/dist/primitives/vendor/radix/react-context-menu/context-menu.js.map +1 -0
  300. package/dist/primitives/vendor/radix/react-context-menu/index.d.ts +2 -0
  301. package/dist/primitives/vendor/radix/react-dialog/dialog.d.ts +97 -0
  302. package/dist/primitives/vendor/radix/react-dialog/dialog.js +262 -0
  303. package/dist/primitives/vendor/radix/react-dialog/dialog.js.map +1 -0
  304. package/dist/primitives/vendor/radix/react-dialog/index.d.ts +4 -0
  305. package/dist/primitives/vendor/radix/react-direction/direction.d.ts +10 -0
  306. package/dist/primitives/vendor/radix/react-direction/direction.js +13 -0
  307. package/dist/primitives/vendor/radix/react-direction/direction.js.map +1 -0
  308. package/dist/primitives/vendor/radix/react-direction/index.d.ts +1 -0
  309. package/dist/primitives/vendor/radix/react-dismissable-layer/dismissable-layer.d.ts +61 -0
  310. package/dist/primitives/vendor/radix/react-dismissable-layer/dismissable-layer.js +336 -0
  311. package/dist/primitives/vendor/radix/react-dismissable-layer/dismissable-layer.js.map +1 -0
  312. package/dist/primitives/vendor/radix/react-dismissable-layer/index.d.ts +4 -0
  313. package/dist/primitives/vendor/radix/react-dropdown-menu/dropdown-menu.d.ts +95 -0
  314. package/dist/primitives/vendor/radix/react-dropdown-menu/dropdown-menu.js +257 -0
  315. package/dist/primitives/vendor/radix/react-dropdown-menu/dropdown-menu.js.map +1 -0
  316. package/dist/primitives/vendor/radix/react-dropdown-menu/index.d.ts +2 -0
  317. package/dist/primitives/vendor/radix/react-focus-guards/focus-guards.d.ts +11 -0
  318. package/dist/primitives/vendor/radix/react-focus-guards/focus-guards.js +49 -0
  319. package/dist/primitives/vendor/radix/react-focus-guards/focus-guards.js.map +1 -0
  320. package/dist/primitives/vendor/radix/react-focus-guards/index.d.ts +1 -0
  321. package/dist/primitives/vendor/radix/react-focus-scope/focus-scope.d.ts +31 -0
  322. package/dist/primitives/vendor/radix/react-focus-scope/focus-scope.js +221 -0
  323. package/dist/primitives/vendor/radix/react-focus-scope/focus-scope.js.map +1 -0
  324. package/dist/primitives/vendor/radix/react-focus-scope/index.d.ts +1 -0
  325. package/dist/primitives/vendor/radix/react-id/id.d.ts +2 -0
  326. package/dist/primitives/vendor/radix/react-id/id.js +17 -0
  327. package/dist/primitives/vendor/radix/react-id/id.js.map +1 -0
  328. package/dist/primitives/vendor/radix/react-id/index.d.ts +1 -0
  329. package/dist/primitives/vendor/radix/react-label/index.d.ts +2 -0
  330. package/dist/primitives/vendor/radix/react-label/label.d.ts +9 -0
  331. package/dist/primitives/vendor/radix/react-label/label.js +21 -0
  332. package/dist/primitives/vendor/radix/react-label/label.js.map +1 -0
  333. package/dist/primitives/vendor/radix/react-menu/index.d.ts +2 -0
  334. package/dist/primitives/vendor/radix/react-menu/menu.d.ts +173 -0
  335. package/dist/primitives/vendor/radix/react-menu/menu.js +806 -0
  336. package/dist/primitives/vendor/radix/react-menu/menu.js.map +1 -0
  337. package/dist/primitives/vendor/radix/react-menubar/index.d.ts +2 -0
  338. package/dist/primitives/vendor/radix/react-menubar/menubar.d.ts +106 -0
  339. package/dist/primitives/vendor/radix/react-menubar/menubar.js +377 -0
  340. package/dist/primitives/vendor/radix/react-menubar/menubar.js.map +1 -0
  341. package/dist/primitives/vendor/radix/react-navigation-menu/index.d.ts +2 -0
  342. package/dist/primitives/vendor/radix/react-navigation-menu/navigation-menu.d.ts +124 -0
  343. package/dist/primitives/vendor/radix/react-navigation-menu/navigation-menu.js +743 -0
  344. package/dist/primitives/vendor/radix/react-navigation-menu/navigation-menu.js.map +1 -0
  345. package/dist/primitives/vendor/radix/react-popover/index.d.ts +1 -0
  346. package/dist/primitives/vendor/radix/react-popover/popover.d.ts +83 -0
  347. package/dist/primitives/vendor/radix/react-popover/popover.js +236 -0
  348. package/dist/primitives/vendor/radix/react-popover/popover.js.map +1 -0
  349. package/dist/primitives/vendor/radix/react-popper/index.d.ts +2 -0
  350. package/dist/primitives/vendor/radix/react-popper/popper.d.ts +44 -0
  351. package/dist/primitives/vendor/radix/react-popper/popper.js +276 -0
  352. package/dist/primitives/vendor/radix/react-popper/popper.js.map +1 -0
  353. package/dist/primitives/vendor/radix/react-portal/index.d.ts +2 -0
  354. package/dist/primitives/vendor/radix/react-portal/portal.d.ts +13 -0
  355. package/dist/primitives/vendor/radix/react-portal/portal.js +21 -0
  356. package/dist/primitives/vendor/radix/react-portal/portal.js.map +1 -0
  357. package/dist/primitives/vendor/radix/react-presence/index.d.ts +2 -0
  358. package/dist/primitives/vendor/radix/react-presence/presence.d.ts +11 -0
  359. package/dist/primitives/vendor/radix/react-presence/presence.js +152 -0
  360. package/dist/primitives/vendor/radix/react-presence/presence.js.map +1 -0
  361. package/dist/primitives/vendor/radix/react-presence/use-state-machine.d.ts +10 -0
  362. package/dist/primitives/vendor/radix/react-presence/use-state-machine.js +12 -0
  363. package/dist/primitives/vendor/radix/react-presence/use-state-machine.js.map +1 -0
  364. package/dist/primitives/vendor/radix/react-primitive/index.d.ts +2 -0
  365. package/dist/primitives/vendor/radix/react-primitive/primitive.d.ts +56 -0
  366. package/dist/primitives/vendor/radix/react-primitive/primitive.js +84 -0
  367. package/dist/primitives/vendor/radix/react-primitive/primitive.js.map +1 -0
  368. package/dist/primitives/vendor/radix/react-progress/index.d.ts +2 -0
  369. package/dist/primitives/vendor/radix/react-progress/progress.d.ts +17 -0
  370. package/dist/primitives/vendor/radix/react-progress/progress.js +79 -0
  371. package/dist/primitives/vendor/radix/react-progress/progress.js.map +1 -0
  372. package/dist/primitives/vendor/radix/react-radio-group/index.d.ts +2 -0
  373. package/dist/primitives/vendor/radix/react-radio-group/radio-group.d.ts +55 -0
  374. package/dist/primitives/vendor/radix/react-radio-group/radio-group.js +173 -0
  375. package/dist/primitives/vendor/radix/react-radio-group/radio-group.js.map +1 -0
  376. package/dist/primitives/vendor/radix/react-radio-group/radio.d.ts +62 -0
  377. package/dist/primitives/vendor/radix/react-radio-group/radio.js +150 -0
  378. package/dist/primitives/vendor/radix/react-radio-group/radio.js.map +1 -0
  379. package/dist/primitives/vendor/radix/react-roving-focus/index.d.ts +2 -0
  380. package/dist/primitives/vendor/radix/react-roving-focus/roving-focus-group.d.ts +47 -0
  381. package/dist/primitives/vendor/radix/react-roving-focus/roving-focus-group.js +218 -0
  382. package/dist/primitives/vendor/radix/react-roving-focus/roving-focus-group.js.map +1 -0
  383. package/dist/primitives/vendor/radix/react-scroll-area/index.d.ts +2 -0
  384. package/dist/primitives/vendor/radix/react-scroll-area/scroll-area.d.ts +121 -0
  385. package/dist/primitives/vendor/radix/react-scroll-area/scroll-area.js +713 -0
  386. package/dist/primitives/vendor/radix/react-scroll-area/scroll-area.js.map +1 -0
  387. package/dist/primitives/vendor/radix/react-scroll-area/use-state-machine.d.ts +10 -0
  388. package/dist/primitives/vendor/radix/react-scroll-area/use-state-machine.js +12 -0
  389. package/dist/primitives/vendor/radix/react-scroll-area/use-state-machine.js.map +1 -0
  390. package/dist/primitives/vendor/radix/react-select/index.d.ts +2 -0
  391. package/dist/primitives/vendor/radix/react-select/select.d.ts +163 -0
  392. package/dist/primitives/vendor/radix/react-select/select.js +1040 -0
  393. package/dist/primitives/vendor/radix/react-select/select.js.map +1 -0
  394. package/dist/primitives/vendor/radix/react-separator/index.d.ts +2 -0
  395. package/dist/primitives/vendor/radix/react-separator/separator.d.ts +20 -0
  396. package/dist/primitives/vendor/radix/react-separator/separator.js +29 -0
  397. package/dist/primitives/vendor/radix/react-separator/separator.js.map +1 -0
  398. package/dist/primitives/vendor/radix/react-slot/index.d.ts +1 -0
  399. package/dist/primitives/vendor/radix/react-slot/slot.d.ts +29 -0
  400. package/dist/primitives/vendor/radix/react-slot/slot.js +107 -0
  401. package/dist/primitives/vendor/radix/react-slot/slot.js.map +1 -0
  402. package/dist/primitives/vendor/radix/react-switch/index.d.ts +2 -0
  403. package/dist/primitives/vendor/radix/react-switch/switch.d.ts +41 -0
  404. package/dist/primitives/vendor/radix/react-switch/switch.js +185 -0
  405. package/dist/primitives/vendor/radix/react-switch/switch.js.map +1 -0
  406. package/dist/primitives/vendor/radix/react-tabs/index.d.ts +2 -0
  407. package/dist/primitives/vendor/radix/react-tabs/tabs.d.ts +54 -0
  408. package/dist/primitives/vendor/radix/react-tabs/tabs.js +145 -0
  409. package/dist/primitives/vendor/radix/react-tabs/tabs.js.map +1 -0
  410. package/dist/primitives/vendor/radix/react-toast/index.d.ts +2 -0
  411. package/dist/primitives/vendor/radix/react-toast/toast.d.ts +125 -0
  412. package/dist/primitives/vendor/radix/react-toast/toast.js +557 -0
  413. package/dist/primitives/vendor/radix/react-toast/toast.js.map +1 -0
  414. package/dist/primitives/vendor/radix/react-tooltip/index.d.ts +2 -0
  415. package/dist/primitives/vendor/radix/react-tooltip/tooltip.d.ts +99 -0
  416. package/dist/primitives/vendor/radix/react-tooltip/tooltip.js +503 -0
  417. package/dist/primitives/vendor/radix/react-tooltip/tooltip.js.map +1 -0
  418. package/dist/primitives/vendor/radix/react-use-callback-ref/index.d.ts +1 -0
  419. package/dist/primitives/vendor/radix/react-use-callback-ref/use-callback-ref.d.ts +6 -0
  420. package/dist/primitives/vendor/radix/react-use-callback-ref/use-callback-ref.js +18 -0
  421. package/dist/primitives/vendor/radix/react-use-callback-ref/use-callback-ref.js.map +1 -0
  422. package/dist/primitives/vendor/radix/react-use-controllable-state/index.d.ts +2 -0
  423. package/dist/primitives/vendor/radix/react-use-controllable-state/use-controllable-state-reducer.d.ts +28 -0
  424. package/dist/primitives/vendor/radix/react-use-controllable-state/use-controllable-state.d.ts +11 -0
  425. package/dist/primitives/vendor/radix/react-use-controllable-state/use-controllable-state.js +59 -0
  426. package/dist/primitives/vendor/radix/react-use-controllable-state/use-controllable-state.js.map +1 -0
  427. package/dist/primitives/vendor/radix/react-use-effect-event/index.d.ts +1 -0
  428. package/dist/primitives/vendor/radix/react-use-effect-event/use-effect-event.d.ts +7 -0
  429. package/dist/primitives/vendor/radix/react-use-is-hydrated/index.d.ts +1 -0
  430. package/dist/primitives/vendor/radix/react-use-is-hydrated/use-is-hydrated-legacy.d.ts +1 -0
  431. package/dist/primitives/vendor/radix/react-use-is-hydrated/use-is-hydrated-legacy.js +18 -0
  432. package/dist/primitives/vendor/radix/react-use-is-hydrated/use-is-hydrated-legacy.js.map +1 -0
  433. package/dist/primitives/vendor/radix/react-use-is-hydrated/use-is-hydrated.d.ts +6 -0
  434. package/dist/primitives/vendor/radix/react-use-is-hydrated/use-is-hydrated.js +19 -0
  435. package/dist/primitives/vendor/radix/react-use-is-hydrated/use-is-hydrated.js.map +1 -0
  436. package/dist/primitives/vendor/radix/react-use-layout-effect/index.d.ts +1 -0
  437. package/dist/primitives/vendor/radix/react-use-layout-effect/use-layout-effect.d.ts +10 -0
  438. package/dist/primitives/vendor/radix/react-use-layout-effect/use-layout-effect.js +15 -0
  439. package/dist/primitives/vendor/radix/react-use-layout-effect/use-layout-effect.js.map +1 -0
  440. package/dist/primitives/vendor/radix/react-use-previous/index.d.ts +1 -0
  441. package/dist/primitives/vendor/radix/react-use-previous/use-previous.d.ts +2 -0
  442. package/dist/primitives/vendor/radix/react-use-previous/use-previous.js +20 -0
  443. package/dist/primitives/vendor/radix/react-use-previous/use-previous.js.map +1 -0
  444. package/dist/primitives/vendor/radix/react-use-size/index.d.ts +1 -0
  445. package/dist/primitives/vendor/radix/react-use-size/use-size.d.ts +5 -0
  446. package/dist/primitives/vendor/radix/react-use-size/use-size.js +42 -0
  447. package/dist/primitives/vendor/radix/react-use-size/use-size.js.map +1 -0
  448. package/dist/primitives/vendor/radix/react-visually-hidden/index.d.ts +2 -0
  449. package/dist/primitives/vendor/radix/react-visually-hidden/visually-hidden.d.ts +21 -0
  450. package/dist/primitives/vendor/radix/react-visually-hidden/visually-hidden.js +32 -0
  451. package/dist/primitives/vendor/radix/react-visually-hidden/visually-hidden.js.map +1 -0
  452. package/dist/primitives/vendor/radix/rect/index.d.ts +2 -0
  453. package/dist/primitives/vendor/radix/rect/observe-element-rect.d.ts +16 -0
  454. package/dist/styles.css +1 -1
  455. package/dist/theme.css +36 -17
  456. package/dist/tokens.d.ts +78 -36
  457. package/dist/tokens.js +63 -32
  458. package/dist/tokens.js.map +1 -1
  459. package/package.json +25 -13
  460. package/vendor-manifest.json +1101 -0
@@ -1,9 +1,10 @@
1
- import { cn } from "../lib/utils.js";
1
+ "use client";
2
+ import { cn, focusRingClasses } from "../lib/utils.js";
2
3
  import { Alert, AlertDescription, AlertTitle } from "./alert.js";
3
4
  import { Button } from "./button.js";
4
5
  import { Status } from "./status.js";
5
6
  import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip.js";
6
- import "react";
7
+ import * as React from "react";
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
8
9
  import CloudOff from "@burtson-labs/icons/react/cloud-off";
9
10
  import WifiOff from "@burtson-labs/icons/react/wifi-off";
@@ -29,7 +30,7 @@ var connection = {
29
30
  },
30
31
  error: {
31
32
  text: "Connection failed",
32
- tone: "danger"
33
+ tone: "destructive"
33
34
  },
34
35
  unknown: {
35
36
  text: "Status unknown",
@@ -56,7 +57,7 @@ var sync = {
56
57
  },
57
58
  error: {
58
59
  text: "Sync failed",
59
- tone: "danger"
60
+ tone: "destructive"
60
61
  },
61
62
  unknown: {
62
63
  text: "Sync status unknown",
@@ -70,8 +71,9 @@ function WithDetail({ detail, children }) {
70
71
  children
71
72
  }), /* @__PURE__ */ jsx(TooltipContent, { children: detail })] });
72
73
  }
73
- function StatusLine({ slot, state, text, tone, pulse, detail, onRetry, className, ...props }) {
74
+ var StatusLine = React.forwardRef(function StatusLine({ slot, state, text, tone, pulse, detail, onRetry, className, ...props }, ref) {
74
75
  return /* @__PURE__ */ jsxs("div", {
76
+ ref,
75
77
  "data-slot": slot,
76
78
  "data-state": state,
77
79
  role: "status",
@@ -83,7 +85,7 @@ function StatusLine({ slot, state, text, tone, pulse, detail, onRetry, className
83
85
  status: tone,
84
86
  pulse,
85
87
  tabIndex: detail ? 0 : void 0,
86
- className: "rounded-sm outline-none focus-visible:ring-[3px] focus-visible:ring-ring/20",
88
+ className: cn("rounded-sm", focusRingClasses, detail && "relative pointer-coarse:before:absolute pointer-coarse:before:inset-x-0 pointer-coarse:before:top-1/2 pointer-coarse:before:h-11 pointer-coarse:before:-translate-y-1/2 pointer-coarse:before:content-['']"),
87
89
  children: [text, detail && typeof detail === "string" && /* @__PURE__ */ jsxs("span", {
88
90
  className: "sr-only",
89
91
  children: [". ", detail]
@@ -98,11 +100,12 @@ function StatusLine({ slot, state, text, tone, pulse, detail, onRetry, className
98
100
  children: "Retry"
99
101
  })]
100
102
  });
101
- }
103
+ });
102
104
  /** A dot and a word for a live connection: model provider, gateway, socket. */
103
- function ConnectionStatus({ state, label, detail, onRetry, ...props }) {
105
+ var ConnectionStatus = React.forwardRef(function ConnectionStatus({ state, label, detail, onRetry, ...props }, ref) {
104
106
  const c = connection[state];
105
107
  return /* @__PURE__ */ jsx(StatusLine, {
108
+ ref,
106
109
  slot: "connection-status",
107
110
  state,
108
111
  text: label ?? c.text,
@@ -112,17 +115,18 @@ function ConnectionStatus({ state, label, detail, onRetry, ...props }) {
112
115
  onRetry: state === "offline" || state === "error" ? onRetry : void 0,
113
116
  ...props
114
117
  });
115
- }
118
+ });
116
119
  /** Whether local changes have reached the server. */
117
- function SyncStatus({ state, lastSynced, pendingCount, detail, onRetry, formatTime = (d) => d.toLocaleTimeString([], {
120
+ var SyncStatus = React.forwardRef(function SyncStatus({ state, lastSynced, pendingCount, detail, onRetry, formatTime = (d) => d.toLocaleTimeString([], {
118
121
  hour: "numeric",
119
122
  minute: "2-digit"
120
- }), ...props }) {
123
+ }), ...props }, ref) {
121
124
  const s = sync[state];
122
125
  let text = s.text;
123
126
  if (state === "synced" && lastSynced) text = `Synced ${formatTime(lastSynced)}`;
124
127
  if (state === "pending" && pendingCount) text = `${pendingCount} ${pendingCount === 1 ? "change" : "changes"} not synced yet`;
125
128
  return /* @__PURE__ */ jsx(StatusLine, {
129
+ ref,
126
130
  slot: "sync-status",
127
131
  state,
128
132
  text,
@@ -132,15 +136,16 @@ function SyncStatus({ state, lastSynced, pendingCount, detail, onRetry, formatTi
132
136
  onRetry: state === "error" ? onRetry : void 0,
133
137
  ...props
134
138
  });
135
- }
139
+ });
136
140
  /**
137
141
  * A full-width notice for connection trouble. It renders nothing while
138
142
  * connected, connecting or unknown, so it can stay mounted.
139
143
  */
140
- function ConnectionBanner({ state, description, onRetry, className, ...props }) {
144
+ var ConnectionBanner = React.forwardRef(function ConnectionBanner({ state, description, onRetry, className, ...props }, ref) {
141
145
  if (state !== "offline" && state !== "error" && state !== "reconnecting") return null;
142
146
  const title = state === "offline" ? "You are offline" : state === "reconnecting" ? "Reconnecting…" : "Could not connect";
143
147
  return /* @__PURE__ */ jsxs(Alert, {
148
+ ref,
144
149
  "data-slot": "connection-banner",
145
150
  "data-state": state,
146
151
  variant: state === "error" ? "destructive" : "warning",
@@ -160,7 +165,7 @@ function ConnectionBanner({ state, description, onRetry, className, ...props })
160
165
  })]
161
166
  })]
162
167
  });
163
- }
168
+ });
164
169
  //#endregion
165
170
  export { ConnectionBanner, ConnectionStatus, SyncStatus };
166
171
 
@@ -1 +1 @@
1
- {"version":3,"file":"connection-status.js","names":[],"sources":["../../src/components/connection-status.tsx"],"sourcesContent":["import CloudOff from '@burtson-labs/icons/react/cloud-off';\nimport WifiOff from '@burtson-labs/icons/react/wifi-off';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Alert, AlertDescription, AlertTitle } from './alert';\nimport { Button } from './button';\nimport { Status } from './status';\nimport { Tooltip, TooltipContent, TooltipTrigger } from './tooltip';\n\ntype Tone = 'neutral' | 'brand' | 'success' | 'warning' | 'danger' | 'info';\n\n/**\n * The host reports the state; these components only present it. `unknown`\n * means nobody has checked yet and never reads as connected.\n */\nexport type ConnectionState =\n 'connected' | 'connecting' | 'reconnecting' | 'offline' | 'error' | 'unknown';\n\nconst connection: Record<ConnectionState, { text: string; tone: Tone; pulse?: boolean }> = {\n connected: { text: 'Connected', tone: 'success' },\n connecting: { text: 'Connecting', tone: 'info', pulse: true },\n reconnecting: { text: 'Reconnecting', tone: 'warning', pulse: true },\n offline: { text: 'Offline', tone: 'neutral' },\n error: { text: 'Connection failed', tone: 'danger' },\n unknown: { text: 'Status unknown', tone: 'neutral' },\n};\n\nexport type SyncState = 'synced' | 'syncing' | 'pending' | 'offline' | 'error' | 'unknown';\n\nconst sync: Record<SyncState, { text: string; tone: Tone; pulse?: boolean }> = {\n synced: { text: 'Synced', tone: 'success' },\n syncing: { text: 'Syncing', tone: 'info', pulse: true },\n pending: { text: 'Changes not synced yet', tone: 'warning' },\n offline: { text: 'Offline, saved on this device', tone: 'neutral' },\n error: { text: 'Sync failed', tone: 'danger' },\n unknown: { text: 'Sync status unknown', tone: 'neutral' },\n};\n\nfunction WithDetail({\n detail,\n children,\n}: {\n detail?: React.ReactNode;\n children: React.ReactElement;\n}) {\n if (!detail) return children;\n return (\n <Tooltip>\n <TooltipTrigger asChild>{children}</TooltipTrigger>\n <TooltipContent>{detail}</TooltipContent>\n </Tooltip>\n );\n}\n\nfunction StatusLine({\n slot,\n state,\n text,\n tone,\n pulse,\n detail,\n onRetry,\n className,\n ...props\n}: Omit<React.ComponentProps<'div'>, 'children'> & {\n slot: string;\n state: string;\n text: React.ReactNode;\n tone: Tone;\n pulse?: boolean;\n detail?: React.ReactNode;\n onRetry?: () => void;\n}) {\n return (\n <div\n data-slot={slot}\n data-state={state}\n role=\"status\"\n className={cn('inline-flex items-center gap-2', className)}\n {...props}\n >\n <WithDetail detail={detail}>\n <Status\n status={tone}\n pulse={pulse}\n tabIndex={detail ? 0 : undefined}\n className=\"rounded-sm outline-none focus-visible:ring-[3px] focus-visible:ring-ring/20\"\n >\n {text}\n {detail && typeof detail === 'string' && <span className=\"sr-only\">. {detail}</span>}\n </Status>\n </WithDetail>\n {onRetry && (\n <Button type=\"button\" variant=\"link\" size=\"xs\" className=\"h-auto px-0\" onClick={onRetry}>\n Retry\n </Button>\n )}\n </div>\n );\n}\n\nexport interface ConnectionStatusProps extends Omit<React.ComponentProps<'div'>, 'children'> {\n state: ConnectionState;\n /** Overrides the default text, e.g. \"Connected to Ollama\". */\n label?: React.ReactNode;\n /** More detail in a tooltip, e.g. the endpoint or last error. */\n detail?: React.ReactNode;\n /** Offered when offline or failed. */\n onRetry?: () => void;\n}\n\n/** A dot and a word for a live connection: model provider, gateway, socket. */\nfunction ConnectionStatus({ state, label, detail, onRetry, ...props }: ConnectionStatusProps) {\n const c = connection[state];\n return (\n <StatusLine\n slot=\"connection-status\"\n state={state}\n text={label ?? c.text}\n tone={c.tone}\n pulse={c.pulse}\n detail={detail}\n onRetry={state === 'offline' || state === 'error' ? onRetry : undefined}\n {...props}\n />\n );\n}\n\nexport interface SyncStatusProps extends Omit<React.ComponentProps<'div'>, 'children'> {\n state: SyncState;\n /** When the last successful sync finished. */\n lastSynced?: Date;\n /** Changes waiting to go up. */\n pendingCount?: number;\n detail?: React.ReactNode;\n /** Offered when sync failed. */\n onRetry?: () => void;\n /** Formats `lastSynced`; the default is the local time. */\n formatTime?: (date: Date) => string;\n}\n\n/** Whether local changes have reached the server. */\nfunction SyncStatus({\n state,\n lastSynced,\n pendingCount,\n detail,\n onRetry,\n formatTime = (d) => d.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' }),\n ...props\n}: SyncStatusProps) {\n const s = sync[state];\n let text = s.text;\n if (state === 'synced' && lastSynced) text = `Synced ${formatTime(lastSynced)}`;\n if (state === 'pending' && pendingCount)\n text = `${pendingCount} ${pendingCount === 1 ? 'change' : 'changes'} not synced yet`;\n return (\n <StatusLine\n slot=\"sync-status\"\n state={state}\n text={text}\n tone={s.tone}\n pulse={s.pulse}\n detail={detail}\n onRetry={state === 'error' ? onRetry : undefined}\n {...props}\n />\n );\n}\n\nexport interface ConnectionBannerProps extends Omit<React.ComponentProps<'div'>, 'children'> {\n state: ConnectionState;\n /** What still works, e.g. \"Messages you send will go out when you reconnect.\" */\n description?: React.ReactNode;\n onRetry?: () => void;\n}\n\n/**\n * A full-width notice for connection trouble. It renders nothing while\n * connected, connecting or unknown, so it can stay mounted.\n */\nfunction ConnectionBanner({\n state,\n description,\n onRetry,\n className,\n ...props\n}: ConnectionBannerProps) {\n if (state !== 'offline' && state !== 'error' && state !== 'reconnecting') return null;\n const title =\n state === 'offline'\n ? 'You are offline'\n : state === 'reconnecting'\n ? 'Reconnecting…'\n : 'Could not connect';\n return (\n <Alert\n data-slot=\"connection-banner\"\n data-state={state}\n variant={state === 'error' ? 'destructive' : 'warning'}\n className={cn('items-center', className)}\n {...props}\n >\n {state === 'offline' ? <WifiOff aria-hidden /> : <CloudOff aria-hidden />}\n <div className=\"flex min-w-0 flex-wrap items-center justify-between gap-x-4 gap-y-2\">\n <div className=\"min-w-0\">\n <AlertTitle>{title}</AlertTitle>\n {description && <AlertDescription>{description}</AlertDescription>}\n </div>\n {onRetry && state !== 'reconnecting' && (\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={onRetry}>\n Retry\n </Button>\n )}\n </div>\n </Alert>\n );\n}\n\nexport { ConnectionBanner, ConnectionStatus, SyncStatus };\n"],"mappings":"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"}
1
+ {"version":3,"file":"connection-status.js","names":[],"sources":["../../src/components/connection-status.tsx"],"sourcesContent":["import CloudOff from '@burtson-labs/icons/react/cloud-off';\nimport WifiOff from '@burtson-labs/icons/react/wifi-off';\nimport * as React from 'react';\n\nimport { cn, focusRingClasses, touchTargetRowClasses } from '../lib/utils';\n\nimport { Alert, AlertDescription, AlertTitle } from './alert';\nimport { Button } from './button';\nimport { Status } from './status';\nimport { Tooltip, TooltipContent, TooltipTrigger } from './tooltip';\n\ntype Tone = 'neutral' | 'brand' | 'success' | 'warning' | 'destructive' | 'info';\n\n/**\n * The host reports the state; these components only present it. `unknown`\n * means nobody has checked yet and never reads as connected.\n */\nexport type ConnectionState =\n 'connected' | 'connecting' | 'reconnecting' | 'offline' | 'error' | 'unknown';\n\nconst connection: Record<ConnectionState, { text: string; tone: Tone; pulse?: boolean }> = {\n connected: { text: 'Connected', tone: 'success' },\n connecting: { text: 'Connecting', tone: 'info', pulse: true },\n reconnecting: { text: 'Reconnecting', tone: 'warning', pulse: true },\n offline: { text: 'Offline', tone: 'neutral' },\n error: { text: 'Connection failed', tone: 'destructive' },\n unknown: { text: 'Status unknown', tone: 'neutral' },\n};\n\nexport type SyncState = 'synced' | 'syncing' | 'pending' | 'offline' | 'error' | 'unknown';\n\nconst sync: Record<SyncState, { text: string; tone: Tone; pulse?: boolean }> = {\n synced: { text: 'Synced', tone: 'success' },\n syncing: { text: 'Syncing', tone: 'info', pulse: true },\n pending: { text: 'Changes not synced yet', tone: 'warning' },\n offline: { text: 'Offline, saved on this device', tone: 'neutral' },\n error: { text: 'Sync failed', tone: 'destructive' },\n unknown: { text: 'Sync status unknown', tone: 'neutral' },\n};\n\nfunction WithDetail({\n detail,\n children,\n}: {\n detail?: React.ReactNode;\n children: React.ReactElement;\n}) {\n if (!detail) return children;\n return (\n <Tooltip>\n <TooltipTrigger asChild>{children}</TooltipTrigger>\n <TooltipContent>{detail}</TooltipContent>\n </Tooltip>\n );\n}\n\ninterface StatusLineProps extends Omit<React.ComponentProps<'div'>, 'children'> {\n slot: string;\n state: string;\n text: React.ReactNode;\n tone: Tone;\n pulse?: boolean;\n detail?: React.ReactNode;\n onRetry?: () => void;\n}\n\nconst StatusLine = React.forwardRef<HTMLDivElement, StatusLineProps>(function StatusLine(\n { slot, state, text, tone, pulse, detail, onRetry, className, ...props },\n ref,\n) {\n return (\n <div\n ref={ref}\n data-slot={slot}\n data-state={state}\n role=\"status\"\n className={cn('inline-flex items-center gap-2', className)}\n {...props}\n >\n <WithDetail detail={detail}>\n <Status\n status={tone}\n pulse={pulse}\n tabIndex={detail ? 0 : undefined}\n className={cn('rounded-sm', focusRingClasses, detail && touchTargetRowClasses)}\n >\n {text}\n {detail && typeof detail === 'string' && <span className=\"sr-only\">. {detail}</span>}\n </Status>\n </WithDetail>\n {onRetry && (\n <Button type=\"button\" variant=\"link\" size=\"xs\" className=\"h-auto px-0\" onClick={onRetry}>\n Retry\n </Button>\n )}\n </div>\n );\n});\n\nexport interface ConnectionStatusProps extends Omit<React.ComponentProps<'div'>, 'children'> {\n state: ConnectionState;\n /** Overrides the default text, e.g. \"Connected to Ollama\". */\n label?: React.ReactNode;\n /** More detail in a tooltip, e.g. the endpoint or last error. */\n detail?: React.ReactNode;\n /** Offered when offline or failed. */\n onRetry?: () => void;\n}\n\n/** A dot and a word for a live connection: model provider, gateway, socket. */\nconst ConnectionStatus = React.forwardRef<HTMLDivElement, ConnectionStatusProps>(\n function ConnectionStatus({ state, label, detail, onRetry, ...props }, ref) {\n const c = connection[state];\n return (\n <StatusLine\n ref={ref}\n slot=\"connection-status\"\n state={state}\n text={label ?? c.text}\n tone={c.tone}\n pulse={c.pulse}\n detail={detail}\n onRetry={state === 'offline' || state === 'error' ? onRetry : undefined}\n {...props}\n />\n );\n },\n);\n\nexport interface SyncStatusProps extends Omit<React.ComponentProps<'div'>, 'children'> {\n state: SyncState;\n /** When the last successful sync finished. */\n lastSynced?: Date;\n /** Changes waiting to go up. */\n pendingCount?: number;\n detail?: React.ReactNode;\n /** Offered when sync failed. */\n onRetry?: () => void;\n /** Formats `lastSynced`; the default is the local time. */\n formatTime?: (date: Date) => string;\n}\n\n/** Whether local changes have reached the server. */\nconst SyncStatus = React.forwardRef<HTMLDivElement, SyncStatusProps>(function SyncStatus(\n {\n state,\n lastSynced,\n pendingCount,\n detail,\n onRetry,\n formatTime = (d) => d.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' }),\n ...props\n },\n ref,\n) {\n const s = sync[state];\n let text = s.text;\n if (state === 'synced' && lastSynced) text = `Synced ${formatTime(lastSynced)}`;\n if (state === 'pending' && pendingCount)\n text = `${pendingCount} ${pendingCount === 1 ? 'change' : 'changes'} not synced yet`;\n return (\n <StatusLine\n ref={ref}\n slot=\"sync-status\"\n state={state}\n text={text}\n tone={s.tone}\n pulse={s.pulse}\n detail={detail}\n onRetry={state === 'error' ? onRetry : undefined}\n {...props}\n />\n );\n});\n\nexport interface ConnectionBannerProps extends Omit<React.ComponentProps<'div'>, 'children'> {\n state: ConnectionState;\n /** What still works, e.g. \"Messages you send will go out when you reconnect.\" */\n description?: React.ReactNode;\n onRetry?: () => void;\n}\n\n/**\n * A full-width notice for connection trouble. It renders nothing while\n * connected, connecting or unknown, so it can stay mounted.\n */\nconst ConnectionBanner = React.forwardRef<HTMLDivElement, ConnectionBannerProps>(\n function ConnectionBanner({ state, description, onRetry, className, ...props }, ref) {\n if (state !== 'offline' && state !== 'error' && state !== 'reconnecting') return null;\n const title =\n state === 'offline'\n ? 'You are offline'\n : state === 'reconnecting'\n ? 'Reconnecting…'\n : 'Could not connect';\n return (\n <Alert\n ref={ref}\n data-slot=\"connection-banner\"\n data-state={state}\n variant={state === 'error' ? 'destructive' : 'warning'}\n className={cn('items-center', className)}\n {...props}\n >\n {state === 'offline' ? <WifiOff aria-hidden /> : <CloudOff aria-hidden />}\n <div className=\"flex min-w-0 flex-wrap items-center justify-between gap-x-4 gap-y-2\">\n <div className=\"min-w-0\">\n <AlertTitle>{title}</AlertTitle>\n {description && <AlertDescription>{description}</AlertDescription>}\n </div>\n {onRetry && state !== 'reconnecting' && (\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={onRetry}>\n Retry\n </Button>\n )}\n </div>\n </Alert>\n );\n },\n);\n\nexport { ConnectionBanner, ConnectionStatus, SyncStatus };\n"],"mappings":";;;;;;;;;;;AAoBA,IAAM,aAAqF;CACzF,WAAW;EAAE,MAAM;EAAa,MAAM;CAAU;CAChD,YAAY;EAAE,MAAM;EAAc,MAAM;EAAQ,OAAO;CAAK;CAC5D,cAAc;EAAE,MAAM;EAAgB,MAAM;EAAW,OAAO;CAAK;CACnE,SAAS;EAAE,MAAM;EAAW,MAAM;CAAU;CAC5C,OAAO;EAAE,MAAM;EAAqB,MAAM;CAAc;CACxD,SAAS;EAAE,MAAM;EAAkB,MAAM;CAAU;AACrD;AAIA,IAAM,OAAyE;CAC7E,QAAQ;EAAE,MAAM;EAAU,MAAM;CAAU;CAC1C,SAAS;EAAE,MAAM;EAAW,MAAM;EAAQ,OAAO;CAAK;CACtD,SAAS;EAAE,MAAM;EAA0B,MAAM;CAAU;CAC3D,SAAS;EAAE,MAAM;EAAiC,MAAM;CAAU;CAClE,OAAO;EAAE,MAAM;EAAe,MAAM;CAAc;CAClD,SAAS;EAAE,MAAM;EAAuB,MAAM;CAAU;AAC1D;AAEA,SAAS,WAAW,EAClB,QACA,YAIC;CACD,IAAI,CAAC,QAAQ,OAAO;CACpB,OACE,qBAAC,SAAD,EAAA,UAAA,CACE,oBAAC,gBAAD;EAAgB,SAAA;EAAS;CAAyB,CAAA,GAClD,oBAAC,gBAAD,EAAA,UAAiB,OAAuB,CAAA,CACjC,EAAA,CAAA;AAEb;AAYA,IAAM,aAAa,MAAM,WAA4C,SAAS,WAC5E,EAAE,MAAM,OAAO,MAAM,MAAM,OAAO,QAAQ,SAAS,WAAW,GAAG,SACjE,KACA;CACA,OACE,qBAAC,OAAD;EACO;EACL,aAAW;EACX,cAAY;EACZ,MAAK;EACL,WAAW,GAAG,kCAAkC,SAAS;EACzD,GAAI;EANN,UAAA,CAQE,oBAAC,YAAD;GAAoB;GAClB,UAAA,qBAAC,QAAD;IACE,QAAQ;IACD;IACP,UAAU,SAAS,IAAI,KAAA;IACvB,WAAW,GAAG,cAAc,kBAAkB,UAAA,4MAA+B;IAJ/E,UAAA,CAMG,MACA,UAAU,OAAO,WAAW,YAAY,qBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA,CAA0B,MAAG,MAAa;IAC7E,CAAA,CAAA;;EACE,CAAA,GACX,WACC,oBAAC,QAAD;GAAQ,MAAK;GAAS,SAAQ;GAAO,MAAK;GAAK,WAAU;GAAc,SAAS;GAAS,UAAA;EAEjF,CAAA,CAEP;;AAET,CAAC;;AAaD,IAAM,mBAAmB,MAAM,WAC7B,SAAS,iBAAiB,EAAE,OAAO,OAAO,QAAQ,SAAS,GAAG,SAAS,KAAK;CAC1E,MAAM,IAAI,WAAW;CACrB,OACE,oBAAC,YAAD;EACO;EACL,MAAK;EACE;EACP,MAAM,SAAS,EAAE;EACjB,MAAM,EAAE;EACR,OAAO,EAAE;EACD;EACR,SAAS,UAAU,aAAa,UAAU,UAAU,UAAU,KAAA;EAC9D,GAAI;CACL,CAAA;AAEL,CACF;;AAgBA,IAAM,aAAa,MAAM,WAA4C,SAAS,WAC5E,EACE,OACA,YACA,cACA,QACA,SACA,cAAc,MAAM,EAAE,mBAAmB,CAAC,GAAG;CAAE,MAAM;CAAW,QAAQ;AAAU,CAAC,GACnF,GAAG,SAEL,KACA;CACA,MAAM,IAAI,KAAK;CACf,IAAI,OAAO,EAAE;CACb,IAAI,UAAU,YAAY,YAAY,OAAO,UAAU,WAAW,UAAU;CAC5E,IAAI,UAAU,aAAa,cACzB,OAAO,GAAG,aAAa,GAAG,iBAAiB,IAAI,WAAW,UAAU;CACtE,OACE,oBAAC,YAAD;EACO;EACL,MAAK;EACE;EACD;EACN,MAAM,EAAE;EACR,OAAO,EAAE;EACD;EACR,SAAS,UAAU,UAAU,UAAU,KAAA;EACvC,GAAI;CACL,CAAA;AAEL,CAAC;;;;;AAaD,IAAM,mBAAmB,MAAM,WAC7B,SAAS,iBAAiB,EAAE,OAAO,aAAa,SAAS,WAAW,GAAG,SAAS,KAAK;CACnF,IAAI,UAAU,aAAa,UAAU,WAAW,UAAU,gBAAgB,OAAO;CACjF,MAAM,QACJ,UAAU,YACN,oBACA,UAAU,iBACR,kBACA;CACR,OACE,qBAAC,OAAD;EACO;EACL,aAAU;EACV,cAAY;EACZ,SAAS,UAAU,UAAU,gBAAgB;EAC7C,WAAW,GAAG,gBAAgB,SAAS;EACvC,GAAI;EANN,UAAA,CAQG,UAAU,YAAY,oBAAC,SAAD,EAAS,eAAA,KAAa,CAAA,IAAI,oBAAC,UAAD,EAAU,eAAA,KAAa,CAAA,GACxE,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,YAAD,EAAA,UAAa,MAAkB,CAAA,GAC9B,eAAe,oBAAC,kBAAD,EAAA,UAAmB,YAA8B,CAAA,CAC9D;GACJ,CAAA,GAAA,WAAW,UAAU,kBACpB,oBAAC,QAAD;IAAQ,MAAK;IAAS,MAAK;IAAK,SAAQ;IAAU,SAAS;IAAS,UAAA;GAE5D,CAAA,CAEP;EACA,CAAA,CAAA;;AAEX,CACF"}
@@ -1,5 +1,5 @@
1
- import { ContextMenu as ContextMenuPrimitive } from 'radix-ui';
2
1
  import * as React from 'react';
2
+ import * as ContextMenuPrimitive from '../primitives/vendor/radix/react-context-menu';
3
3
  /**
4
4
  * A right-click menu. Wrap the target in ContextMenuTrigger (use asChild to keep
5
5
  * your element); the menu opens at the pointer, and from the keyboard with the
@@ -7,24 +7,25 @@ import * as React from 'react';
7
7
  * DropdownMenu, so a command can appear in both.
8
8
  */
9
9
  declare function ContextMenu(props: React.ComponentProps<typeof ContextMenuPrimitive.Root>): React.JSX.Element;
10
- declare function ContextMenuTrigger(props: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>): React.JSX.Element;
10
+ declare const ContextMenuTrigger: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuTriggerProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
11
11
  declare function ContextMenuGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.Group>): React.JSX.Element;
12
- declare function ContextMenuContent({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Content>): React.JSX.Element;
13
- declare function ContextMenuItem({ className, inset, variant, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
12
+ declare const ContextMenuContent: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
13
+ export interface ContextMenuItemProps extends React.ComponentProps<typeof ContextMenuPrimitive.Item> {
14
14
  inset?: boolean;
15
15
  variant?: 'default' | 'destructive';
16
- }): React.JSX.Element;
17
- declare function ContextMenuCheckboxItem({ className, children, checked, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>): React.JSX.Element;
16
+ }
17
+ declare const ContextMenuItem: React.ForwardRefExoticComponent<Omit<ContextMenuItemProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
18
+ declare const ContextMenuCheckboxItem: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuCheckboxItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
18
19
  declare function ContextMenuRadioGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>): React.JSX.Element;
19
- declare function ContextMenuRadioItem({ className, children, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>): React.JSX.Element;
20
- declare function ContextMenuLabel({ className, inset, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
20
+ declare const ContextMenuRadioItem: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuRadioItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
21
+ declare const ContextMenuLabel: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuLabelProps & React.RefAttributes<HTMLDivElement> & {
21
22
  inset?: boolean;
22
- }): React.JSX.Element;
23
- declare function ContextMenuSeparator({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>): React.JSX.Element;
24
- declare function ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
23
+ }, "ref"> & React.RefAttributes<HTMLDivElement>>;
24
+ declare const ContextMenuSeparator: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
25
+ declare const ContextMenuShortcut: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
25
26
  declare function ContextMenuSub(props: React.ComponentProps<typeof ContextMenuPrimitive.Sub>): React.JSX.Element;
26
- declare function ContextMenuSubTrigger({ className, inset, children, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
27
+ declare const ContextMenuSubTrigger: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuSubTriggerProps & React.RefAttributes<HTMLDivElement> & {
27
28
  inset?: boolean;
28
- }): React.JSX.Element;
29
- declare function ContextMenuSubContent({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>): React.JSX.Element;
29
+ }, "ref"> & React.RefAttributes<HTMLDivElement>>;
30
+ declare const ContextMenuSubContent: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuSubContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
30
31
  export { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, };
@@ -1,7 +1,8 @@
1
+ "use client";
1
2
  import { cn } from "../lib/utils.js";
2
- import { menuItemClasses, surfaceClasses } from "./popover.js";
3
- import { ContextMenu } from "radix-ui";
4
- import "react";
3
+ import { menuItemClasses, menuLabelClasses, surfaceClasses } from "./popover.js";
4
+ import { CheckboxItem, Content, Group, Item, ItemIndicator, Label, Portal, RadioGroup, RadioItem, Root, Separator, Sub, SubContent, SubTrigger, Trigger } from "../primitives/vendor/radix/react-context-menu/context-menu.js";
5
+ import * as React from "react";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  import ChevronRight from "@burtson-labs/icons/react/chevron-right";
7
8
  import Check from "@burtson-labs/icons/react/check";
@@ -12,102 +13,111 @@ import Check from "@burtson-labs/icons/react/check";
12
13
  * context-menu key or Shift+F10 on the focused target. Same rows as
13
14
  * DropdownMenu, so a command can appear in both.
14
15
  */
15
- function ContextMenu$1(props) {
16
- return /* @__PURE__ */ jsx(ContextMenu.Root, {
16
+ function ContextMenu(props) {
17
+ return /* @__PURE__ */ jsx(Root, {
17
18
  "data-slot": "context-menu",
18
19
  ...props
19
20
  });
20
21
  }
21
- function ContextMenuTrigger(props) {
22
- return /* @__PURE__ */ jsx(ContextMenu.Trigger, {
22
+ var ContextMenuTrigger = React.forwardRef(function ContextMenuTrigger(props, ref) {
23
+ return /* @__PURE__ */ jsx(Trigger, {
24
+ ref,
23
25
  "data-slot": "context-menu-trigger",
24
26
  ...props
25
27
  });
26
- }
28
+ });
27
29
  function ContextMenuGroup(props) {
28
- return /* @__PURE__ */ jsx(ContextMenu.Group, {
30
+ return /* @__PURE__ */ jsx(Group, {
29
31
  "data-slot": "context-menu-group",
30
32
  ...props
31
33
  });
32
34
  }
33
- function ContextMenuContent({ className, ...props }) {
34
- return /* @__PURE__ */ jsx(ContextMenu.Portal, { children: /* @__PURE__ */ jsx(ContextMenu.Content, {
35
+ var ContextMenuContent = React.forwardRef(function ContextMenuContent({ className, ...props }, ref) {
36
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Content, {
37
+ ref,
35
38
  "data-slot": "context-menu-content",
36
39
  className: cn(surfaceClasses, "max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1", className),
37
40
  ...props
38
41
  }) });
39
- }
40
- function ContextMenuItem({ className, inset, variant = "default", ...props }) {
41
- return /* @__PURE__ */ jsx(ContextMenu.Item, {
42
+ });
43
+ var ContextMenuItem = React.forwardRef(function ContextMenuItem({ className, inset, variant = "default", ...props }, ref) {
44
+ return /* @__PURE__ */ jsx(Item, {
45
+ ref,
42
46
  "data-slot": "context-menu-item",
43
47
  "data-inset": inset || void 0,
44
48
  "data-variant": variant,
45
49
  className: cn(menuItemClasses, "data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive", className),
46
50
  ...props
47
51
  });
48
- }
49
- function ContextMenuCheckboxItem({ className, children, checked, ...props }) {
50
- return /* @__PURE__ */ jsxs(ContextMenu.CheckboxItem, {
52
+ });
53
+ var ContextMenuCheckboxItem = React.forwardRef(function ContextMenuCheckboxItem({ className, children, checked, ...props }, ref) {
54
+ return /* @__PURE__ */ jsxs(CheckboxItem, {
55
+ ref,
51
56
  "data-slot": "context-menu-checkbox-item",
52
57
  className: cn(menuItemClasses, "pl-8", className),
53
58
  checked,
54
59
  ...props,
55
60
  children: [/* @__PURE__ */ jsx("span", {
56
61
  className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center",
57
- children: /* @__PURE__ */ jsx(ContextMenu.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, {
62
+ children: /* @__PURE__ */ jsx(ItemIndicator, { children: /* @__PURE__ */ jsx(Check, {
58
63
  className: "size-4 text-foreground",
59
64
  "aria-hidden": true
60
65
  }) })
61
66
  }), children]
62
67
  });
63
- }
68
+ });
64
69
  function ContextMenuRadioGroup(props) {
65
- return /* @__PURE__ */ jsx(ContextMenu.RadioGroup, {
70
+ return /* @__PURE__ */ jsx(RadioGroup, {
66
71
  "data-slot": "context-menu-radio-group",
67
72
  ...props
68
73
  });
69
74
  }
70
- function ContextMenuRadioItem({ className, children, ...props }) {
71
- return /* @__PURE__ */ jsxs(ContextMenu.RadioItem, {
75
+ var ContextMenuRadioItem = React.forwardRef(function ContextMenuRadioItem({ className, children, ...props }, ref) {
76
+ return /* @__PURE__ */ jsxs(RadioItem, {
77
+ ref,
72
78
  "data-slot": "context-menu-radio-item",
73
79
  className: cn(menuItemClasses, "pl-8", className),
74
80
  ...props,
75
81
  children: [/* @__PURE__ */ jsx("span", {
76
82
  className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center",
77
- children: /* @__PURE__ */ jsx(ContextMenu.ItemIndicator, { children: /* @__PURE__ */ jsx("span", { className: "block size-2 rounded-full bg-foreground" }) })
83
+ children: /* @__PURE__ */ jsx(ItemIndicator, { children: /* @__PURE__ */ jsx("span", { className: "block size-2 rounded-full bg-foreground" }) })
78
84
  }), children]
79
85
  });
80
- }
81
- function ContextMenuLabel({ className, inset, ...props }) {
82
- return /* @__PURE__ */ jsx(ContextMenu.Label, {
86
+ });
87
+ var ContextMenuLabel = React.forwardRef(function ContextMenuLabel({ className, inset, ...props }, ref) {
88
+ return /* @__PURE__ */ jsx(Label, {
89
+ ref,
83
90
  "data-slot": "context-menu-label",
84
91
  "data-inset": inset || void 0,
85
- className: cn("px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8", className),
92
+ className: cn(menuLabelClasses, "data-[inset]:pl-8", className),
86
93
  ...props
87
94
  });
88
- }
89
- function ContextMenuSeparator({ className, ...props }) {
90
- return /* @__PURE__ */ jsx(ContextMenu.Separator, {
95
+ });
96
+ var ContextMenuSeparator = React.forwardRef(function ContextMenuSeparator({ className, ...props }, ref) {
97
+ return /* @__PURE__ */ jsx(Separator, {
98
+ ref,
91
99
  "data-slot": "context-menu-separator",
92
100
  className: cn("-mx-1 my-1 h-px bg-border", className),
93
101
  ...props
94
102
  });
95
- }
96
- function ContextMenuShortcut({ className, ...props }) {
103
+ });
104
+ var ContextMenuShortcut = React.forwardRef(function ContextMenuShortcut({ className, ...props }, ref) {
97
105
  return /* @__PURE__ */ jsx("span", {
106
+ ref,
98
107
  "data-slot": "context-menu-shortcut",
99
108
  className: cn("ml-auto text-xs tracking-widest text-muted-foreground", className),
100
109
  ...props
101
110
  });
102
- }
111
+ });
103
112
  function ContextMenuSub(props) {
104
- return /* @__PURE__ */ jsx(ContextMenu.Sub, {
113
+ return /* @__PURE__ */ jsx(Sub, {
105
114
  "data-slot": "context-menu-sub",
106
115
  ...props
107
116
  });
108
117
  }
109
- function ContextMenuSubTrigger({ className, inset, children, ...props }) {
110
- return /* @__PURE__ */ jsxs(ContextMenu.SubTrigger, {
118
+ var ContextMenuSubTrigger = React.forwardRef(function ContextMenuSubTrigger({ className, inset, children, ...props }, ref) {
119
+ return /* @__PURE__ */ jsxs(SubTrigger, {
120
+ ref,
111
121
  "data-slot": "context-menu-sub-trigger",
112
122
  "data-inset": inset || void 0,
113
123
  className: cn(menuItemClasses, "data-[state=open]:bg-secondary", className),
@@ -117,15 +127,16 @@ function ContextMenuSubTrigger({ className, inset, children, ...props }) {
117
127
  "aria-hidden": true
118
128
  })]
119
129
  });
120
- }
121
- function ContextMenuSubContent({ className, ...props }) {
122
- return /* @__PURE__ */ jsx(ContextMenu.Portal, { children: /* @__PURE__ */ jsx(ContextMenu.SubContent, {
130
+ });
131
+ var ContextMenuSubContent = React.forwardRef(function ContextMenuSubContent({ className, ...props }, ref) {
132
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(SubContent, {
133
+ ref,
123
134
  "data-slot": "context-menu-sub-content",
124
135
  className: cn(surfaceClasses, "min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden p-1", className),
125
136
  ...props
126
137
  }) });
127
- }
138
+ });
128
139
  //#endregion
129
- export { ContextMenu$1 as ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger };
140
+ export { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger };
130
141
 
131
142
  //# sourceMappingURL=context-menu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-menu.js","names":["ContextMenu","ContextMenuPrimitive","itemClasses"],"sources":["../../src/components/context-menu.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { ContextMenu as ContextMenuPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\n/**\n * A right-click menu. Wrap the target in ContextMenuTrigger (use asChild to keep\n * your element); the menu opens at the pointer, and from the keyboard with the\n * context-menu key or Shift+F10 on the focused target. Same rows as\n * DropdownMenu, so a command can appear in both.\n */\nfunction ContextMenu(props: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {\n return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />;\n}\n\nfunction ContextMenuTrigger(props: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {\n return <ContextMenuPrimitive.Trigger data-slot=\"context-menu-trigger\" {...props} />;\n}\n\nfunction ContextMenuGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {\n return <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />;\n}\n\nfunction ContextMenuContent({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n data-slot=\"context-menu-content\"\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n}\n\nfunction ContextMenuItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <ContextMenuPrimitive.Item\n data-slot=\"context-menu-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ContextMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {\n return (\n <ContextMenuPrimitive.CheckboxItem\n data-slot=\"context-menu-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction ContextMenuRadioGroup(\n props: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>,\n) {\n return <ContextMenuPrimitive.RadioGroup data-slot=\"context-menu-radio-group\" {...props} />;\n}\n\nfunction ContextMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {\n return (\n <ContextMenuPrimitive.RadioItem\n data-slot=\"context-menu-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n );\n}\n\nfunction ContextMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & { inset?: boolean }) {\n return (\n <ContextMenuPrimitive.Label\n data-slot=\"context-menu-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ContextMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {\n return (\n <ContextMenuPrimitive.Separator\n data-slot=\"context-menu-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"context-menu-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuSub(props: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {\n return <ContextMenuPrimitive.Sub data-slot=\"context-menu-sub\" {...props} />;\n}\n\nfunction ContextMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <ContextMenuPrimitive.SubTrigger\n data-slot=\"context-menu-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-secondary', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </ContextMenuPrimitive.SubTrigger>\n );\n}\n\nfunction ContextMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.SubContent\n data-slot=\"context-menu-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n}\n\nexport {\n ContextMenu,\n ContextMenuCheckboxItem,\n ContextMenuContent,\n ContextMenuGroup,\n ContextMenuItem,\n ContextMenuLabel,\n ContextMenuRadioGroup,\n ContextMenuRadioItem,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuTrigger,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"context-menu.js","names":["ContextMenuPrimitive.Root","ContextMenuPrimitive.Trigger","ContextMenuPrimitive.Group","ContextMenuPrimitive.Portal","ContextMenuPrimitive.Content","ContextMenuPrimitive.Item","itemClasses","ContextMenuPrimitive.CheckboxItem","ContextMenuPrimitive.ItemIndicator","ContextMenuPrimitive.RadioGroup","ContextMenuPrimitive.RadioItem","ContextMenuPrimitive.Label","ContextMenuPrimitive.Separator","ContextMenuPrimitive.Sub","ContextMenuPrimitive.SubTrigger","ContextMenuPrimitive.SubContent"],"sources":["../../src/components/context-menu.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\nimport * as ContextMenuPrimitive from '../primitives/vendor/radix/react-context-menu';\n\nimport { menuItemClasses as itemClasses, menuLabelClasses, surfaceClasses } from './popover';\n\n/**\n * A right-click menu. Wrap the target in ContextMenuTrigger (use asChild to keep\n * your element); the menu opens at the pointer, and from the keyboard with the\n * context-menu key or Shift+F10 on the focused target. Same rows as\n * DropdownMenu, so a command can appear in both.\n */\nfunction ContextMenu(props: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {\n return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />;\n}\n\nconst ContextMenuTrigger = React.forwardRef<\n HTMLSpanElement,\n React.ComponentProps<typeof ContextMenuPrimitive.Trigger>\n>(function ContextMenuTrigger(props, ref) {\n return <ContextMenuPrimitive.Trigger ref={ref} data-slot=\"context-menu-trigger\" {...props} />;\n});\n\nfunction ContextMenuGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {\n return <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />;\n}\n\nconst ContextMenuContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof ContextMenuPrimitive.Content>\n>(function ContextMenuContent({ className, ...props }, ref) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n ref={ref}\n data-slot=\"context-menu-content\"\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n});\n\nexport interface ContextMenuItemProps extends React.ComponentProps<\n typeof ContextMenuPrimitive.Item\n> {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}\n\nconst ContextMenuItem = React.forwardRef<HTMLDivElement, ContextMenuItemProps>(\n function ContextMenuItem({ className, inset, variant = 'default', ...props }, ref) {\n return (\n <ContextMenuPrimitive.Item\n ref={ref}\n data-slot=\"context-menu-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n },\n);\n\nconst ContextMenuCheckboxItem = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>\n>(function ContextMenuCheckboxItem({ className, children, checked, ...props }, ref) {\n return (\n <ContextMenuPrimitive.CheckboxItem\n ref={ref}\n data-slot=\"context-menu-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n );\n});\n\nfunction ContextMenuRadioGroup(\n props: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>,\n) {\n return <ContextMenuPrimitive.RadioGroup data-slot=\"context-menu-radio-group\" {...props} />;\n}\n\nconst ContextMenuRadioItem = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>\n>(function ContextMenuRadioItem({ className, children, ...props }, ref) {\n return (\n <ContextMenuPrimitive.RadioItem\n ref={ref}\n data-slot=\"context-menu-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n );\n});\n\nconst ContextMenuLabel = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof ContextMenuPrimitive.Label> & { inset?: boolean }\n>(function ContextMenuLabel({ className, inset, ...props }, ref) {\n return (\n <ContextMenuPrimitive.Label\n ref={ref}\n data-slot=\"context-menu-label\"\n data-inset={inset || undefined}\n className={cn(menuLabelClasses, 'data-[inset]:pl-8', className)}\n {...props}\n />\n );\n});\n\nconst ContextMenuSeparator = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof ContextMenuPrimitive.Separator>\n>(function ContextMenuSeparator({ className, ...props }, ref) {\n return (\n <ContextMenuPrimitive.Separator\n ref={ref}\n data-slot=\"context-menu-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n});\n\nconst ContextMenuShortcut = React.forwardRef<HTMLSpanElement, React.ComponentProps<'span'>>(\n function ContextMenuShortcut({ className, ...props }, ref) {\n return (\n <span\n ref={ref}\n data-slot=\"context-menu-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n },\n);\n\nfunction ContextMenuSub(props: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {\n return <ContextMenuPrimitive.Sub data-slot=\"context-menu-sub\" {...props} />;\n}\n\nconst ContextMenuSubTrigger = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & { inset?: boolean }\n>(function ContextMenuSubTrigger({ className, inset, children, ...props }, ref) {\n return (\n <ContextMenuPrimitive.SubTrigger\n ref={ref}\n data-slot=\"context-menu-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-secondary', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </ContextMenuPrimitive.SubTrigger>\n );\n});\n\nconst ContextMenuSubContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof ContextMenuPrimitive.SubContent>\n>(function ContextMenuSubContent({ className, ...props }, ref) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.SubContent\n ref={ref}\n data-slot=\"context-menu-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n});\n\nexport {\n ContextMenu,\n ContextMenuCheckboxItem,\n ContextMenuContent,\n ContextMenuGroup,\n ContextMenuItem,\n ContextMenuLabel,\n ContextMenuRadioGroup,\n ContextMenuRadioItem,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuTrigger,\n};\n"],"mappings":"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"}
@@ -10,5 +10,5 @@ export interface ConversationProps extends React.ComponentProps<'div'> {
10
10
  * streams, unless the reader has scrolled up; then a "Jump to latest" button
11
11
  * appears instead of yanking them back down.
12
12
  */
13
- declare function Conversation({ children, empty, label, className, ...props }: ConversationProps): React.JSX.Element;
13
+ declare const Conversation: React.ForwardRefExoticComponent<Omit<ConversationProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
14
14
  export { Conversation };
@@ -1,4 +1,5 @@
1
- import { cn } from "../lib/utils.js";
1
+ "use client";
2
+ import { cn, focusRingClasses } from "../lib/utils.js";
2
3
  import * as React from "react";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
5
  import ArrowDown from "@burtson-labs/icons/react/arrow-down";
@@ -8,7 +9,7 @@ import ArrowDown from "@burtson-labs/icons/react/arrow-down";
8
9
  * streams, unless the reader has scrolled up; then a "Jump to latest" button
9
10
  * appears instead of yanking them back down.
10
11
  */
11
- function Conversation({ children, empty, label = "Conversation", className, ...props }) {
12
+ var Conversation = React.forwardRef(function Conversation({ children, empty, label = "Conversation", className, ...props }, ref) {
12
13
  const scroller = React.useRef(null);
13
14
  const content = React.useRef(null);
14
15
  const pinned = React.useRef(true);
@@ -43,6 +44,7 @@ function Conversation({ children, empty, label = "Conversation", className, ...p
43
44
  setAtBottom(bottom);
44
45
  };
45
46
  return /* @__PURE__ */ jsxs("div", {
47
+ ref,
46
48
  "data-slot": "conversation",
47
49
  className: cn("relative min-h-0", className),
48
50
  ...props,
@@ -54,7 +56,7 @@ function Conversation({ children, empty, label = "Conversation", className, ...p
54
56
  "aria-relevant": "additions text",
55
57
  tabIndex: 0,
56
58
  onScroll,
57
- className: "size-full overflow-y-auto outline-none focus-visible:ring-[3px] focus-visible:ring-ring/20",
59
+ className: cn("size-full overflow-y-auto", focusRingClasses, "focus-visible:outline-offset-[-2px]"),
58
60
  children: /* @__PURE__ */ jsx("div", {
59
61
  ref: content,
60
62
  className: "grid gap-5 p-4",
@@ -67,11 +69,11 @@ function Conversation({ children, empty, label = "Conversation", className, ...p
67
69
  setAtBottom(true);
68
70
  scrollToBottom(typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches ? "auto" : "smooth");
69
71
  },
70
- className: "absolute bottom-3 left-1/2 inline-flex -translate-x-1/2 animate-in items-center gap-1.5 rounded-full border border-border-strong bg-surface-raised px-3 py-1.5 text-xs font-semibold shadow-md outline-none hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/20 [&_svg]:size-3.5",
72
+ className: cn("absolute bottom-3 left-1/2 inline-flex -translate-x-1/2 animate-in items-center gap-1.5 rounded-full border border-border-strong bg-surface-raised px-3 py-1.5 text-xs font-semibold shadow-md hover:bg-muted [&_svg]:size-3.5 pointer-coarse:min-h-11", "outline-none focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"),
71
73
  children: [/* @__PURE__ */ jsx(ArrowDown, { "aria-hidden": true }), " Jump to latest"]
72
74
  })]
73
75
  });
74
- }
76
+ });
75
77
  //#endregion
76
78
  export { Conversation };
77
79
 
@@ -1 +1 @@
1
- {"version":3,"file":"conversation.js","names":[],"sources":["../../src/components/conversation.tsx"],"sourcesContent":["import ArrowDown from '@burtson-labs/icons/react/arrow-down';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport interface ConversationProps extends React.ComponentProps<'div'> {\n /** Shown instead of the messages when there are none. */\n empty?: React.ReactNode;\n /** Accessible name for the message log. */\n label?: string;\n}\n\n/**\n * A scrolling message log that stays pinned to the newest message while it\n * streams, unless the reader has scrolled up; then a \"Jump to latest\" button\n * appears instead of yanking them back down.\n */\nfunction Conversation({\n children,\n empty,\n label = 'Conversation',\n className,\n ...props\n}: ConversationProps) {\n const scroller = React.useRef<HTMLDivElement>(null);\n const content = React.useRef<HTMLDivElement>(null);\n const pinned = React.useRef(true);\n const [atBottom, setAtBottom] = React.useState(true);\n const hasMessages = React.Children.toArray(children).length > 0;\n\n const scrollToBottom = React.useCallback((behavior: ScrollBehavior = 'auto') => {\n const el = scroller.current;\n if (!el) return;\n if (typeof el.scrollTo === 'function') el.scrollTo({ top: el.scrollHeight, behavior });\n else el.scrollTop = el.scrollHeight;\n }, []);\n\n React.useEffect(() => {\n const el = content.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n // Content grows while a reply streams; follow it only if pinned.\n const ro = new ResizeObserver(() => {\n if (pinned.current) scrollToBottom();\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [scrollToBottom]);\n\n React.useEffect(() => {\n if (pinned.current) scrollToBottom();\n }, [children, scrollToBottom]);\n\n const onScroll = () => {\n const el = scroller.current;\n if (!el) return;\n const bottom = el.scrollHeight - el.scrollTop - el.clientHeight < 32;\n pinned.current = bottom;\n setAtBottom(bottom);\n };\n\n return (\n <div data-slot=\"conversation\" className={cn('relative min-h-0', className)} {...props}>\n <div\n ref={scroller}\n role=\"log\"\n aria-label={label}\n aria-live=\"polite\"\n aria-relevant=\"additions text\"\n // A scrollable region must be reachable by keyboard (WCAG 2.1.1).\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n onScroll={onScroll}\n className=\"size-full overflow-y-auto outline-none focus-visible:ring-[3px] focus-visible:ring-ring/20\"\n >\n <div ref={content} className=\"grid gap-5 p-4\">\n {hasMessages ? children : empty}\n </div>\n </div>\n {!atBottom && (\n <button\n type=\"button\"\n onClick={() => {\n pinned.current = true;\n setAtBottom(true);\n scrollToBottom(\n typeof matchMedia === 'function' &&\n matchMedia('(prefers-reduced-motion: reduce)').matches\n ? 'auto'\n : 'smooth',\n );\n }}\n className=\"absolute bottom-3 left-1/2 inline-flex -translate-x-1/2 animate-in items-center gap-1.5 rounded-full border border-border-strong bg-surface-raised px-3 py-1.5 text-xs font-semibold shadow-md outline-none hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/20 [&_svg]:size-3.5\"\n >\n <ArrowDown aria-hidden /> Jump to latest\n </button>\n )}\n </div>\n );\n}\n\nexport { Conversation };\n"],"mappings":";;;;;;;;;;AAiBA,SAAS,aAAa,EACpB,UACA,OACA,QAAQ,gBACR,WACA,GAAG,SACiB;CACpB,MAAM,WAAW,MAAM,OAAuB,IAAI;CAClD,MAAM,UAAU,MAAM,OAAuB,IAAI;CACjD,MAAM,SAAS,MAAM,OAAO,IAAI;CAChC,MAAM,CAAC,UAAU,eAAe,MAAM,SAAS,IAAI;CACnD,MAAM,cAAc,MAAM,SAAS,QAAQ,QAAQ,CAAC,CAAC,SAAS;CAE9D,MAAM,iBAAiB,MAAM,aAAa,WAA2B,WAAW;EAC9E,MAAM,KAAK,SAAS;EACpB,IAAI,CAAC,IAAI;EACT,IAAI,OAAO,GAAG,aAAa,YAAY,GAAG,SAAS;GAAE,KAAK,GAAG;GAAc;EAAS,CAAC;OAChF,GAAG,YAAY,GAAG;CACzB,GAAG,CAAC,CAAC;CAEL,MAAM,gBAAgB;EACpB,MAAM,KAAK,QAAQ;EACnB,IAAI,CAAC,MAAM,OAAO,mBAAmB,aAAa;EAElD,MAAM,KAAK,IAAI,qBAAqB;GAClC,IAAI,OAAO,SAAS,eAAe;EACrC,CAAC;EACD,GAAG,QAAQ,EAAE;EACb,aAAa,GAAG,WAAW;CAC7B,GAAG,CAAC,cAAc,CAAC;CAEnB,MAAM,gBAAgB;EACpB,IAAI,OAAO,SAAS,eAAe;CACrC,GAAG,CAAC,UAAU,cAAc,CAAC;CAE7B,MAAM,iBAAiB;EACrB,MAAM,KAAK,SAAS;EACpB,IAAI,CAAC,IAAI;EACT,MAAM,SAAS,GAAG,eAAe,GAAG,YAAY,GAAG,eAAe;EAClE,OAAO,UAAU;EACjB,YAAY,MAAM;CACpB;CAEA,OACE,qBAAC,OAAD;EAAK,aAAU;EAAe,WAAW,GAAG,oBAAoB,SAAS;EAAG,GAAI;EAAhF,UAAA,CACE,oBAAC,OAAD;GACE,KAAK;GACL,MAAK;GACL,cAAY;GACZ,aAAU;GACV,iBAAc;GAGd,UAAU;GACA;GACV,WAAU;GAEV,UAAA,oBAAC,OAAD;IAAK,KAAK;IAAS,WAAU;IAC1B,UAAA,cAAc,WAAW;GACvB,CAAA;EACF,CAAA,GACJ,CAAC,YACA,qBAAC,UAAD;GACE,MAAK;GACL,eAAe;IACb,OAAO,UAAU;IACjB,YAAY,IAAI;IAChB,eACE,OAAO,eAAe,cACpB,WAAW,kCAAkC,CAAC,CAAC,UAC7C,SACA,QACN;GACF;GACA,WAAU;GAZZ,UAAA,CAcE,oBAAC,WAAD,EAAW,eAAA,KAAa,CAAA,GAAC,iBACnB;EAEP,CAAA,CAAA;;AAET"}
1
+ {"version":3,"file":"conversation.js","names":[],"sources":["../../src/components/conversation.tsx"],"sourcesContent":["import ArrowDown from '@burtson-labs/icons/react/arrow-down';\nimport * as React from 'react';\n\nimport { cn, focusRingClasses } from '../lib/utils';\n\nexport interface ConversationProps extends React.ComponentProps<'div'> {\n /** Shown instead of the messages when there are none. */\n empty?: React.ReactNode;\n /** Accessible name for the message log. */\n label?: string;\n}\n\n/**\n * A scrolling message log that stays pinned to the newest message while it\n * streams, unless the reader has scrolled up; then a \"Jump to latest\" button\n * appears instead of yanking them back down.\n */\nconst Conversation = React.forwardRef<HTMLDivElement, ConversationProps>(function Conversation(\n { children, empty, label = 'Conversation', className, ...props },\n ref,\n) {\n const scroller = React.useRef<HTMLDivElement>(null);\n const content = React.useRef<HTMLDivElement>(null);\n const pinned = React.useRef(true);\n const [atBottom, setAtBottom] = React.useState(true);\n const hasMessages = React.Children.toArray(children).length > 0;\n\n const scrollToBottom = React.useCallback((behavior: ScrollBehavior = 'auto') => {\n const el = scroller.current;\n if (!el) return;\n if (typeof el.scrollTo === 'function') el.scrollTo({ top: el.scrollHeight, behavior });\n else el.scrollTop = el.scrollHeight;\n }, []);\n\n React.useEffect(() => {\n const el = content.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n // Content grows while a reply streams; follow it only if pinned.\n const ro = new ResizeObserver(() => {\n if (pinned.current) scrollToBottom();\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [scrollToBottom]);\n\n React.useEffect(() => {\n if (pinned.current) scrollToBottom();\n }, [children, scrollToBottom]);\n\n const onScroll = () => {\n const el = scroller.current;\n if (!el) return;\n const bottom = el.scrollHeight - el.scrollTop - el.clientHeight < 32;\n pinned.current = bottom;\n setAtBottom(bottom);\n };\n\n return (\n <div\n ref={ref}\n data-slot=\"conversation\"\n className={cn('relative min-h-0', className)}\n {...props}\n >\n <div\n ref={scroller}\n role=\"log\"\n aria-label={label}\n aria-live=\"polite\"\n aria-relevant=\"additions text\"\n // A scrollable region must be reachable by keyboard (WCAG 2.1.1).\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n onScroll={onScroll}\n className={cn(\n 'size-full overflow-y-auto',\n focusRingClasses,\n 'focus-visible:outline-offset-[-2px]',\n )}\n >\n <div ref={content} className=\"grid gap-5 p-4\">\n {hasMessages ? children : empty}\n </div>\n </div>\n {!atBottom && (\n <button\n type=\"button\"\n onClick={() => {\n pinned.current = true;\n setAtBottom(true);\n scrollToBottom(\n typeof matchMedia === 'function' &&\n matchMedia('(prefers-reduced-motion: reduce)').matches\n ? 'auto'\n : 'smooth',\n );\n }}\n className={cn(\n 'absolute bottom-3 left-1/2 inline-flex -translate-x-1/2 animate-in items-center gap-1.5 rounded-full border border-border-strong bg-surface-raised px-3 py-1.5 text-xs font-semibold shadow-md hover:bg-muted [&_svg]:size-3.5 pointer-coarse:min-h-11',\n focusRingClasses,\n )}\n >\n <ArrowDown aria-hidden /> Jump to latest\n </button>\n )}\n </div>\n );\n});\n\nexport { Conversation };\n"],"mappings":";;;;;;;;;;;AAiBA,IAAM,eAAe,MAAM,WAA8C,SAAS,aAChF,EAAE,UAAU,OAAO,QAAQ,gBAAgB,WAAW,GAAG,SACzD,KACA;CACA,MAAM,WAAW,MAAM,OAAuB,IAAI;CAClD,MAAM,UAAU,MAAM,OAAuB,IAAI;CACjD,MAAM,SAAS,MAAM,OAAO,IAAI;CAChC,MAAM,CAAC,UAAU,eAAe,MAAM,SAAS,IAAI;CACnD,MAAM,cAAc,MAAM,SAAS,QAAQ,QAAQ,CAAC,CAAC,SAAS;CAE9D,MAAM,iBAAiB,MAAM,aAAa,WAA2B,WAAW;EAC9E,MAAM,KAAK,SAAS;EACpB,IAAI,CAAC,IAAI;EACT,IAAI,OAAO,GAAG,aAAa,YAAY,GAAG,SAAS;GAAE,KAAK,GAAG;GAAc;EAAS,CAAC;OAChF,GAAG,YAAY,GAAG;CACzB,GAAG,CAAC,CAAC;CAEL,MAAM,gBAAgB;EACpB,MAAM,KAAK,QAAQ;EACnB,IAAI,CAAC,MAAM,OAAO,mBAAmB,aAAa;EAElD,MAAM,KAAK,IAAI,qBAAqB;GAClC,IAAI,OAAO,SAAS,eAAe;EACrC,CAAC;EACD,GAAG,QAAQ,EAAE;EACb,aAAa,GAAG,WAAW;CAC7B,GAAG,CAAC,cAAc,CAAC;CAEnB,MAAM,gBAAgB;EACpB,IAAI,OAAO,SAAS,eAAe;CACrC,GAAG,CAAC,UAAU,cAAc,CAAC;CAE7B,MAAM,iBAAiB;EACrB,MAAM,KAAK,SAAS;EACpB,IAAI,CAAC,IAAI;EACT,MAAM,SAAS,GAAG,eAAe,GAAG,YAAY,GAAG,eAAe;EAClE,OAAO,UAAU;EACjB,YAAY,MAAM;CACpB;CAEA,OACE,qBAAC,OAAD;EACO;EACL,aAAU;EACV,WAAW,GAAG,oBAAoB,SAAS;EAC3C,GAAI;EAJN,UAAA,CAME,oBAAC,OAAD;GACE,KAAK;GACL,MAAK;GACL,cAAY;GACZ,aAAU;GACV,iBAAc;GAGd,UAAU;GACA;GACV,WAAW,GACT,6BACA,kBACA,qCACF;GAEA,UAAA,oBAAC,OAAD;IAAK,KAAK;IAAS,WAAU;IAC1B,UAAA,cAAc,WAAW;GACvB,CAAA;EACF,CAAA,GACJ,CAAC,YACA,qBAAC,UAAD;GACE,MAAK;GACL,eAAe;IACb,OAAO,UAAU;IACjB,YAAY,IAAI;IAChB,eACE,OAAO,eAAe,cACpB,WAAW,kCAAkC,CAAC,CAAC,UAC7C,SACA,QACN;GACF;GACA,WAAW,GACT,0PAAA,4HAEF;GAfF,UAAA,CAiBE,oBAAC,WAAD,EAAW,eAAA,KAAa,CAAA,GAAC,iBACnB;EAEP,CAAA,CAAA;;AAET,CAAC"}
@@ -13,5 +13,5 @@ export interface CopyButtonProps extends Omit<IconButtonProps, 'label' | 'childr
13
13
  * browser blocks the clipboard it raises a toast (needs a mounted Toaster)
14
14
  * asking the person to copy by hand.
15
15
  */
16
- declare function CopyButton({ value, label, variant, size, onCopySuccess, onCopyError, ...props }: CopyButtonProps): React.JSX.Element;
16
+ declare const CopyButton: React.ForwardRefExoticComponent<Omit<CopyButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
17
17
  export { CopyButton };
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { IconButton } from "./icon-button.js";
2
3
  import { toast } from "./toaster.js";
3
4
  import * as React from "react";
@@ -10,7 +11,7 @@ import Copy from "@burtson-labs/icons/react/copy";
10
11
  * browser blocks the clipboard it raises a toast (needs a mounted Toaster)
11
12
  * asking the person to copy by hand.
12
13
  */
13
- function CopyButton({ value, label = "Copy", variant = "ghost", size = "icon-sm", onCopySuccess, onCopyError, ...props }) {
14
+ var CopyButton = React.forwardRef(function CopyButton({ value, label = "Copy", variant = "ghost", size = "icon-sm", onCopySuccess, onCopyError, ...props }, ref) {
14
15
  const [message, setMessage] = React.useState("");
15
16
  const [copied, setCopied] = React.useState(false);
16
17
  const timer = React.useRef(void 0);
@@ -34,6 +35,7 @@ function CopyButton({ value, label = "Copy", variant = "ghost", size = "icon-sm"
34
35
  }
35
36
  };
36
37
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(IconButton, {
38
+ ref,
37
39
  "data-slot": "copy-button",
38
40
  label: copied ? "Copied" : label,
39
41
  variant,
@@ -49,7 +51,7 @@ function CopyButton({ value, label = "Copy", variant = "ghost", size = "icon-sm"
49
51
  className: "sr-only",
50
52
  children: message
51
53
  })] });
52
- }
54
+ });
53
55
  //#endregion
54
56
  export { CopyButton };
55
57
 
@@ -1 +1 @@
1
- {"version":3,"file":"copy-button.js","names":["_Fragment"],"sources":["../../src/components/copy-button.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport Copy from '@burtson-labs/icons/react/copy';\nimport * as React from 'react';\n\nimport { IconButton, type IconButtonProps } from './icon-button';\nimport { toast } from './toaster';\n\nexport interface CopyButtonProps extends Omit<IconButtonProps, 'label' | 'children' | 'onClick'> {\n /** The text to put on the clipboard. */\n value: string;\n /** Accessible name, e.g. \"Copy API key\". */\n label?: string;\n onCopySuccess?: () => void;\n onCopyError?: (error: unknown) => void;\n}\n\n/**\n * Icon button that copies `value` and shows a check for a moment. When the\n * browser blocks the clipboard it raises a toast (needs a mounted Toaster)\n * asking the person to copy by hand.\n */\nfunction CopyButton({\n value,\n label = 'Copy',\n variant = 'ghost',\n size = 'icon-sm',\n onCopySuccess,\n onCopyError,\n ...props\n}: CopyButtonProps) {\n const [message, setMessage] = React.useState('');\n const [copied, setCopied] = React.useState(false);\n const timer = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n React.useEffect(() => () => clearTimeout(timer.current), []);\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setCopied(true);\n setMessage('Copied to clipboard.');\n onCopySuccess?.();\n clearTimeout(timer.current);\n timer.current = setTimeout(() => setCopied(false), 1600);\n } catch (error) {\n setMessage('Copy blocked. Select the text and copy it manually.');\n onCopyError?.(error);\n toast({\n title: 'Copy blocked by the browser',\n description: 'Select the text and copy it by hand.',\n variant: 'destructive',\n });\n }\n };\n\n return (\n <>\n <IconButton\n data-slot=\"copy-button\"\n label={copied ? 'Copied' : label}\n variant={variant}\n size={size}\n onClick={() => void copy()}\n {...props}\n >\n {copied ? <Check aria-hidden className=\"text-success\" /> : <Copy aria-hidden />}\n </IconButton>\n <span role=\"status\" className=\"sr-only\">\n {message}\n </span>\n </>\n );\n}\n\nexport { CopyButton };\n"],"mappings":";;;;;;;;;;;;AAqBA,SAAS,WAAW,EAClB,OACA,QAAQ,QACR,UAAU,SACV,OAAO,WACP,eACA,aACA,GAAG,SACe;CAClB,MAAM,CAAC,SAAS,cAAc,MAAM,SAAS,EAAE;CAC/C,MAAM,CAAC,QAAQ,aAAa,MAAM,SAAS,KAAK;CAChD,MAAM,QAAQ,MAAM,OAAkD,KAAA,CAAS;CAC/E,MAAM,sBAAsB,aAAa,MAAM,OAAO,GAAG,CAAC,CAAC;CAE3D,MAAM,OAAO,YAAY;EACvB,IAAI;GACF,MAAM,UAAU,UAAU,UAAU,KAAK;GACzC,UAAU,IAAI;GACd,WAAW,sBAAsB;GACjC,gBAAgB;GAChB,aAAa,MAAM,OAAO;GAC1B,MAAM,UAAU,iBAAiB,UAAU,KAAK,GAAG,IAAI;EACzD,SAAS,OAAO;GACd,WAAW,qDAAqD;GAChE,cAAc,KAAK;GACnB,MAAM;IACJ,OAAO;IACP,aAAa;IACb,SAAS;GACX,CAAC;EACH;CACF;CAEA,OACE,qBAAAA,UAAA,EAAA,UAAA,CACE,oBAAC,YAAD;EACE,aAAU;EACV,OAAO,SAAS,WAAW;EAClB;EACH;EACN,eAAe,KAAK,KAAK;EACzB,GAAI;EAEH,UAAA,SAAS,oBAAC,OAAD;GAAO,eAAA;GAAY,WAAU;EAAgB,CAAA,IAAI,oBAAC,MAAD,EAAM,eAAA,KAAa,CAAA;CACpE,CAAA,GACZ,oBAAC,QAAD;EAAM,MAAK;EAAS,WAAU;EAC3B,UAAA;CACG,CAAA,CACN,EAAA,CAAA;AAEN"}
1
+ {"version":3,"file":"copy-button.js","names":["_Fragment"],"sources":["../../src/components/copy-button.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport Copy from '@burtson-labs/icons/react/copy';\nimport * as React from 'react';\n\nimport { IconButton, type IconButtonProps } from './icon-button';\nimport { toast } from './toaster';\n\nexport interface CopyButtonProps extends Omit<IconButtonProps, 'label' | 'children' | 'onClick'> {\n /** The text to put on the clipboard. */\n value: string;\n /** Accessible name, e.g. \"Copy API key\". */\n label?: string;\n onCopySuccess?: () => void;\n onCopyError?: (error: unknown) => void;\n}\n\n/**\n * Icon button that copies `value` and shows a check for a moment. When the\n * browser blocks the clipboard it raises a toast (needs a mounted Toaster)\n * asking the person to copy by hand.\n */\nconst CopyButton = React.forwardRef<HTMLButtonElement, CopyButtonProps>(function CopyButton(\n {\n value,\n label = 'Copy',\n variant = 'ghost',\n size = 'icon-sm',\n onCopySuccess,\n onCopyError,\n ...props\n },\n ref,\n) {\n const [message, setMessage] = React.useState('');\n const [copied, setCopied] = React.useState(false);\n const timer = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n React.useEffect(() => () => clearTimeout(timer.current), []);\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setCopied(true);\n setMessage('Copied to clipboard.');\n onCopySuccess?.();\n clearTimeout(timer.current);\n timer.current = setTimeout(() => setCopied(false), 1600);\n } catch (error) {\n setMessage('Copy blocked. Select the text and copy it manually.');\n onCopyError?.(error);\n toast({\n title: 'Copy blocked by the browser',\n description: 'Select the text and copy it by hand.',\n variant: 'destructive',\n });\n }\n };\n\n return (\n <>\n <IconButton\n ref={ref}\n data-slot=\"copy-button\"\n label={copied ? 'Copied' : label}\n variant={variant}\n size={size}\n onClick={() => void copy()}\n {...props}\n >\n {copied ? <Check aria-hidden className=\"text-success\" /> : <Copy aria-hidden />}\n </IconButton>\n <span role=\"status\" className=\"sr-only\">\n {message}\n </span>\n </>\n );\n});\n\nexport { CopyButton };\n"],"mappings":";;;;;;;;;;;;;AAqBA,IAAM,aAAa,MAAM,WAA+C,SAAS,WAC/E,EACE,OACA,QAAQ,QACR,UAAU,SACV,OAAO,WACP,eACA,aACA,GAAG,SAEL,KACA;CACA,MAAM,CAAC,SAAS,cAAc,MAAM,SAAS,EAAE;CAC/C,MAAM,CAAC,QAAQ,aAAa,MAAM,SAAS,KAAK;CAChD,MAAM,QAAQ,MAAM,OAAkD,KAAA,CAAS;CAC/E,MAAM,sBAAsB,aAAa,MAAM,OAAO,GAAG,CAAC,CAAC;CAE3D,MAAM,OAAO,YAAY;EACvB,IAAI;GACF,MAAM,UAAU,UAAU,UAAU,KAAK;GACzC,UAAU,IAAI;GACd,WAAW,sBAAsB;GACjC,gBAAgB;GAChB,aAAa,MAAM,OAAO;GAC1B,MAAM,UAAU,iBAAiB,UAAU,KAAK,GAAG,IAAI;EACzD,SAAS,OAAO;GACd,WAAW,qDAAqD;GAChE,cAAc,KAAK;GACnB,MAAM;IACJ,OAAO;IACP,aAAa;IACb,SAAS;GACX,CAAC;EACH;CACF;CAEA,OACE,qBAAAA,UAAA,EAAA,UAAA,CACE,oBAAC,YAAD;EACO;EACL,aAAU;EACV,OAAO,SAAS,WAAW;EAClB;EACH;EACN,eAAe,KAAK,KAAK;EACzB,GAAI;EAEH,UAAA,SAAS,oBAAC,OAAD;GAAO,eAAA;GAAY,WAAU;EAAgB,CAAA,IAAI,oBAAC,MAAD,EAAM,eAAA,KAAa,CAAA;CACpE,CAAA,GACZ,oBAAC,QAAD;EAAM,MAAK;EAAS,WAAU;EAC3B,UAAA;CACG,CAAA,CACN,EAAA,CAAA;AAEN,CAAC"}