@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
@@ -6,10 +6,10 @@ import { Button } from "./button.js";
6
6
  import { Input } from "./input.js";
7
7
  import { useColorArea } from "../hooks/use-color-area.js";
8
8
  import { formatColor, getChannels, hsvaToRgba, parseColor, pointToHueSat, pointToSaturationValue, setChannel } from "../lib/color.js";
9
- import { TARGET_RATIO, contrastOf, fixColorForContrast, nextFixLevel, wcagLevels } from "../lib/contrast.js";
9
+ import { TARGET_RATIO, contrastOf, fixColorForContrast, formatContrastRatio, nextFixLevel, wcagLevels } from "../lib/contrast.js";
10
10
  import { NumberField, NumberFieldGroup, NumberFieldInput } from "./number-field.js";
11
11
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select.js";
12
- import { createContext, useContext, useEffect, useRef, useState, useSyncExternalStore } from "react";
12
+ import { createContext, useContext, useEffect, useId, useRef, useState, useSyncExternalStore } from "react";
13
13
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
14
14
  import { Popover } from "@base-ui/react/popover";
15
15
  import { Slider } from "@base-ui/react/slider";
@@ -111,8 +111,9 @@ function useColorState(props) {
111
111
  const setChannelValue = (id, next) => commit(setChannel(hsvaRef.current, id, next));
112
112
  const setFromString = (raw) => {
113
113
  const parsed = parseColor(raw);
114
- if (!parsed) return;
114
+ if (!parsed) return false;
115
115
  commit(reconcileAchromatic(hsvaRef.current, parsed));
116
+ return true;
116
117
  };
117
118
  const setFormat = (next) => {
118
119
  if (formatProp === void 0) setFormatState(next);
@@ -241,6 +242,7 @@ function ColorPickerArea({ className, style, ...props }) {
241
242
  setHsva(axis === "s" ? { s: next } : { v: next });
242
243
  }
243
244
  return /* @__PURE__ */ jsxs("div", {
245
+ "data-focus-ring": "within",
244
246
  ref: areaRef,
245
247
  "data-control-ui": "color-picker",
246
248
  "data-control-family": "color-picker",
@@ -318,6 +320,10 @@ function ColorPickerHue({ className, "aria-label": ariaLabel, "aria-labelledby":
318
320
  "data-control-ui": "color-picker",
319
321
  "data-control-family": "color-picker",
320
322
  "data-slot": "hue",
323
+ format: {
324
+ style: "unit",
325
+ unit: "degree"
326
+ },
321
327
  "aria-label": ariaLabelledBy === void 0 ? ariaLabel ?? "Hue" : ariaLabel,
322
328
  "aria-labelledby": ariaLabelledBy,
323
329
  value: hsva.h,
@@ -340,6 +346,7 @@ function ColorPickerHue({ className, "aria-label": ariaLabel, "aria-labelledby":
340
346
  "data-control-ui": "color-picker",
341
347
  "data-control-family": "color-picker",
342
348
  "data-slot": "hue-thumb",
349
+ "data-focus-ring": "within",
343
350
  className: RING_THUMB
344
351
  })
345
352
  })
@@ -360,6 +367,7 @@ function ColorPickerAlpha({ className, "aria-label": ariaLabel, "aria-labelledby
360
367
  "aria-label": ariaLabelledBy === void 0 ? ariaLabel ?? "Opacity" : ariaLabel,
361
368
  "aria-labelledby": ariaLabelledBy,
362
369
  value: hsva.a,
370
+ format: { style: "percent" },
363
371
  min: 0,
364
372
  max: 1,
365
373
  step: .01,
@@ -382,6 +390,7 @@ function ColorPickerAlpha({ className, "aria-label": ariaLabel, "aria-labelledby
382
390
  "data-control-ui": "color-picker",
383
391
  "data-control-family": "color-picker",
384
392
  "data-slot": "alpha-thumb",
393
+ "data-focus-ring": "within",
385
394
  className: RING_THUMB
386
395
  })
387
396
  })
@@ -404,6 +413,7 @@ function ColorPickerWheel({ className, style, ...props }) {
404
413
  const left = 50 + radius * Math.cos(rad);
405
414
  const top = 50 + radius * Math.sin(rad);
406
415
  return /* @__PURE__ */ jsxs("div", {
416
+ "data-focus-ring": "within",
407
417
  ref: areaRef,
408
418
  "data-control-ui": "color-picker",
409
419
  "data-control-family": "color-picker",
@@ -456,38 +466,62 @@ function ColorPickerWheel({ className, style, ...props }) {
456
466
  ]
457
467
  });
458
468
  }
459
- function ColorPickerInput({ size = "sm", className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }) {
469
+ function ColorPickerInput({ size = "sm", className, invalidLabel = "Enter a hex, rgb(), hsl() or oklch() color.", "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, onFocus, onBlur, onKeyDown, ...props }) {
460
470
  const { valueString, setFromString, disabled } = useColorPicker();
471
+ const invalidMessageId = useId();
461
472
  const [draft, setDraft] = useState(valueString);
462
473
  const [editing, setEditing] = useState(false);
474
+ const [invalid, setInvalid] = useState(false);
475
+ const describedBy = [ariaDescribedBy, invalid ? invalidMessageId : void 0].filter(Boolean).join(" ") || void 0;
463
476
  const shown = editing ? draft : valueString;
464
477
  const commit = () => {
465
- setFromString(draft);
478
+ const accepted = setFromString(draft);
479
+ setInvalid(!accepted);
480
+ if (accepted) setEditing(false);
481
+ };
482
+ const revert = () => {
483
+ setInvalid(false);
466
484
  setEditing(false);
467
485
  };
468
- return /* @__PURE__ */ jsx(Input, {
469
- size,
470
- value: shown,
471
- disabled,
486
+ return /* @__PURE__ */ jsxs("span", {
472
487
  "data-control-ui": "color-picker",
473
488
  "data-control-family": "color-picker",
474
489
  "data-slot": "input",
475
- spellCheck: false,
476
- autoComplete: "off",
477
- "aria-label": ariaLabelledBy === void 0 ? ariaLabel ?? "Color value" : ariaLabel,
478
- "aria-labelledby": ariaLabelledBy,
479
- className,
480
- onFocus: () => {
481
- setDraft(valueString);
482
- setEditing(true);
483
- },
484
- onChange: (event) => setDraft(event.target.value),
485
- onBlur: commit,
486
- onKeyDown: (event) => {
487
- if (event.key === "Enter") commit();
488
- else if (event.key === "Escape") setEditing(false);
489
- },
490
- ...props
490
+ className: "contents",
491
+ children: [/* @__PURE__ */ jsx(Input, {
492
+ ...props,
493
+ size,
494
+ value: shown,
495
+ disabled,
496
+ spellCheck: false,
497
+ autoComplete: "off",
498
+ "aria-label": ariaLabelledBy === void 0 ? ariaLabel ?? "Color value" : ariaLabel,
499
+ "aria-labelledby": ariaLabelledBy,
500
+ "aria-invalid": invalid || void 0,
501
+ "aria-describedby": describedBy,
502
+ className,
503
+ onFocus: (event) => {
504
+ onFocus?.(event);
505
+ if (editing) return;
506
+ setDraft(valueString);
507
+ setEditing(true);
508
+ },
509
+ onChange: (event) => setDraft(event.target.value),
510
+ onBlur: (event) => {
511
+ onBlur?.(event);
512
+ commit();
513
+ },
514
+ onKeyDown: (event) => {
515
+ onKeyDown?.(event);
516
+ if (event.defaultPrevented) return;
517
+ if (event.key === "Enter") commit();
518
+ else if (event.key === "Escape") revert();
519
+ }
520
+ }), invalid ? /* @__PURE__ */ jsx("span", {
521
+ id: invalidMessageId,
522
+ className: "sr-only",
523
+ children: invalidLabel
524
+ }) : null]
491
525
  });
492
526
  }
493
527
  function ColorPickerFormatSelect({ formats = [
@@ -617,7 +651,7 @@ function ColorPickerSwatches({ colors, label, className, children, ...props }) {
617
651
  });
618
652
  }
619
653
  function ColorPickerSwatch({ color, className, "aria-label": ariaLabel, ...props }) {
620
- const { setFromString, valueString } = useColorPicker();
654
+ const { setFromString, valueString, disabled } = useColorPicker();
621
655
  const selected = sameColor(valueString, color);
622
656
  return /* @__PURE__ */ jsxs("button", {
623
657
  type: "button",
@@ -628,8 +662,9 @@ function ColorPickerSwatch({ color, className, "aria-label": ariaLabel, ...props
628
662
  "aria-pressed": selected,
629
663
  "aria-label": ariaLabel ?? `Set color ${color}`,
630
664
  title: color,
665
+ disabled,
631
666
  onClick: () => setFromString(color),
632
- className: cn("relative shrink-0 cursor-pointer overflow-hidden", className),
667
+ className: cn("relative shrink-0 cursor-pointer overflow-hidden disabled:cursor-not-allowed", className),
633
668
  ...props,
634
669
  children: [/* @__PURE__ */ jsx("span", {
635
670
  "data-control-ui": "color-picker",
@@ -652,21 +687,22 @@ function ColorPickerSwatch({ color, className, "aria-label": ariaLabel, ...props
652
687
  });
653
688
  }
654
689
  function ColorPickerSwatchAdd({ onAdd, className, children, ...props }) {
655
- const { valueString } = useColorPicker();
690
+ const { valueString, disabled } = useColorPicker();
656
691
  return /* @__PURE__ */ jsx("button", {
657
692
  type: "button",
658
693
  "data-control-ui": "color-picker",
659
694
  "data-control-family": "color-picker",
660
695
  "data-slot": "swatch-add",
661
696
  "aria-label": "Add current color",
697
+ disabled,
662
698
  onClick: () => onAdd?.(valueString),
663
- className: cn("flex shrink-0 cursor-pointer items-center justify-center", className),
699
+ className: cn("relative flex shrink-0 cursor-pointer items-center justify-center disabled:cursor-not-allowed", className),
664
700
  ...props,
665
701
  children: children ?? /* @__PURE__ */ jsx(PlusIcon, {})
666
702
  });
667
703
  }
668
- function ColorPickerContrast({ background = "#ffffff", className, ...props }) {
669
- const { hsva, setFromString } = useColorPicker();
704
+ function ColorPickerContrast({ background = "#ffffff", passLabel = "Passes", failLabel = "Fails", className, ...props }) {
705
+ const { hsva, setFromString, disabled } = useColorPicker();
670
706
  const bg = parseColor(background);
671
707
  if (!bg) return null;
672
708
  const bgRgba = hsvaToRgba(bg);
@@ -689,14 +725,18 @@ function ColorPickerContrast({ background = "#ffffff", className, ...props }) {
689
725
  "data-control-ui": "color-picker",
690
726
  "data-control-family": "color-picker",
691
727
  "data-slot": "contrast-ratio",
692
- children: [ratio.toFixed(2), ":1"]
728
+ children: [formatContrastRatio(ratio), ":1"]
693
729
  }),
694
730
  /* @__PURE__ */ jsx(WcagPill, {
695
731
  ok: levels.AA,
732
+ passLabel,
733
+ failLabel,
696
734
  children: "AA"
697
735
  }),
698
736
  /* @__PURE__ */ jsx(WcagPill, {
699
737
  ok: levels.AAA,
738
+ passLabel,
739
+ failLabel,
700
740
  children: "AAA"
701
741
  }),
702
742
  target ? /* @__PURE__ */ jsxs("button", {
@@ -704,14 +744,15 @@ function ColorPickerContrast({ background = "#ffffff", className, ...props }) {
704
744
  "data-control-ui": "color-picker",
705
745
  "data-control-family": "color-picker",
706
746
  "data-slot": "contrast-fix",
747
+ disabled,
707
748
  onClick: applyFix,
708
- className: "ml-auto cursor-pointer",
709
- children: ["Fix → ", target]
749
+ className: "ms-auto cursor-pointer disabled:cursor-not-allowed",
750
+ children: ["Fix for ", target]
710
751
  }) : null
711
752
  ]
712
753
  });
713
754
  }
714
- function WcagPill({ ok, children }) {
755
+ function WcagPill({ ok, passLabel, failLabel, children }) {
715
756
  return /* @__PURE__ */ jsxs("span", {
716
757
  "data-control-ui": "color-picker",
717
758
  "data-control-family": "color-picker",
@@ -719,7 +760,14 @@ function WcagPill({ ok, children }) {
719
760
  "data-passing": ok ? "true" : void 0,
720
761
  className: "inline-flex items-center",
721
762
  children: [
722
- ok ? "✓" : "✕",
763
+ /* @__PURE__ */ jsx("span", {
764
+ "aria-hidden": "true",
765
+ children: ok ? "✓" : "✕"
766
+ }),
767
+ /* @__PURE__ */ jsx("span", {
768
+ className: "sr-only",
769
+ children: ok ? passLabel : failLabel
770
+ }),
723
771
  " ",
724
772
  children
725
773
  ]
@@ -1,4 +1,3 @@
1
1
  //#region src/ui/combobox-disabled-selection.d.ts
2
- export declare function shouldAcceptComboboxValueChange<Value>(value: Value | null, disabledValues: ReadonlySet<unknown>): boolean;
3
- export declare function emitComboboxValueChange<Value>(value: Value | null, disabledValues: ReadonlySet<unknown>, onValueChange: (value: Value | null) => void): boolean;
2
+ export declare function shouldAcceptComboboxValueChange(next: unknown, previous: unknown, disabledValues: ReadonlySet<unknown>): boolean;
4
3
  //#endregion
@@ -1,11 +1,10 @@
1
1
  //#region src/ui/combobox-disabled-selection.ts
2
- function shouldAcceptComboboxValueChange(value, disabledValues) {
3
- return value === null || !disabledValues.has(value);
4
- }
5
- function emitComboboxValueChange(value, disabledValues, onValueChange) {
6
- if (!shouldAcceptComboboxValueChange(value, disabledValues)) return false;
7
- onValueChange(value);
8
- return true;
2
+ function shouldAcceptComboboxValueChange(next, previous, disabledValues) {
3
+ if (Array.isArray(next)) {
4
+ const kept = new Set(Array.isArray(previous) ? previous : []);
5
+ return next.every((item) => kept.has(item) || !disabledValues.has(item));
6
+ }
7
+ return next === null || next === previous || !disabledValues.has(next);
9
8
  }
10
9
  //#endregion
11
- export { emitComboboxValueChange, shouldAcceptComboboxValueChange };
10
+ export { shouldAcceptComboboxValueChange };
@@ -1,30 +1,11 @@
1
- import { OpenChangeEventDetails } from "../control-props.js";
2
1
  import { ControlSize } from "../control-variants.js";
3
2
  import { PopupKnobStyle } from "../knob-contracts/popup-knobs.js";
4
3
  import { FieldKnobStyle } from "../knob-contracts/field-knobs.js";
5
4
  import { CSSProperties, ComponentProps, ReactNode } from "react";
6
5
  import { Combobox as Combobox$1 } from "@base-ui/react/combobox";
7
6
  //#region src/ui/combobox.d.ts
8
- export type ComboboxProps<Value = string> = {
9
- children?: ReactNode;
7
+ export type ComboboxProps<Value = string, Multiple extends boolean | undefined = false> = Pick<Combobox$1.Root.Props<Value, Multiple>, "children" | "multiple" | "value" | "defaultValue" | "onValueChange" | "inputValue" | "defaultInputValue" | "onInputValueChange" | "open" | "defaultOpen" | "onOpenChange" | "disabled" | "readOnly" | "required" | "name" | "autoHighlight" | "itemToStringLabel" | "isItemEqualToValue" | "filter" | "modal"> & {
10
8
  items?: readonly Value[];
11
- value?: Value | null;
12
- defaultValue?: Value | null;
13
- onValueChange?: (value: Value | null) => void;
14
- inputValue?: string;
15
- defaultInputValue?: string;
16
- onInputValueChange?: (inputValue: string) => void;
17
- open?: boolean;
18
- defaultOpen?: boolean;
19
- onOpenChange?: (open: boolean, eventDetails: OpenChangeEventDetails) => void;
20
- disabled?: boolean;
21
- readOnly?: boolean;
22
- required?: boolean;
23
- name?: string;
24
- autoHighlight?: boolean;
25
- itemToStringLabel?: (itemValue: Value) => string;
26
- isItemEqualToValue?: (itemValue: Value, value: Value) => boolean;
27
- filter?: Combobox$1.Root.Props<Value>["filter"];
28
9
  };
29
10
  export type ComboboxInputProps = Omit<Omit<ComponentProps<"input">, "size">, "style"> & {
30
11
  style?: CSSProperties & FieldKnobStyle;
@@ -34,8 +15,9 @@ export type ComboboxInputProps = Omit<Omit<ComponentProps<"input">, "size">, "st
34
15
  export type ComboboxTriggerProps = ComponentProps<"button"> & {
35
16
  style?: CSSProperties & FieldKnobStyle;
36
17
  };
37
- export type ComboboxContentProps = Omit<ComponentProps<"div"> & {
18
+ export type ComboboxContentProps = Omit<Combobox$1.Popup.Props & {
38
19
  sideOffset?: number;
20
+ anchor?: Combobox$1.Positioner.Props["anchor"];
39
21
  }, "style"> & {
40
22
  style?: CSSProperties & PopupKnobStyle;
41
23
  };
@@ -59,10 +41,10 @@ export type ComboboxGroupProps = ComponentProps<"div"> & {
59
41
  export type ComboboxGroupLabelProps = Omit<ComponentProps<"div">, "style"> & {
60
42
  style?: CSSProperties & PopupKnobStyle;
61
43
  };
62
- export declare function Combobox<Value = string>({ children, onValueChange, autoHighlight, ...props }: ComboboxProps<Value>): import("react").JSX.Element;
44
+ export declare function Combobox<Value = string, Multiple extends boolean | undefined = false>({ children, onValueChange, autoHighlight, ...props }: ComboboxProps<Value, Multiple>): import("react").JSX.Element;
63
45
  export declare function ComboboxTrigger({ className, children, ...props }: ComboboxTriggerProps): import("react").JSX.Element;
64
46
  export declare function ComboboxInput({ size, className, ...props }: ComboboxInputProps): import("react").JSX.Element;
65
- export declare function ComboboxContent({ className, children, sideOffset, ...props }: ComboboxContentProps): import("react").JSX.Element;
47
+ export declare function ComboboxContent({ className, children, sideOffset, anchor, ...props }: ComboboxContentProps): import("react").JSX.Element;
66
48
  export declare function ComboboxList<Value = unknown>({ className, children, ...props }: ComboboxListProps<Value>): import("react").JSX.Element;
67
49
  export declare function ComboboxEmpty({ className, children, ...props }: ComboboxEmptyProps): import("react").JSX.Element;
68
50
  export declare function ComboboxItem<Value = unknown>({ className, children, disabled, value, ...props }: ComboboxItemProps<Value>): import("react").JSX.Element;
@@ -2,8 +2,9 @@
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { controlEffectsAttribute } from "../skin.js";
4
4
  import { useSkin } from "../skin-provider.js";
5
+ import { ScrollArea } from "./scroll-area.js";
5
6
  import { popupItemStructureClasses } from "../surface-variants.js";
6
- import { emitComboboxValueChange } from "./combobox-disabled-selection.js";
7
+ import { shouldAcceptComboboxValueChange } from "./combobox-disabled-selection.js";
7
8
  import { createContext, use, useEffect, useState } from "react";
8
9
  import { jsx, jsxs } from "react/jsx-runtime";
9
10
  import { Combobox as Combobox$1 } from "@base-ui/react/combobox";
@@ -11,6 +12,7 @@ import { Combobox as Combobox$1 } from "@base-ui/react/combobox";
11
12
  const ComboboxDisabledValueContext = createContext(null);
12
13
  function Combobox({ children, onValueChange, autoHighlight = true, ...props }) {
13
14
  const [disabledValues] = useState(() => /* @__PURE__ */ new Set());
15
+ const [committedValue, setCommittedValue] = useState(() => props.value ?? props.defaultValue ?? null);
14
16
  const [disabledValueRegistry] = useState(() => ({ register(value, disabled) {
15
17
  if (!disabled || value === void 0) return () => {};
16
18
  disabledValues.add(value);
@@ -21,9 +23,15 @@ function Combobox({ children, onValueChange, autoHighlight = true, ...props }) {
21
23
  children: /* @__PURE__ */ jsx(Combobox$1.Root, {
22
24
  autoHighlight,
23
25
  ...props,
24
- onValueChange: onValueChange ? (value) => {
25
- if (!Array.isArray(value)) emitComboboxValueChange(value, disabledValues, onValueChange);
26
- } : void 0,
26
+ onValueChange: (value, eventDetails) => {
27
+ const previousValue = props.value === void 0 ? committedValue : props.value;
28
+ if (!shouldAcceptComboboxValueChange(value, previousValue, disabledValues)) {
29
+ eventDetails.cancel();
30
+ return;
31
+ }
32
+ setCommittedValue(value);
33
+ onValueChange?.(value, eventDetails);
34
+ },
27
35
  children
28
36
  })
29
37
  });
@@ -61,8 +69,9 @@ function ComboboxTrigger({ className, children, ...props }) {
61
69
  function ComboboxInput({ size = "md", className, ...props }) {
62
70
  return /* @__PURE__ */ jsxs(Combobox$1.InputGroup, {
63
71
  "data-control-ui": "combobox",
72
+ "data-control-family": "field",
64
73
  "data-field-kind": "combobox",
65
- "data-slot": "root",
74
+ "data-slot": "input-group",
66
75
  className: "relative flex w-full items-center",
67
76
  children: [/* @__PURE__ */ jsx(Combobox$1.Input, {
68
77
  "data-control-ui": "combobox",
@@ -73,10 +82,10 @@ function ComboboxInput({ size = "md", className, ...props }) {
73
82
  "data-size": size,
74
83
  className: cn("w-full min-w-0 disabled:cursor-not-allowed", className),
75
84
  ...props
76
- }), /* @__PURE__ */ jsx(ComboboxTrigger, { className: "absolute right-1.5 top-1/2 -translate-y-1/2" })]
85
+ }), /* @__PURE__ */ jsx(ComboboxTrigger, { className: "absolute end-1.5 top-1/2 -translate-y-1/2" })]
77
86
  });
78
87
  }
79
- function ComboboxContent({ className, children, sideOffset = 6, ...props }) {
88
+ function ComboboxContent({ className, children, sideOffset = 6, anchor, ...props }) {
80
89
  const skin = useSkin();
81
90
  return /* @__PURE__ */ jsx(Combobox$1.Portal, { children: /* @__PURE__ */ jsx(Combobox$1.Positioner, {
82
91
  "data-control-ui": "combobox",
@@ -88,6 +97,7 @@ function ComboboxContent({ className, children, sideOffset = 6, ...props }) {
88
97
  side: "bottom",
89
98
  align: "start",
90
99
  sideOffset,
100
+ anchor,
91
101
  className: "z-(--z-popup)",
92
102
  children: /* @__PURE__ */ jsx(Combobox$1.Popup, {
93
103
  "data-control-ui": "combobox",
@@ -103,15 +113,21 @@ function ComboboxContent({ className, children, sideOffset = 6, ...props }) {
103
113
  }) });
104
114
  }
105
115
  function ComboboxList({ className, children, ...props }) {
106
- return /* @__PURE__ */ jsx(Combobox$1.List, {
107
- "data-control-ui": "combobox",
108
- "data-popup-kind": "combobox",
109
- "data-slot": "list",
110
- "data-control-family": "popup",
111
- "data-popup-part": "list-content",
112
- className: cn("max-h-[min(18rem,var(--available-height))] overflow-y-auto overscroll-contain", className),
113
- ...props,
114
- children
116
+ return /* @__PURE__ */ jsx(ScrollArea, {
117
+ className: "w-full",
118
+ viewportClassName: "overscroll-contain",
119
+ maxHeight: "min(18rem, var(--available-height))",
120
+ lockAxis: "x",
121
+ children: /* @__PURE__ */ jsx(Combobox$1.List, {
122
+ "data-control-ui": "combobox",
123
+ "data-popup-kind": "combobox",
124
+ "data-slot": "list",
125
+ "data-control-family": "popup",
126
+ "data-popup-part": "list-content",
127
+ className,
128
+ ...props,
129
+ children
130
+ })
115
131
  });
116
132
  }
117
133
  function ComboboxEmpty({ className, children, ...props }) {
@@ -145,6 +161,10 @@ function ComboboxItem({ className, children, disabled, value, ...props }) {
145
161
  className: cn(popupItemStructureClasses, className),
146
162
  ...props,
147
163
  children: [/* @__PURE__ */ jsx("span", {
164
+ "data-control-ui": "combobox",
165
+ "data-control-family": "popup",
166
+ "data-popup-kind": "combobox",
167
+ "data-slot": "item-text",
148
168
  className: "flex min-w-0 flex-1 items-center truncate",
149
169
  children
150
170
  }), /* @__PURE__ */ jsx("span", {
@@ -19,15 +19,21 @@ export type CommandInputProps = Omit<ComponentProps<typeof Command$1.Input>, "st
19
19
  style?: CSSProperties & PopupKnobStyle;
20
20
  };
21
21
  export declare function CommandInput({ className, ...props }: CommandInputProps): import("react").JSX.Element;
22
- export declare function CommandList({ className, children, ...props }: ComponentProps<typeof Command$1.List> & {
22
+ export type CommandListProps = Omit<ComponentProps<typeof Command$1.List>, "style"> & {
23
23
  style?: CSSProperties & PopupKnobStyle;
24
- }): import("react").JSX.Element;
24
+ getResultsLabel?: (count: number) => string;
25
+ };
26
+ export declare function CommandList({ className, children, getResultsLabel, ...props }: CommandListProps): import("react").JSX.Element;
25
27
  export type CommandEmptyProps = Omit<ComponentProps<typeof Command$1.Empty>, "style" | "title"> & {
26
28
  style?: CSSProperties & PopupKnobStyle;
27
29
  title?: ReactNode;
28
30
  description?: ReactNode;
29
31
  };
30
32
  export declare function CommandEmpty({ className, children, title, description, ...props }: CommandEmptyProps): import("react").JSX.Element;
33
+ export type CommandLoadingProps = Omit<ComponentProps<typeof Command$1.Loading>, "style"> & {
34
+ style?: CSSProperties & PopupKnobStyle;
35
+ };
36
+ export declare function CommandLoading({ label, className, ...props }: CommandLoadingProps): import("react").JSX.Element;
31
37
  export type CommandGroupProps = Omit<ComponentProps<typeof Command$1.Group>, "style"> & {
32
38
  style?: CSSProperties & PopupKnobStyle;
33
39
  };
@@ -1,10 +1,12 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { LiveStatus } from "./live-status.js";
3
4
  import { ScrollArea } from "./scroll-area.js";
4
5
  import { popupItemStructureClasses } from "../surface-variants.js";
5
6
  import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "./empty.js";
6
7
  import { Dialog, DialogContent, DialogDescription, DialogTitle } from "./dialog.js";
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { useEffect, useRef } from "react";
9
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
10
  import { Command as Command$1, useCommandState } from "cmdk";
9
11
  //#region src/ui/command.tsx
10
12
  function Command({ chrome = "standalone", className, ...props }) {
@@ -38,6 +40,7 @@ function CommandDialog({ title = "Command palette", description = "Search for a
38
40
  }),
39
41
  /* @__PURE__ */ jsx(Command, {
40
42
  chrome: "embedded",
43
+ label: title,
41
44
  ...commandProps,
42
45
  "data-control-ui": "command",
43
46
  "data-popup-kind": "command",
@@ -102,9 +105,21 @@ function CommandListSurface({ hasResults, ...props }) {
102
105
  role: hasResults ? "listbox" : "group"
103
106
  });
104
107
  }
105
- function CommandList({ className, children, ...props }) {
106
- const hasResults = useCommandState((state) => state.filtered.count > 0);
107
- return /* @__PURE__ */ jsx(ScrollArea, {
108
+ function defaultResultsLabel(count) {
109
+ if (count === 0) return "No results found";
110
+ return count === 1 ? "1 result" : `${count} results`;
111
+ }
112
+ function CommandList({ className, children, getResultsLabel = defaultResultsLabel, ...props }) {
113
+ const count = useCommandState((state) => state.filtered.count);
114
+ const search = useCommandState((state) => state.search);
115
+ const hasResults = count > 0;
116
+ const viewportRef = useRef(null);
117
+ useEffect(() => {
118
+ const frame = requestAnimationFrame(() => viewportRef.current?.scrollTo({ top: 0 }));
119
+ return () => cancelAnimationFrame(frame);
120
+ }, [search]);
121
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ScrollArea, {
122
+ viewportRef,
108
123
  maxHeight: "min(360px, var(--available-height, 360px))",
109
124
  className: "min-h-0 w-full",
110
125
  children: /* @__PURE__ */ jsx(Command$1.List, {
@@ -120,7 +135,7 @@ function CommandList({ className, children, ...props }) {
120
135
  children
121
136
  })
122
137
  })
123
- });
138
+ }), /* @__PURE__ */ jsx(LiveStatus, { message: search ? getResultsLabel(count) : "" })] });
124
139
  }
125
140
  function CommandEmpty({ className, children, title = "No results found", description = "Try a different search term.", ...props }) {
126
141
  return /* @__PURE__ */ jsx(Command$1.Empty, {
@@ -131,14 +146,22 @@ function CommandEmpty({ className, children, title = "No results found", descrip
131
146
  "data-slot": "empty",
132
147
  className,
133
148
  ...props,
134
- children: /* @__PURE__ */ jsx("div", {
135
- role: "status",
136
- children: children ?? /* @__PURE__ */ jsx(Empty, { children: /* @__PURE__ */ jsxs(EmptyHeader, { children: [
137
- /* @__PURE__ */ jsx(EmptyMedia, { children: /* @__PURE__ */ jsx(CommandEmptyIcon, {}) }),
138
- /* @__PURE__ */ jsx(EmptyTitle, { children: title }),
139
- description ? /* @__PURE__ */ jsx(EmptyDescription, { children: description }) : null
140
- ] }) })
141
- })
149
+ children: /* @__PURE__ */ jsx("div", { children: children ?? /* @__PURE__ */ jsx(Empty, { children: /* @__PURE__ */ jsxs(EmptyHeader, { children: [
150
+ /* @__PURE__ */ jsx(EmptyMedia, { children: /* @__PURE__ */ jsx(CommandEmptyIcon, {}) }),
151
+ /* @__PURE__ */ jsx(EmptyTitle, { children: title }),
152
+ description ? /* @__PURE__ */ jsx(EmptyDescription, { children: description }) : null
153
+ ] }) }) })
154
+ });
155
+ }
156
+ function CommandLoading({ label = "Loading results", className, ...props }) {
157
+ return /* @__PURE__ */ jsx(Command$1.Loading, {
158
+ "data-control-ui": "command",
159
+ "data-control-family": "popup",
160
+ "data-popup-kind": "command",
161
+ "data-slot": "loading",
162
+ label,
163
+ className,
164
+ ...props
142
165
  });
143
166
  }
144
167
  function CommandEmptyIcon() {
@@ -166,7 +189,7 @@ function CommandGroup({ className, ...props }) {
166
189
  "data-control-family": "popup",
167
190
  "data-popup-kind": "command",
168
191
  "data-slot": "group",
169
- className: cn("p-[var(--popover-padding)]", className),
192
+ className,
170
193
  ...props
171
194
  });
172
195
  }
@@ -208,9 +231,10 @@ function CommandShortcut({ className, ...props }) {
208
231
  "data-control-family": "popup",
209
232
  "data-popup-part": "shortcut",
210
233
  "data-slot": "shortcut",
234
+ "aria-hidden": "true",
211
235
  className: cn(className),
212
236
  ...props
213
237
  });
214
238
  }
215
239
  //#endregion
216
- export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut };
240
+ export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut };
@@ -17,6 +17,7 @@ function ContextMenuTrigger({ className, ...props }) {
17
17
  "data-control-family": "popup",
18
18
  "data-popup-kind": "context-menu",
19
19
  "data-slot": "trigger",
20
+ tabIndex: 0,
20
21
  className,
21
22
  ...props
22
23
  });
@@ -153,6 +154,7 @@ function ContextMenuShortcut({ className, ...props }) {
153
154
  "data-slot": "shortcut",
154
155
  "data-control-family": "popup",
155
156
  "data-popup-part": "shortcut",
157
+ "aria-hidden": "true",
156
158
  className: cn(className),
157
159
  ...props
158
160
  });
@@ -175,6 +177,7 @@ function ContextMenuSubTrigger({ className, inset = false, children, ...props })
175
177
  "data-popup-kind": "context-menu",
176
178
  "data-control-family": "popup",
177
179
  "data-slot": "sub-trigger-indicator",
180
+ "data-icon-dir": "inline",
178
181
  "aria-hidden": "true",
179
182
  children: "›"
180
183
  })]
@@ -15,6 +15,7 @@ export type DialogContentProps = Omit<ComponentProps<"div">, "style"> & {
15
15
  style?: CSSProperties & PopupKnobStyle;
16
16
  } & {
17
17
  showCloseButton?: boolean;
18
+ closeLabel?: string;
18
19
  };
19
20
  export declare function Dialog(props: DialogProps): import("react").JSX.Element;
20
21
  export declare function DialogTrigger({ className, ...props }: ComponentProps<typeof Dialog$1.Trigger> & {
@@ -22,7 +23,7 @@ export declare function DialogTrigger({ className, ...props }: ComponentProps<ty
22
23
  }): import("react").JSX.Element;
23
24
  export type DialogCloseProps = Omit<ComponentProps<typeof Dialog$1.Close>, "render"> & Pick<ButtonProps, "variant" | "size" | "tone" | "iconOnly">;
24
25
  export declare function DialogClose({ className, children, variant, size, tone, iconOnly, ...props }: DialogCloseProps): import("react").JSX.Element;
25
- export declare function DialogContent({ className, children, showCloseButton, ...props }: DialogContentProps): import("react").JSX.Element;
26
+ export declare function DialogContent({ className, children, showCloseButton, closeLabel, ...props }: DialogContentProps): import("react").JSX.Element;
26
27
  export declare function DialogHeader({ className, ...props }: ComponentProps<"div"> & {
27
28
  style?: CSSProperties & PopupKnobStyle;
28
29
  }): import("react").JSX.Element;