@ctrl-ui/react 0.8.6 → 0.8.8

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 (376) hide show
  1. package/dist/action-bar.d.ts +15 -7
  2. package/dist/action-bar.js +39 -19
  3. package/dist/activity.js +7 -15
  4. package/dist/audio-recorder.d.ts +14 -4
  5. package/dist/audio-recorder.js +82 -29
  6. package/dist/audio-visualizer.js +1 -1
  7. package/dist/blocks/coding-agent.js +54 -57
  8. package/dist/blocks/design-canvas-data.d.ts +32 -0
  9. package/dist/blocks/design-canvas-data.js +100 -0
  10. package/dist/blocks/design-canvas-inspector.d.ts +8 -0
  11. package/dist/blocks/design-canvas-inspector.js +238 -0
  12. package/dist/blocks/design-canvas.d.ts +21 -0
  13. package/dist/blocks/design-canvas.js +452 -0
  14. package/dist/blocks/discussion.d.ts +28 -0
  15. package/dist/blocks/discussion.js +67 -0
  16. package/dist/blocks/file-explorer-data.d.ts +1 -0
  17. package/dist/blocks/file-explorer-data.js +4 -1
  18. package/dist/blocks/file-explorer.d.ts +9 -1
  19. package/dist/blocks/file-explorer.js +461 -192
  20. package/dist/blocks/settings.d.ts +2 -1
  21. package/dist/blocks/settings.js +101 -79
  22. package/dist/blocks/team-chat.d.ts +12 -0
  23. package/dist/blocks/team-chat.js +26 -0
  24. package/dist/blocks/theme-toggle.js +23 -31
  25. package/dist/chat-composer-attachment.d.ts +12 -3
  26. package/dist/chat-composer-attachment.js +61 -19
  27. package/dist/chat-composer-editor/extensions/mention.d.ts +5 -1
  28. package/dist/chat-composer-editor/extensions/mention.js +58 -27
  29. package/dist/chat-composer-editor/ghost.js +2 -4
  30. package/dist/chat-composer-editor/types.d.ts +5 -0
  31. package/dist/chat-composer-editor.d.ts +1 -1
  32. package/dist/chat-composer-editor.js +71 -28
  33. package/dist/chat-composer.d.ts +13 -32
  34. package/dist/chat-composer.js +54 -13
  35. package/dist/chat-layout.d.ts +19 -0
  36. package/dist/chat-layout.js +96 -32
  37. package/dist/chat-message/social.d.ts +26 -0
  38. package/dist/chat-message/social.js +122 -0
  39. package/dist/chat-message.d.ts +28 -29
  40. package/dist/chat-message.js +106 -25
  41. package/dist/context.d.ts +2 -2
  42. package/dist/context.js +38 -23
  43. package/dist/dynamic-notification-canvas-loop.d.ts +24 -0
  44. package/dist/dynamic-notification-canvas-loop.js +113 -0
  45. package/dist/dynamic-notification-glass.js +23 -114
  46. package/dist/dynamic-notification-liquid.js +14 -118
  47. package/dist/dynamic-notification.d.ts +16 -8
  48. package/dist/dynamic-notification.js +85 -22
  49. package/dist/email/email-brand.d.ts +7 -4
  50. package/dist/email/email-brand.js +9 -6
  51. package/dist/email/email-code.d.ts +3 -2
  52. package/dist/email/email-code.js +11 -9
  53. package/dist/email/email-footer.d.ts +5 -3
  54. package/dist/email/email-footer.js +11 -5
  55. package/dist/email/email.d.ts +31 -9
  56. package/dist/email/email.js +50 -26
  57. package/dist/email/templates.d.ts +10 -9
  58. package/dist/email/templates.js +102 -38
  59. package/dist/email/theme.js +1 -1
  60. package/dist/environment-variables.d.ts +4 -2
  61. package/dist/environment-variables.js +52 -32
  62. package/dist/filter-bar/context.d.ts +32 -0
  63. package/dist/filter-bar/context.js +11 -0
  64. package/dist/filter-bar/editor.d.ts +14 -0
  65. package/dist/filter-bar/editor.js +216 -0
  66. package/dist/filter-bar/model.d.ts +10 -0
  67. package/dist/filter-bar/model.js +57 -0
  68. package/dist/filter-bar/motion.d.ts +10 -0
  69. package/dist/filter-bar/motion.js +84 -0
  70. package/dist/filter-bar/parts.d.ts +19 -0
  71. package/dist/filter-bar/parts.js +244 -0
  72. package/dist/filter-bar/types.d.ts +54 -0
  73. package/dist/filter-bar/types.js +0 -0
  74. package/dist/filter-bar.d.ts +27 -0
  75. package/dist/filter-bar.js +310 -0
  76. package/dist/hooks/use-audio-recorder.js +12 -6
  77. package/dist/hooks/use-chat-composer.d.ts +21 -7
  78. package/dist/hooks/use-chat-composer.js +32 -5
  79. package/dist/hooks/use-chat-message.d.ts +28 -2
  80. package/dist/hooks/use-chat-message.js +41 -10
  81. package/dist/hooks/use-chat-thread-scroll.js +43 -7
  82. package/dist/hooks/use-color-area.d.ts +3 -3
  83. package/dist/hooks/use-color-area.js +13 -12
  84. package/dist/hooks/use-copy-to-clipboard.d.ts +2 -1
  85. package/dist/hooks/use-copy-to-clipboard.js +20 -20
  86. package/dist/hooks/use-dropzone.d.ts +7 -4
  87. package/dist/hooks/use-dropzone.js +34 -3
  88. package/dist/hooks/use-dynamic-notification.d.ts +6 -2
  89. package/dist/hooks/use-dynamic-notification.js +26 -10
  90. package/dist/hooks/use-mobile.d.ts +3 -2
  91. package/dist/hooks/use-mobile.js +8 -4
  92. package/dist/hooks/use-textarea-trigger-menu.js +2 -1
  93. package/dist/hooks/use-trigger-menu.d.ts +54 -0
  94. package/dist/hooks/use-trigger-menu.js +102 -47
  95. package/dist/hooks/use-user-ask.d.ts +2 -0
  96. package/dist/hooks/use-user-ask.js +35 -41
  97. package/dist/inline-attachment.d.ts +6 -2
  98. package/dist/inline-attachment.js +44 -29
  99. package/dist/inline-citation.d.ts +12 -5
  100. package/dist/inline-citation.js +25 -16
  101. package/dist/knob-contracts/audio-recorder-knobs.d.ts +1 -1
  102. package/dist/knob-contracts/audio-recorder-knobs.js +2 -1
  103. package/dist/knob-contracts/audio-visualizer-knobs.d.ts +1 -1
  104. package/dist/knob-contracts/audio-visualizer-knobs.js +2 -1
  105. package/dist/knob-contracts/avatar-knobs.d.ts +1 -1
  106. package/dist/knob-contracts/avatar-knobs.js +6 -1
  107. package/dist/knob-contracts/badge-knobs.d.ts +1 -1
  108. package/dist/knob-contracts/badge-knobs.js +2 -1
  109. package/dist/knob-contracts/breadcrumb-knobs.d.ts +4 -0
  110. package/dist/knob-contracts/breadcrumb-knobs.js +8 -0
  111. package/dist/knob-contracts/button-knobs.d.ts +1 -1
  112. package/dist/knob-contracts/button-knobs.js +1 -0
  113. package/dist/knob-contracts/chat-layout-knobs.d.ts +1 -1
  114. package/dist/knob-contracts/chat-layout-knobs.js +2 -1
  115. package/dist/knob-contracts/chat-message-knobs.d.ts +1 -1
  116. package/dist/knob-contracts/chat-message-knobs.js +8 -1
  117. package/dist/knob-contracts/choice-knobs.d.ts +1 -1
  118. package/dist/knob-contracts/choice-knobs.js +1 -0
  119. package/dist/knob-contracts/code-diff-knobs.d.ts +1 -1
  120. package/dist/knob-contracts/code-diff-knobs.js +2 -0
  121. package/dist/knob-contracts/code-knobs.d.ts +1 -1
  122. package/dist/knob-contracts/code-knobs.js +2 -1
  123. package/dist/knob-contracts/collapsible-knobs.d.ts +1 -1
  124. package/dist/knob-contracts/collapsible-knobs.js +1 -1
  125. package/dist/knob-contracts/dynamic-notification-knobs.d.ts +1 -1
  126. package/dist/knob-contracts/dynamic-notification-knobs.js +2 -0
  127. package/dist/knob-contracts/emoji-picker-knobs.d.ts +4 -0
  128. package/dist/knob-contracts/emoji-picker-knobs.js +10 -0
  129. package/dist/knob-contracts/field-knobs.d.ts +1 -1
  130. package/dist/knob-contracts/field-knobs.js +5 -1
  131. package/dist/knob-contracts/filter-bar-knobs.d.ts +4 -0
  132. package/dist/knob-contracts/filter-bar-knobs.js +15 -0
  133. package/dist/knob-contracts/infinite-canvas-knobs.d.ts +1 -1
  134. package/dist/knob-contracts/infinite-canvas-knobs.js +3 -0
  135. package/dist/knob-contracts/markdown-knobs.d.ts +1 -1
  136. package/dist/knob-contracts/markdown-knobs.js +3 -1
  137. package/dist/knob-contracts/page-layout-knobs.d.ts +1 -1
  138. package/dist/knob-contracts/page-layout-knobs.js +4 -1
  139. package/dist/knob-contracts/popup-knobs.d.ts +1 -1
  140. package/dist/knob-contracts/popup-knobs.js +28 -0
  141. package/dist/knob-contracts/range-knobs.d.ts +1 -1
  142. package/dist/knob-contracts/range-knobs.js +1 -0
  143. package/dist/knob-contracts/rich-tooltip-knobs.d.ts +1 -1
  144. package/dist/knob-contracts/rich-tooltip-knobs.js +2 -1
  145. package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
  146. package/dist/knob-contracts/sidebar-knobs.js +27 -2
  147. package/dist/knob-contracts/spinner-knobs.d.ts +1 -1
  148. package/dist/knob-contracts/spinner-knobs.js +1 -1
  149. package/dist/knob-contracts/stepper-knobs.d.ts +1 -1
  150. package/dist/knob-contracts/stepper-knobs.js +4 -1
  151. package/dist/knob-contracts/switch-knobs.d.ts +1 -1
  152. package/dist/knob-contracts/switch-knobs.js +5 -0
  153. package/dist/knob-contracts/table-of-contents-knobs.d.ts +1 -1
  154. package/dist/knob-contracts/table-of-contents-knobs.js +4 -5
  155. package/dist/knob-contracts/tabs-knobs.d.ts +1 -1
  156. package/dist/knob-contracts/tabs-knobs.js +1 -0
  157. package/dist/knob-contracts/tree-knobs.d.ts +1 -1
  158. package/dist/knob-contracts/tree-knobs.js +2 -1
  159. package/dist/lib/cn.js +0 -4
  160. package/dist/lib/contrast.d.ts +1 -0
  161. package/dist/lib/contrast.js +17 -5
  162. package/dist/lib/dropzone-validation.js +41 -28
  163. package/dist/lib/env-file.d.ts +1 -1
  164. package/dist/lib/env-file.js +5 -5
  165. package/dist/lib/motion.d.ts +4 -0
  166. package/dist/lib/motion.js +15 -0
  167. package/dist/lib/trigger-detect.js +6 -8
  168. package/dist/markdown-block.js +13 -8
  169. package/dist/popup-parts.d.ts +8 -0
  170. package/dist/popup-parts.js +43 -0
  171. package/dist/scripts/contrast-eval.js +5 -4
  172. package/dist/source-badge.js +3 -1
  173. package/dist/styles/code.css +0 -2
  174. package/dist/styles/effects.css +6 -32
  175. package/dist/styles/index.css +14 -8
  176. package/dist/styles/recipes/accordion.css +9 -6
  177. package/dist/styles/recipes/action-bar.css +0 -15
  178. package/dist/styles/recipes/activity.css +5 -11
  179. package/dist/styles/recipes/alert.css +4 -4
  180. package/dist/styles/recipes/audio-recorder.css +15 -3
  181. package/dist/styles/recipes/audio-visualizer.css +13 -2
  182. package/dist/styles/recipes/avatar.css +78 -1
  183. package/dist/styles/recipes/badge.css +14 -4
  184. package/dist/styles/recipes/breadcrumb.css +77 -0
  185. package/dist/styles/recipes/button-group.css +6 -8
  186. package/dist/styles/recipes/button-states.css +66 -0
  187. package/dist/styles/recipes/button.css +26 -85
  188. package/dist/styles/recipes/calendar.css +17 -23
  189. package/dist/styles/recipes/card.css +2 -2
  190. package/dist/styles/recipes/chat-composer-attachment.css +9 -3
  191. package/dist/styles/recipes/chat-composer.css +21 -16
  192. package/dist/styles/recipes/chat-layout.css +64 -2
  193. package/dist/styles/recipes/chat-message-social.css +123 -0
  194. package/dist/styles/recipes/chat-message.css +157 -37
  195. package/dist/styles/recipes/choice.css +25 -21
  196. package/dist/styles/recipes/code-diff.css +51 -26
  197. package/dist/styles/recipes/code.css +44 -18
  198. package/dist/styles/recipes/collapsible.css +43 -1
  199. package/dist/styles/recipes/color-picker-details.css +3 -4
  200. package/dist/styles/recipes/color-picker-values.css +9 -8
  201. package/dist/styles/recipes/color-picker.css +23 -4
  202. package/dist/styles/recipes/context.css +3 -3
  203. package/dist/styles/recipes/dockable-panel.css +18 -7
  204. package/dist/styles/recipes/dropzone.css +7 -8
  205. package/dist/styles/recipes/dynamic-notification-input.css +8 -5
  206. package/dist/styles/recipes/dynamic-notification-motion.css +12 -21
  207. package/dist/styles/recipes/dynamic-notification.css +40 -26
  208. package/dist/styles/recipes/emoji-picker.css +132 -0
  209. package/dist/styles/recipes/empty.css +5 -4
  210. package/dist/styles/recipes/environment-variables.css +4 -15
  211. package/dist/styles/recipes/field-parts.css +89 -21
  212. package/dist/styles/recipes/field.css +83 -26
  213. package/dist/styles/recipes/filter-bar.css +161 -0
  214. package/dist/styles/recipes/gradient-editor.css +18 -7
  215. package/dist/styles/recipes/infinite-canvas.css +51 -4
  216. package/dist/styles/recipes/inline-attachment.css +9 -4
  217. package/dist/styles/recipes/inline-citation.css +10 -4
  218. package/dist/styles/recipes/item.css +23 -9
  219. package/dist/styles/recipes/markdown-block.css +5 -4
  220. package/dist/styles/recipes/markdown.css +68 -26
  221. package/dist/styles/recipes/morphing-panel.css +8 -8
  222. package/dist/styles/recipes/page-layout.css +36 -10
  223. package/dist/styles/recipes/pagination.css +5 -6
  224. package/dist/styles/recipes/phone-input.css +12 -8
  225. package/dist/styles/recipes/popup-controls.css +175 -26
  226. package/dist/styles/recipes/popup-drawer.css +35 -44
  227. package/dist/styles/recipes/popup-lists.css +139 -29
  228. package/dist/styles/recipes/popup-motion.css +4 -45
  229. package/dist/styles/recipes/popup-toast.css +55 -26
  230. package/dist/styles/recipes/popup.css +149 -153
  231. package/dist/styles/recipes/range.css +55 -19
  232. package/dist/styles/recipes/resizable.css +36 -7
  233. package/dist/styles/recipes/rich-tooltip.css +24 -34
  234. package/dist/styles/recipes/scroll-area.css +8 -1
  235. package/dist/styles/recipes/sidebar-menu.css +149 -34
  236. package/dist/styles/recipes/sidebar-parts.css +154 -0
  237. package/dist/styles/recipes/sidebar.css +187 -128
  238. package/dist/styles/recipes/source-badge.css +1 -1
  239. package/dist/styles/recipes/spinner.css +12 -1
  240. package/dist/styles/recipes/stepper.css +31 -13
  241. package/dist/styles/recipes/switch.css +68 -23
  242. package/dist/styles/recipes/table-of-contents.css +49 -41
  243. package/dist/styles/recipes/table.css +14 -10
  244. package/dist/styles/recipes/tabs.css +38 -12
  245. package/dist/styles/recipes/task-list.css +7 -14
  246. package/dist/styles/recipes/thread-rail.css +42 -19
  247. package/dist/styles/recipes/timeline.css +2 -0
  248. package/dist/styles/recipes/toolbar.css +27 -25
  249. package/dist/styles/recipes/track-highlight.css +12 -8
  250. package/dist/styles/recipes/transcript-divider.css +2 -2
  251. package/dist/styles/recipes/tree.css +31 -4
  252. package/dist/styles/recipes/user-ask-details.css +0 -1
  253. package/dist/styles/recipes/user-ask.css +4 -4
  254. package/dist/styles/theme.css +287 -107
  255. package/dist/task-list.d.ts +4 -1
  256. package/dist/task-list.js +24 -8
  257. package/dist/thread-rail.d.ts +1 -1
  258. package/dist/thread-rail.js +61 -19
  259. package/dist/transcript-divider.js +2 -1
  260. package/dist/ui/alert.d.ts +3 -1
  261. package/dist/ui/alert.js +14 -8
  262. package/dist/ui/autocomplete.js +7 -1
  263. package/dist/ui/avatar.d.ts +8 -0
  264. package/dist/ui/avatar.js +23 -3
  265. package/dist/ui/badge.js +1 -1
  266. package/dist/ui/breadcrumb.d.ts +27 -0
  267. package/dist/ui/breadcrumb.js +88 -0
  268. package/dist/ui/button.d.ts +2 -1
  269. package/dist/ui/button.js +1 -1
  270. package/dist/ui/calendar.js +2 -2
  271. package/dist/ui/card.d.ts +3 -1
  272. package/dist/ui/card.js +12 -7
  273. package/dist/ui/checkbox-group.js +1 -1
  274. package/dist/ui/checkbox.d.ts +2 -0
  275. package/dist/ui/code-diff.d.ts +1 -1
  276. package/dist/ui/code-diff.js +71 -27
  277. package/dist/ui/code.d.ts +5 -3
  278. package/dist/ui/code.js +27 -28
  279. package/dist/ui/color-picker.d.ts +5 -2
  280. package/dist/ui/color-picker.js +84 -36
  281. package/dist/ui/combobox-disabled-selection.d.ts +1 -2
  282. package/dist/ui/combobox-disabled-selection.js +7 -8
  283. package/dist/ui/combobox.d.ts +5 -23
  284. package/dist/ui/combobox.js +36 -16
  285. package/dist/ui/command.d.ts +8 -2
  286. package/dist/ui/command.js +39 -15
  287. package/dist/ui/context-menu.js +3 -0
  288. package/dist/ui/dialog.d.ts +2 -1
  289. package/dist/ui/dialog.js +3 -22
  290. package/dist/ui/dockable-panel-geometry.d.ts +1 -0
  291. package/dist/ui/dockable-panel-geometry.js +7 -1
  292. package/dist/ui/dockable-panel.d.ts +9 -6
  293. package/dist/ui/dockable-panel.js +81 -33
  294. package/dist/ui/drawer.d.ts +7 -4
  295. package/dist/ui/drawer.js +35 -22
  296. package/dist/ui/dropdown-menu.js +4 -3
  297. package/dist/ui/dropzone.d.ts +5 -3
  298. package/dist/ui/dropzone.js +78 -17
  299. package/dist/ui/emoji-picker.d.ts +18 -0
  300. package/dist/ui/emoji-picker.js +136 -0
  301. package/dist/ui/empty.d.ts +3 -1
  302. package/dist/ui/empty.js +12 -7
  303. package/dist/ui/field.js +1 -1
  304. package/dist/ui/gradient-editor.d.ts +1 -1
  305. package/dist/ui/gradient-editor.js +37 -21
  306. package/dist/ui/infinite-canvas.d.ts +13 -1
  307. package/dist/ui/infinite-canvas.js +139 -20
  308. package/dist/ui/input-group.d.ts +2 -4
  309. package/dist/ui/input-group.js +13 -14
  310. package/dist/ui/input-otp.d.ts +1 -1
  311. package/dist/ui/input-otp.js +32 -15
  312. package/dist/ui/input.js +11 -2
  313. package/dist/ui/item.d.ts +2 -1
  314. package/dist/ui/item.js +11 -7
  315. package/dist/ui/live-status.d.ts +7 -0
  316. package/dist/ui/live-status.js +17 -0
  317. package/dist/ui/markdown-elements.d.ts +6 -0
  318. package/dist/ui/markdown-elements.js +42 -9
  319. package/dist/ui/menubar.js +2 -2
  320. package/dist/ui/morphing-panel.js +2 -1
  321. package/dist/ui/native-select.d.ts +1 -1
  322. package/dist/ui/native-select.js +24 -11
  323. package/dist/ui/number-field.d.ts +1 -1
  324. package/dist/ui/number-field.js +13 -2
  325. package/dist/ui/page-layout.d.ts +2 -2
  326. package/dist/ui/page-layout.js +2 -4
  327. package/dist/ui/pagination.d.ts +7 -5
  328. package/dist/ui/pagination.js +19 -13
  329. package/dist/ui/phone-input.d.ts +1 -0
  330. package/dist/ui/phone-input.js +56 -58
  331. package/dist/ui/radio-group.d.ts +3 -0
  332. package/dist/ui/radio-group.js +11 -1
  333. package/dist/ui/resizable.d.ts +20 -2
  334. package/dist/ui/resizable.js +130 -8
  335. package/dist/ui/responsive-dialog.d.ts +1 -1
  336. package/dist/ui/responsive-dialog.js +9 -23
  337. package/dist/ui/rich-tooltip.d.ts +10 -4
  338. package/dist/ui/rich-tooltip.js +81 -33
  339. package/dist/ui/scroll-area.d.ts +4 -1
  340. package/dist/ui/scroll-area.js +44 -28
  341. package/dist/ui/select.d.ts +2 -1
  342. package/dist/ui/select.js +57 -32
  343. package/dist/ui/sidebar-menu.d.ts +5 -1
  344. package/dist/ui/sidebar-menu.js +31 -33
  345. package/dist/ui/sidebar-provider.d.ts +10 -1
  346. package/dist/ui/sidebar-provider.js +38 -13
  347. package/dist/ui/sidebar-resize-rail.js +7 -3
  348. package/dist/ui/sidebar.d.ts +11 -6
  349. package/dist/ui/sidebar.js +46 -23
  350. package/dist/ui/slider.js +31 -22
  351. package/dist/ui/spinner.d.ts +3 -2
  352. package/dist/ui/spinner.js +3 -2
  353. package/dist/ui/stepper.d.ts +8 -1
  354. package/dist/ui/stepper.js +74 -25
  355. package/dist/ui/switch.d.ts +1 -0
  356. package/dist/ui/table-of-contents.d.ts +5 -4
  357. package/dist/ui/table-of-contents.js +143 -52
  358. package/dist/ui/table.js +15 -9
  359. package/dist/ui/textarea.d.ts +1 -1
  360. package/dist/ui/textarea.js +20 -9
  361. package/dist/ui/timeline.d.ts +3 -1
  362. package/dist/ui/timeline.js +17 -9
  363. package/dist/ui/toast.d.ts +11 -5
  364. package/dist/ui/toast.js +100 -54
  365. package/dist/ui/toggle.d.ts +1 -1
  366. package/dist/ui/toggle.js +2 -1
  367. package/dist/ui/toolbar.d.ts +3 -2
  368. package/dist/ui/toolbar.js +4 -2
  369. package/dist/ui/tooltip.js +3 -20
  370. package/dist/ui/tree.js +120 -80
  371. package/dist/ui/trigger-menu.js +7 -2
  372. package/dist/user-ask.d.ts +10 -5
  373. package/dist/user-ask.js +31 -11
  374. package/package.json +5 -1
  375. package/dist/hooks/use-keyboard-navigation.d.ts +0 -3
  376. package/dist/hooks/use-keyboard-navigation.js +0 -22
