@womp/kookie-ui 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/components.css +190 -185
  2. package/dist/cjs/components/_internal/base-button.d.ts +11 -1
  3. package/dist/cjs/components/_internal/base-button.d.ts.map +1 -1
  4. package/dist/cjs/components/_internal/base-button.js +1 -1
  5. package/dist/cjs/components/_internal/base-button.js.map +4 -4
  6. package/dist/cjs/components/_internal/menu-context.d.ts +2 -0
  7. package/dist/cjs/components/_internal/menu-context.d.ts.map +1 -1
  8. package/dist/cjs/components/_internal/menu-context.js +1 -1
  9. package/dist/cjs/components/_internal/menu-context.js.map +3 -3
  10. package/dist/cjs/components/_internal/pane-chrome.d.ts +17 -2
  11. package/dist/cjs/components/_internal/pane-chrome.d.ts.map +1 -1
  12. package/dist/cjs/components/_internal/pane-chrome.js +1 -1
  13. package/dist/cjs/components/_internal/pane-chrome.js.map +4 -4
  14. package/dist/cjs/components/_internal/shell-sidebar.js +1 -1
  15. package/dist/cjs/components/_internal/shell-sidebar.js.map +4 -4
  16. package/dist/cjs/components/accordion.d.ts +2 -2
  17. package/dist/cjs/components/accordion.d.ts.map +1 -1
  18. package/dist/cjs/components/accordion.js +1 -1
  19. package/dist/cjs/components/accordion.js.map +4 -4
  20. package/dist/cjs/components/alert-dialog.d.ts.map +1 -1
  21. package/dist/cjs/components/alert-dialog.js +1 -1
  22. package/dist/cjs/components/alert-dialog.js.map +3 -3
  23. package/dist/cjs/components/avatar.d.ts +1 -1
  24. package/dist/cjs/components/avatar.d.ts.map +1 -1
  25. package/dist/cjs/components/avatar.js +1 -1
  26. package/dist/cjs/components/avatar.js.map +3 -3
  27. package/dist/cjs/components/avatar.props.d.ts +8 -0
  28. package/dist/cjs/components/avatar.props.d.ts.map +1 -1
  29. package/dist/cjs/components/avatar.props.js +1 -1
  30. package/dist/cjs/components/avatar.props.js.map +2 -2
  31. package/dist/cjs/components/blockquote.d.ts +1 -1
  32. package/dist/cjs/components/blockquote.d.ts.map +1 -1
  33. package/dist/cjs/components/blockquote.js +1 -1
  34. package/dist/cjs/components/blockquote.js.map +4 -4
  35. package/dist/cjs/components/button.js +1 -1
  36. package/dist/cjs/components/button.js.map +4 -4
  37. package/dist/cjs/components/chatbar.d.ts.map +1 -1
  38. package/dist/cjs/components/chatbar.js +1 -1
  39. package/dist/cjs/components/chatbar.js.map +4 -4
  40. package/dist/cjs/components/checkbox-group.d.ts.map +1 -1
  41. package/dist/cjs/components/checkbox-group.js +1 -1
  42. package/dist/cjs/components/checkbox-group.js.map +3 -3
  43. package/dist/cjs/components/checkbox-group.primitive.d.ts +12 -5
  44. package/dist/cjs/components/checkbox-group.primitive.d.ts.map +1 -1
  45. package/dist/cjs/components/checkbox-group.primitive.js +1 -1
  46. package/dist/cjs/components/checkbox-group.primitive.js.map +3 -3
  47. package/dist/cjs/components/checkbox.js +1 -1
  48. package/dist/cjs/components/checkbox.js.map +3 -3
  49. package/dist/cjs/components/chip.d.ts.map +1 -1
  50. package/dist/cjs/components/chip.js +1 -1
  51. package/dist/cjs/components/chip.js.map +3 -3
  52. package/dist/cjs/components/code.d.ts.map +1 -1
  53. package/dist/cjs/components/code.js +1 -1
  54. package/dist/cjs/components/code.js.map +2 -2
  55. package/dist/cjs/components/combobox.js +1 -1
  56. package/dist/cjs/components/combobox.js.map +3 -3
  57. package/dist/cjs/components/context-menu.d.ts.map +1 -1
  58. package/dist/cjs/components/context-menu.js +1 -1
  59. package/dist/cjs/components/context-menu.js.map +4 -4
  60. package/dist/cjs/components/dialog.d.ts +1 -1
  61. package/dist/cjs/components/dialog.d.ts.map +1 -1
  62. package/dist/cjs/components/dialog.js +1 -1
  63. package/dist/cjs/components/dialog.js.map +3 -3
  64. package/dist/cjs/components/dropdown-menu.d.ts.map +1 -1
  65. package/dist/cjs/components/dropdown-menu.js +1 -1
  66. package/dist/cjs/components/dropdown-menu.js.map +4 -4
  67. package/dist/cjs/components/icons.d.ts +3 -1
  68. package/dist/cjs/components/icons.d.ts.map +1 -1
  69. package/dist/cjs/components/icons.js +1 -1
  70. package/dist/cjs/components/icons.js.map +3 -3
  71. package/dist/cjs/components/index.d.ts +1 -1
  72. package/dist/cjs/components/index.d.ts.map +1 -1
  73. package/dist/cjs/components/index.js +2 -10
  74. package/dist/cjs/components/index.js.map +4 -4
  75. package/dist/cjs/components/message-scroller.d.ts.map +1 -1
  76. package/dist/cjs/components/message-scroller.js +1 -1
  77. package/dist/cjs/components/message-scroller.js.map +4 -4
  78. package/dist/cjs/components/navbar.d.ts.map +1 -1
  79. package/dist/cjs/components/navbar.js +1 -1
  80. package/dist/cjs/components/navbar.js.map +3 -3
  81. package/dist/cjs/components/notice.d.ts +4 -1
  82. package/dist/cjs/components/notice.d.ts.map +1 -1
  83. package/dist/cjs/components/notice.js +1 -1
  84. package/dist/cjs/components/notice.js.map +4 -4
  85. package/dist/cjs/components/progress.d.ts.map +1 -1
  86. package/dist/cjs/components/progress.js +1 -1
  87. package/dist/cjs/components/progress.js.map +3 -3
  88. package/dist/cjs/components/schemas/button.schema.d.ts +2 -2
  89. package/dist/cjs/components/schemas/toggle.schema.d.ts +1 -1
  90. package/dist/cjs/components/scroll-area.d.ts +3 -1
  91. package/dist/cjs/components/scroll-area.d.ts.map +1 -1
  92. package/dist/cjs/components/scroll-area.js +1 -1
  93. package/dist/cjs/components/scroll-area.js.map +4 -4
  94. package/dist/cjs/components/segmented-control.d.ts +3 -1
  95. package/dist/cjs/components/segmented-control.d.ts.map +1 -1
  96. package/dist/cjs/components/segmented-control.js +1 -1
  97. package/dist/cjs/components/segmented-control.js.map +3 -3
  98. package/dist/cjs/components/select.d.ts.map +1 -1
  99. package/dist/cjs/components/select.js +1 -1
  100. package/dist/cjs/components/select.js.map +3 -3
  101. package/dist/cjs/components/separator.d.ts.map +1 -1
  102. package/dist/cjs/components/separator.js +1 -1
  103. package/dist/cjs/components/separator.js.map +3 -3
  104. package/dist/cjs/components/sheet.d.ts +1 -0
  105. package/dist/cjs/components/sheet.d.ts.map +1 -1
  106. package/dist/cjs/components/sheet.js +1 -1
  107. package/dist/cjs/components/sheet.js.map +3 -3
  108. package/dist/cjs/components/shell.d.ts +12 -1
  109. package/dist/cjs/components/shell.d.ts.map +1 -1
  110. package/dist/cjs/components/shell.js +1 -1
  111. package/dist/cjs/components/shell.js.map +4 -4
  112. package/dist/cjs/components/sidebar.d.ts.map +1 -1
  113. package/dist/cjs/components/sidebar.js +1 -1
  114. package/dist/cjs/components/sidebar.js.map +4 -4
  115. package/dist/cjs/components/slider.d.ts.map +1 -1
  116. package/dist/cjs/components/slider.js +1 -1
  117. package/dist/cjs/components/slider.js.map +3 -3
  118. package/dist/cjs/components/spinner.d.ts.map +1 -1
  119. package/dist/cjs/components/spinner.js +1 -1
  120. package/dist/cjs/components/spinner.js.map +3 -3
  121. package/dist/cjs/components/table.d.ts.map +1 -1
  122. package/dist/cjs/components/table.js +1 -1
  123. package/dist/cjs/components/table.js.map +4 -4
  124. package/dist/cjs/components/tabs.d.ts.map +1 -1
  125. package/dist/cjs/components/tabs.js +1 -1
  126. package/dist/cjs/components/tabs.js.map +2 -2
  127. package/dist/cjs/components/text-area.js +1 -1
  128. package/dist/cjs/components/text-area.js.map +2 -2
  129. package/dist/cjs/components/text-field.js +2 -2
  130. package/dist/cjs/components/text-field.js.map +2 -2
  131. package/dist/cjs/components/toggle.d.ts +3 -2
  132. package/dist/cjs/components/toggle.d.ts.map +1 -1
  133. package/dist/cjs/components/toggle.js +1 -9
  134. package/dist/cjs/components/toggle.js.map +4 -4
  135. package/dist/cjs/components/toolbar.d.ts +80 -8
  136. package/dist/cjs/components/toolbar.d.ts.map +1 -1
  137. package/dist/cjs/components/toolbar.js +1 -1
  138. package/dist/cjs/components/toolbar.js.map +4 -4
  139. package/dist/cjs/components/virtual-menu.d.ts +3 -5
  140. package/dist/cjs/components/virtual-menu.d.ts.map +1 -1
  141. package/dist/cjs/components/virtual-menu.js +1 -1
  142. package/dist/cjs/components/virtual-menu.js.map +3 -3
  143. package/dist/cjs/helpers/extract-margin-props.d.ts +7 -7
  144. package/dist/cjs/hooks/use-scroll-edges.d.ts +4 -2
  145. package/dist/cjs/hooks/use-scroll-edges.d.ts.map +1 -1
  146. package/dist/cjs/hooks/use-scroll-edges.js +1 -1
  147. package/dist/cjs/hooks/use-scroll-edges.js.map +3 -3
  148. package/dist/cjs/index.js +5 -5
  149. package/dist/cjs/index.js.map +4 -4
  150. package/dist/cjs/props/index.js +1 -1
  151. package/dist/cjs/props/index.js.map +2 -2
  152. package/dist/esm/chunk-3VTS4C63.js +2 -0
  153. package/dist/esm/chunk-3VTS4C63.js.map +7 -0
  154. package/dist/esm/chunk-3WE4E2WQ.js +2 -0
  155. package/dist/esm/chunk-3WE4E2WQ.js.map +7 -0
  156. package/dist/esm/chunk-3XUY5WFA.js +2 -0
  157. package/dist/esm/chunk-3XUY5WFA.js.map +7 -0
  158. package/dist/esm/chunk-3XZOE2IQ.js +2 -0
  159. package/dist/esm/chunk-3XZOE2IQ.js.map +7 -0
  160. package/dist/esm/chunk-432YLNB3.js +2 -0
  161. package/dist/esm/chunk-432YLNB3.js.map +7 -0
  162. package/dist/esm/chunk-4QKZYCCH.js +2 -0
  163. package/dist/esm/chunk-4QKZYCCH.js.map +7 -0
  164. package/dist/esm/chunk-4R5EMVB3.js +2 -0
  165. package/dist/esm/chunk-4R5EMVB3.js.map +7 -0
  166. package/dist/esm/chunk-4ZOVV3TY.js +2 -0
  167. package/dist/esm/chunk-4ZOVV3TY.js.map +7 -0
  168. package/dist/esm/{chunk-IX5HIHVI.js → chunk-62ZGP4ET.js} +2 -2
  169. package/dist/esm/{chunk-IX5HIHVI.js.map → chunk-62ZGP4ET.js.map} +3 -3
  170. package/dist/esm/chunk-BGAJ2MDF.js +2 -0
  171. package/dist/esm/chunk-BGAJ2MDF.js.map +7 -0
  172. package/dist/esm/chunk-CHPT42BY.js +2 -0
  173. package/dist/esm/{chunk-Y3JYEEFB.js.map → chunk-CHPT42BY.js.map} +2 -2
  174. package/dist/esm/{chunk-KS4U4VPH.js → chunk-CMHUK7OG.js} +2 -2
  175. package/dist/esm/{chunk-KS4U4VPH.js.map → chunk-CMHUK7OG.js.map} +2 -2
  176. package/dist/esm/chunk-CN6F4REJ.js +2 -0
  177. package/dist/esm/chunk-CN6F4REJ.js.map +7 -0
  178. package/dist/esm/chunk-DUTZUWZP.js +2 -0
  179. package/dist/esm/chunk-DUTZUWZP.js.map +7 -0
  180. package/dist/esm/chunk-FDJV5RXX.js +2 -0
  181. package/dist/esm/chunk-FDJV5RXX.js.map +7 -0
  182. package/dist/esm/chunk-G2JD52O5.js +2 -0
  183. package/dist/esm/{chunk-23KT3D2Z.js.map → chunk-G2JD52O5.js.map} +3 -3
  184. package/dist/esm/{chunk-6DDOR73D.js → chunk-G4ETY2NP.js} +2 -2
  185. package/dist/esm/chunk-GPOCLDBR.js +2 -0
  186. package/dist/esm/chunk-GPOCLDBR.js.map +7 -0
  187. package/dist/esm/chunk-GYP66ZK2.js +2 -0
  188. package/dist/esm/chunk-GYP66ZK2.js.map +7 -0
  189. package/dist/esm/chunk-H5BYPX6V.js +2 -0
  190. package/dist/esm/chunk-H5BYPX6V.js.map +7 -0
  191. package/dist/esm/chunk-H5G7UECV.js +2 -0
  192. package/dist/esm/chunk-H5G7UECV.js.map +7 -0
  193. package/dist/esm/chunk-I4FLQELQ.js +2 -0
  194. package/dist/esm/chunk-I4FLQELQ.js.map +7 -0
  195. package/dist/esm/chunk-JYQGCXXI.js +2 -0
  196. package/dist/esm/chunk-JYQGCXXI.js.map +7 -0
  197. package/dist/esm/chunk-KA5UE2VN.js +2 -0
  198. package/dist/esm/chunk-KA5UE2VN.js.map +7 -0
  199. package/dist/esm/{chunk-QGCXTULQ.js → chunk-KEGCX5VM.js} +2 -2
  200. package/dist/esm/chunk-KVHKPUZ2.js +2 -0
  201. package/dist/esm/chunk-KVHKPUZ2.js.map +7 -0
  202. package/dist/esm/{chunk-FFG32ERA.js → chunk-N3WBEQWL.js} +3 -3
  203. package/dist/esm/chunk-N3WBEQWL.js.map +7 -0
  204. package/dist/esm/{chunk-HKPXDQ2B.js → chunk-NC3CJUE3.js} +2 -2
  205. package/dist/esm/chunk-P2MV6HLA.js +2 -0
  206. package/dist/esm/{chunk-7SS4UUJH.js.map → chunk-P2MV6HLA.js.map} +3 -3
  207. package/dist/esm/chunk-PALE5UWK.js +2 -0
  208. package/dist/esm/{chunk-DSPYHO3L.js.map → chunk-PALE5UWK.js.map} +2 -2
  209. package/dist/esm/chunk-PDMCLVYT.js +2 -0
  210. package/dist/esm/chunk-PDMCLVYT.js.map +7 -0
  211. package/dist/esm/chunk-PM6QY3JO.js +2 -0
  212. package/dist/esm/{chunk-ZEX2DECM.js.map → chunk-PM6QY3JO.js.map} +3 -3
  213. package/dist/esm/chunk-RKZVXVBN.js +2 -0
  214. package/dist/esm/chunk-RKZVXVBN.js.map +7 -0
  215. package/dist/esm/chunk-TXQZ5HLV.js +2 -0
  216. package/dist/esm/chunk-TXQZ5HLV.js.map +7 -0
  217. package/dist/esm/chunk-UKASIY6M.js +2 -0
  218. package/dist/esm/chunk-UKASIY6M.js.map +7 -0
  219. package/dist/esm/{chunk-OJQNLROL.js → chunk-UY6WJUNA.js} +2 -2
  220. package/dist/esm/chunk-V5O3TF57.js +2 -0
  221. package/dist/esm/{chunk-3KQE2PSJ.js.map → chunk-V5O3TF57.js.map} +3 -3
  222. package/dist/esm/chunk-VUNCI6A6.js +2 -0
  223. package/dist/esm/chunk-VUNCI6A6.js.map +7 -0
  224. package/dist/esm/{chunk-JBHRV364.js → chunk-VUPIJNG2.js} +2 -2
  225. package/dist/esm/chunk-W6BN5QLH.js +2 -0
  226. package/dist/esm/{chunk-ZNDCZM5A.js.map → chunk-W6BN5QLH.js.map} +2 -2
  227. package/dist/esm/chunk-WG5ORTIW.js +2 -0
  228. package/dist/esm/chunk-WG5ORTIW.js.map +7 -0
  229. package/dist/esm/chunk-WMVR2XBR.js +2 -0
  230. package/dist/esm/{chunk-XKSU3NLG.js.map → chunk-WMVR2XBR.js.map} +2 -2
  231. package/dist/esm/{chunk-NNZTSXKH.js → chunk-WX7SX5BN.js} +2 -2
  232. package/dist/esm/chunk-XOACTIBL.js +2 -0
  233. package/dist/esm/chunk-XOACTIBL.js.map +7 -0
  234. package/dist/esm/components/_internal/base-button.d.ts +11 -1
  235. package/dist/esm/components/_internal/base-button.d.ts.map +1 -1
  236. package/dist/esm/components/_internal/base-button.js +1 -1
  237. package/dist/esm/components/_internal/menu-context.d.ts +2 -0
  238. package/dist/esm/components/_internal/menu-context.d.ts.map +1 -1
  239. package/dist/esm/components/_internal/menu-context.js +1 -1
  240. package/dist/esm/components/_internal/pane-chrome.d.ts +17 -2
  241. package/dist/esm/components/_internal/pane-chrome.d.ts.map +1 -1
  242. package/dist/esm/components/_internal/pane-chrome.js +1 -1
  243. package/dist/esm/components/_internal/shell-bottom.js +1 -1
  244. package/dist/esm/components/_internal/shell-inspector.js +1 -1
  245. package/dist/esm/components/_internal/shell-sidebar.js +1 -1
  246. package/dist/esm/components/accordion.d.ts +2 -2
  247. package/dist/esm/components/accordion.d.ts.map +1 -1
  248. package/dist/esm/components/accordion.js +1 -1
  249. package/dist/esm/components/alert-dialog.d.ts.map +1 -1
  250. package/dist/esm/components/alert-dialog.js +1 -1
  251. package/dist/esm/components/avatar.d.ts +1 -1
  252. package/dist/esm/components/avatar.d.ts.map +1 -1
  253. package/dist/esm/components/avatar.js +1 -1
  254. package/dist/esm/components/avatar.props.d.ts +8 -0
  255. package/dist/esm/components/avatar.props.d.ts.map +1 -1
  256. package/dist/esm/components/avatar.props.js +1 -1
  257. package/dist/esm/components/blockquote.d.ts +1 -1
  258. package/dist/esm/components/blockquote.d.ts.map +1 -1
  259. package/dist/esm/components/blockquote.js +1 -1
  260. package/dist/esm/components/button.js +1 -1
  261. package/dist/esm/components/chatbar.d.ts.map +1 -1
  262. package/dist/esm/components/chatbar.js +1 -1
  263. package/dist/esm/components/checkbox-group.d.ts.map +1 -1
  264. package/dist/esm/components/checkbox-group.js +1 -1
  265. package/dist/esm/components/checkbox-group.primitive.d.ts +12 -5
  266. package/dist/esm/components/checkbox-group.primitive.d.ts.map +1 -1
  267. package/dist/esm/components/checkbox-group.primitive.js +1 -1
  268. package/dist/esm/components/checkbox.js +1 -1
  269. package/dist/esm/components/chip.d.ts.map +1 -1
  270. package/dist/esm/components/chip.js +1 -1
  271. package/dist/esm/components/code.d.ts.map +1 -1
  272. package/dist/esm/components/code.js +1 -1
  273. package/dist/esm/components/combobox.js +1 -1
  274. package/dist/esm/components/context-menu.d.ts.map +1 -1
  275. package/dist/esm/components/context-menu.js +1 -1
  276. package/dist/esm/components/dialog.d.ts +1 -1
  277. package/dist/esm/components/dialog.d.ts.map +1 -1
  278. package/dist/esm/components/dialog.js +1 -1
  279. package/dist/esm/components/dropdown-menu.d.ts.map +1 -1
  280. package/dist/esm/components/dropdown-menu.js +1 -1
  281. package/dist/esm/components/icons.d.ts +3 -1
  282. package/dist/esm/components/icons.d.ts.map +1 -1
  283. package/dist/esm/components/icons.js +1 -1
  284. package/dist/esm/components/index.d.ts +1 -1
  285. package/dist/esm/components/index.d.ts.map +1 -1
  286. package/dist/esm/components/index.js +1 -1
  287. package/dist/esm/components/message-scroller.d.ts.map +1 -1
  288. package/dist/esm/components/message-scroller.js +1 -1
  289. package/dist/esm/components/navbar.d.ts.map +1 -1
  290. package/dist/esm/components/navbar.js +1 -1
  291. package/dist/esm/components/notice.d.ts +4 -1
  292. package/dist/esm/components/notice.d.ts.map +1 -1
  293. package/dist/esm/components/notice.js +1 -1
  294. package/dist/esm/components/progress.d.ts.map +1 -1
  295. package/dist/esm/components/progress.js +1 -1
  296. package/dist/esm/components/schemas/button.schema.d.ts +2 -2
  297. package/dist/esm/components/schemas/toggle.schema.d.ts +1 -1
  298. package/dist/esm/components/scroll-area.d.ts +3 -1
  299. package/dist/esm/components/scroll-area.d.ts.map +1 -1
  300. package/dist/esm/components/scroll-area.js +1 -1
  301. package/dist/esm/components/segmented-control.d.ts +3 -1
  302. package/dist/esm/components/segmented-control.d.ts.map +1 -1
  303. package/dist/esm/components/segmented-control.js +1 -1
  304. package/dist/esm/components/select.d.ts.map +1 -1
  305. package/dist/esm/components/select.js +1 -1
  306. package/dist/esm/components/separator.d.ts.map +1 -1
  307. package/dist/esm/components/separator.js +1 -1
  308. package/dist/esm/components/sheet.d.ts +1 -0
  309. package/dist/esm/components/sheet.d.ts.map +1 -1
  310. package/dist/esm/components/sheet.js +1 -1
  311. package/dist/esm/components/shell.d.ts +12 -1
  312. package/dist/esm/components/shell.d.ts.map +1 -1
  313. package/dist/esm/components/shell.js +1 -1
  314. package/dist/esm/components/sidebar.d.ts.map +1 -1
  315. package/dist/esm/components/sidebar.js +1 -1
  316. package/dist/esm/components/slider.d.ts.map +1 -1
  317. package/dist/esm/components/slider.js +1 -1
  318. package/dist/esm/components/spinner.d.ts.map +1 -1
  319. package/dist/esm/components/spinner.js +1 -1
  320. package/dist/esm/components/table.d.ts.map +1 -1
  321. package/dist/esm/components/table.js +1 -1
  322. package/dist/esm/components/tabs.d.ts.map +1 -1
  323. package/dist/esm/components/tabs.js +1 -1
  324. package/dist/esm/components/text-area.js +1 -1
  325. package/dist/esm/components/text-field.js +1 -1
  326. package/dist/esm/components/toggle.d.ts +3 -2
  327. package/dist/esm/components/toggle.d.ts.map +1 -1
  328. package/dist/esm/components/toggle.js +1 -1
  329. package/dist/esm/components/toolbar.d.ts +80 -8
  330. package/dist/esm/components/toolbar.d.ts.map +1 -1
  331. package/dist/esm/components/toolbar.js +1 -1
  332. package/dist/esm/components/virtual-menu.d.ts +3 -5
  333. package/dist/esm/components/virtual-menu.d.ts.map +1 -1
  334. package/dist/esm/components/virtual-menu.js +1 -1
  335. package/dist/esm/helpers/extract-margin-props.d.ts +7 -7
  336. package/dist/esm/hooks/index.js +1 -1
  337. package/dist/esm/hooks/use-scroll-edges.d.ts +4 -2
  338. package/dist/esm/hooks/use-scroll-edges.d.ts.map +1 -1
  339. package/dist/esm/hooks/use-scroll-edges.js +1 -1
  340. package/dist/esm/index.js +1 -1
  341. package/dist/esm/props/index.js +1 -1
  342. package/package.json +1 -1
  343. package/src/components/_internal/base-button.tsx +51 -12
  344. package/src/components/_internal/base-sidebar-menu.css +8 -0
  345. package/src/components/_internal/menu-context.tsx +11 -0
  346. package/src/components/_internal/pane-chrome.tsx +45 -8
  347. package/src/components/accordion.css +35 -3
  348. package/src/components/accordion.tsx +12 -16
  349. package/src/components/alert-dialog.tsx +59 -161
  350. package/src/components/avatar.props.tsx +6 -0
  351. package/src/components/avatar.tsx +57 -71
  352. package/src/components/blockquote.tsx +8 -9
  353. package/src/components/chatbar.tsx +27 -20
  354. package/src/components/checkbox-group.primitive.tsx +40 -51
  355. package/src/components/checkbox-group.tsx +1 -9
  356. package/src/components/chip.css +18 -20
  357. package/src/components/chip.tsx +3 -4
  358. package/src/components/code.tsx +3 -2
  359. package/src/components/context-menu.tsx +23 -5
  360. package/src/components/dialog.tsx +59 -160
  361. package/src/components/dropdown-menu.tsx +8 -5
  362. package/src/components/icons.tsx +11 -1
  363. package/src/components/index.tsx +7 -0
  364. package/src/components/message-scroller.tsx +48 -26
  365. package/src/components/navbar.tsx +34 -69
  366. package/src/components/notice.tsx +6 -3
  367. package/src/components/progress.tsx +6 -3
  368. package/src/components/scroll-area.css +28 -2
  369. package/src/components/scroll-area.tsx +49 -3
  370. package/src/components/segmented-control.css +8 -130
  371. package/src/components/segmented-control.tsx +36 -5
  372. package/src/components/select.tsx +23 -3
  373. package/src/components/separator.tsx +13 -1
  374. package/src/components/sheet.css +7 -6
  375. package/src/components/sheet.tsx +76 -143
  376. package/src/components/shell.css +14 -0
  377. package/src/components/shell.tsx +29 -8
  378. package/src/components/sidebar.tsx +27 -16
  379. package/src/components/slider.tsx +51 -32
  380. package/src/components/spinner.tsx +10 -2
  381. package/src/components/table.tsx +18 -5
  382. package/src/components/tabs.css +34 -0
  383. package/src/components/tabs.tsx +0 -2
  384. package/src/components/text-area.css +2 -1
  385. package/src/components/text-area.tsx +1 -1
  386. package/src/components/text-field.tsx +1 -1
  387. package/src/components/toggle.tsx +21 -39
  388. package/src/components/toolbar.css +34 -0
  389. package/src/components/toolbar.tsx +432 -23
  390. package/src/components/virtual-menu.tsx +110 -37
  391. package/src/hooks/use-scroll-edges.ts +11 -2
  392. package/src/styles/utilities/truncate.css +10 -0
  393. package/styles.css +195 -185
  394. package/utilities.css +5 -0
  395. package/dist/esm/chunk-23KT3D2Z.js +0 -2
  396. package/dist/esm/chunk-3JA7SJDT.js +0 -2
  397. package/dist/esm/chunk-3JA7SJDT.js.map +0 -7
  398. package/dist/esm/chunk-3KQE2PSJ.js +0 -2
  399. package/dist/esm/chunk-5BWLY27A.js +0 -2
  400. package/dist/esm/chunk-5BWLY27A.js.map +0 -7
  401. package/dist/esm/chunk-6CK7UTNH.js +0 -2
  402. package/dist/esm/chunk-6CK7UTNH.js.map +0 -7
  403. package/dist/esm/chunk-6RK26HIY.js +0 -2
  404. package/dist/esm/chunk-6RK26HIY.js.map +0 -7
  405. package/dist/esm/chunk-7ESWH773.js +0 -2
  406. package/dist/esm/chunk-7ESWH773.js.map +0 -7
  407. package/dist/esm/chunk-7SS4UUJH.js +0 -2
  408. package/dist/esm/chunk-AB3QCCUM.js +0 -2
  409. package/dist/esm/chunk-AB3QCCUM.js.map +0 -7
  410. package/dist/esm/chunk-BEP4AH5V.js +0 -2
  411. package/dist/esm/chunk-BEP4AH5V.js.map +0 -7
  412. package/dist/esm/chunk-BOL3VVSN.js +0 -2
  413. package/dist/esm/chunk-BOL3VVSN.js.map +0 -7
  414. package/dist/esm/chunk-DBROSD2J.js +0 -2
  415. package/dist/esm/chunk-DBROSD2J.js.map +0 -7
  416. package/dist/esm/chunk-DSPYHO3L.js +0 -2
  417. package/dist/esm/chunk-E2D2VWUI.js +0 -2
  418. package/dist/esm/chunk-E2D2VWUI.js.map +0 -7
  419. package/dist/esm/chunk-EMNSA65L.js +0 -2
  420. package/dist/esm/chunk-EMNSA65L.js.map +0 -7
  421. package/dist/esm/chunk-FFG32ERA.js.map +0 -7
  422. package/dist/esm/chunk-FHPHEIYJ.js +0 -2
  423. package/dist/esm/chunk-FHPHEIYJ.js.map +0 -7
  424. package/dist/esm/chunk-FJFBM7HW.js +0 -2
  425. package/dist/esm/chunk-FJFBM7HW.js.map +0 -7
  426. package/dist/esm/chunk-FYT7TYGS.js +0 -2
  427. package/dist/esm/chunk-FYT7TYGS.js.map +0 -7
  428. package/dist/esm/chunk-GLV7VGBH.js +0 -2
  429. package/dist/esm/chunk-GLV7VGBH.js.map +0 -7
  430. package/dist/esm/chunk-HIKMKGPT.js +0 -2
  431. package/dist/esm/chunk-HIKMKGPT.js.map +0 -7
  432. package/dist/esm/chunk-L2R62BOB.js +0 -2
  433. package/dist/esm/chunk-L2R62BOB.js.map +0 -7
  434. package/dist/esm/chunk-LHIS3UKQ.js +0 -2
  435. package/dist/esm/chunk-LHIS3UKQ.js.map +0 -7
  436. package/dist/esm/chunk-NQDMTOGB.js +0 -2
  437. package/dist/esm/chunk-NQDMTOGB.js.map +0 -7
  438. package/dist/esm/chunk-Q6MFPATL.js +0 -2
  439. package/dist/esm/chunk-Q6MFPATL.js.map +0 -7
  440. package/dist/esm/chunk-QOHJIF25.js +0 -2
  441. package/dist/esm/chunk-QOHJIF25.js.map +0 -7
  442. package/dist/esm/chunk-R4XJNQX5.js +0 -2
  443. package/dist/esm/chunk-R4XJNQX5.js.map +0 -7
  444. package/dist/esm/chunk-UE3HATOA.js +0 -2
  445. package/dist/esm/chunk-UE3HATOA.js.map +0 -7
  446. package/dist/esm/chunk-V32EP3S7.js +0 -2
  447. package/dist/esm/chunk-V32EP3S7.js.map +0 -7
  448. package/dist/esm/chunk-XKSU3NLG.js +0 -2
  449. package/dist/esm/chunk-XRCMPBAY.js +0 -2
  450. package/dist/esm/chunk-XRCMPBAY.js.map +0 -7
  451. package/dist/esm/chunk-Y3JYEEFB.js +0 -2
  452. package/dist/esm/chunk-YZM54IJE.js +0 -2
  453. package/dist/esm/chunk-YZM54IJE.js.map +0 -7
  454. package/dist/esm/chunk-ZEX2DECM.js +0 -2
  455. package/dist/esm/chunk-ZJI2IK7C.js +0 -2
  456. package/dist/esm/chunk-ZJI2IK7C.js.map +0 -7
  457. package/dist/esm/chunk-ZNDCZM5A.js +0 -2
  458. /package/dist/esm/{chunk-6DDOR73D.js.map → chunk-G4ETY2NP.js.map} +0 -0
  459. /package/dist/esm/{chunk-QGCXTULQ.js.map → chunk-KEGCX5VM.js.map} +0 -0
  460. /package/dist/esm/{chunk-HKPXDQ2B.js.map → chunk-NC3CJUE3.js.map} +0 -0
  461. /package/dist/esm/{chunk-OJQNLROL.js.map → chunk-UY6WJUNA.js.map} +0 -0
  462. /package/dist/esm/{chunk-JBHRV364.js.map → chunk-VUPIJNG2.js.map} +0 -0
  463. /package/dist/esm/{chunk-NNZTSXKH.js.map → chunk-WX7SX5BN.js.map} +0 -0
