@kortix/ui 0.0.0-stage → 0.14.3

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 (416) hide show
  1. package/README.md +155 -2
  2. package/dist/_vendor/kortix-shared.js +341 -0
  3. package/dist/chat/agent-picker.d.ts +8 -0
  4. package/dist/chat/agent-picker.js +18 -0
  5. package/dist/chat/composer.d.ts +31 -0
  6. package/dist/chat/composer.js +114 -0
  7. package/dist/chat/index.d.ts +22 -0
  8. package/dist/chat/index.js +22 -0
  9. package/dist/chat/markdown.d.ts +10 -0
  10. package/dist/chat/markdown.js +36 -0
  11. package/dist/chat/message-list.d.ts +25 -0
  12. package/dist/chat/message-list.js +73 -0
  13. package/dist/chat/message-view.d.ts +17 -0
  14. package/dist/chat/message-view.js +86 -0
  15. package/dist/chat/model-picker.d.ts +10 -0
  16. package/dist/chat/model-picker.js +68 -0
  17. package/dist/chat/permission-prompt.d.ts +10 -0
  18. package/dist/chat/permission-prompt.js +40 -0
  19. package/dist/chat/question-prompt.d.ts +8 -0
  20. package/dist/chat/question-prompt.js +60 -0
  21. package/dist/chat/send-failure.d.ts +9 -0
  22. package/dist/chat/send-failure.js +21 -0
  23. package/dist/chat/session-thread.d.ts +28 -0
  24. package/dist/chat/session-thread.js +47 -0
  25. package/dist/chat/streaming-markdown.d.ts +21 -0
  26. package/dist/chat/streaming-markdown.js +59 -0
  27. package/dist/chat/tool-call.d.ts +4 -0
  28. package/dist/chat/tool-call.js +150 -0
  29. package/dist/chat/user-message-parts.d.ts +6 -0
  30. package/dist/chat/user-message-parts.js +11 -0
  31. package/dist/components/ui/accordion.d.ts +7 -0
  32. package/dist/components/ui/accordion.js +18 -0
  33. package/dist/components/ui/alert-dialog.d.ts +19 -0
  34. package/dist/components/ui/alert-dialog.js +48 -0
  35. package/dist/components/ui/alert.d.ts +13 -0
  36. package/dist/components/ui/alert.js +67 -0
  37. package/dist/components/ui/avatar.d.ts +11 -0
  38. package/dist/components/ui/avatar.js +23 -0
  39. package/dist/components/ui/back-pill.d.ts +13 -0
  40. package/dist/components/ui/back-pill.js +18 -0
  41. package/dist/components/ui/badge.d.ts +10 -0
  42. package/dist/components/ui/badge.js +42 -0
  43. package/dist/components/ui/breadcrumb.d.ts +11 -0
  44. package/dist/components/ui/breadcrumb.js +28 -0
  45. package/dist/components/ui/bubble.d.ts +20 -0
  46. package/dist/components/ui/bubble.js +38 -0
  47. package/dist/components/ui/button-group.d.ts +9 -0
  48. package/dist/components/ui/button-group.js +32 -0
  49. package/dist/components/ui/button.d.ts +13 -0
  50. package/dist/components/ui/button.js +67 -0
  51. package/dist/components/ui/calendar.d.ts +4 -0
  52. package/dist/components/ui/calendar.js +39 -0
  53. package/dist/components/ui/card.d.ts +96 -0
  54. package/dist/components/ui/card.js +291 -0
  55. package/dist/components/ui/chain-of-thought.d.ts +75 -0
  56. package/dist/components/ui/chain-of-thought.js +66 -0
  57. package/dist/components/ui/chart.d.ts +65 -0
  58. package/dist/components/ui/chart.js +118 -0
  59. package/dist/components/ui/checkbox-group.d.ts +19 -0
  60. package/dist/components/ui/checkbox-group.js +41 -0
  61. package/dist/components/ui/checkbox.d.ts +14 -0
  62. package/dist/components/ui/checkbox.js +27 -0
  63. package/dist/components/ui/collapsible.d.ts +5 -0
  64. package/dist/components/ui/collapsible.js +14 -0
  65. package/dist/components/ui/command.d.ts +58 -0
  66. package/dist/components/ui/command.js +135 -0
  67. package/dist/components/ui/confirm-dialog.d.ts +19 -0
  68. package/dist/components/ui/confirm-dialog.js +30 -0
  69. package/dist/components/ui/context-menu.d.ts +45 -0
  70. package/dist/components/ui/context-menu.js +93 -0
  71. package/dist/components/ui/count-badge.d.ts +26 -0
  72. package/dist/components/ui/count-badge.js +26 -0
  73. package/dist/components/ui/data-grid.d.ts +24 -0
  74. package/dist/components/ui/data-grid.js +107 -0
  75. package/dist/components/ui/date-range-picker.d.ts +119 -0
  76. package/dist/components/ui/date-range-picker.js +190 -0
  77. package/dist/components/ui/definition-list.d.ts +15 -0
  78. package/dist/components/ui/definition-list.js +26 -0
  79. package/dist/components/ui/dialog.d.ts +29 -0
  80. package/dist/components/ui/dialog.js +52 -0
  81. package/dist/components/ui/disclosure.d.ts +121 -0
  82. package/dist/components/ui/disclosure.js +138 -0
  83. package/dist/components/ui/dot-matrix/dotm-3x3-10.d.ts +4 -0
  84. package/dist/components/ui/dot-matrix/dotm-3x3-10.js +29 -0
  85. package/dist/components/ui/dot-matrix/dotm-3x3-12.d.ts +4 -0
  86. package/dist/components/ui/dot-matrix/dotm-3x3-12.js +19 -0
  87. package/dist/components/ui/dot-matrix/dotm-3x3-13.d.ts +4 -0
  88. package/dist/components/ui/dot-matrix/dotm-3x3-13.js +19 -0
  89. package/dist/components/ui/dot-matrix/dotm-3x3-15.d.ts +4 -0
  90. package/dist/components/ui/dot-matrix/dotm-3x3-15.js +22 -0
  91. package/dist/components/ui/dot-matrix/dotm-3x3-16.d.ts +4 -0
  92. package/dist/components/ui/dot-matrix/dotm-3x3-16.js +5 -0
  93. package/dist/components/ui/dot-matrix/dotm-3x3-18.d.ts +4 -0
  94. package/dist/components/ui/dot-matrix/dotm-3x3-18.js +5 -0
  95. package/dist/components/ui/dot-matrix/dotm-3x3-19.d.ts +4 -0
  96. package/dist/components/ui/dot-matrix/dotm-3x3-19.js +5 -0
  97. package/dist/components/ui/dot-matrix/dotm-3x3-2.d.ts +4 -0
  98. package/dist/components/ui/dot-matrix/dotm-3x3-2.js +3 -0
  99. package/dist/components/ui/dot-matrix/dotm-3x3-20.d.ts +4 -0
  100. package/dist/components/ui/dot-matrix/dotm-3x3-20.js +5 -0
  101. package/dist/components/ui/dot-matrix/dotm-3x3-21.d.ts +4 -0
  102. package/dist/components/ui/dot-matrix/dotm-3x3-21.js +5 -0
  103. package/dist/components/ui/dot-matrix/dotm-3x3-3.d.ts +4 -0
  104. package/dist/components/ui/dot-matrix/dotm-3x3-3.js +3 -0
  105. package/dist/components/ui/dot-matrix/dotm-3x3-4.d.ts +4 -0
  106. package/dist/components/ui/dot-matrix/dotm-3x3-4.js +3 -0
  107. package/dist/components/ui/dot-matrix/dotm-3x3-5.d.ts +4 -0
  108. package/dist/components/ui/dot-matrix/dotm-3x3-5.js +3 -0
  109. package/dist/components/ui/dot-matrix/dotm-3x3-6.d.ts +4 -0
  110. package/dist/components/ui/dot-matrix/dotm-3x3-6.js +19 -0
  111. package/dist/components/ui/dot-matrix/dotm-3x3-7.d.ts +4 -0
  112. package/dist/components/ui/dot-matrix/dotm-3x3-7.js +19 -0
  113. package/dist/components/ui/dot-matrix/dotm-3x3-8.d.ts +4 -0
  114. package/dist/components/ui/dot-matrix/dotm-3x3-8.js +19 -0
  115. package/dist/components/ui/dot-matrix/dotm-3x3-9.d.ts +4 -0
  116. package/dist/components/ui/dot-matrix/dotm-3x3-9.js +23 -0
  117. package/dist/components/ui/dot-matrix/dotm-circular-1.d.ts +4 -0
  118. package/dist/components/ui/dot-matrix/dotm-circular-1.js +28 -0
  119. package/dist/components/ui/dot-matrix/dotm-circular-10.d.ts +4 -0
  120. package/dist/components/ui/dot-matrix/dotm-circular-10.js +40 -0
  121. package/dist/components/ui/dot-matrix/dotm-circular-11.d.ts +4 -0
  122. package/dist/components/ui/dot-matrix/dotm-circular-11.js +37 -0
  123. package/dist/components/ui/dot-matrix/dotm-circular-12.d.ts +4 -0
  124. package/dist/components/ui/dot-matrix/dotm-circular-12.js +42 -0
  125. package/dist/components/ui/dot-matrix/dotm-circular-14.d.ts +4 -0
  126. package/dist/components/ui/dot-matrix/dotm-circular-14.js +37 -0
  127. package/dist/components/ui/dot-matrix/dotm-circular-15.d.ts +4 -0
  128. package/dist/components/ui/dot-matrix/dotm-circular-15.js +49 -0
  129. package/dist/components/ui/dot-matrix/dotm-circular-17.d.ts +4 -0
  130. package/dist/components/ui/dot-matrix/dotm-circular-17.js +31 -0
  131. package/dist/components/ui/dot-matrix/dotm-circular-2.d.ts +4 -0
  132. package/dist/components/ui/dot-matrix/dotm-circular-2.js +37 -0
  133. package/dist/components/ui/dot-matrix/dotm-circular-3.d.ts +4 -0
  134. package/dist/components/ui/dot-matrix/dotm-circular-3.js +54 -0
  135. package/dist/components/ui/dot-matrix/dotm-circular-4.d.ts +4 -0
  136. package/dist/components/ui/dot-matrix/dotm-circular-4.js +35 -0
  137. package/dist/components/ui/dot-matrix/dotm-circular-5.d.ts +4 -0
  138. package/dist/components/ui/dot-matrix/dotm-circular-5.js +30 -0
  139. package/dist/components/ui/dot-matrix/dotm-circular-6.d.ts +4 -0
  140. package/dist/components/ui/dot-matrix/dotm-circular-6.js +37 -0
  141. package/dist/components/ui/dot-matrix/dotm-circular-7.d.ts +4 -0
  142. package/dist/components/ui/dot-matrix/dotm-circular-7.js +25 -0
  143. package/dist/components/ui/dot-matrix/dotm-circular-8.d.ts +4 -0
  144. package/dist/components/ui/dot-matrix/dotm-circular-8.js +26 -0
  145. package/dist/components/ui/dot-matrix/dotm-circular-9.d.ts +4 -0
  146. package/dist/components/ui/dot-matrix/dotm-circular-9.js +41 -0
  147. package/dist/components/ui/dot-matrix/dotm-square-1.d.ts +4 -0
  148. package/dist/components/ui/dot-matrix/dotm-square-1.js +27 -0
  149. package/dist/components/ui/dot-matrix/dotm-square-10.d.ts +4 -0
  150. package/dist/components/ui/dot-matrix/dotm-square-10.js +27 -0
  151. package/dist/components/ui/dot-matrix/dotm-square-11.d.ts +4 -0
  152. package/dist/components/ui/dot-matrix/dotm-square-11.js +25 -0
  153. package/dist/components/ui/dot-matrix/dotm-square-12.d.ts +4 -0
  154. package/dist/components/ui/dot-matrix/dotm-square-12.js +28 -0
  155. package/dist/components/ui/dot-matrix/dotm-square-13.d.ts +4 -0
  156. package/dist/components/ui/dot-matrix/dotm-square-13.js +45 -0
  157. package/dist/components/ui/dot-matrix/dotm-square-14.d.ts +4 -0
  158. package/dist/components/ui/dot-matrix/dotm-square-14.js +38 -0
  159. package/dist/components/ui/dot-matrix/dotm-square-15.d.ts +4 -0
  160. package/dist/components/ui/dot-matrix/dotm-square-15.js +31 -0
  161. package/dist/components/ui/dot-matrix/dotm-square-16.d.ts +4 -0
  162. package/dist/components/ui/dot-matrix/dotm-square-16.js +33 -0
  163. package/dist/components/ui/dot-matrix/dotm-square-17.d.ts +4 -0
  164. package/dist/components/ui/dot-matrix/dotm-square-17.js +27 -0
  165. package/dist/components/ui/dot-matrix/dotm-square-18.d.ts +4 -0
  166. package/dist/components/ui/dot-matrix/dotm-square-18.js +29 -0
  167. package/dist/components/ui/dot-matrix/dotm-square-19.d.ts +4 -0
  168. package/dist/components/ui/dot-matrix/dotm-square-19.js +74 -0
  169. package/dist/components/ui/dot-matrix/dotm-square-2.d.ts +4 -0
  170. package/dist/components/ui/dot-matrix/dotm-square-2.js +72 -0
  171. package/dist/components/ui/dot-matrix/dotm-square-20.d.ts +4 -0
  172. package/dist/components/ui/dot-matrix/dotm-square-20.js +79 -0
  173. package/dist/components/ui/dot-matrix/dotm-square-3.d.ts +4 -0
  174. package/dist/components/ui/dot-matrix/dotm-square-3.js +23 -0
  175. package/dist/components/ui/dot-matrix/dotm-square-4.d.ts +4 -0
  176. package/dist/components/ui/dot-matrix/dotm-square-4.js +41 -0
  177. package/dist/components/ui/dot-matrix/dotm-square-5.d.ts +4 -0
  178. package/dist/components/ui/dot-matrix/dotm-square-5.js +23 -0
  179. package/dist/components/ui/dot-matrix/dotm-square-6.d.ts +4 -0
  180. package/dist/components/ui/dot-matrix/dotm-square-6.js +20 -0
  181. package/dist/components/ui/dot-matrix/dotm-square-7.d.ts +4 -0
  182. package/dist/components/ui/dot-matrix/dotm-square-7.js +43 -0
  183. package/dist/components/ui/dot-matrix/dotm-square-8.d.ts +4 -0
  184. package/dist/components/ui/dot-matrix/dotm-square-8.js +57 -0
  185. package/dist/components/ui/dot-matrix/dotm-square-9.d.ts +4 -0
  186. package/dist/components/ui/dot-matrix/dotm-square-9.js +89 -0
  187. package/dist/components/ui/dot-matrix/session-dot-matrix.d.ts +46 -0
  188. package/dist/components/ui/dot-matrix/session-dot-matrix.js +153 -0
  189. package/dist/components/ui/drawer.d.ts +15 -0
  190. package/dist/components/ui/drawer.js +35 -0
  191. package/dist/components/ui/dropdown-menu.d.ts +49 -0
  192. package/dist/components/ui/dropdown-menu.js +113 -0
  193. package/dist/components/ui/emoji-picker.d.ts +15 -0
  194. package/dist/components/ui/emoji-picker.js +137 -0
  195. package/dist/components/ui/emoji-tint.d.ts +41 -0
  196. package/dist/components/ui/emoji-tint.js +131 -0
  197. package/dist/components/ui/empty.d.ts +11 -0
  198. package/dist/components/ui/empty.js +33 -0
  199. package/dist/components/ui/entity-avatar.d.ts +84 -0
  200. package/dist/components/ui/entity-avatar.js +106 -0
  201. package/dist/components/ui/faded-scroll-area.d.ts +8 -0
  202. package/dist/components/ui/faded-scroll-area.js +80 -0
  203. package/dist/components/ui/favicon-avatar.d.ts +32 -0
  204. package/dist/components/ui/favicon-avatar.js +18 -0
  205. package/dist/components/ui/field.d.ts +15 -0
  206. package/dist/components/ui/field.js +48 -0
  207. package/dist/components/ui/file-tree.d.ts +32 -0
  208. package/dist/components/ui/file-tree.js +30 -0
  209. package/dist/components/ui/glyph-face.d.ts +18 -0
  210. package/dist/components/ui/glyph-face.js +37 -0
  211. package/dist/components/ui/glyph-paths-source.d.ts +2 -0
  212. package/dist/components/ui/glyph-paths-source.js +40 -0
  213. package/dist/components/ui/glyph-paths.generated.d.ts +2 -0
  214. package/dist/components/ui/glyph-paths.generated.js +207 -0
  215. package/dist/components/ui/glyph-picker.d.ts +22 -0
  216. package/dist/components/ui/glyph-picker.js +118 -0
  217. package/dist/components/ui/glyph-registry.d.ts +36 -0
  218. package/dist/components/ui/glyph-registry.js +479 -0
  219. package/dist/components/ui/glyph-tint.d.ts +6 -0
  220. package/dist/components/ui/glyph-tint.js +93 -0
  221. package/dist/components/ui/hint.d.ts +14 -0
  222. package/dist/components/ui/hint.js +12 -0
  223. package/dist/components/ui/histogram-bars.d.ts +38 -0
  224. package/dist/components/ui/histogram-bars.js +93 -0
  225. package/dist/components/ui/hover-card.d.ts +28 -0
  226. package/dist/components/ui/hover-card.js +35 -0
  227. package/dist/components/ui/icon-provider.d.ts +23 -0
  228. package/dist/components/ui/icon-provider.js +30 -0
  229. package/dist/components/ui/info-banner.d.ts +14 -0
  230. package/dist/components/ui/info-banner.js +72 -0
  231. package/dist/components/ui/inline-meta.d.ts +6 -0
  232. package/dist/components/ui/inline-meta.js +8 -0
  233. package/dist/components/ui/input-group.d.ts +19 -0
  234. package/dist/components/ui/input-group.js +73 -0
  235. package/dist/components/ui/input.d.ts +26 -0
  236. package/dist/components/ui/input.js +23 -0
  237. package/dist/components/ui/item.d.ts +23 -0
  238. package/dist/components/ui/item.js +67 -0
  239. package/dist/components/ui/kbd.d.ts +3 -0
  240. package/dist/components/ui/kbd.js +20 -0
  241. package/dist/components/ui/kortix-asterisk.d.ts +6 -0
  242. package/dist/components/ui/kortix-asterisk.js +17 -0
  243. package/dist/components/ui/kortix-icons.d.ts +2 -0
  244. package/dist/components/ui/kortix-icons.js +17 -0
  245. package/dist/components/ui/kortix-loader.d.ts +76 -0
  246. package/dist/components/ui/kortix-loader.js +74 -0
  247. package/dist/components/ui/kortix-logo.d.ts +30 -0
  248. package/dist/components/ui/kortix-logo.js +47 -0
  249. package/dist/components/ui/label.d.ts +4 -0
  250. package/dist/components/ui/label.js +9 -0
  251. package/dist/components/ui/list.d.ts +15 -0
  252. package/dist/components/ui/list.js +25 -0
  253. package/dist/components/ui/loading.d.ts +19 -0
  254. package/dist/components/ui/loading.js +31 -0
  255. package/dist/components/ui/local-time.d.ts +34 -0
  256. package/dist/components/ui/local-time.js +60 -0
  257. package/dist/components/ui/map.d.ts +101 -0
  258. package/dist/components/ui/map.js +257 -0
  259. package/dist/components/ui/marker.d.ts +14 -0
  260. package/dist/components/ui/marker.js +28 -0
  261. package/dist/components/ui/menu-recipe.d.ts +102 -0
  262. package/dist/components/ui/menu-recipe.js +129 -0
  263. package/dist/components/ui/mermaid-render.d.ts +51 -0
  264. package/dist/components/ui/mermaid-render.js +65 -0
  265. package/dist/components/ui/mermaid-renderer.d.ts +13 -0
  266. package/dist/components/ui/mermaid-renderer.js +340 -0
  267. package/dist/components/ui/message.d.ts +15 -0
  268. package/dist/components/ui/message.js +26 -0
  269. package/dist/components/ui/modal.d.ts +104 -0
  270. package/dist/components/ui/modal.js +180 -0
  271. package/dist/components/ui/navigation-menu.d.ts +16 -0
  272. package/dist/components/ui/navigation-menu.js +35 -0
  273. package/dist/components/ui/page-search-bar.d.ts +11 -0
  274. package/dist/components/ui/page-search-bar.js +13 -0
  275. package/dist/components/ui/phone-input.d.ts +7 -0
  276. package/dist/components/ui/phone-input.js +59 -0
  277. package/dist/components/ui/pixel-kortix-mark.d.ts +13 -0
  278. package/dist/components/ui/pixel-kortix-mark.js +40 -0
  279. package/dist/components/ui/popover.d.ts +10 -0
  280. package/dist/components/ui/popover.js +38 -0
  281. package/dist/components/ui/portal.d.ts +5 -0
  282. package/dist/components/ui/portal.js +15 -0
  283. package/dist/components/ui/preview-image.d.ts +14 -0
  284. package/dist/components/ui/preview-image.js +58 -0
  285. package/dist/components/ui/progress-ring.d.ts +6 -0
  286. package/dist/components/ui/progress-ring.js +9 -0
  287. package/dist/components/ui/progress.d.ts +6 -0
  288. package/dist/components/ui/progress.js +8 -0
  289. package/dist/components/ui/radio-group.d.ts +12 -0
  290. package/dist/components/ui/radio-group.js +20 -0
  291. package/dist/components/ui/resizable.d.ts +24 -0
  292. package/dist/components/ui/resizable.js +16 -0
  293. package/dist/components/ui/scroll-area.d.ts +5 -0
  294. package/dist/components/ui/scroll-area.js +11 -0
  295. package/dist/components/ui/section-card.d.ts +37 -0
  296. package/dist/components/ui/section-card.js +14 -0
  297. package/dist/components/ui/section.d.ts +10 -0
  298. package/dist/components/ui/section.js +22 -0
  299. package/dist/components/ui/select.d.ts +25 -0
  300. package/dist/components/ui/select.js +59 -0
  301. package/dist/components/ui/separator.d.ts +4 -0
  302. package/dist/components/ui/separator.js +8 -0
  303. package/dist/components/ui/shader-safe.d.ts +48 -0
  304. package/dist/components/ui/shader-safe.js +74 -0
  305. package/dist/components/ui/sheet.d.ts +32 -0
  306. package/dist/components/ui/sheet.js +55 -0
  307. package/dist/components/ui/sidebar-context.d.ts +72 -0
  308. package/dist/components/ui/sidebar-context.js +36 -0
  309. package/dist/components/ui/sidebar-menu-primitives.d.ts +38 -0
  310. package/dist/components/ui/sidebar-menu-primitives.js +97 -0
  311. package/dist/components/ui/sidebar-panel.d.ts +36 -0
  312. package/dist/components/ui/sidebar-panel.js +265 -0
  313. package/dist/components/ui/sidebar-peek.d.ts +27 -0
  314. package/dist/components/ui/sidebar-peek.js +70 -0
  315. package/dist/components/ui/sidebar-width.d.ts +48 -0
  316. package/dist/components/ui/sidebar-width.js +62 -0
  317. package/dist/components/ui/sidebar.d.ts +18 -0
  318. package/dist/components/ui/sidebar.js +194 -0
  319. package/dist/components/ui/skeleton.d.ts +3 -0
  320. package/dist/components/ui/skeleton.js +6 -0
  321. package/dist/components/ui/slider-native.d.ts +7 -0
  322. package/dist/components/ui/slider-native.js +16 -0
  323. package/dist/components/ui/slider.d.ts +14 -0
  324. package/dist/components/ui/slider.js +48 -0
  325. package/dist/components/ui/sliding-tab-indicator.d.ts +61 -0
  326. package/dist/components/ui/sliding-tab-indicator.js +128 -0
  327. package/dist/components/ui/split-sheet.d.ts +61 -0
  328. package/dist/components/ui/split-sheet.js +239 -0
  329. package/dist/components/ui/spotlight-card.d.ts +8 -0
  330. package/dist/components/ui/spotlight-card.js +43 -0
  331. package/dist/components/ui/status-ring.d.ts +38 -0
  332. package/dist/components/ui/status-ring.js +38 -0
  333. package/dist/components/ui/status.d.ts +58 -0
  334. package/dist/components/ui/status.js +76 -0
  335. package/dist/components/ui/stepper.d.ts +28 -0
  336. package/dist/components/ui/stepper.js +73 -0
  337. package/dist/components/ui/switch.d.ts +8 -0
  338. package/dist/components/ui/switch.js +131 -0
  339. package/dist/components/ui/system-message.d.ts +23 -0
  340. package/dist/components/ui/system-message.js +51 -0
  341. package/dist/components/ui/table.d.ts +10 -0
  342. package/dist/components/ui/table.js +28 -0
  343. package/dist/components/ui/tabs.d.ts +73 -0
  344. package/dist/components/ui/tabs.js +207 -0
  345. package/dist/components/ui/tag.d.ts +7 -0
  346. package/dist/components/ui/tag.js +22 -0
  347. package/dist/components/ui/text-shimmer.d.ts +13 -0
  348. package/dist/components/ui/text-shimmer.js +91 -0
  349. package/dist/components/ui/textarea.d.ts +33 -0
  350. package/dist/components/ui/textarea.js +87 -0
  351. package/dist/components/ui/toast.d.ts +105 -0
  352. package/dist/components/ui/toast.js +233 -0
  353. package/dist/components/ui/toggle.d.ts +12 -0
  354. package/dist/components/ui/toggle.js +26 -0
  355. package/dist/components/ui/tooltip.d.ts +9 -0
  356. package/dist/components/ui/tooltip.js +16 -0
  357. package/dist/components/ui/trigger-variants.d.ts +14 -0
  358. package/dist/components/ui/trigger-variants.js +67 -0
  359. package/dist/components/ui/type-to-confirm-dialog.d.ts +88 -0
  360. package/dist/components/ui/type-to-confirm-dialog.js +101 -0
  361. package/dist/components/ui/typed-title-logic.d.ts +22 -0
  362. package/dist/components/ui/typed-title-logic.js +33 -0
  363. package/dist/components/ui/typed-title.d.ts +38 -0
  364. package/dist/components/ui/typed-title.js +66 -0
  365. package/dist/components/ui/typing-animation.d.ts +36 -0
  366. package/dist/components/ui/typing-animation.js +141 -0
  367. package/dist/components/ui/user-avatar.d.ts +47 -0
  368. package/dist/components/ui/user-avatar.js +46 -0
  369. package/dist/hooks/use-debounce.d.ts +4 -0
  370. package/dist/hooks/use-debounce.js +17 -0
  371. package/dist/hooks/use-is-dark.d.ts +2 -0
  372. package/dist/hooks/use-is-dark.js +27 -0
  373. package/dist/hooks/use-mobile.d.ts +2 -0
  374. package/dist/hooks/use-mobile.js +15 -0
  375. package/dist/hooks/use-proximity-hover.d.ts +52 -0
  376. package/dist/hooks/use-proximity-hover.js +232 -0
  377. package/dist/icons/close.d.ts +2 -0
  378. package/dist/icons/close.js +7 -0
  379. package/dist/icons/copy.d.ts +3 -0
  380. package/dist/icons/copy.js +6 -0
  381. package/dist/icons/sidebar-toggle.d.ts +13 -0
  382. package/dist/icons/sidebar-toggle.js +13 -0
  383. package/dist/index.d.ts +24 -0
  384. package/dist/index.js +33 -0
  385. package/dist/lib/dotmatrix-core.d.ts +113 -0
  386. package/dist/lib/dotmatrix-core.js +920 -0
  387. package/dist/lib/dotmatrix-hooks.d.ts +28 -0
  388. package/dist/lib/dotmatrix-hooks.js +151 -0
  389. package/dist/lib/favicon.d.ts +4 -0
  390. package/dist/lib/favicon.js +21 -0
  391. package/dist/lib/font-weight.d.ts +6 -0
  392. package/dist/lib/font-weight.js +6 -0
  393. package/dist/lib/icon-config.d.ts +33 -0
  394. package/dist/lib/icon-config.js +22 -0
  395. package/dist/lib/icon-context.d.ts +34 -0
  396. package/dist/lib/icon-context.js +81 -0
  397. package/dist/lib/portal-root.d.ts +8 -0
  398. package/dist/lib/portal-root.js +26 -0
  399. package/dist/lib/settle.d.ts +16 -0
  400. package/dist/lib/settle.js +29 -0
  401. package/dist/lib/springs.d.ts +31 -0
  402. package/dist/lib/springs.js +29 -0
  403. package/dist/lib/utils.d.ts +2 -0
  404. package/dist/lib/utils.js +5 -0
  405. package/dist/lib/z-stack.d.ts +55 -0
  406. package/dist/lib/z-stack.js +130 -0
  407. package/dist/providers/ui-provider.d.ts +141 -0
  408. package/dist/providers/ui-provider.js +93 -0
  409. package/dist/styles/dotmatrix-loader.css +1239 -0
  410. package/dist/styles/fonts.css +46 -0
  411. package/dist/styles/tailwind.css +10 -0
  412. package/dist/styles/theme.css +1019 -0
  413. package/dist/styles/tokens.css +146 -0
  414. package/dist/styles.css +2 -0
  415. package/package.json +881 -4
  416. package/skills/kortix-ui/SKILL.md +150 -0