@@ -1,17 +1,9 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
- import { TrackHighlight } from "../extensions/track-highlight.js";
4
- import { useEffect, useState } from "react";
3
+ import { useEffect, useRef, useState, useSyncExternalStore } from "react";
5
4
  import { jsx, jsxs } from "react/jsx-runtime";
6
5
  //#region src/ui/table-of-contents.tsx
7
- const tableOfContentsVariants = [
8
- "background",
9
- "trail",
10
- "both"
11
- ];
12
- const DETECTION_MARGIN = "-80px 0px -20% 0px";
13
- const TOC_ITEM_SELECTOR = "[data-control-ui=\"table-of-contents\"][data-slot=\"item\"]";
14
- const TOC_ACTIVE_SELECTOR = "[data-control-ui=\"table-of-contents\"][data-slot=\"item\"][data-active]";
6
+ const tableOfContentsVariants = ["range", "progress"];
15
7
  function getScrollContainer(el) {
16
8
  let node = el.parentElement;
17
9
  while (node) {
@@ -20,7 +12,7 @@ function getScrollContainer(el) {
20
12
  }
21
13
  return null;
22
14
  }
23
- function useVisibleSections(ids) {
15
+ function useVisibleSections(ids, knobSourceRef) {
24
16
  const [visibleState, setVisibleState] = useState({
25
17
  idsKey: "",
26
18
  visibleIds: []
@@ -30,6 +22,8 @@ function useVisibleSections(ids) {
30
22
  const elements = (idsKey ? idsKey.split("|") : []).map((id) => document.getElementById(id)).filter((el) => el !== null);
31
23
  const firstElement = elements[0];
32
24
  if (!firstElement) return;
25
+ const knobSource = knobSourceRef.current;
26
+ const scrollInset = knobSource ? readLengthKnob(getComputedStyle(knobSource), "--cui-table-of-contents-scroll-inset") : 0;
33
27
  const order = new Map(elements.map((el, index) => [el.id, index]));
34
28
  const visible = /* @__PURE__ */ new Set();
35
29
  const observer = new IntersectionObserver((entries) => {
@@ -41,14 +35,21 @@ function useVisibleSections(ids) {
41
35
  });
42
36
  }, {
43
37
  root: getScrollContainer(firstElement),
44
- rootMargin: DETECTION_MARGIN,
38
+ rootMargin: `-${scrollInset}px 0px -20% 0px`,
45
39
  threshold: 0
46
40
  });
47
41
  for (const el of elements) observer.observe(el);
48
42
  return () => observer.disconnect();
49
- }, [idsKey]);
43
+ }, [idsKey, knobSourceRef]);
50
44
  return visibleState.idsKey === idsKey ? visibleState.visibleIds : [];
51
45
  }