@@ -6,12 +6,15 @@ import { Toolbar as ToolbarPrimitive } from 'radix-ui';
6
6
 
7
7
  import { toolbarRootPropDefs } from './toolbar.props.js';
8
8
  import { Button } from './button.js';
9
+ import * as DropdownMenu from './dropdown-menu.js';
9
10
  import { Text } from './text.js';
10
11
  import { extractProps } from '../helpers/extract-props.js';
11
12
  import { useThemeSize } from '../helpers/theme-size.js';
13
+ import { layoutPropDefs } from '../props/layout.props.js';
12
14
  import { usePaneBandSize } from './_internal/pane-chrome.js';
13
15
 
14
16
  import type { ButtonProps } from './button.js';
17
+ import type { LayoutProps } from '../props/layout.props.js';
15
18
  import type { TextProps } from './text.js';
16
19
  import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';
17
20
  import type { GetPropDefTypes } from '../props/prop-def.js';
@@ -42,14 +45,25 @@ const ToolbarContext = React.createContext<ToolbarContextValue | null>(null);
42
45
  /** Set by a `ToolbarGroup`: its children rest quiet, and `disabled` turns them all off. */
43
46
  const ToolbarGroupContext = React.createContext<{ disabled: boolean } | null>(null);
44
47
 
45
- function useToolbarContext(consumer: string): ToolbarContextValue {
46
- const context = React.useContext(ToolbarContext);
47
- if (!context) {
48
- throw new Error(`${consumer} must be rendered inside a Toolbar.`);
49
- }
50
- return context;
48
+ /**
49
+ * True while a subtree is drawn into a `ToolbarOverflow`'s menu instead of into the row (v2
50
+ * `InOverflow`). The parts answer it themselves: a `ToolbarButton` renders a menu item, a
51
+ * `ToolbarGroup` a menu group, a `ToolbarSeparator` a menu separator.
52
+ */
53
+ const InOverflowContext = React.createContext(false);
54
+
55
+ /**
56
+ * True while this subtree is drawn into a `ToolbarOverflow`'s "More" menu instead of the row.
57
+ *
58
+ * The toolbar's own parts handle this already. Use it in your own component inside a
59
+ * `ToolbarOverflow` to render a different form in the menu.
60
+ */
61
+ function useToolbarOverflow(): boolean {
62
+ return React.useContext(InOverflowContext);
51
63
  }
52
64
 
65
+ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
66
+
53
67
  // ============================================================================
54
68
  // Toolbar (root)
55
69
  // ============================================================================
@@ -58,7 +72,8 @@ type ToolbarOwnProps = GetPropDefTypes<typeof toolbarRootPropDefs>;
58
72
 
59
73
  interface ToolbarProps
60
74
  extends ComponentPropsWithout<typeof ToolbarPrimitive.Root, RemovedProps | 'orientation'>,
61
- ToolbarOwnProps {
75
+ ToolbarOwnProps,
76
+ LayoutProps {
62
77
  /**
63
78
  * Gives every control a surface of its own, for a row that content passes behind, such as
64
79
  * `Shell.PaneHeader float`. Buttons rest `raised` instead of `soft`, and a group's well is
@@ -86,7 +101,8 @@ interface ToolbarProps
86
101
  * ```
87
102
  */
88
103
  const ToolbarRoot = React.forwardRef<HTMLDivElement, ToolbarProps>((props, forwardedRef) => {
89
- // In a Shell pane's header or footer, a toolbar with no size rests one step above the Shell's.
104
+ // Inside a Shell (a pane's header or footer, or the content area), a toolbar with no size
105
+ // rests one step above the Shell's. A pane's scrolling list has no band.
90
106
  const band = usePaneBandSize();
91
107
  // Elsewhere it takes the nearest Theme's size.
92
108
  const size: ToolbarSize = useThemeSize(props.size ?? band ?? undefined, toolbarRootPropDefs.size);
@@ -94,6 +110,7 @@ const ToolbarRoot = React.forwardRef<HTMLDivElement, ToolbarProps>((props, forwa
94
110
  const { className, orientation: _orientation, backdrop = false, children, ...rootProps } = extractProps(
95
111
  { ...props, size },
96
112
  toolbarRootPropDefs,
113
+ layoutPropDefs,
97
114
  );
98
115
 
99
116
  const context = React.useMemo(() => ({ size, orientation, backdrop }), [size, orientation, backdrop]);
@@ -125,15 +142,28 @@ interface ToolbarGroupProps extends ComponentPropsWithout<'div', RemovedProps> {
125
142
  * Controls that belong together, drawn as one quiet well that stands level with a button
126
143
  * beside it. Buttons inside it rest as `ghost` unless they state a `variant`.
127
144
  * To cluster controls without a well, use a `Flex`.
145
+ *
146
+ * In a `ToolbarOverflow`'s menu it is a menu group. Outside a `Toolbar` (rendered through a
147
+ * portal, for example) it still draws its well, as a horizontal group.
128
148
  */
129
149
  const ToolbarGroup = React.forwardRef<HTMLDivElement, ToolbarGroupProps>(
130
150
  ({ className, disabled = false, children, ...props }, forwardedRef) => {
131
- const { orientation } = useToolbarContext('ToolbarGroup');
151
+ const toolbar = React.useContext(ToolbarContext);
152
+ const overflow = React.useContext(InOverflowContext);
132
153
  const group = React.useMemo(() => ({ disabled }), [disabled]);
154
+
155
+ if (overflow) {
156
+ return (
157
+ <DropdownMenu.Group {...props} ref={forwardedRef} className={className}>
158
+ <ToolbarGroupContext.Provider value={group}>{children}</ToolbarGroupContext.Provider>
159
+ </DropdownMenu.Group>
160
+ );
161
+ }
162
+
133
163
  return (
134
164
  <div
135
165
  role="group"
136
- data-orientation={orientation}
166
+ data-orientation={toolbar?.orientation ?? 'horizontal'}
137
167
  data-disabled={disabled || undefined}
138
168
  {...props}
139
169
  ref={forwardedRef}
@@ -150,7 +180,7 @@ ToolbarGroup.displayName = 'Toolbar.Group';
150
180
  // ToolbarButton
151
181
  // ============================================================================
152
182
 
153
- type ToolbarButtonBaseProps = Omit<ButtonProps, 'as' | 'asChild' | 'variant' | 'emphasis'>;
183
+ type ToolbarButtonBaseProps = Omit<ButtonProps, 'as' | 'variant' | 'emphasis'>;
154
184
 
155
185
  /** A labelled button: takes every `Button` prop. */
156
186
  type ToolbarTextButtonProps = ToolbarButtonBaseProps &
@@ -172,29 +202,76 @@ function isPressed(value: React.AriaAttributes['aria-pressed']) {
172
202
  return value === true || value === 'true';
173
203
  }
174
204
 
205
+ /** Does an `asChild` child render a native `<button>`? Only then is it a Radix Toolbar.Button. */
206
+ function isButtonElement(children: React.ReactNode) {
207
+ return React.isValidElement(children) && children.type === 'button';
208
+ }
209
+
175
210
  /**
176
211
  * A `Button` that joins the toolbar's keyboard navigation, so a row of them is one tab stop.
177
212
  *
178
213
  * Set `iconOnly` (with an `aria-label`) for a symbol-only control. Set `aria-pressed` for a
179
- * control that toggles; a pressed button wears Button's pressed look.
214
+ * control that toggles; a pressed button wears Button's pressed look. Set `asChild` to render
215
+ * your own element, such as a link: `<ToolbarButton asChild><a href="/docs">Docs</a></ToolbarButton>`.
216
+ * A link stays in the arrow-key row and gets no `type` attribute.
180
217
  *
181
218
  * It takes the toolbar's `size`, and rests as a gray `soft` button (`raised` in a toolbar with
182
- * `backdrop`, gray `ghost` inside a `ToolbarGroup`). A stated `size`, `variant` or `color` wins; a stated `variant` without a
183
- * `color` takes Button's own default colour. It throws outside a `Toolbar`.
219
+ * `backdrop`, gray `ghost` inside a `ToolbarGroup`). A stated `size`, `variant` or `color` wins; a
220
+ * stated `variant` without a `color` takes Button's own default colour.
221
+ *
222
+ * In a `ToolbarOverflow`'s menu it renders a menu item; an icon-only button uses its
223
+ * `aria-label` as the item's text. Outside a `Toolbar` (rendered through a React portal, for
224
+ * example) it renders a plain Button with the same rest look, as its own tab stop. Use
225
+ * `ToolbarSlot` and `ToolbarFill` for a control that should join the row's arrow keys.
184
226
  */
185
227
  const ToolbarButton = React.forwardRef<HTMLButtonElement, ToolbarButtonProps>((props, forwardedRef) => {
186
- const toolbar = useToolbarContext('ToolbarButton');
228
+ const toolbar = React.useContext(ToolbarContext);
187
229
  const group = React.useContext(ToolbarGroupContext);
188
- const { iconOnly, size, variant, emphasis, color, disabled, ...rest } = props;
230
+ const overflow = React.useContext(InOverflowContext);
231
+ const { iconOnly, size, variant, emphasis, color, disabled, asChild, onKeyDown, ...rest } = props;
232
+ const off = disabled || group?.disabled || undefined;
233
+
234
+ if (overflow) {
235
+ return (
236
+ <ToolbarOverflowItem
237
+ // Only what a menu row means comes across; Button's box props (size, loading,
238
+ // tooltip, fullWidth and the rest) would land on the DOM as unknown attributes.
239
+ id={rest.id}
240
+ className={rest.className}
241
+ style={rest.style}
242
+ onClick={rest.onClick as React.MouseEventHandler<HTMLDivElement> | undefined}
243
+ aria-label={rest['aria-label']}
244
+ ref={forwardedRef as unknown as React.Ref<HTMLDivElement>}
245
+ asChild={asChild}
246
+ iconOnly={iconOnly}
247
+ disabled={off}
248
+ color={color}
249
+ >
250
+ {rest.children}
251
+ </ToolbarOverflowItem>
252
+ );
253
+ }
254
+
255
+ // In a vertical toolbar, Up and Down belong to the toolbar. A menu trigger rendering this
256
+ // hands its open-on-arrow handler in through `onKeyDown`; those two keys skip it (v2).
257
+ const handleKeyDown =
258
+ toolbar?.orientation === 'vertical' && onKeyDown
259
+ ? (event: React.KeyboardEvent<HTMLButtonElement>) => {
260
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') return;
261
+ onKeyDown(event);
262
+ }
263
+ : onKeyDown;
189
264
 
190
265
  const pressed = isPressed(props['aria-pressed']);
191
266
  const stateProps =
192
267
  'data-state' in props || props['aria-pressed'] === undefined ? {} : { 'data-state': pressed ? 'on' : 'off' };
193
268
 
194
269
  const shared = {
195
- size: size ?? toolbar.size,
270
+ size: size ?? toolbar?.size,
196
271
  // A caller states the look by `variant` or the rank by `emphasis`, never both.
197
- ...(emphasis !== undefined ? { emphasis } : { variant: variant ?? (group ? 'ghost' : toolbar.backdrop ? 'raised' : 'soft') }),
272
+ ...(emphasis !== undefined
273
+ ? { emphasis }
274
+ : { variant: variant ?? (group ? 'ghost' : toolbar?.backdrop ? 'raised' : 'soft') }),
198
275
  // The gray rest is a pair with the default variant: a caller who states a variant or an
199
276
  // emphasis gets Button's own colour for it unless they state a colour too.
200
277
  color: color ?? (variant || emphasis ? undefined : 'gray'),
@@ -202,16 +279,316 @@ const ToolbarButton = React.forwardRef<HTMLButtonElement, ToolbarButtonProps>((p
202
279
  } as const;
203
280
 
204
281
  // The text and icon-only branches share every prop but the name; one Button renders both.
205
- const buttonProps = { ...rest, ...(iconOnly ? { iconOnly: true } : {}), ...shared } as ButtonProps;
282
+ const buttonProps = {
283
+ ...rest,
284
+ ...(iconOnly ? { iconOnly: true } : {}),
285
+ ...(asChild ? { asChild: true } : {}),
286
+ ...(handleKeyDown ? { onKeyDown: handleKeyDown } : {}),
287
+ ...shared,
288
+ } as ButtonProps;
289
+
290
+ // Outside a toolbar there is no row to join: a plain Button, not a throw.
291
+ if (!toolbar) {
292
+ return <Button {...buttonProps} ref={forwardedRef} disabled={off} />;
293
+ }
294
+
295
+ // A link (or any non-button child) joins the row as a Radix Toolbar.Link, which sets no
296
+ // `type`. Toolbar.Button would stamp `type="button"` on it.
297
+ if (asChild && !isButtonElement(rest.children)) {
298
+ return (
299
+ <ToolbarPrimitive.Link asChild ref={forwardedRef as unknown as React.Ref<HTMLAnchorElement>}>
300
+ <Button {...buttonProps} disabled={off} />
301
+ </ToolbarPrimitive.Link>
302
+ );
303
+ }
206
304
 
207
305
  return (
208
- <ToolbarPrimitive.Button asChild ref={forwardedRef} disabled={disabled || group?.disabled || undefined}>
306
+ <ToolbarPrimitive.Button asChild ref={forwardedRef} disabled={off}>
209
307
  <Button {...buttonProps} />
210
308
  </ToolbarPrimitive.Button>
211
309
  );
212
310
  });
213
311
  ToolbarButton.displayName = 'Toolbar.Button';
214
312
 
313
+ interface ToolbarOverflowItemProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onSelect' | 'color'> {
314
+ asChild?: boolean;
315
+ iconOnly?: boolean;
316
+ disabled?: boolean;
317
+ color?: ButtonProps['color'];
318
+ }
319
+
320
+ /**
321
+ * A ToolbarButton drawn into the overflow menu: the same element, as a menu item. An icon-only
322
+ * button's `aria-label` becomes the item's text beside its icon, since a menu row has room for
323
+ * words. What prices a box (size, variant, emphasis, iconOnly) does not come across.
324
+ */
325
+ const ToolbarOverflowItem = React.forwardRef<HTMLDivElement, ToolbarOverflowItemProps>(
326
+ ({ asChild, iconOnly, disabled, color, children, 'aria-label': label, ...props }, forwardedRef) => {
327
+ const words = iconOnly ? label : undefined;
328
+ const itemProps = {
329
+ ...props,
330
+ ...(iconOnly ? {} : label ? { 'aria-label': label } : {}),
331
+ disabled,
332
+ ...(color ? { color: color as DropdownMenu.ItemProps['color'] } : {}),
333
+ };
334
+ if (asChild && React.isValidElement<{ children?: React.ReactNode }>(children)) {
335
+ const child = words
336
+ ? React.cloneElement(children, undefined, children.props.children, <span>{words}</span>)
337
+ : children;
338
+ return (
339
+ <DropdownMenu.Item {...itemProps} ref={forwardedRef} asChild>
340
+ {child}
341
+ </DropdownMenu.Item>
342
+ );
343
+ }
344
+ return (
345
+ <DropdownMenu.Item {...itemProps} ref={forwardedRef}>
346
+ {children}
347
+ {words}
348
+ </DropdownMenu.Item>
349
+ );
350
+ },
351
+ );
352
+ ToolbarOverflowItem.displayName = 'Toolbar.OverflowItem';
353
+
354
+ // ============================================================================
355
+ // ToolbarOverflow
356
+ // ============================================================================
357
+
358
+ interface ToolbarOverflowProps extends ComponentPropsWithout<'div', RemovedProps> {
359
+ /** The accessible name of the "More" button. Defaults to `More`. */
360
+ label?: string;
361
+ /** The controls in the cluster, in order. The ones that don't fit move into the "More" menu. */
362
+ children?: React.ReactNode;
363
+ }
364
+
365
+ /** Three filled dots for the "More" button. Internal, so the library carries no icon set. */
366
+ function MoreIcon() {
367
+ return (
368
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="currentcolor" aria-hidden xmlns="http://www.w3.org/2000/svg">
369
+ <circle cx="3.25" cy="8" r="1.25" />
370
+ <circle cx="8" cy="8" r="1.25" />
371
+ <circle cx="12.75" cy="8" r="1.25" />
372
+ </svg>
373
+ );
374
+ }
375
+
376
+ /**
377
+ * A cluster of controls that collapses into a "More" menu when the row runs out of room.
378
+ *
379
+ * It takes the room the row leaves, and when its controls don't fit, they move into the menu
380
+ * from the end of the cluster. A `ToolbarButton` shows as a menu item there, and a
381
+ * `ToolbarGroup` as a menu group. Use `useToolbarOverflow()` in your own components to render a
382
+ * different form in the menu.
383
+ *
384
+ * It measures on mount and on resize (v2 ToolbarOverflow): each control's width is cached while
385
+ * it is in the row, since a hidden control has no width to measure.
386
+ */
387
+ const ToolbarOverflow = React.forwardRef<HTMLDivElement, ToolbarOverflowProps>(
388
+ ({ label = 'More', className, children, ...props }, forwardedRef) => {
389
+ const items = React.Children.toArray(children);
390
+ const count = items.length;
391
+
392
+ const rootRef = React.useRef<HTMLDivElement | null>(null);
393
+ const widths = React.useRef<number[]>([]);
394
+ const triggerWidth = React.useRef(0);
395
+ const [shown, setShown] = React.useState(count);
396
+ const [tick, setTick] = React.useState(0);
397
+
398
+ // A different set of children is a different set of widths: show them all and measure again.
399
+ const [measuredCount, setMeasuredCount] = React.useState(count);
400
+ if (measuredCount !== count) {
401
+ setMeasuredCount(count);
402
+ setShown(count);
403
+ }
404
+ useIsomorphicLayoutEffect(() => {
405
+ widths.current = [];
406
+ }, [count]);
407
+
408
+ useIsomorphicLayoutEffect(() => {
409
+ const root = rootRef.current;
410
+ if (!root) return;
411
+
412
+ // The root's children are one seat per visible child, then the trigger.
413
+ const kids = Array.from(root.children) as HTMLElement[];
414
+ const visible = Math.min(shown, count);
415
+ for (let i = 0; i < visible; i++) {
416
+ const el = kids[i];
417
+ if (el) widths.current[i] = el.offsetWidth;
418
+ }
419
+ const trigger = kids[visible];
420
+ if (trigger) triggerWidth.current = trigger.offsetWidth;
421
+
422
+ const gap = Number.parseFloat(getComputedStyle(root).columnGap) || 0;
423
+ const available = root.clientWidth;
424
+
425
+ let total = 0;
426
+ let counted = 0;
427
+ for (let i = 0; i < count; i++) {
428
+ const width = widths.current[i];
429
+ // Never seen in the row, so there is nothing to decide with yet.
430
+ if (width === undefined) return;
431
+ // An empty seat leaves the layout, so it spends no gap.
432
+ if (width === 0) continue;
433
+ total += width + (counted > 0 ? gap : 0);
434
+ counted += 1;
435
+ }
436
+
437
+ let next = count;
438
+ if (total > available) {
439
+ // Before the trigger exists, the row's height stands in for its width: an icon-only
440
+ // button is square. The next pass, before paint, corrects it.
441
+ const budget = available - (triggerWidth.current || root.clientHeight) - gap;
442
+ let used = 0;
443
+ let drawn = 0;
444
+ next = 0;
445
+ for (let i = 0; i < count; i++) {
446
+ const own = widths.current[i]!;
447
+ if (own > 0) {
448
+ const width = own + (drawn > 0 ? gap : 0);
449
+ if (used + width > budget) break;
450
+ used += width;
451
+ drawn += 1;
452
+ }
453
+ next += 1;
454
+ }
455
+ }
456
+ if (next !== shown) setShown(next);
457
+ }, [shown, count, tick]);
458
+
459
+ // Watch the row and every seat in it: a control whose content changes (a page's actions
460
+ // arriving after navigation) changes its width without the row's width changing.
461
+ React.useEffect(() => {
462
+ const root = rootRef.current;
463
+ if (!root || typeof ResizeObserver === 'undefined') return;
464
+ const observer = new ResizeObserver(() => setTick((n) => n + 1));
465
+ observer.observe(root);
466
+ for (const seat of Array.from(root.children)) observer.observe(seat);
467
+ return () => observer.disconnect();
468
+ }, [shown, count]);
469
+
470
+ const attach = React.useCallback(
471
+ (node: HTMLDivElement | null) => {
472
+ rootRef.current = node;
473
+ if (typeof forwardedRef === 'function') forwardedRef(node);
474
+ else if (forwardedRef) forwardedRef.current = node;
475
+ },
476
+ [forwardedRef],
477
+ );
478
+
479
+ return (
480
+ <div {...props} ref={attach} className={classNames('kui-ToolbarOverflow', className)}>
481
+ {items.slice(0, shown).map((item, i) => (
482
+ // The seat is a position in the row, so its key is the index.
483
+ <div key={i} className="kui-ToolbarOverflowSeat">
484
+ {item}
485
+ </div>
486
+ ))}
487
+ {shown < count ? (
488
+ <DropdownMenu.Root>
489
+ <DropdownMenu.Trigger>
490
+ <ToolbarButton iconOnly aria-label={label}>
491
+ <MoreIcon />
492
+ </ToolbarButton>
493
+ </DropdownMenu.Trigger>
494
+ <DropdownMenu.Content align="end">
495
+ <InOverflowContext.Provider value>{items.slice(shown)}</InOverflowContext.Provider>
496
+ </DropdownMenu.Content>
497
+ </DropdownMenu.Root>
498
+ ) : null}
499
+ </div>
500
+ );
501
+ },
502
+ );
503
+ ToolbarOverflow.displayName = 'Toolbar.Overflow';
504
+
505
+ // ============================================================================
506
+ // ToolbarSlot and ToolbarFill
507
+ // ============================================================================
508
+
509
+ type SlotEntry = { id: string; node: React.ReactNode };
510
+
511
+ const EMPTY_ENTRIES: readonly SlotEntry[] = [];
512
+ const slotEntries = new Map<string, readonly SlotEntry[]>();
513
+ const slotListeners = new Set<() => void>();
514
+
515
+ function subscribeSlots(listener: () => void) {
516
+ slotListeners.add(listener);
517
+ return () => {
518
+ slotListeners.delete(listener);
519
+ };
520
+ }
521
+
522
+ function setSlotEntry(name: string, id: string, node: React.ReactNode) {
523
+ const list = slotEntries.get(name) ?? EMPTY_ENTRIES;
524
+ const index = list.findIndex((entry) => entry.id === id);
525
+ const next = index === -1 ? [...list, { id, node }] : list.map((entry) => (entry.id === id ? { id, node } : entry));
526
+ slotEntries.set(name, next);
527
+ slotListeners.forEach((listener) => listener());
528
+ }
529
+
530
+ function removeSlotEntry(name: string, id: string) {
531
+ const list = slotEntries.get(name);
532
+ if (!list) return;
533
+ const next = list.filter((entry) => entry.id !== id);
534
+ if (next.length === 0) slotEntries.delete(name);
535
+ else slotEntries.set(name, next);
536
+ slotListeners.forEach((listener) => listener());
537
+ }
538
+
539
+ interface ToolbarSlotProps {
540
+ /** Which `ToolbarFill` renders here. Use one name per slot. Defaults to `default`. */
541
+ name?: string;
542
+ }
543
+
544
+ /**
545
+ * A place in a toolbar that content elsewhere in the app fills, such as a page adding its own
546
+ * actions to a header toolbar the layout owns.
547
+ *
548
+ * It renders whatever the `ToolbarFill` with the same `name` holds, as if it were written here:
549
+ * the controls take the toolbar's size and join its arrow-key row. It adds no element.
550
+ */
551
+ function ToolbarSlot({ name = 'default' }: ToolbarSlotProps) {
552
+ const entries = React.useSyncExternalStore(
553
+ subscribeSlots,
554
+ () => slotEntries.get(name) ?? EMPTY_ENTRIES,
555
+ () => EMPTY_ENTRIES,
556
+ );
557
+ return (
558
+ <>
559
+ {entries.map((entry) => (
560
+ <React.Fragment key={entry.id}>{entry.node}</React.Fragment>
561
+ ))}
562
+ </>
563
+ );
564
+ }
565
+ ToolbarSlot.displayName = 'Toolbar.Slot';
566
+
567
+ interface ToolbarFillProps {
568
+ /** The `ToolbarSlot` to render into. Defaults to `default`. */
569
+ name?: string;
570
+ /** The controls to show in the slot, such as `ToolbarButton`s. */
571
+ children?: React.ReactNode;
572
+ }
573
+
574
+ /**
575
+ * Sends its children to the `ToolbarSlot` with the same `name`, and renders nothing where it
576
+ * is written. Use it instead of a React portal: a portal keeps the page's React tree, so a
577
+ * ToolbarButton in it can't join the toolbar's arrow keys.
578
+ *
579
+ * The children render inside the toolbar, so they read the toolbar's context, not the page's.
580
+ * They appear after the page mounts on the client, not in server-rendered HTML.
581
+ */
582
+ function ToolbarFill({ name = 'default', children }: ToolbarFillProps) {
583
+ const id = React.useId();
584
+ useIsomorphicLayoutEffect(() => {
585
+ setSlotEntry(name, id, children);
586
+ }, [name, id, children]);
587
+ useIsomorphicLayoutEffect(() => () => removeSlotEntry(name, id), [name, id]);
588
+ return null;
589
+ }
590
+ ToolbarFill.displayName = 'Toolbar.Fill';
591
+
215
592
  // ============================================================================
216
593
  // ToolbarSeparator
217
594
  // ============================================================================
@@ -220,11 +597,25 @@ type ToolbarSeparatorProps = ComponentPropsWithout<typeof ToolbarPrimitive.Separ
220
597
 
221
598
  /**
222
599
  * A gray hairline between two clusters, announced as a separator. Its direction is always
223
- * opposite to the toolbar's.
600
+ * opposite to the toolbar's. In a `ToolbarOverflow`'s menu it is a menu separator.
224
601
  */
225
602
  const ToolbarSeparator = React.forwardRef<HTMLDivElement, ToolbarSeparatorProps>(
226
603
  ({ className, ...props }, forwardedRef) => {
227
- useToolbarContext('ToolbarSeparator');
604
+ const toolbar = React.useContext(ToolbarContext);
605
+ const overflow = React.useContext(InOverflowContext);
606
+ if (overflow) return <DropdownMenu.Separator {...props} ref={forwardedRef} className={className} />;
607
+ if (!toolbar) {
608
+ return (
609
+ <div
610
+ role="separator"
611
+ aria-orientation="vertical"
612
+ data-orientation="vertical"
613
+ {...props}
614
+ ref={forwardedRef}
615
+ className={classNames('kui-ToolbarSeparator', className)}
616
+ />
617
+ );
618
+ }
228
619
  return (
229
620
  <ToolbarPrimitive.Separator
230
621
  {...props}
@@ -259,7 +650,9 @@ interface ToolbarTitleProps {
259
650
  */
260
651
  const ToolbarTitle = React.forwardRef<HTMLSpanElement, ToolbarTitleProps>(
261
652
  ({ className, children, style, id }, forwardedRef) => {
262
- const { size } = useToolbarContext('ToolbarTitle');
653
+ const toolbar = React.useContext(ToolbarContext);
654
+ const themeSize = useThemeSize<ToolbarSize>(undefined, toolbarRootPropDefs.size);
655
+ const size = toolbar?.size ?? themeSize;
263
656
  if (children === undefined || children === null || children === false) return null;
264
657
  return (
265
658
  <Text
@@ -289,6 +682,9 @@ const Toolbar = Object.assign(ToolbarRoot, {
289
682
  Button: ToolbarButton,
290
683
  Separator: ToolbarSeparator,
291
684
  Title: ToolbarTitle,
685
+ Overflow: ToolbarOverflow,
686
+ Slot: ToolbarSlot,
687
+ Fill: ToolbarFill,
292
688
  });
293
689
 
294
690
  export {
@@ -297,11 +693,18 @@ export {
297
693
  ToolbarButton,
298
694
  ToolbarSeparator,
299
695
  ToolbarTitle,
696
+ ToolbarOverflow,
697
+ ToolbarSlot,
698
+ ToolbarFill,
699
+ useToolbarOverflow,
300
700
  ToolbarRoot as Root,
301
701
  ToolbarGroup as Group,
302
702
  ToolbarButton as Button,
303
703
  ToolbarSeparator as Separator,
304
704
  ToolbarTitle as Title,
705
+ ToolbarOverflow as Overflow,
706
+ ToolbarSlot as Slot,
707
+ ToolbarFill as Fill,
305
708
  };
306
709
  export type {
307
710
  ToolbarProps,
@@ -309,9 +712,15 @@ export type {
309
712
  ToolbarButtonProps,
310
713
  ToolbarSeparatorProps,
311
714
  ToolbarTitleProps,
715
+ ToolbarOverflowProps,
716
+ ToolbarSlotProps,
717
+ ToolbarFillProps,
312
718
  ToolbarProps as RootProps,
313
719
  ToolbarGroupProps as GroupProps,
314
720
  ToolbarButtonProps as ButtonProps,
315
721
  ToolbarSeparatorProps as SeparatorProps,
316
722
  ToolbarTitleProps as TitleProps,
723
+ ToolbarOverflowProps as OverflowProps,
724
+ ToolbarSlotProps as SlotProps,
725
+ ToolbarFillProps as FillProps,
317
726
  };