@@ -0,0 +1,67 @@
1
+ import { cva } from 'class-variance-authority';
2
+ /**
3
+ * The shared look for every disclosure trigger in the system — Select, Dropdown,
4
+ * Popover, Sheet, Modal, Dialog. One definition so a bare trigger renders the
5
+ * same box regardless of which overlay it opens.
6
+ *
7
+ * `secondary` (default) and `outline` draw the input field surface; `transparent`
8
+ * keeps `border-transparent` from the base, so the box metrics stay identical
9
+ * and a row of mixed variants aligns to the same baseline.
10
+ *
11
+ * Triggers rendered with `asChild` opt out entirely — the child owns its styling.
12
+ */
13
+ /** Literal classes, not composed from input.tsx, so Tailwind can see every prefixed one. */
14
+ const fieldTriggerClasses = [
15
+ 'bg-popover border-border',
16
+ 'focus-visible:border-ring focus-visible:ring-ring/15 focus-visible:ring-3',
17
+ 'data-[state=open]:border-ring data-[state=open]:ring-ring/15 data-[state=open]:ring-3',
18
+ ].join(' ');
19
+ export const triggerVariants = cva([
20
+ 'group/ui-trigger flex w-fit shrink-0 cursor-pointer items-center justify-between gap-2 rounded-md border border-transparent font-normal outline-none',
21
+ 'text-foreground data-placeholder:text-muted-foreground',
22
+ // Never `transition-all`: only the properties that actually change on hover/press.
23
+ 'transition-[background-color,border-color,color,box-shadow,transform] duration-150 ease-out',
24
+ 'focus-visible:ring-kortix-base focus-visible:ring-[0.6px] focus-visible:outline-none data-[state=open]:ring-0',
25
+ 'disabled:cursor-not-allowed disabled:opacity-50',
26
+ // One line, ellipsised. `truncate`, not `line-clamp-1`: line-clamp sets
27
+ // `display: -webkit-box` on every direct <span>, which out-ranks a child's
28
+ // own `flex` — an icon + label wrapper then stacked the icon ABOVE the
29
+ // label and lost its gap. `truncate` changes overflow only, not display.
30
+ '[&>span]:min-w-0 [&>span]:truncate [&>span]:text-left',
31
+ ], {
32
+ variants: {
33
+ variant: {
34
+ // `secondary` and `outline` are form-field triggers: they draw the exact
35
+ // surface `Input` draws (`inputSurfaceClasses` in input.tsx), and an OPEN
36
+ // trigger shows the same border + 3px halo as a focused input, so a
37
+ // Select beside a text field reads as one form.
38
+ secondary: fieldTriggerClasses,
39
+ outline: fieldTriggerClasses,
40
+ // Only the borderless toolbar trigger takes a press scale. A form field
41
+ // does not shrink under the pointer — an input never does, and a
42
+ // Select beside it should behave the same.
43
+ transparent: 'bg-transparent hover:bg-foreground/5 motion-safe:active:scale-[0.98]',
44
+ },
45
+ size: {
46
+ sm: 'h-8 px-2.5 text-sm',
47
+ md: 'h-10 px-3.5 text-sm',
48
+ lg: 'h-11 px-4 text-base',
49
+ },
50
+ },
51
+ defaultVariants: {
52
+ variant: 'secondary',
53
+ size: 'sm',
54
+ },
55
+ });
56
+ /** Caret sizing per trigger size — matches the text step of each size. */
57
+ export const TRIGGER_ICON_SIZE = {
58
+ sm: 'size-4',
59
+ md: 'size-4',
60
+ lg: 'size-4.5',
61
+ };
62
+ /** The caret classes: muted, shrink-proof, and flipped while the overlay is open. */
63
+ export const TRIGGER_CARET_CLASS = [
64
+ 'text-muted-foreground shrink-0',
65
+ 'motion-safe:transition-transform motion-safe:duration-200 motion-safe:ease-out',
66
+ 'group-data-[state=open]/ui-trigger:rotate-180',
67
+ ].join(' ');
@@ -0,0 +1,88 @@
1
+ /**
2
+ * A destructive confirmation that only arms once the user has TYPED an exact
3
+ * phrase — the workspace name, the account name, whatever uniquely identifies
4
+ * the thing being destroyed.
5
+ *
6
+ * **When to use this instead of `ConfirmDialog`.** `ConfirmDialog`
7
+ * (`confirm-dialog.tsx`) stays the default for every destructive mutation:
8
+ * revoke a key, delete a secret, disconnect a channel. Reach for THIS one only
9
+ * when the action is both irreversible AND ambiguous — i.e. the user could
10
+ * plausibly be looking at the wrong entity. A single click, even a confirmed
11
+ * one, does not distinguish "delete this workspace" from "delete the workspace
12
+ * I meant". Typing the name does.
13
+ *
14
+ * **Why `Modal` and not `AlertDialog`.** The moment a confirmation grows an
15
+ * input it is a form, and `ConfirmDialog`'s `AlertDialog` shell has no room for
16
+ * one. `profile-tab.tsx`'s Delete-account flow already made this call (it
17
+ * hand-rolls a `Modal` with a "type delete to confirm" field); this component
18
+ * is that same pattern promoted to a primitive so the next destructive flow
19
+ * composes it instead of copying it. Profile's own dialog is deliberately left
20
+ * alone here — it carries an extra grace-period radio group, so adopting this
21
+ * is its own change, not a drive-by.
22
+ *
23
+ * **Why the phrase is the entity's name, not a fixed word.** A fixed word
24
+ * ("delete", "DELETE") proves the user read a prompt. The entity's name proves
25
+ * the user knows WHICH entity they are destroying. The expensive mistake in
26
+ * practice is not clicking too fast — it is clicking correctly on the wrong
27
+ * workspace.
28
+ *
29
+ * The matcher is `confirmationPhraseMatches` below, exported and tested
30
+ * separately: this dialog renders through a Radix portal, which emits nothing
31
+ * under `renderToStaticMarkup`, so a test that reached for the button's
32
+ * `disabled` attribute in rendered output would silently be unable to fail.
33
+ * See `type-to-confirm-dialog.test.ts`.
34
+ */
35
+ import { type ReactNode } from 'react';
36
+ /**
37
+ * Does what the user typed authorize the destructive action?
38
+ *
39
+ * Three deliberate rules, each guarding a specific failure:
40
+ *
41
+ * 1. **An empty/blank `phrase` NEVER arms.** This is the important one. The
42
+ * phrase is usually a name read out of a query (`project?.name`), which is
43
+ * `undefined` while that query is still loading. A naive
44
+ * `typed === phrase` would then compare `'' === ''` and arm the destroy
45
+ * button on an untouched dialog — the precise opposite of this component's
46
+ * reason to exist.
47
+ * 2. **Both sides are trimmed.** Names get copied out of the surrounding UI and
48
+ * arrive with a trailing space. Leading/trailing whitespace is a paste
49
+ * artifact, never intent, and rejecting it only teaches users to distrust
50
+ * the field.
51
+ * 3. **The comparison is case-insensitive.** Case adds friction without adding
52
+ * safety: the guarantee being bought is "the user knows which entity this
53
+ * is", and typing `acme prod` for `Acme Prod` demonstrates that fully. A
54
+ * case-sensitive match would reject it and buy nothing.
55
+ */
56
+ export declare function confirmationPhraseMatches(typed: string, phrase: string): boolean;
57
+ export interface TypeToConfirmDialogProps {
58
+ open: boolean;
59
+ onOpenChange: (open: boolean) => void;
60
+ /** Stable across entities — "Delete workspace?", not "Delete Acme?". The
61
+ * entity's name belongs in `description`, where it does not make the
62
+ * heading jump around between openings. */
63
+ title: string;
64
+ /** One or two sentences naming the entity and the irreversibility. */
65
+ description: ReactNode;
66
+ /** What the action destroys or stops, one item per line. Rendered as a
67
+ * bulleted list inside a bordered panel. Static per call site, so index
68
+ * keys are safe. */
69
+ consequences?: readonly ReactNode[];
70
+ /** Heading above `consequences`. */
71
+ consequencesTitle?: string;
72
+ /** What SURVIVES the action. Optional, but include it whenever something
73
+ * meaningful does — a user who has just been told "this is permanent"
74
+ * reads an unqualified warning as "my code is gone too". */
75
+ reassurance?: ReactNode;
76
+ /** The exact string the user must type. While this is blank the confirm
77
+ * button never arms — see `confirmationPhraseMatches`. */
78
+ confirmPhrase: string;
79
+ /** Verb phrase for the armed button, e.g. "Delete workspace". */
80
+ confirmLabel: string;
81
+ /** Non-destructive dismissal. Phrase it as the safe outcome ("Keep
82
+ * workspace"), not as a neutral "Cancel" — at the moment of decision the
83
+ * escape hatch should read as a choice, not an abort. */
84
+ cancelLabel?: string;
85
+ onConfirm: () => void;
86
+ isPending?: boolean;
87
+ }
88
+ export declare function TypeToConfirmDialog({ open, onOpenChange, ...content }: TypeToConfirmDialogProps): import("react").JSX.Element;
@@ -0,0 +1,101 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ /**
4
+ * A destructive confirmation that only arms once the user has TYPED an exact
5
+ * phrase — the workspace name, the account name, whatever uniquely identifies
6
+ * the thing being destroyed.
7
+ *
8
+ * **When to use this instead of `ConfirmDialog`.** `ConfirmDialog`
9
+ * (`confirm-dialog.tsx`) stays the default for every destructive mutation:
10
+ * revoke a key, delete a secret, disconnect a channel. Reach for THIS one only
11
+ * when the action is both irreversible AND ambiguous — i.e. the user could
12
+ * plausibly be looking at the wrong entity. A single click, even a confirmed
13
+ * one, does not distinguish "delete this workspace" from "delete the workspace
14
+ * I meant". Typing the name does.
15
+ *
16
+ * **Why `Modal` and not `AlertDialog`.** The moment a confirmation grows an
17
+ * input it is a form, and `ConfirmDialog`'s `AlertDialog` shell has no room for
18
+ * one. `profile-tab.tsx`'s Delete-account flow already made this call (it
19
+ * hand-rolls a `Modal` with a "type delete to confirm" field); this component
20
+ * is that same pattern promoted to a primitive so the next destructive flow
21
+ * composes it instead of copying it. Profile's own dialog is deliberately left
22
+ * alone here — it carries an extra grace-period radio group, so adopting this
23
+ * is its own change, not a drive-by.
24
+ *
25
+ * **Why the phrase is the entity's name, not a fixed word.** A fixed word
26
+ * ("delete", "DELETE") proves the user read a prompt. The entity's name proves
27
+ * the user knows WHICH entity they are destroying. The expensive mistake in
28
+ * practice is not clicking too fast — it is clicking correctly on the wrong
29
+ * workspace.
30
+ *
31
+ * The matcher is `confirmationPhraseMatches` below, exported and tested
32
+ * separately: this dialog renders through a Radix portal, which emits nothing
33
+ * under `renderToStaticMarkup`, so a test that reached for the button's
34
+ * `disabled` attribute in rendered output would silently be unable to fail.
35
+ * See `type-to-confirm-dialog.test.ts`.
36
+ */
37
+ import { useId, useState } from 'react';
38
+ import { useUiStrings } from '../../providers/ui-provider.js';
39
+ import { Button } from './button.js';
40
+ import { Input } from './input.js';
41
+ import { Label } from './label.js';
42
+ import Loading from './loading.js';
43
+ import { Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle, } from './modal.js';
44
+ /**
45
+ * Does what the user typed authorize the destructive action?
46
+ *
47
+ * Three deliberate rules, each guarding a specific failure:
48
+ *
49
+ * 1. **An empty/blank `phrase` NEVER arms.** This is the important one. The
50
+ * phrase is usually a name read out of a query (`project?.name`), which is
51
+ * `undefined` while that query is still loading. A naive
52
+ * `typed === phrase` would then compare `'' === ''` and arm the destroy
53
+ * button on an untouched dialog — the precise opposite of this component's
54
+ * reason to exist.
55
+ * 2. **Both sides are trimmed.** Names get copied out of the surrounding UI and
56
+ * arrive with a trailing space. Leading/trailing whitespace is a paste
57
+ * artifact, never intent, and rejecting it only teaches users to distrust
58
+ * the field.
59
+ * 3. **The comparison is case-insensitive.** Case adds friction without adding
60
+ * safety: the guarantee being bought is "the user knows which entity this
61
+ * is", and typing `acme prod` for `Acme Prod` demonstrates that fully. A
62
+ * case-sensitive match would reject it and buy nothing.
63
+ */
64
+ export function confirmationPhraseMatches(typed, phrase) {
65
+ const target = phrase.trim();
66
+ if (!target)
67
+ return false;
68
+ return typed.trim().toLowerCase() === target.toLowerCase();
69
+ }
70
+ export function TypeToConfirmDialog({ open, onOpenChange, ...content }) {
71
+ return (_jsx(Modal, { open: open, onOpenChange: onOpenChange, children: _jsx(ModalContent, { className: "lg:max-w-md", children: _jsx(TypeToConfirmBody, { onOpenChange: onOpenChange, ...content }) }) }));
72
+ }
73
+ function TypeToConfirmBody({ onOpenChange, title, description, consequences, consequencesTitle = 'This removes:', reassurance, confirmPhrase, confirmLabel, cancelLabel, onConfirm, isPending = false, }) {
74
+ const strings = useUiStrings();
75
+ const [typed, setTyped] = useState('');
76
+ const inputId = useId();
77
+ // Derived, never stored: if `confirmPhrase` changes while the dialog is open
78
+ // (the entity is renamed in another tab), the button disarms on the next
79
+ // render instead of holding a stale "armed" flag.
80
+ const armed = confirmationPhraseMatches(typed, confirmPhrase);
81
+ const canSubmit = armed && !isPending;
82
+ return (_jsxs(_Fragment, { children: [_jsxs(ModalHeader, { className: "space-y-1.5", children: [_jsx(ModalTitle, { children: title }), _jsx(ModalDescription, { className: "text-pretty", children: description })] }), _jsxs("form", { onSubmit: (e) => {
83
+ e.preventDefault();
84
+ // Guarded, not just visually disabled: Enter in the text field
85
+ // submits the form, and a disabled button does not stop that.
86
+ if (canSubmit)
87
+ onConfirm();
88
+ }, children: [_jsxs(ModalBody, { children: [consequences?.length ? (_jsxs("div", { className: "bg-popover space-y-2 rounded-md border px-4 py-3", children: [_jsx("p", { className: "text-sm font-medium", children: consequencesTitle }), _jsx("ul", { className: "text-muted-foreground list-disc space-y-1.5 pl-5 text-sm text-pretty", children: (() => {
89
+ // Callers pass static string lists — key by content, with an
90
+ // occurrence counter for repeats and non-text nodes.
91
+ const seen = new Map();
92
+ return consequences.map((item) => {
93
+ const base = typeof item === 'string' || typeof item === 'number' ? String(item) : 'node';
94
+ const n = seen.get(base) ?? 0;
95
+ seen.set(base, n + 1);
96
+ return _jsx("li", { children: item }, n === 0 ? base : `${base}#${n}`);
97
+ });
98
+ })() })] })) : null, reassurance ? (_jsx("p", { className: "text-muted-foreground text-sm text-pretty", children: reassurance })) : null, _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: inputId, className: "text-sm font-normal", children: ["Type", ' ', _jsx("span", { className: "text-foreground font-medium break-all", children: confirmPhrase }), " to confirm"] }), _jsx(Input, { id: inputId, value: typed, onChange: (e) => setTyped(e.target.value), disabled: isPending, autoComplete: "off", autoCorrect: "off", autoCapitalize: "none", spellCheck: false, "aria-describedby": `${inputId}-hint` }), _jsx("p", { id: `${inputId}-hint`, className: "sr-only", "aria-live": "polite", children: armed
99
+ ? `Confirmed. ${confirmLabel} is now enabled.`
100
+ : `Type the exact name to enable ${confirmLabel}.` })] })] }), _jsxs(ModalFooter, { className: "sm:justify-between", children: [_jsx(Button, { type: "button", variant: "outline-ghost", onClick: () => onOpenChange(false), disabled: isPending, className: "w-full sm:w-auto", children: cancelLabel ?? strings.cancel }), _jsxs(Button, { type: "submit", variant: "destructive", disabled: !canSubmit, className: "w-full gap-1.5 sm:w-auto", children: [isPending ? _jsx(Loading, { className: "size-4 shrink-0" }) : null, confirmLabel] })] })] })] }));
101
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * When a title should type itself in.
3
+ *
4
+ * Pure, and separate from the component, because this is the whole decision —
5
+ * the rendering is a detail. A session title types when its VALUE CHANGES, not
6
+ * when it renders. That distinction is what keeps the effect off the frequency
7
+ * cliff: a page load, a scroll back up, a re-sort of the list and a re-render
8
+ * from unrelated state all paint titles instantly, because none of them change
9
+ * a title. Twenty rows typing at once on load would be noise; this cannot
10
+ * produce it.
11
+ */
12
+ /** How long between characters. A fast, confident typist — slow enough to read
13
+ * as typing, quick enough that a 40-character title lands in ~1.4s. Shared by
14
+ * every surface so the effect is one thing, not per-list guesswork. */
15
+ export declare const TYPE_SPEED_MS = 36;
16
+ export declare function shouldTypeOnChange({ previous, next, reduceMotion, }: {
17
+ /** What this row last displayed. `null` means it has never displayed
18
+ * anything — the very first render. */
19
+ previous: string | null;
20
+ next: string;
21
+ reduceMotion: boolean;
22
+ }): boolean;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * When a title should type itself in.
3
+ *
4
+ * Pure, and separate from the component, because this is the whole decision —
5
+ * the rendering is a detail. A session title types when its VALUE CHANGES, not
6
+ * when it renders. That distinction is what keeps the effect off the frequency
7
+ * cliff: a page load, a scroll back up, a re-sort of the list and a re-render
8
+ * from unrelated state all paint titles instantly, because none of them change
9
+ * a title. Twenty rows typing at once on load would be noise; this cannot
10
+ * produce it.
11
+ */
12
+ /** How long between characters. A fast, confident typist — slow enough to read
13
+ * as typing, quick enough that a 40-character title lands in ~1.4s. Shared by
14
+ * every surface so the effect is one thing, not per-list guesswork. */
15
+ export const TYPE_SPEED_MS = 36;
16
+ export function shouldTypeOnChange({ previous, next, reduceMotion, }) {
17
+ // First render is never an animation. The row is appearing with whatever the
18
+ // title already is; there was no change to show, and animating here is what
19
+ // would make a cold page load type twenty titles at once.
20
+ if (previous === null)
21
+ return false;
22
+ if (previous === next)
23
+ return false;
24
+ // Reduced motion still gets the new title — instantly. Typing is decoration
25
+ // over a value that is already correct, so removing it costs nothing; a fade
26
+ // would be the compromise if the motion carried meaning, and it does not.
27
+ if (reduceMotion)
28
+ return false;
29
+ // An empty title has nothing to type. Guarded because the animation would
30
+ // otherwise complete on an empty string and leave the cursor blinking on a
31
+ // row with no text.
32
+ return next.length > 0;
33
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * A title that types itself in when it changes.
3
+ *
4
+ * The sessions list shows "New session" the moment a session is created, then
5
+ * swaps it for the real name seconds later when the agent has one. That swap
6
+ * used to be an instant text replacement — the row simply said something
7
+ * different on the next frame, with nothing to say a value had been written.
8
+ * Typing it says so.
9
+ *
10
+ * TWO PIECES on purpose. `useTypeOnChange` is the trigger and is shared, so
11
+ * every list agrees on WHEN a title types. `TypedTitle` is one rendering of it,
12
+ * for rows that show a title as plain inline text. The sidebar renders its own
13
+ * (it wraps the title in a hover-scrolling marquee) and takes only the hook —
14
+ * shared decision, surface-specific presentation.
15
+ */
16
+ import { TYPE_SPEED_MS } from './typed-title-logic.js';
17
+ export { TYPE_SPEED_MS };
18
+ export declare function useTypeOnChange(text: string): {
19
+ isTyping: boolean;
20
+ /** Remount key for the typing element. A run must restart from character
21
+ * zero when the title changes again mid-type — without a changing key the
22
+ * animation keeps its old progress and types the tail of a string nobody
23
+ * asked for. */
24
+ runId: number;
25
+ /** Hand to the animation's `onComplete`. */
26
+ stop: () => void;
27
+ };
28
+ /**
29
+ * Inline typed title for a list row.
30
+ *
31
+ * Renders as plain text at rest — no wrapper, no extra element — so a row that
32
+ * is not animating costs exactly what it did before, and the parent's
33
+ * `truncate` keeps ellipsising long titles as it always has.
34
+ */
35
+ export declare function TypedTitle({ text, className }: {
36
+ text: string;
37
+ className?: string;
38
+ }): import("react").JSX.Element;
@@ -0,0 +1,66 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * A title that types itself in when it changes.
5
+ *
6
+ * The sessions list shows "New session" the moment a session is created, then
7
+ * swaps it for the real name seconds later when the agent has one. That swap
8
+ * used to be an instant text replacement — the row simply said something
9
+ * different on the next frame, with nothing to say a value had been written.
10
+ * Typing it says so.
11
+ *
12
+ * TWO PIECES on purpose. `useTypeOnChange` is the trigger and is shared, so
13
+ * every list agrees on WHEN a title types. `TypedTitle` is one rendering of it,
14
+ * for rows that show a title as plain inline text. The sidebar renders its own
15
+ * (it wraps the title in a hover-scrolling marquee) and takes only the hook —
16
+ * shared decision, surface-specific presentation.
17
+ */
18
+ import { shouldTypeOnChange, TYPE_SPEED_MS } from './typed-title-logic.js';
19
+ import { TypingAnimation } from './typing-animation.js';
20
+ import { cn } from '../../lib/utils.js';
21
+ import { useReducedMotion } from 'motion/react';
22
+ import { useCallback, useEffect, useRef, useState } from 'react';
23
+ export { TYPE_SPEED_MS };
24
+ export function useTypeOnChange(text) {
25
+ // The last value this row DISPLAYED, in a ref rather than state: it must not
26
+ // itself cause a render, and it has to update in the same pass that decides
27
+ // to animate, or a second change arriving mid-type compares against a stale
28
+ // value and is missed.
29
+ const previousRef = useRef(null);
30
+ const [isTyping, setIsTyping] = useState(false);
31
+ const [runId, setRunId] = useState(0);
32
+ const reduceMotion = !!useReducedMotion();
33
+ useEffect(() => {
34
+ const previous = previousRef.current;
35
+ previousRef.current = text;
36
+ if (!shouldTypeOnChange({ previous, next: text, reduceMotion }))
37
+ return;
38
+ setIsTyping(true);
39
+ setRunId((id) => id + 1);
40
+ }, [text, reduceMotion]);
41
+ const stop = useCallback(() => setIsTyping(false), []);
42
+ return { isTyping, runId, stop };
43
+ }
44
+ /**
45
+ * Inline typed title for a list row.
46
+ *
47
+ * Renders as plain text at rest — no wrapper, no extra element — so a row that
48
+ * is not animating costs exactly what it did before, and the parent's
49
+ * `truncate` keeps ellipsising long titles as it always has.
50
+ */
51
+ export function TypedTitle({ text, className }) {
52
+ const { isTyping, runId, stop } = useTypeOnChange(text);
53
+ if (!isTyping)
54
+ return _jsx("span", { className: className, children: text });
55
+ return (_jsx(TypingAnimation, {
56
+ // The row is already on screen and the title has already changed —
57
+ // waiting for an intersection observer would mean a visible row types
58
+ // late, or a row scrolled past types nothing at all.
59
+ startOnView: false, showCursor: true, blinkCursor: true, cursorStyle: "line", typeSpeed: TYPE_SPEED_MS, onComplete: stop,
60
+ // The component ships marketing-hero defaults (`leading-20`, negative
61
+ // tracking) that belong to a headline, not a 13px list row. Reset both
62
+ // so the typed text sits on the same baseline and rhythm as the plain
63
+ // text it replaces — any drift here reads as the row twitching when the
64
+ // animation starts and again when it ends.
65
+ className: cn('leading-none tracking-normal', className), children: text }, runId));
66
+ }
@@ -0,0 +1,36 @@
1
+ import { type DOMMotionComponents, type HTMLMotionProps, type MotionProps } from 'motion/react';
2
+ declare const motionElements: {
3
+ readonly article: import("motion/react").ForwardRefComponent<HTMLElement, HTMLMotionProps<"article">>;
4
+ readonly div: import("motion/react").ForwardRefComponent<HTMLDivElement, HTMLMotionProps<"div">>;
5
+ readonly h1: import("motion/react").ForwardRefComponent<HTMLHeadingElement, HTMLMotionProps<"h1">>;
6
+ readonly h2: import("motion/react").ForwardRefComponent<HTMLHeadingElement, HTMLMotionProps<"h2">>;
7
+ readonly h3: import("motion/react").ForwardRefComponent<HTMLHeadingElement, HTMLMotionProps<"h3">>;
8
+ readonly h4: import("motion/react").ForwardRefComponent<HTMLHeadingElement, HTMLMotionProps<"h4">>;
9
+ readonly h5: import("motion/react").ForwardRefComponent<HTMLHeadingElement, HTMLMotionProps<"h5">>;
10
+ readonly h6: import("motion/react").ForwardRefComponent<HTMLHeadingElement, HTMLMotionProps<"h6">>;
11
+ readonly li: import("motion/react").ForwardRefComponent<HTMLLIElement, HTMLMotionProps<"li">>;
12
+ readonly p: import("motion/react").ForwardRefComponent<HTMLParagraphElement, HTMLMotionProps<"p">>;
13
+ readonly section: import("motion/react").ForwardRefComponent<HTMLElement, HTMLMotionProps<"section">>;
14
+ readonly span: import("motion/react").ForwardRefComponent<HTMLSpanElement, HTMLMotionProps<"span">>;
15
+ };
16
+ type MotionElementType = Extract<keyof DOMMotionComponents, keyof typeof motionElements>;
17
+ interface TypingAnimationProps extends Omit<MotionProps, 'children'> {
18
+ children?: string;
19
+ words?: string[];
20
+ className?: string;
21
+ duration?: number;
22
+ typeSpeed?: number;
23
+ deleteSpeed?: number;
24
+ delay?: number;
25
+ pauseDelay?: number;
26
+ loop?: boolean;
27
+ as?: MotionElementType;
28
+ startOnView?: boolean;
29
+ showCursor?: boolean;
30
+ blinkCursor?: boolean;
31
+ cursorStyle?: 'line' | 'block' | 'underscore';
32
+ /** Fires once when a non-looping animation finishes typing the last word. */
33
+ onComplete?: () => void;
34
+ }
35
+ export declare function TypingAnimation({ children, words, className, duration, typeSpeed, deleteSpeed, delay, pauseDelay, loop, as: Component, startOnView, showCursor, blinkCursor, cursorStyle, onComplete, ...props }: TypingAnimationProps): import("react").JSX.Element;
36
+ export {};
@@ -0,0 +1,141 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { m, useInView, } from 'motion/react';
4
+ import { useEffect, useMemo, useRef, useState, } from 'react';
5
+ import { cn } from '../../lib/utils.js';
6
+ const motionElements = {
7
+ article: m.article,
8
+ div: m.div,
9
+ h1: m.h1,
10
+ h2: m.h2,
11
+ h3: m.h3,
12
+ h4: m.h4,
13
+ h5: m.h5,
14
+ h6: m.h6,
15
+ li: m.li,
16
+ p: m.p,
17
+ section: m.section,
18
+ span: m.span,
19
+ };
20
+ export function TypingAnimation({ children, words, className, duration = 100, typeSpeed, deleteSpeed, delay = 0, pauseDelay = 1000, loop = false, as: Component = 'span', startOnView = true, showCursor = true, blinkCursor = true, cursorStyle = 'line', onComplete, ...props }) {
21
+ const MotionComponent = motionElements[Component];
22
+ const [displayedText, setDisplayedText] = useState('');
23
+ const [currentWordIndex, setCurrentWordIndex] = useState(0);
24
+ const [currentCharIndex, setCurrentCharIndex] = useState(0);
25
+ const [phase, setPhase] = useState('typing');
26
+ const elementRef = useRef(null);
27
+ const isInView = useInView(elementRef, {
28
+ amount: 0.3,
29
+ once: true,
30
+ });
31
+ const wordsToAnimate = useMemo(() => words ?? (children ? [children] : []), [words, children]);
32
+ const hasMultipleWords = wordsToAnimate.length > 1;
33
+ const typingSpeed = typeSpeed ?? duration;
34
+ const deletingSpeed = deleteSpeed ?? typingSpeed / 2;
35
+ const shouldStart = startOnView ? isInView : true;
36
+ const animationSourceKey = useMemo(() => (words ? words.join('\u0000') : (children ?? '')), [words, children]);
37
+ useEffect(() => {
38
+ setDisplayedText('');
39
+ setCurrentWordIndex(0);
40
+ setCurrentCharIndex(0);
41
+ setPhase('typing');
42
+ }, [animationSourceKey]);
43
+ useEffect(() => {
44
+ let timeout = null;
45
+ if (shouldStart && wordsToAnimate.length > 0) {
46
+ const timeoutDelay = delay > 0 && displayedText === ''
47
+ ? delay
48
+ : phase === 'typing'
49
+ ? typingSpeed
50
+ : phase === 'deleting'
51
+ ? deletingSpeed
52
+ : pauseDelay;
53
+ timeout = setTimeout(() => {
54
+ const currentWord = wordsToAnimate[currentWordIndex] || '';
55
+ const graphemes = Array.from(currentWord);
56
+ switch (phase) {
57
+ case 'typing':
58
+ if (currentCharIndex < graphemes.length) {
59
+ setDisplayedText(graphemes.slice(0, currentCharIndex + 1).join(''));
60
+ setCurrentCharIndex((prev) => prev + 1);
61
+ }
62
+ else {
63
+ if (hasMultipleWords || loop) {
64
+ const isLastWord = currentWordIndex === wordsToAnimate.length - 1;
65
+ if (!isLastWord || loop) {
66
+ setPhase('pause');
67
+ }
68
+ }
69
+ }
70
+ break;
71
+ case 'pause':
72
+ setPhase('deleting');
73
+ break;
74
+ case 'deleting':
75
+ if (currentCharIndex > 0) {
76
+ setDisplayedText(graphemes.slice(0, currentCharIndex - 1).join(''));
77
+ setCurrentCharIndex((prev) => prev - 1);
78
+ }
79
+ else {
80
+ const nextIndex = (currentWordIndex + 1) % wordsToAnimate.length;
81
+ setCurrentWordIndex(nextIndex);
82
+ setPhase('typing');
83
+ }
84
+ break;
85
+ }
86
+ }, timeoutDelay);
87
+ }
88
+ return () => {
89
+ if (timeout !== null) {
90
+ clearTimeout(timeout);
91
+ }
92
+ };
93
+ }, [
94
+ shouldStart,
95
+ phase,
96
+ currentCharIndex,
97
+ currentWordIndex,
98
+ displayedText,
99
+ wordsToAnimate,
100
+ hasMultipleWords,
101
+ loop,
102
+ typingSpeed,
103
+ deletingSpeed,
104
+ pauseDelay,
105
+ delay,
106
+ ]);
107
+ const currentWordGraphemes = Array.from(wordsToAnimate[currentWordIndex] || '');
108
+ const isComplete = !loop &&
109
+ currentWordIndex === wordsToAnimate.length - 1 &&
110
+ currentCharIndex >= currentWordGraphemes.length &&
111
+ phase !== 'deleting';
112
+ const onCompleteRef = useRef(onComplete);
113
+ useEffect(() => {
114
+ onCompleteRef.current = onComplete;
115
+ }, [onComplete]);
116
+ const didFireCompleteRef = useRef(false);
117
+ useEffect(() => {
118
+ didFireCompleteRef.current = false;
119
+ }, [animationSourceKey]);
120
+ useEffect(() => {
121
+ if (!isComplete || didFireCompleteRef.current)
122
+ return;
123
+ didFireCompleteRef.current = true;
124
+ onCompleteRef.current?.();
125
+ }, [isComplete]);
126
+ const shouldShowCursor = showCursor &&
127
+ !isComplete &&
128
+ (hasMultipleWords || loop || currentCharIndex < currentWordGraphemes.length);
129
+ const getCursorChar = () => {
130
+ switch (cursorStyle) {
131
+ case 'block':
132
+ return '▌';
133
+ case 'underscore':
134
+ return '_';
135
+ case 'line':
136
+ default:
137
+ return '|';
138
+ }
139
+ };
140
+ return (_jsxs(MotionComponent, { ref: elementRef, className: cn('leading-20 tracking-[-0.02em]', Component === 'span' && 'inline-block', className), ...props, children: [displayedText, shouldShowCursor && (_jsx("span", { className: cn('inline-block', blinkCursor && 'animate-blink-cursor'), children: getCursorChar() }))] }));
141
+ }
@@ -0,0 +1,47 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * `text` goes on the fallback itself: the primitive's fallback sets its own
4
+ * `text-sm`, which beat a size class on the root. Two initials at 14px
5
+ * semibold filled the 22px `sm` tile edge to edge and overflowed an 18px one.
6
+ * `xs` and `sm` hold ONE initial, as EntityAvatar does: `text-xs` (13px) is
7
+ * the floor of the type scale, and two letters at 13px still fill an 18px tile.
8
+ */
9
+ declare const SIZE_MAP: {
10
+ readonly xs: {
11
+ readonly box: "size-5";
12
+ readonly text: "text-xs";
13
+ readonly initials: 1;
14
+ };
15
+ readonly sm: {
16
+ readonly box: "size-6";
17
+ readonly text: "text-xs";
18
+ readonly initials: 1;
19
+ };
20
+ readonly md: {
21
+ readonly box: "size-8";
22
+ readonly text: "text-xs";
23
+ readonly initials: 2;
24
+ };
25
+ readonly lg: {
26
+ readonly box: "size-10";
27
+ readonly text: "text-sm";
28
+ readonly initials: 2;
29
+ };
30
+ readonly xl: {
31
+ readonly box: "size-14";
32
+ readonly text: "text-base";
33
+ readonly initials: 2;
34
+ };
35
+ };
36
+ export type UserAvatarSize = keyof typeof SIZE_MAP;
37
+ export interface UserAvatarProps {
38
+ email: string;
39
+ name?: string | null;
40
+ avatarUrl?: string | null;
41
+ size?: UserAvatarSize;
42
+ className?: string;
43
+ ring?: boolean;
44
+ variant?: 'default' | 'primary';
45
+ }
46
+ export declare function UserAvatar({ email, name, avatarUrl, size, variant, className, ring, }: UserAvatarProps): React.JSX.Element;
47
+ export {};