46
+ function subscribeToHash(onChange) {
47
+ window.addEventListener("hashchange", onChange);
48
+ return () => window.removeEventListener("hashchange", onChange);
49
+ }
50
+ function useLocationHash() {
51
+ return useSyncExternalStore(subscribeToHash, () => window.location.hash, () => "");
52
+ }
52
53
  function collectLevels(items, fallbackLevel = 2) {
53
54
  return items.flatMap((item) => {
54
55
  const level = item.level ?? fallbackLevel;
@@ -72,22 +73,98 @@ function normalizeItems(items, baseLevel, fallbackLevel = 2, nestingDepth = 0) {
72
73
  function flattenItems(items) {
73
74
  return items.flatMap((item) => [item, ...flattenItems(item.children ?? [])]);
74
75
  }
75
- function activeIdsInRange(visibleIds, targetIds) {
76
- let firstIndex = targetIds.length;
77
- let lastIndex = -1;
78
- for (const id of visibleIds) {
79
- const index = targetIds.indexOf(id);
80
- if (index < 0) continue;
81
- firstIndex = Math.min(firstIndex, index);
82
- lastIndex = Math.max(lastIndex, index);
76
+ function findActiveItems(visibleIds, flatItems, targetIds) {
77
+ const indexes = visibleIds.map((id) => targetIds.indexOf(id)).filter((index) => index >= 0);
78
+ if (indexes.length === 0) return [];
79
+ return flatItems.slice(Math.min(...indexes), Math.max(...indexes) + 1);
80
+ }
81
+ function readLengthKnob(style, knob) {
82
+ return Number.parseFloat(style.getPropertyValue(knob)) || 0;
83
+ }
84
+ function inDocumentOrder([, a], [, b]) {
85
+ return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
86
+ }
87
+ function measureRail(track, itemElements) {
88
+ const style = getComputedStyle(track);
89
+ const indentSize = readLengthKnob(style, "--cui-table-of-contents-item-indent-size");
90
+ const strokeInset = Math.max(readLengthKnob(style, "--cui-table-of-contents-rail-size"), readLengthKnob(style, "--cui-table-of-contents-trail-size")) / 2;
91
+ const isRtl = style.direction === "rtl";
92
+ const points = [];
93
+ let length = 0;
94
+ const lineTo = (x, y) => {
95
+ const previous = points.at(-1);
96
+ if (previous) length += Math.hypot(x - previous.x, y - previous.y);
97
+ points.push({
98
+ x,
99
+ y
100
+ });
101
+ return length;
102
+ };
103
+ const stops = /* @__PURE__ */ new Map();
104
+ for (const [href, item] of [...itemElements].sort(inDocumentOrder)) {
105
+ const inlineOffset = Number(item.dataset.depth) * indentSize + strokeInset;
106
+ const x = isRtl ? track.clientWidth - inlineOffset : inlineOffset;
107
+ const top = item.offsetTop;
108
+ const previous = points.at(-1);
109
+ const topStop = lineTo(previous?.x ?? x, top);
110
+ if (previous && previous.x !== x) lineTo(x, top + Math.min(indentSize, item.offsetHeight / 2));
111
+ stops.set(href, {
112
+ top: topStop,
113
+ center: lineTo(x, top + item.offsetHeight / 2),
114
+ bottom: lineTo(x, top + item.offsetHeight)
115
+ });
83
116
  }
84
- if (lastIndex < 0) return /* @__PURE__ */ new Set();
85
- return new Set(targetIds.slice(firstIndex, lastIndex + 1));
117
+ return {
118
+ path: points.map(({ x, y }, index) => `${index === 0 ? "M" : "L"}${x} ${y}`).join(""),
119
+ length,
120
+ stops
121
+ };
122
+ }
123
+ function useRailGeometry(trackRef, itemElements) {
124
+ const [rail, setRail] = useState(null);
125
+ useEffect(() => {
126
+ const track = trackRef.current;
127
+ if (!track) return;
128
+ const measure = () => setRail(measureRail(track, itemElements));
129
+ const resizeObserver = new ResizeObserver(measure);
130
+ const mutationObserver = new MutationObserver(measure);
131
+ resizeObserver.observe(track);
132
+ mutationObserver.observe(track, {
133
+ subtree: true,
134
+ childList: true,
135
+ attributeFilter: ["data-depth"]
136
+ });
137
+ return () => {
138
+ resizeObserver.disconnect();
139
+ mutationObserver.disconnect();
140
+ };
141
+ }, [trackRef, itemElements]);
142
+ return rail;
86
143
  }
87
- function TableOfContents({ items, label = "On this page", variant = "both", className, style, ...props }) {
144
+ function trailStyle(rail, activeItems, variant) {
145
+ const firstStop = rail.stops.get(activeItems[0]?.href ?? "");
146
+ const lastStop = rail.stops.get(activeItems.at(-1)?.href ?? "");
147
+ const start = variant === "progress" ? 0 : firstStop?.top ?? 0;
148
+ const end = variant === "progress" ? firstStop?.center ?? 0 : lastStop?.bottom ?? 0;
149
+ return {
150
+ "--_toc-rail-length": `${rail.length}px`,
151
+ "--_toc-trail-start": `${start}px`,
152
+ "--_toc-trail-length": `${Math.max(0, end - start)}px`,
153
+ "--_toc-indicator-distance": `${firstStop?.center ?? 0}px`
154
+ };
155
+ }
156
+ function TableOfContents({ items, label = "On this page", variant = "range", indicator, className, style, ...props }) {
157
+ const trackRef = useRef(null);
158
+ const [itemElements] = useState(() => /* @__PURE__ */ new Map());
88
159
  const normalizedItems = normalizeItems(items, Math.min(...collectLevels(items), 2));
89
- const targetIds = flattenItems(normalizedItems).map((item) => item.href.replace(/^#/, ""));
90
- const activeSet = activeIdsInRange(useVisibleSections(targetIds), targetIds);
160
+ const flatItems = flattenItems(normalizedItems);
161
+ const targetIds = flatItems.map((item) => item.href.replace(/^#/, ""));
162
+ const activeItems = findActiveItems(useVisibleSections(targetIds, trackRef), flatItems, targetIds);
163
+ const activeHrefs = new Set(activeItems.map((item) => item.href));
164
+ const locationHash = useLocationHash();
165
+ const currentHref = activeHrefs.has(locationHash) ? locationHash : activeItems[0]?.href;
166
+ const rail = useRailGeometry(trackRef, itemElements);
167
+ const hasActiveSection = activeItems.length > 0;
91
168
  if (items.length === 0) return null;
92
169
  return /* @__PURE__ */ jsxs("nav", {
93
170
  "data-control-ui": "table-of-contents",
@@ -104,69 +181,83 @@ function TableOfContents({ items, label = "On this page", variant = "both", clas
104
181
  "data-slot": "label",
105
182
  children: label
106
183
  }), /* @__PURE__ */ jsxs("div", {
184
+ ref: trackRef,
107
185
  "data-control-ui": "table-of-contents",
108
186
  "data-control-family": "table-of-contents",
109
187
  "data-slot": "track",
110
- className: "relative isolate",
188
+ className: "relative",
189
+ style: rail ? trailStyle(rail, activeItems, variant) : void 0,
111
190
  children: [
112
- /* @__PURE__ */ jsx("span", {
191
+ rail && /* @__PURE__ */ jsxs("svg", {
113
192
  "aria-hidden": true,
114
- "data-control-ui": "table-of-contents",
115
- "data-control-family": "table-of-contents",
116
- "data-slot": "rail",
117
- className: "pointer-events-none absolute inset-y-0 start-0 -z-20"
118
- }),
119
- /* @__PURE__ */ jsx(TrackHighlight, {
120
- "data-variant": variant,
121
- itemSelector: TOC_ITEM_SELECTOR,
122
- activeSelector: TOC_ACTIVE_SELECTOR,
123
- range: true,
124
- followHover: false,
125
- children: variant !== "background" && /* @__PURE__ */ jsx("div", {
126
- "aria-hidden": true,
193
+ className: "pointer-events-none absolute inset-0 size-full overflow-visible",
194
+ children: [/* @__PURE__ */ jsx("path", {
195
+ "data-control-ui": "table-of-contents",
196
+ "data-control-family": "table-of-contents",
197
+ "data-slot": "rail",
198
+ d: rail.path
199
+ }), /* @__PURE__ */ jsx("path", {
127
200
  "data-control-ui": "table-of-contents",
128
201
  "data-control-family": "table-of-contents",
129
202
  "data-slot": "trail",
130
- className: "absolute inset-y-0 start-0"
131
- })
203
+ "data-visible": hasActiveSection || void 0,
204
+ d: rail.path
205
+ })]
132
206
  }),
133
207
  /* @__PURE__ */ jsx(TocList, {
134
208
  items: normalizedItems,
135
- activeSet,
136
- variant,
209
+ activeHrefs,
210
+ currentHref,
211
+ itemElements,
137
212
  root: true
213
+ }),
214
+ rail && indicator && /* @__PURE__ */ jsx("span", {
215
+ "aria-hidden": true,
216
+ "data-control-ui": "table-of-contents",
217
+ "data-control-family": "table-of-contents",
218
+ "data-slot": "indicator",
219
+ "data-visible": hasActiveSection || void 0,
220
+ className: "pointer-events-none absolute top-0 left-0",
221
+ style: { offsetPath: `path("${rail.path}")` },
222
+ children: indicator
138
223
  })
139
224
  ]
140
225
  })]
141
226
  });
142
227
  }
143
- function TocList({ items, activeSet, variant, root = false }) {
228
+ function TocList({ items, activeHrefs, currentHref, itemElements, root = false }) {
144
229
  return /* @__PURE__ */ jsx("ul", {
145
230
  "data-control-ui": "table-of-contents",
146
231
  "data-control-family": "table-of-contents",
147
232
  "data-slot": "list",
148
233
  "data-nested": root ? void 0 : "true",
149
234
  children: items.map((item) => {
150
- const targetId = item.href.replace(/^#/, "");
151
- const isActive = activeSet.has(targetId);
235
+ const isActive = activeHrefs.has(item.href);
152
236
  const itemStyle = { "--_toc-depth": item.depth };
153
237
  return /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsx("a", {
238
+ ref: (element) => {
239
+ if (!element) return;
240
+ itemElements.set(item.href, element);
241
+ return () => {
242
+ itemElements.delete(item.href);
243
+ };
244
+ },
154
245
  "data-control-ui": "table-of-contents",
155
246
  "data-control-family": "table-of-contents",
156
247
  "data-slot": "item",
157
248
  "data-active": isActive || void 0,
158
- "data-variant": variant,
159
249
  "data-level": item.level,
160
250
  "data-depth": item.depth,
161
- "aria-current": isActive ? "location" : void 0,
251
+ "aria-current": item.href === currentHref ? "location" : void 0,
162
252
  href: item.href,
163
253
  className: "block",
164
254
  style: itemStyle,
165
255
  children: item.label
166
256
  }), item.children && /* @__PURE__ */ jsx(TocList, {
167
257
  items: item.children,
168
- activeSet,
169
- variant
258
+ activeHrefs,
259
+ currentHref,
260
+ itemElements
170
261
  })] }, item.href);
171
262
  })
172
263
  });
package/dist/ui/table.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { cn } from "../lib/cn.js";
2
+ import { ScrollArea } from "./scroll-area.js";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  //#region src/ui/table.tsx
4
5
  function Table({ className, ...props }) {
@@ -6,13 +7,18 @@ function Table({ className, ...props }) {
6
7
  "data-control-ui": "table",
7
8
  "data-control-family": "table",
8
9
  "data-slot": "container",
9
- className: "relative w-full overflow-x-auto",
10
- children: /* @__PURE__ */ jsx("table", {
11
- "data-control-ui": "table",
12
- "data-control-family": "table",
13
- "data-slot": "root",
14
- className: cn("w-full caption-bottom", className),
15
- ...props
10
+ className: "relative w-full",
11
+ children: /* @__PURE__ */ jsx(ScrollArea, {
12
+ lockAxis: "y",
13
+ "aria-label": props["aria-label"],
14
+ "aria-labelledby": props["aria-labelledby"],
15
+ children: /* @__PURE__ */ jsx("table", {
16
+ "data-control-ui": "table",
17
+ "data-control-family": "table",
18
+ "data-slot": "root",
19
+ className: cn("w-full caption-bottom", className),
20
+ ...props
21
+ })
16
22
  })
17
23
  });
18
24
  }
@@ -57,7 +63,7 @@ function TableHead({ className, ...props }) {
57
63
  "data-control-ui": "table",
58
64
  "data-control-family": "table",
59
65
  "data-slot": "head",
60
- className: cn("whitespace-nowrap align-middle [&:has([role=checkbox])]:pr-0", className),
66
+ className: cn("whitespace-nowrap align-middle [&:has([role=checkbox])]:pe-0", className),
61
67
  ...props
62
68
  });
63
69
  }
@@ -66,7 +72,7 @@ function TableCell({ className, ...props }) {
66
72
  "data-control-ui": "table",
67
73
  "data-control-family": "table",
68
74
  "data-slot": "cell",
69
- className: cn("whitespace-nowrap align-middle [&:has([role=checkbox])]:pr-0", className),
75
+ className: cn("whitespace-nowrap align-middle [&:has([role=checkbox])]:pe-0", className),
70
76
  ...props
71
77
  });
72
78
  }
@@ -4,5 +4,5 @@ import { CSSProperties, ComponentProps } from "react";
4
4
  export type TextareaProps = Omit<ComponentProps<"textarea">, "style"> & {
5
5
  style?: CSSProperties & FieldKnobStyle;
6
6
  };
7
- export declare function Textarea({ className, ...props }: TextareaProps): import("react").JSX.Element;
7
+ export declare function Textarea({ ref, id, name, value, defaultValue, disabled, autoFocus, className, ...props }: TextareaProps): import("react").JSX.Element;
8
8
  //#endregion
@@ -1,15 +1,26 @@
1
+ "use client";
1
2
  import { cn } from "../lib/cn.js";
2
3
  import { jsx } from "react/jsx-runtime";
4
+ import { Input } from "@base-ui/react/input";
3
5
  //#region src/ui/textarea.tsx
4
- function Textarea({ className, ...props }) {
5
- return /* @__PURE__ */ jsx("textarea", {
6
- "data-control-ui": "textarea",
7
- "data-field-kind": "textarea",
8
- "data-slot": "root",
9
- "data-control-family": "field",
10
- "data-control": "true",
11
- className: cn("field-sizing-content w-full min-w-0 resize-none", className),
12
- ...props
6
+ function Textarea({ ref, id, name, value, defaultValue, disabled, autoFocus, className, ...props }) {
7
+ return /* @__PURE__ */ jsx(Input, {
8
+ ref,
9
+ id,
10
+ name,
11
+ value,
12
+ defaultValue,
13
+ disabled,
14
+ autoFocus,
15
+ render: /* @__PURE__ */ jsx("textarea", {
16
+ ...props,
17
+ "data-control-ui": "textarea",
18
+ "data-field-kind": "textarea",
19
+ "data-slot": "root",
20
+ "data-control-family": "field",
21
+ "data-control": "true",
22
+ className: cn("field-sizing-content w-full min-w-0 resize-none", className)
23
+ })
13
24
  });
14
25
  }
15
26
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { RenderProp } from "../control-props.js";
1
2
  import { TimelineKnobStyle } from "../knob-contracts/timeline-knobs.js";
2
3
  import { CSSProperties, ComponentProps } from "react";
3
4
  //#region src/ui/timeline.d.ts
@@ -20,6 +21,7 @@ export type TimelineContentProps = ComponentProps<"div"> & {
20
21
  style?: CSSProperties & TimelineKnobStyle;
21
22
  };
22
23
  export type TimelineTitleProps = Omit<ComponentProps<"div">, "style"> & {
24
+ render?: RenderProp<ComponentProps<"div">>;
23
25
  style?: CSSProperties & TimelineKnobStyle;
24
26
  };
25
27
  export type TimelineDescriptionProps = Omit<ComponentProps<"div">, "style"> & {
@@ -33,7 +35,7 @@ export declare function TimelineItem({ state, className, ...props }: TimelineIte
33
35
  export declare function TimelineIndicator({ className, ...props }: TimelineIndicatorProps): import("react").JSX.Element;
34
36
  export declare function TimelineSeparator({ className, ...props }: TimelineSeparatorProps): import("react").JSX.Element;
35
37
  export declare function TimelineContent({ className, ...props }: TimelineContentProps): import("react").JSX.Element;
36
- export declare function TimelineTitle({ className, ...props }: TimelineTitleProps): import("react").JSX.Element;
38
+ export declare function TimelineTitle({ render, className, ...props }: TimelineTitleProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
37
39
  export declare function TimelineDescription({ className, ...props }: TimelineDescriptionProps): import("react").JSX.Element;
38
40
  export declare function TimelineMeta({ className, ...props }: TimelineMetaProps): import("react").JSX.Element;
39
41
  //#endregion
@@ -1,4 +1,6 @@
1
+ "use client";
1
2
  import { cn } from "../lib/cn.js";
3
+ import { useRender } from "@base-ui/react/use-render";
2
4
  import { jsx } from "react/jsx-runtime";
3
5
  //#region src/ui/timeline.tsx
4
6
  function Timeline({ className, ...props }) {
@@ -16,13 +18,15 @@ function TimelineItem({ state = "neutral", className, ...props }) {
16
18
  "data-control-family": "timeline",
17
19
  "data-slot": "item",
18
20
  "data-state": state,
21
+ "aria-current": state === "running" ? "step" : void 0,
19
22
  ...props,
20
23
  className: cn("group/timeline-item relative grid min-w-0 grid-cols-[1rem_minmax(0,1fr)]", className)
21
24
  });
22
25
  }
23
26
  function TimelineIndicator({ className, ...props }) {
24
27
  return /* @__PURE__ */ jsx("span", {
25
- "aria-hidden": "true",
28
+ role: props["aria-label"] ? "img" : void 0,
29
+ "aria-hidden": props["aria-label"] ? void 0 : true,
26
30
  "data-control-ui": "timeline",
27
31
  "data-control-family": "timeline",
28
32
  "data-slot": "indicator",
@@ -37,7 +41,7 @@ function TimelineSeparator({ className, ...props }) {
37
41
  "data-control-family": "timeline",
38
42
  "data-slot": "separator",
39
43
  ...props,
40
- className: cn("absolute top-5 bottom-0 left-[calc(0.5rem-0.5px)] col-start-1 w-px group-last/timeline-item:hidden", className)
44
+ className: cn("absolute top-5 bottom-0 start-[calc(0.5rem-0.5px)] col-start-1 w-px group-last/timeline-item:hidden", className)
41
45
  });
42
46
  }
43
47
  function TimelineContent({ className, ...props }) {
@@ -49,13 +53,17 @@ function TimelineContent({ className, ...props }) {
49
53
  className: cn("col-start-2 row-start-1 grid min-w-0", className)
50
54
  });
51
55
  }
52
- function TimelineTitle({ className, ...props }) {
53
- return /* @__PURE__ */ jsx("div", {
54
- "data-control-ui": "timeline",
55
- "data-control-family": "timeline",
56
- "data-slot": "title",
57
- ...props,
58
- className: cn("min-w-0", className)
56
+ function TimelineTitle({ render, className, ...props }) {
57
+ return useRender({
58
+ defaultTagName: "div",
59
+ render,
60
+ props: {
61
+ ...props,
62
+ "data-control-ui": "timeline",
63
+ "data-control-family": "timeline",
64
+ "data-slot": "title",
65
+ className: cn("min-w-0", className)
66
+ }
59
67
  });
60
68
  }
61
69
  function TimelineDescription({ className, ...props }) {
@@ -1,7 +1,7 @@
1
1
  import { ButtonProps } from "./button.js";
2
2
  import { PopupKnobStyle } from "../knob-contracts/popup-knobs.js";
3
3
  import { CSSProperties, ReactNode } from "react";
4
- import { Toast } from "@base-ui/react/toast";
4
+ import { Toast, ToastManagerAddOptions, ToastManagerPromiseOptions } from "@base-ui/react/toast";
5
5
  //#region src/ui/toast.d.ts
6
6
  export type ToasterProps = {
7
7
  className?: string;
@@ -11,18 +11,24 @@ export type ToasterProps = {
11
11
  indicatorStyle?: CSSProperties & PopupKnobStyle;
12
12
  actionStyle?: ButtonProps["style"];
13
13
  closeStyle?: ButtonProps["style"];
14
+ closeLabel?: string;
15
+ successLabel?: string;
16
+ errorLabel?: string;
17
+ warningLabel?: string;
18
+ infoLabel?: string;
14
19
  };
15
20
  export declare const toastManager: import("@base-ui/react").ToastManager<any>;
16
- type ToastOptions = Omit<Parameters<typeof toastManager.add>[0], "title">;
17
- export declare const toast: ((title: ReactNode, options?: ToastOptions) => string) & {
21
+ type ToastOptions = Omit<ToastManagerAddOptions<object>, "title">;
22
+ declare function show(title: ReactNode, options?: ToastOptions): string;
23
+ export declare const toast: typeof show & {
18
24
  success: (title: ReactNode, options?: ToastOptions) => string;
19
25
  error: (title: ReactNode, options?: ToastOptions) => string;
20
26
  warning: (title: ReactNode, options?: ToastOptions) => string;
21
27
  info: (title: ReactNode, options?: ToastOptions) => string;
22
28
  message: (title: ReactNode, options?: ToastOptions) => string;
23
- promise: (...args: Parameters<typeof toastManager.promise>) => Promise<unknown>;
29
+ promise: <Value>(promise: Promise<Value>, options: ToastManagerPromiseOptions<Value, object>) => Promise<Value>;
24
30
  dismiss: (id?: string) => void;
25
31
  };
26
32
  export declare const useToast: typeof Toast.useToastManager;
27
- export declare function Toaster({ className, timeout, limit, rootStyle, indicatorStyle, actionStyle, closeStyle }: ToasterProps): import("react").JSX.Element;
33
+ export declare function Toaster({ className, timeout, limit, rootStyle, indicatorStyle, actionStyle, closeStyle, closeLabel, successLabel, errorLabel, warningLabel, infoLabel }: ToasterProps): import("react").JSX.Element;
28
34
  //#endregion