@justanarthur/modo-ui 0.6.0-canary.8 → 0.6.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 (490) hide show
  1. package/README.md +66 -164
  2. package/dist/base.css +4 -141
  3. package/dist/blocks/sidebar-app/index.js +26 -40
  4. package/dist/components/AI/input-message/index.js +16 -23
  5. package/dist/components/AI/thinking-indicator/index.js +6 -9
  6. package/dist/components/accordion/index.d.ts +11 -39
  7. package/dist/components/accordion/index.js +13 -18
  8. package/dist/components/badge/index.d.ts +11 -18
  9. package/dist/components/badge/index.js +7 -12
  10. package/dist/components/button/index.d.ts +17 -53
  11. package/dist/components/button/index.js +6 -11
  12. package/dist/components/card/index.d.ts +9 -32
  13. package/dist/components/card/index.js +11 -17
  14. package/dist/components/copy/index.d.ts +8 -41
  15. package/dist/components/copy/index.js +9 -15
  16. package/dist/components/inputs/checkbox/index.d.ts +9 -28
  17. package/dist/components/inputs/checkbox/index.js +13 -18
  18. package/dist/components/inputs/color-picker/index.d.ts +14 -22
  19. package/dist/components/inputs/color-picker/index.js +18 -26
  20. package/dist/components/inputs/combobox/index.d.ts +20 -85
  21. package/dist/components/inputs/combobox/index.js +18 -27
  22. package/dist/components/inputs/date-time/calendar/index.d.ts +18 -24
  23. package/dist/components/inputs/date-time/calendar/index.js +11 -15
  24. package/dist/components/inputs/date-time/date-picker/index.d.ts +16 -105
  25. package/dist/components/inputs/date-time/date-picker/index.js +25 -35
  26. package/dist/components/inputs/date-time/date-range-picker/index.d.ts +12 -106
  27. package/dist/components/inputs/date-time/date-range-picker/index.js +24 -35
  28. package/dist/components/inputs/date-time/duration-picker/index.d.ts +13 -66
  29. package/dist/components/inputs/date-time/duration-picker/index.js +24 -33
  30. package/dist/components/inputs/date-time/month-picker/index.d.ts +10 -60
  31. package/dist/components/inputs/date-time/month-picker/index.js +23 -32
  32. package/dist/components/inputs/date-time/time-picker/index.d.ts +10 -58
  33. package/dist/components/inputs/date-time/time-picker/index.js +24 -33
  34. package/dist/components/inputs/input/index.d.ts +13 -95
  35. package/dist/components/inputs/input/index.js +9 -18
  36. package/dist/components/inputs/radio/index.d.ts +5 -20
  37. package/dist/components/inputs/radio/index.js +12 -16
  38. package/dist/components/inputs/search/index.d.ts +3 -3
  39. package/dist/components/inputs/search/index.js +18 -26
  40. package/dist/components/inputs/select/index.d.ts +23 -99
  41. package/dist/components/inputs/select/index.js +14 -29
  42. package/dist/components/inputs/slider/index.d.ts +0 -9
  43. package/dist/components/inputs/slider/index.js +5 -8
  44. package/dist/components/inputs/switch/index.d.ts +2 -8
  45. package/dist/components/inputs/switch/index.js +12 -15
  46. package/dist/components/inputs/textarea/index.d.ts +1 -20
  47. package/dist/components/inputs/textarea/index.js +6 -9
  48. package/dist/components/navigation/sidebar/index.d.ts +21 -44
  49. package/dist/components/navigation/sidebar/index.js +31 -42
  50. package/dist/components/navigation/tabs/index.d.ts +2 -8
  51. package/dist/components/navigation/tabs/index.js +10 -15
  52. package/dist/components/navigation/tabs-subtle/index.js +10 -13
  53. package/dist/components/overlays/alert-dialog/index.d.ts +16 -135
  54. package/dist/components/overlays/alert-dialog/index.js +13 -23
  55. package/dist/components/overlays/command/index.d.ts +20 -25
  56. package/dist/components/overlays/command/index.js +17 -25
  57. package/dist/components/overlays/context-menu/index.d.ts +17 -39
  58. package/dist/components/overlays/context-menu/index.js +18 -29
  59. package/dist/components/overlays/dialog/index.d.ts +16 -42
  60. package/dist/components/overlays/dialog/index.js +12 -20
  61. package/dist/components/overlays/dropdown/index.d.ts +34 -304
  62. package/dist/components/overlays/dropdown/index.js +17 -44
  63. package/dist/components/overlays/popover/index.d.ts +12 -38
  64. package/dist/components/overlays/popover/index.js +9 -13
  65. package/dist/components/overlays/preview-card/index.js +8 -12
  66. package/dist/components/overlays/sheet/index.d.ts +8 -25
  67. package/dist/components/overlays/sheet/index.js +13 -19
  68. package/dist/components/overlays/toast/index.d.ts +50 -209
  69. package/dist/components/overlays/toast/index.js +10 -23
  70. package/dist/components/overlays/tooltip/index.d.ts +21 -123
  71. package/dist/components/overlays/tooltip/index.js +6 -16
  72. package/dist/components/table/index.d.ts +8 -63
  73. package/dist/components/table/index.js +9 -20
  74. package/dist/index.d.ts +1048 -2999
  75. package/dist/index.js +82 -231
  76. package/dist/preset.d.ts +0 -22
  77. package/dist/preset.js +2 -24
  78. package/dist/primitives/code/index.js +5 -8
  79. package/dist/primitives/craft/index.js +6 -10
  80. package/dist/primitives/fluid-hover/index.js +8 -10
  81. package/dist/primitives/morph/index.js +10 -16
  82. package/dist/primitives/motion/index.js +8 -11
  83. package/dist/primitives/scroll-area/index.js +3 -5
  84. package/dist/primitives/sizes/index.js +4 -6
  85. package/dist/primitives/surface/index.js +4 -6
  86. package/dist/shared/{components-4y816hwp.js → components-0q0sqfh4.js} +49 -27
  87. package/dist/shared/components-0sn7ypjw.js +61 -0
  88. package/dist/shared/{components-vc864c51.js → components-11da9ajg.js} +5 -8
  89. package/dist/shared/components-1434p1mh.js +123 -0
  90. package/dist/shared/{components-t2a3qmy9.js → components-1z6tdadk.js} +24 -40
  91. package/dist/shared/{components-qs4rkqsj.js → components-27nnvrwe.js} +14 -15
  92. package/dist/shared/{components-av5t26rc.js → components-2dxkv6zm.js} +7 -8
  93. package/dist/shared/{components-wqrvqq5p.js → components-2ecg8svx.js} +152 -234
  94. package/dist/shared/{components-3ydr2fqe.js → components-2ph6t61s.js} +34 -37
  95. package/dist/shared/{components-6gk118w3.js → components-39jq9va1.js} +24 -29
  96. package/dist/shared/components-3ky44908.js +9 -0
  97. package/dist/shared/{components-y1qvbawa.js → components-3mkepka5.js} +25 -28
  98. package/dist/shared/{components-xqszvkj4.js → components-4700p9kz.js} +22 -24
  99. package/dist/shared/{components-yhgq0qxx.js → components-59efxjd9.js} +12 -13
  100. package/dist/shared/{components-9j9abkct.js → components-5vgpnxgy.js} +27 -51
  101. package/dist/shared/{components-8tt3xbb5.js → components-5xc2j8jz.js} +18 -19
  102. package/dist/shared/{components-jymmaevv.js → components-6p8tfcd6.js} +29 -57
  103. package/dist/shared/{components-4nck8acq.js → components-7r3etddy.js} +54 -19
  104. package/dist/shared/{components-skfd7kff.js → components-8snj490h.js} +32 -78
  105. package/dist/shared/{components-ctqmge8t.js → components-b0eac83j.js} +30 -9
  106. package/dist/shared/{components-9sttq78t.js → components-b2wyq2cq.js} +59 -41
  107. package/dist/shared/{components-vkwq2k96.js → components-b3c5et5b.js} +38 -49
  108. package/dist/shared/{components-rrbpmfx4.js → components-c6s6b43g.js} +2 -3
  109. package/dist/shared/{components-pw06rbxq.js → components-chacnk61.js} +19 -19
  110. package/dist/shared/{components-71nbt03m.js → components-cv16mryv.js} +7 -26
  111. package/dist/shared/{components-eqze3y30.js → components-d6xtjht3.js} +30 -35
  112. package/dist/shared/{components-5y5shqfd.js → components-dk0gjr5a.js} +18 -19
  113. package/dist/shared/{components-khspp26b.js → components-fzrq6tr3.js} +34 -37
  114. package/dist/shared/{components-km7fhgbk.js → components-gc5vtq2f.js} +30 -66
  115. package/dist/shared/components-gf5s6ap9.js +42 -0
  116. package/dist/shared/{components-qqcmtrbv.js → components-gz8zf3ec.js} +55 -56
  117. package/dist/shared/{components-mattt5jp.js → components-h2ajmhwn.js} +35 -107
  118. package/dist/shared/{components-awra5sff.js → components-hqeq3w9q.js} +16 -24
  119. package/dist/shared/{components-5tzhqbcw.js → components-hw9yk32z.js} +24 -36
  120. package/dist/shared/components-hyq23phv.js +310 -0
  121. package/dist/shared/{components-8mt5bsv6.js → components-jbbmdr74.js} +22 -41
  122. package/dist/shared/{components-dcc02hs2.js → components-jjw69c4c.js} +4 -7
  123. package/dist/shared/{components-2syq4mwc.js → components-jthe1pwb.js} +420 -139
  124. package/dist/shared/{components-r7q1zm7r.js → components-jwst3vtj.js} +76 -224
  125. package/dist/shared/{components-qdm3yh26.js → components-kvr7f9hy.js} +10 -19
  126. package/dist/shared/{components-s8yqk2dc.js → components-kwa6mrf9.js} +11 -46
  127. package/dist/shared/{components-de99ykt7.js → components-men63rwj.js} +2 -3
  128. package/dist/shared/{components-6b0zb8z3.js → components-mjthm1kf.js} +9 -13
  129. package/dist/shared/{components-2c64r8c9.js → components-n42c79bz.js} +22 -23
  130. package/dist/shared/{components-tz1fv35x.js → components-n7mjr357.js} +2 -3
  131. package/dist/shared/components-ng72k97e.js +128 -0
  132. package/dist/shared/{components-dyae0y7h.js → components-pbmqctfa.js} +65 -169
  133. package/dist/shared/{components-px2zm7dc.js → components-q5xj5c16.js} +8 -9
  134. package/dist/shared/components-raknhppb.js +64 -0
  135. package/dist/shared/{components-8rb25gbe.js → components-rr7a6ja9.js} +27 -59
  136. package/dist/shared/{components-5012r6gr.js → components-s083f38z.js} +34 -164
  137. package/dist/shared/components-s5ngg32c.js +267 -0
  138. package/dist/shared/components-sn1rxx1d.js +143 -0
  139. package/dist/shared/{components-r8eqs7gz.js → components-ta7shw28.js} +4 -4
  140. package/dist/shared/{components-9as3rf68.js → components-vc7vq5nz.js} +3 -6
  141. package/dist/shared/{components-ft3zdc79.js → components-vfbhxf5r.js} +5 -6
  142. package/dist/shared/components-vynjtrk6.js +19 -0
  143. package/dist/shared/{components-w0xq6q9k.js → components-w1r67ag9.js} +149 -294
  144. package/dist/shared/{components-z0bqtvcp.js → components-w90endve.js} +72 -71
  145. package/dist/shared/{components-t5pk5nmc.js → components-wvp1m52g.js} +102 -149
  146. package/dist/shared/components-wy9jpqny.js +146 -0
  147. package/dist/shared/{components-5sxjeh6h.js → components-y9y0g8er.js} +28 -52
  148. package/dist/shared/components-ypp01w3p.js +986 -0
  149. package/dist/shared/{components-t50hrswb.js → components-zfnmn5d4.js} +36 -82
  150. package/dist/shared/{components-jqpefjsn.js → components-zrkzcayz.js} +6 -54
  151. package/dist/shared/{components-vf45j12c.js → components-zx6b6yby.js} +18 -4
  152. package/dist/styles.css +32 -320
  153. package/dist/tailwind.css +0 -16
  154. package/dist/tokens.css +0 -67
  155. package/package.json +4 -227
  156. package/DESIGN.md +0 -623
  157. package/blocks/sidebar-app/examples.mdx +0 -33
  158. package/blocks/sidebar-app/index.tsx +0 -218
  159. package/blocks/sidebar-app/inset-topbar.tsx +0 -25
  160. package/blocks/sidebar-app/menu-grid.ts +0 -26
  161. package/blocks/sidebar-app/nav-data.ts +0 -36
  162. package/blocks/sidebar-app/search-field.tsx +0 -48
  163. package/blocks/sidebar-app/user-footer.tsx +0 -67
  164. package/blocks/sidebar-app/workspace-header.tsx +0 -129
  165. package/components/AI/input-message/examples.mdx +0 -130
  166. package/components/AI/input-message/file-thumbnail.tsx +0 -173
  167. package/components/AI/input-message/index.tsx +0 -1385
  168. package/components/AI/thinking-indicator/examples.mdx +0 -27
  169. package/components/AI/thinking-indicator/index.tsx +0 -210
  170. package/components/accordion/examples.mdx +0 -233
  171. package/components/accordion/index.tsx +0 -1071
  172. package/components/avatar/examples.mdx +0 -95
  173. package/components/avatar/index.tsx +0 -129
  174. package/components/badge/change-demo.tsx +0 -29
  175. package/components/badge/examples.mdx +0 -124
  176. package/components/badge/index.tsx +0 -225
  177. package/components/badge/variants.ts +0 -73
  178. package/components/button/examples.mdx +0 -168
  179. package/components/button/index.tsx +0 -424
  180. package/components/button/loading-demo.tsx +0 -25
  181. package/components/button/variants.ts +0 -168
  182. package/components/card/examples.mdx +0 -251
  183. package/components/card/index.tsx +0 -1070
  184. package/components/copy/examples.mdx +0 -125
  185. package/components/copy/index.tsx +0 -662
  186. package/components/inputs/checkbox/examples.mdx +0 -87
  187. package/components/inputs/checkbox/index.tsx +0 -611
  188. package/components/inputs/checkbox/select-all-demo.tsx +0 -48
  189. package/components/inputs/color-picker/examples.mdx +0 -111
  190. package/components/inputs/color-picker/index.tsx +0 -1981
  191. package/components/inputs/color-picker/variants.ts +0 -401
  192. package/components/inputs/combobox/examples.mdx +0 -366
  193. package/components/inputs/combobox/index.tsx +0 -1527
  194. package/components/inputs/combobox/remote-demo.tsx +0 -105
  195. package/components/inputs/date-time/calendar/examples.mdx +0 -45
  196. package/components/inputs/date-time/calendar/index.tsx +0 -370
  197. package/components/inputs/date-time/calendar/use-month-window.ts +0 -173
  198. package/components/inputs/date-time/date-picker/examples.mdx +0 -243
  199. package/components/inputs/date-time/date-picker/index.tsx +0 -476
  200. package/components/inputs/date-time/date-picker/masked-date-input.tsx +0 -348
  201. package/components/inputs/date-time/date-range-picker/examples.mdx +0 -93
  202. package/components/inputs/date-time/date-range-picker/index.tsx +0 -525
  203. package/components/inputs/date-time/duration-picker/examples.mdx +0 -40
  204. package/components/inputs/date-time/duration-picker/index.tsx +0 -253
  205. package/components/inputs/date-time/month-picker/examples.mdx +0 -45
  206. package/components/inputs/date-time/month-picker/index.tsx +0 -254
  207. package/components/inputs/date-time/picker-shell.tsx +0 -581
  208. package/components/inputs/date-time/time-columns.tsx +0 -94
  209. package/components/inputs/date-time/time-picker/examples.mdx +0 -57
  210. package/components/inputs/date-time/time-picker/index.tsx +0 -227
  211. package/components/inputs/field/examples.mdx +0 -117
  212. package/components/inputs/field/index.tsx +0 -268
  213. package/components/inputs/file-dropzone/examples.mdx +0 -83
  214. package/components/inputs/file-dropzone/file-row.tsx +0 -201
  215. package/components/inputs/file-dropzone/index.tsx +0 -316
  216. package/components/inputs/file-dropzone/upload-demo.tsx +0 -67
  217. package/components/inputs/file-dropzone/variants.ts +0 -94
  218. package/components/inputs/input/examples.mdx +0 -166
  219. package/components/inputs/input/index.tsx +0 -494
  220. package/components/inputs/input/password-demo.tsx +0 -30
  221. package/components/inputs/label/examples.mdx +0 -67
  222. package/components/inputs/label/index.tsx +0 -85
  223. package/components/inputs/number-input/examples.mdx +0 -69
  224. package/components/inputs/number-input/index.tsx +0 -221
  225. package/components/inputs/radio/examples.mdx +0 -77
  226. package/components/inputs/radio/index.tsx +0 -636
  227. package/components/inputs/search/examples.mdx +0 -74
  228. package/components/inputs/search/index.tsx +0 -333
  229. package/components/inputs/select/examples.mdx +0 -296
  230. package/components/inputs/select/index.tsx +0 -1044
  231. package/components/inputs/select/variants.ts +0 -32
  232. package/components/inputs/slider/examples.mdx +0 -153
  233. package/components/inputs/slider/index.tsx +0 -1867
  234. package/components/inputs/switch/examples.mdx +0 -96
  235. package/components/inputs/switch/index.tsx +0 -504
  236. package/components/inputs/textarea/examples.mdx +0 -126
  237. package/components/inputs/textarea/index.tsx +0 -207
  238. package/components/navigation/navigation-menu/examples.mdx +0 -136
  239. package/components/navigation/navigation-menu/index.tsx +0 -704
  240. package/components/navigation/pagination/examples.mdx +0 -74
  241. package/components/navigation/pagination/index.tsx +0 -401
  242. package/components/navigation/sidebar/examples.mdx +0 -325
  243. package/components/navigation/sidebar/index.tsx +0 -453
  244. package/components/navigation/sidebar/sidebar-core.tsx +0 -1408
  245. package/components/navigation/sidebar/sidebar-menu.tsx +0 -1495
  246. package/components/navigation/sidebar/sidebar.css +0 -74
  247. package/components/navigation/sidebar/variants.ts +0 -55
  248. package/components/navigation/tabs/examples.mdx +0 -89
  249. package/components/navigation/tabs/index.tsx +0 -494
  250. package/components/navigation/tabs-subtle/examples.mdx +0 -49
  251. package/components/navigation/tabs-subtle/index.tsx +0 -512
  252. package/components/overlays/alert-dialog/examples.mdx +0 -123
  253. package/components/overlays/alert-dialog/index.tsx +0 -276
  254. package/components/overlays/alert-dialog/pending-demo.tsx +0 -36
  255. package/components/overlays/command/examples.mdx +0 -113
  256. package/components/overlays/command/index.tsx +0 -425
  257. package/components/overlays/context-menu/examples.mdx +0 -56
  258. package/components/overlays/context-menu/index.tsx +0 -279
  259. package/components/overlays/dialog/examples.mdx +0 -165
  260. package/components/overlays/dialog/index.tsx +0 -451
  261. package/components/overlays/dropdown/dropdown-search.tsx +0 -395
  262. package/components/overlays/dropdown/examples.mdx +0 -444
  263. package/components/overlays/dropdown/index.tsx +0 -1241
  264. package/components/overlays/dropdown/menu-item.tsx +0 -510
  265. package/components/overlays/dropdown/menu-parts.tsx +0 -725
  266. package/components/overlays/popover/anchored-demo.tsx +0 -59
  267. package/components/overlays/popover/examples.mdx +0 -203
  268. package/components/overlays/popover/index.tsx +0 -317
  269. package/components/overlays/preview-card/examples.mdx +0 -61
  270. package/components/overlays/preview-card/index.tsx +0 -204
  271. package/components/overlays/sheet/examples.mdx +0 -101
  272. package/components/overlays/sheet/index.tsx +0 -307
  273. package/components/overlays/toast/examples.mdx +0 -85
  274. package/components/overlays/toast/global-demo.tsx +0 -72
  275. package/components/overlays/toast/index.tsx +0 -544
  276. package/components/overlays/toast/manager.ts +0 -193
  277. package/components/overlays/tooltip/examples.mdx +0 -106
  278. package/components/overlays/tooltip/index.tsx +0 -539
  279. package/components/progress/examples.mdx +0 -59
  280. package/components/progress/index.tsx +0 -174
  281. package/components/progress/progress.css +0 -49
  282. package/components/progress/step-demo.tsx +0 -27
  283. package/components/table/examples.mdx +0 -188
  284. package/components/table/index.tsx +0 -535
  285. package/components/table/sort-demo.tsx +0 -61
  286. package/dist/components/avatar/index.d.ts +0 -46
  287. package/dist/components/avatar/index.js +0 -19
  288. package/dist/components/badge/variants.d.ts +0 -33
  289. package/dist/components/badge/variants.js +0 -10
  290. package/dist/components/button/variants.d.ts +0 -39
  291. package/dist/components/button/variants.js +0 -8
  292. package/dist/components/inputs/color-picker/variants.d.ts +0 -61
  293. package/dist/components/inputs/color-picker/variants.js +0 -28
  294. package/dist/components/inputs/field/index.d.ts +0 -116
  295. package/dist/components/inputs/field/index.js +0 -29
  296. package/dist/components/inputs/file-dropzone/index.d.ts +0 -167
  297. package/dist/components/inputs/file-dropzone/index.js +0 -33
  298. package/dist/components/inputs/file-dropzone/variants.d.ts +0 -35
  299. package/dist/components/inputs/file-dropzone/variants.js +0 -12
  300. package/dist/components/inputs/label/index.d.ts +0 -32
  301. package/dist/components/inputs/label/index.js +0 -11
  302. package/dist/components/inputs/number-input/index.d.ts +0 -87
  303. package/dist/components/inputs/number-input/index.js +0 -21
  304. package/dist/components/inputs/select/variants.d.ts +0 -5
  305. package/dist/components/inputs/select/variants.js +0 -6
  306. package/dist/components/navigation/navigation-menu/index.d.ts +0 -126
  307. package/dist/components/navigation/navigation-menu/index.js +0 -41
  308. package/dist/components/navigation/pagination/index.d.ts +0 -75
  309. package/dist/components/navigation/pagination/index.js +0 -41
  310. package/dist/components/navigation/sidebar/variants.d.ts +0 -25
  311. package/dist/components/navigation/sidebar/variants.js +0 -28
  312. package/dist/components/progress/index.d.ts +0 -56
  313. package/dist/components/progress/index.js +0 -15
  314. package/dist/docs/index.d.ts +0 -83
  315. package/dist/docs/index.js +0 -288
  316. package/dist/docs/vite.d.ts +0 -31
  317. package/dist/docs/vite.js +0 -45
  318. package/dist/lib/date-locale.d.ts +0 -26
  319. package/dist/lib/date-locale.js +0 -24
  320. package/dist/lib/field-classes.d.ts +0 -149
  321. package/dist/lib/field-classes.js +0 -41
  322. package/dist/lib/field-variants.d.ts +0 -47
  323. package/dist/lib/field-variants.js +0 -26
  324. package/dist/lib/fluid-hover-highlight.d.ts +0 -112
  325. package/dist/lib/fluid-hover-highlight.js +0 -17
  326. package/dist/lib/focus-ring.d.ts +0 -18
  327. package/dist/lib/focus-ring.js +0 -11
  328. package/dist/lib/goo-indicator.d.ts +0 -46
  329. package/dist/lib/goo-indicator.js +0 -14
  330. package/dist/lib/icon-context.d.ts +0 -30
  331. package/dist/lib/icon-context.js +0 -12
  332. package/dist/lib/inert.d.ts +0 -9
  333. package/dist/lib/inert.js +0 -8
  334. package/dist/lib/morph-layers.d.ts +0 -93
  335. package/dist/lib/morph-layers.js +0 -13
  336. package/dist/lib/morph-part.d.ts +0 -21
  337. package/dist/lib/morph-part.js +0 -12
  338. package/dist/lib/popup.d.ts +0 -20
  339. package/dist/lib/popup.js +0 -12
  340. package/dist/lib/reduced-motion.d.ts +0 -9
  341. package/dist/lib/reduced-motion.js +0 -6
  342. package/dist/lib/row-index.d.ts +0 -10
  343. package/dist/lib/row-index.js +0 -8
  344. package/dist/lib/row-order.d.ts +0 -28
  345. package/dist/lib/row-order.js +0 -10
  346. package/dist/lib/scroll-column.d.ts +0 -31
  347. package/dist/lib/scroll-column.js +0 -19
  348. package/dist/lib/shape-context.d.ts +0 -30
  349. package/dist/lib/shape-context.js +0 -13
  350. package/dist/lib/shape-radius.d.ts +0 -19
  351. package/dist/lib/shape-radius.js +0 -6
  352. package/dist/lib/size-context.d.ts +0 -94
  353. package/dist/lib/size-context.js +0 -20
  354. package/dist/lib/size-scale.d.ts +0 -79
  355. package/dist/lib/size-scale.js +0 -8
  356. package/dist/lib/slot.d.ts +0 -39
  357. package/dist/lib/slot.js +0 -14
  358. package/dist/lib/springs.d.ts +0 -44
  359. package/dist/lib/springs.js +0 -8
  360. package/dist/lib/surface-classes.d.ts +0 -19
  361. package/dist/lib/surface-classes.js +0 -10
  362. package/dist/lib/surface-context.d.ts +0 -9
  363. package/dist/lib/surface-context.js +0 -8
  364. package/dist/lib/use-controllable-state.d.ts +0 -2
  365. package/dist/lib/use-controllable-state.js +0 -6
  366. package/dist/lib/use-fluid-hover.d.ts +0 -138
  367. package/dist/lib/use-fluid-hover.js +0 -14
  368. package/dist/lib/use-is-mobile.d.ts +0 -2
  369. package/dist/lib/use-is-mobile.js +0 -6
  370. package/dist/lib/use-keyboard-nav-gate.d.ts +0 -20
  371. package/dist/lib/use-keyboard-nav-gate.js +0 -7
  372. package/dist/lib/use-merge-split.d.ts +0 -47
  373. package/dist/lib/use-merge-split.js +0 -15
  374. package/dist/lib/use-morph.d.ts +0 -101
  375. package/dist/lib/use-morph.js +0 -20
  376. package/dist/lib/use-touch-primary.d.ts +0 -2
  377. package/dist/lib/use-touch-primary.js +0 -6
  378. package/dist/lib/utils.d.ts +0 -3
  379. package/dist/lib/utils.js +0 -6
  380. package/dist/primitives/separator/index.d.ts +0 -25
  381. package/dist/primitives/separator/index.js +0 -9
  382. package/dist/primitives/skeleton/index.d.ts +0 -35
  383. package/dist/primitives/skeleton/index.js +0 -13
  384. package/dist/shared/components-124epb7f.js +0 -53
  385. package/dist/shared/components-1kab3j44.js +0 -337
  386. package/dist/shared/components-26snnbs9.js +0 -322
  387. package/dist/shared/components-34txk9rj.js +0 -35
  388. package/dist/shared/components-3h92d94m.js +0 -23
  389. package/dist/shared/components-4vfm04wq.js +0 -82
  390. package/dist/shared/components-54nq988h.js +0 -123
  391. package/dist/shared/components-7s7pykk5.js +0 -281
  392. package/dist/shared/components-7zkhz3r8.js +0 -399
  393. package/dist/shared/components-8v644a0s.js +0 -298
  394. package/dist/shared/components-a4evvq8h.js +0 -271
  395. package/dist/shared/components-adkarj8n.js +0 -35
  396. package/dist/shared/components-b1e239g3.js +0 -28
  397. package/dist/shared/components-b94t6qtj.js +0 -143
  398. package/dist/shared/components-c9yr4ed1.js +0 -44
  399. package/dist/shared/components-cwg1d0w6.js +0 -254
  400. package/dist/shared/components-d3shbwqq.js +0 -95
  401. package/dist/shared/components-dhgk6mbt.js +0 -16
  402. package/dist/shared/components-drxrtnp2.js +0 -25
  403. package/dist/shared/components-ej4r7wmj.js +0 -482
  404. package/dist/shared/components-f7h57m6t.js +0 -59
  405. package/dist/shared/components-fejdzvqc.js +0 -448
  406. package/dist/shared/components-gx4h5rbb.js +0 -40
  407. package/dist/shared/components-gyt7my41.js +0 -328
  408. package/dist/shared/components-h6p86be3.js +0 -19
  409. package/dist/shared/components-h83az0bz.js +0 -33
  410. package/dist/shared/components-hdzrqqpx.js +0 -55
  411. package/dist/shared/components-krtx3m5b.js +0 -84
  412. package/dist/shared/components-kswxnm3h.js +0 -24
  413. package/dist/shared/components-mpa2y6x8.js +0 -277
  414. package/dist/shared/components-mrbaxt8q.js +0 -62
  415. package/dist/shared/components-pt5ftm4p.js +0 -38
  416. package/dist/shared/components-rpw4md2b.js +0 -179
  417. package/dist/shared/components-rtadhd9j.js +0 -64
  418. package/dist/shared/components-tz4gaf1v.js +0 -23
  419. package/dist/shared/components-wbbckbw8.js +0 -34
  420. package/dist/shared/components-xdqmt6ed.js +0 -20
  421. package/dist/shared/components-xjkdvnbg.js +0 -107
  422. package/dist/shared/components-z3v0n0de.js +0 -11
  423. package/dist/shared/components-z6dfqtyt.js +0 -1545
  424. package/dist/tokens/colors.css +0 -230
  425. package/dist/tokens/motion.css +0 -40
  426. package/dist/tokens/radius.css +0 -10
  427. package/dist/tokens/spacing.css +0 -9
  428. package/dist/tokens/typography.css +0 -119
  429. package/docs/chrome.css +0 -120
  430. package/docs/chrome.tsx +0 -283
  431. package/docs/index.ts +0 -9
  432. package/docs/vite.ts +0 -85
  433. package/index.ts +0 -60
  434. package/lib/date-locale.ts +0 -195
  435. package/lib/field-classes.ts +0 -121
  436. package/lib/field-variants.ts +0 -117
  437. package/lib/fluid-hover-highlight.tsx +0 -139
  438. package/lib/focus-ring.tsx +0 -46
  439. package/lib/goo-indicator.tsx +0 -261
  440. package/lib/icon-context.tsx +0 -310
  441. package/lib/inert.ts +0 -22
  442. package/lib/morph-layers.tsx +0 -102
  443. package/lib/morph-part.tsx +0 -49
  444. package/lib/popup.ts +0 -52
  445. package/lib/reduced-motion.ts +0 -19
  446. package/lib/row-index.tsx +0 -29
  447. package/lib/row-order.tsx +0 -126
  448. package/lib/scroll-column.tsx +0 -273
  449. package/lib/shape-context.tsx +0 -138
  450. package/lib/shape-radius.ts +0 -67
  451. package/lib/size-context.tsx +0 -66
  452. package/lib/size-scale.ts +0 -115
  453. package/lib/slot.ts +0 -115
  454. package/lib/springs.ts +0 -62
  455. package/lib/surface-classes.ts +0 -58
  456. package/lib/surface-context.tsx +0 -21
  457. package/lib/use-controllable-state.ts +0 -44
  458. package/lib/use-fluid-hover.ts +0 -541
  459. package/lib/use-is-mobile.ts +0 -25
  460. package/lib/use-keyboard-nav-gate.ts +0 -45
  461. package/lib/use-merge-split.tsx +0 -209
  462. package/lib/use-morph.ts +0 -557
  463. package/lib/use-touch-primary.tsx +0 -43
  464. package/lib/utils.ts +0 -37
  465. package/preset.ts +0 -199
  466. package/primitives/code/examples.mdx +0 -27
  467. package/primitives/code/index.tsx +0 -80
  468. package/primitives/craft/demos.tsx +0 -173
  469. package/primitives/craft/examples.mdx +0 -142
  470. package/primitives/craft/index.tsx +0 -76
  471. package/primitives/fluid-hover/examples.mdx +0 -84
  472. package/primitives/fluid-hover/index.tsx +0 -316
  473. package/primitives/morph/examples.mdx +0 -139
  474. package/primitives/morph/index.tsx +0 -192
  475. package/primitives/motion/examples.mdx +0 -100
  476. package/primitives/motion/index.tsx +0 -160
  477. package/primitives/scroll-area/examples.mdx +0 -58
  478. package/primitives/scroll-area/index.tsx +0 -204
  479. package/primitives/separator/examples.mdx +0 -30
  480. package/primitives/separator/index.tsx +0 -53
  481. package/primitives/sizes/examples.mdx +0 -167
  482. package/primitives/sizes/index.tsx +0 -89
  483. package/primitives/skeleton/examples.mdx +0 -51
  484. package/primitives/skeleton/index.tsx +0 -72
  485. package/primitives/skeleton/skeleton.css +0 -15
  486. package/primitives/surface/examples.mdx +0 -173
  487. package/primitives/surface/index.tsx +0 -109
  488. package/primitives/surface/surface.css +0 -176
  489. /package/dist/shared/{components-3ey0hzpb.js → components-1v7rxytx.js} +0 -0
  490. /package/dist/shared/{components-jcnjay5g.js → components-ezxhrmer.js} +0 -0
@@ -1,725 +0,0 @@
1
- /*
2
- * Local addition (not part of Fluid Functionalism): the children-based menu
3
- * parts shadcn's DropdownMenu has and the FF port lacked. Groups, value-keyed
4
- * checkbox and radio rows, and submenus, all on Base UI's Menu
5
- * (`Menu.Group`, `Menu.CheckboxItem`, `Menu.RadioGroup` / `Menu.RadioItem`,
6
- * `Menu.SubmenuRoot` / `Menu.SubmenuTrigger`). The rows are `MenuItem`; a
7
- * submenu is a panel of its own (fluid hover, keyboard ring, selection
8
- * backgrounds) that grows out of its trigger row through the morph engine.
9
- * `useMenuPanel` is the state both popups share; both draw the shared
10
- * keyboard ring (`lib/focus-ring.tsx`, pinned to the rounded shape).
11
- */
12
-
13
- import { Menu, type MenuRootChangeEventDetails } from '@base-ui/react/menu'
14
- import {
15
- type ComponentProps,
16
- createContext,
17
- type FocusEvent,
18
- forwardRef,
19
- type HTMLAttributes,
20
- type MutableRefObject,
21
- type ReactNode,
22
- type RefObject,
23
- type SyntheticEvent,
24
- useCallback,
25
- useContext,
26
- useEffect,
27
- useImperativeHandle,
28
- useMemo,
29
- useRef,
30
- useState,
31
- } from 'react'
32
- import { FluidHoverHighlight } from '../../../lib/fluid-hover-highlight'
33
- import { FocusRing } from '../../../lib/focus-ring'
34
- import { type IconComponent, useIcon } from '../../../lib/icon-context'
35
- import { MorphSurface } from '../../../lib/morph-layers'
36
- import { isDisabledRow, popupScrollAreaClass, popupViewportClass } from '../../../lib/popup'
37
- import { RowOrderContext, useRowOrder, useRowSlot } from '../../../lib/row-order'
38
- import { shapeMap } from '../../../lib/shape-context'
39
- import { useSize } from '../../../lib/size-context'
40
- import { SURFACE_BG, SURFACE_SHADOW } from '../../../lib/surface-classes'
41
- import { SurfaceProvider, useSurface } from '../../../lib/surface-context'
42
- import { useControllableState } from '../../../lib/use-controllable-state'
43
- import { type ItemRect, type UseFluidHoverReturn, useFluidHover } from '../../../lib/use-fluid-hover'
44
- import { useKeyboardNavGate } from '../../../lib/use-keyboard-nav-gate'
45
- import { SelectionBackgrounds, useMergeSplitBlocks, useSelectionRuns } from '../../../lib/use-merge-split'
46
- import { type MorphOrigin, useMorph, useMorphOrigin } from '../../../lib/use-morph'
47
- import { cn } from '../../../lib/utils'
48
- import { ScrollArea } from '../../../primitives/scroll-area'
49
- import {
50
- DropdownContext,
51
- type DropdownContextValue,
52
- MenuItem,
53
- type MenuItemRenderOptions,
54
- useDropdown,
55
- } from './menu-item'
56
-
57
- // Menus keep the "rounded" shape whatever the rest of the UI is (index.tsx).
58
- const shape = shapeMap.rounded
59
-
60
- const NO_INDICES: number[] = []
61
-
62
- type MenuPositionerProps = ComponentProps<typeof Menu.Positioner>
63
- type MenuPopupProps = ComponentProps<typeof Menu.Popup>
64
- type MenuPortalProps = ComponentProps<typeof Menu.Portal>
65
-
66
- function mergeRefs<T>(...refs: (React.Ref<T> | undefined)[]) {
67
- return (node: T | null) => {
68
- for (const ref of refs) {
69
- if (typeof ref === 'function') ref(node)
70
- else if (ref) (ref as MutableRefObject<T | null>).current = node
71
- }
72
- }
73
- }
74
-
75
- /**
76
- * A submenu is a React child of the popup that holds its trigger, so its
77
- * events bubble there through the portal. A panel acts only on events that
78
- * happened in its own DOM.
79
- */
80
- const ownEvent = (e: SyntheticEvent) => (e.currentTarget as Node).contains(e.target as Node)
81
-
82
- /** Runs a caller's handler, then the panel's own, so spread HTML attributes never replace what the popup needs. */
83
- function chain<E>(theirs: ((e: E) => void) | undefined, own: (e: E) => void) {
84
- return (e: E) => {
85
- theirs?.(e)
86
- own(e)
87
- }
88
- }
89
-
90
- /** Wraps a MenuItem's styled row in the Base UI menu-item primitive. */
91
- function renderPopupItem({
92
- radio,
93
- checkbox,
94
- checked,
95
- value,
96
- disabled,
97
- label,
98
- closeOnClick,
99
- onClick,
100
- element,
101
- children,
102
- }: MenuItemRenderOptions) {
103
- if (checkbox)
104
- return (
105
- <Menu.CheckboxItem
106
- checked={!!checked}
107
- disabled={disabled}
108
- label={label}
109
- closeOnClick={closeOnClick}
110
- onClick={onClick}
111
- render={element}
112
- >
113
- {children}
114
- </Menu.CheckboxItem>
115
- )
116
- if (radio)
117
- return (
118
- <Menu.RadioItem
119
- value={value}
120
- disabled={disabled}
121
- label={label}
122
- closeOnClick={closeOnClick}
123
- onClick={onClick}
124
- render={element}
125
- >
126
- {children}
127
- </Menu.RadioItem>
128
- )
129
- return (
130
- <Menu.Item disabled={disabled} label={label} closeOnClick={closeOnClick} onClick={onClick} render={element}>
131
- {children}
132
- </Menu.Item>
133
- )
134
- }
135
-
136
- /** The rows a `Dropdown.CheckboxItem` / `Dropdown.RadioItem` reports checked, for the merged selection background. */
137
- function useValueChecked() {
138
- const [valueChecked, setValueChecked] = useState(NO_INDICES)
139
- const reportChecked = useCallback(
140
- (index: number, on: boolean) =>
141
- setValueChecked(prev =>
142
- on === prev.includes(index) ? prev : on ? [...prev, index] : prev.filter(i => i !== index),
143
- ),
144
- [],
145
- )
146
- return { valueChecked, reportChecked }
147
- }
148
-
149
- // ---------------------------------------------------------------------------
150
- // The state a popup panel keeps: fluid hover, the row order, the keyboard
151
- // ring, the highlight an open submenu pins, and the value-checked rows.
152
- // ---------------------------------------------------------------------------
153
-
154
- function useMenuPanel(containerRef: RefObject<HTMLDivElement | null>, open: boolean) {
155
- // Annotated: left to inference, the declaration emit names this type through the
156
- // root barrel (`import("../../..")`), a cycle that makes bunup's d.ts bundling
157
- // silently drop `index.d.ts` and every entry importing the dropdown.
158
- const hover: UseFluidHoverReturn = useFluidHover(containerRef, { isItemDisabled: isDisabledRow })
159
- const { activeIndex, setActiveIndex, itemRects, isMeasured } = hover
160
- const rowOrder = useRowOrder()
161
- const [focusedIndex, setFocusedIndex] = useState<number | null>(null)
162
- const { keyboardNavRef, trackKeyboardNav } = useKeyboardNavGate(open)
163
-
164
- const [pinned, setPinned] = useState<number | null>(null)
165
- const pin = useCallback((index: number, on: boolean) => setPinned(p => (on ? index : p === index ? null : p)), [])
166
-
167
- const { valueChecked, reportChecked } = useValueChecked()
168
-
169
- // A close drops the ring and the highlight, so the next open doesn't
170
- // spring them over from the last row.
171
- useEffect(() => {
172
- if (open) return
173
- setFocusedIndex(null)
174
- setActiveIndex(null)
175
- }, [open, setActiveIndex])
176
-
177
- const lit = activeIndex ?? pinned
178
- const shownHover = useMemo(() => ({ ...hover, activeIndex: lit }), [hover, lit])
179
- const focusRect: ItemRect | null = isMeasured && focusedIndex !== null ? (itemRects[focusedIndex] ?? null) : null
180
-
181
- /** A row took focus: light it, and ring it when the keyboard moved it. */
182
- const focusRow = useCallback(
183
- (e: FocusEvent) => {
184
- const row = (e.target as HTMLElement).closest<HTMLElement>('[data-fluid-hover-index]')
185
- if (!row) return false
186
- const index = Number(row.getAttribute('data-fluid-hover-index'))
187
- // Base UI keeps disabled rows focusable; they get the ring, never the light.
188
- setActiveIndex(isDisabledRow(row) ? null : index)
189
- setFocusedIndex(keyboardNavRef.current && (e.target as HTMLElement).matches(':focus-visible') ? index : null)
190
- return true
191
- },
192
- [keyboardNavRef, setActiveIndex],
193
- )
194
-
195
- return {
196
- hover,
197
- shownHover,
198
- lit,
199
- rowOrder,
200
- focusRect,
201
- setFocusedIndex,
202
- focusRow,
203
- trackKeyboardNav,
204
- pin,
205
- valueChecked,
206
- reportChecked,
207
- }
208
- }
209
-
210
- // ---------------------------------------------------------------------------
211
- // Dropdown.Group
212
- // ---------------------------------------------------------------------------
213
-
214
- /** True inside a `Dropdown.Group`, where `Dropdown.Label` names the group. */
215
- const DropdownGroupContext = createContext(false)
216
-
217
- interface DropdownGroupProps extends HTMLAttributes<HTMLDivElement> {
218
- /** Rows, with an optional `Dropdown.Label` first: it becomes the group's accessible name. */
219
- children?: ReactNode
220
- /** Extra classes. */
221
- className?: string
222
- }
223
-
224
- /** A run of related rows (role="group"), named by the `Dropdown.Label` inside it. */
225
- const DropdownGroup = forwardRef<HTMLDivElement, DropdownGroupProps>(({ className, ...props }, ref) => {
226
- const own = useRef<HTMLDivElement>(null)
227
- useRowSlot(own, undefined, true)
228
- return (
229
- <DropdownGroupContext.Provider value={true}>
230
- <Menu.Group ref={mergeRefs(own, ref)} className={cn('flex flex-col', className)} {...props} />
231
- </DropdownGroupContext.Provider>
232
- )
233
- })
234
-
235
- DropdownGroup.displayName = 'DropdownGroup'
236
-
237
- // ---------------------------------------------------------------------------
238
- // Dropdown.CheckboxItem
239
- // ---------------------------------------------------------------------------
240
-
241
- interface DropdownCheckboxItemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect' | 'defaultChecked'> {
242
- /** Whether the row is checked. Pair with `onCheckedChange`. */
243
- checked?: boolean
244
- /** Initial checked state, for an uncontrolled row. Defaults to `false`. */
245
- defaultChecked?: boolean
246
- /** Called with the new state when the row is toggled. */
247
- onCheckedChange?: (checked: boolean) => void
248
- /** Optional leading icon. */
249
- icon?: IconComponent
250
- /** The row text. Omit it to pass the row's content as `children`. */
251
- label?: string
252
- /** Typeahead text for a row whose content is more than a string (an icon beside markup): the key a press matches while the menu is open. Defaults to `label`, else the row's text `children`. */
253
- textValue?: string
254
- /** The row's content when there is no `label`. */
255
- children?: ReactNode
256
- /** Position among the panel's rows. Omitted, the row takes its place in document order. */
257
- index?: number
258
- /** Called when the row is picked, before it toggles. With `closeOnClick`, `event.preventDefault()` keeps the menu open. */
259
- onSelect?: (event: Event) => void
260
- /** Dims the row; the pointer and the keyboard skip it. Defaults to `false`. */
261
- disabled?: boolean
262
- /** Whether toggling closes the menu. Defaults to `false`. */
263
- closeOnClick?: boolean
264
- /** Indents the row to the label column of rows with an icon. Defaults to `false`. */
265
- inset?: boolean
266
- /** A keyboard shortcut shown muted at the row's end. */
267
- shortcut?: ReactNode
268
- /** Extra classes for the row. */
269
- className?: string
270
- }
271
-
272
- /** A row that toggles on and off by itself (role="menuitemcheckbox"), keyed on its own state rather than an index. */
273
- const DropdownCheckboxItem = forwardRef<HTMLDivElement, DropdownCheckboxItemProps>(
274
- ({ checked, defaultChecked = false, onCheckedChange, onSelect, closeOnClick = false, ...props }, ref) => {
275
- const [on, setOn] = useControllableState(checked, defaultChecked, onCheckedChange)
276
- return (
277
- <MenuItem
278
- ref={ref}
279
- kind="checkbox"
280
- checked={on}
281
- closeOnClick={closeOnClick}
282
- onSelect={event => {
283
- onSelect?.(event)
284
- setOn(prev => !prev)
285
- }}
286
- {...props}
287
- />
288
- )
289
- },
290
- )
291
-
292
- DropdownCheckboxItem.displayName = 'DropdownCheckboxItem'
293
-
294
- // ---------------------------------------------------------------------------
295
- // Dropdown.RadioGroup + Dropdown.RadioItem
296
- // ---------------------------------------------------------------------------
297
-
298
- const RadioValueContext = createContext<{ value?: string; select: (value: string) => void } | null>(null)
299
-
300
- interface DropdownRadioGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, 'defaultValue' | 'onChange'> {
301
- /** The picked row's value. Pair with `onValueChange`. */
302
- value?: string
303
- /** Initial value, for an uncontrolled group. */
304
- defaultValue?: string
305
- /** Called with the picked row's value. */
306
- onValueChange?: (value: string) => void
307
- /** `Dropdown.RadioItem` rows, plus an optional `Dropdown.Label`. */
308
- children?: ReactNode
309
- /** Extra classes. */
310
- className?: string
311
- }
312
-
313
- /** One choice among its `Dropdown.RadioItem` rows, keyed on their `value`. */
314
- const DropdownRadioGroup = forwardRef<HTMLDivElement, DropdownRadioGroupProps>(
315
- ({ value, defaultValue, onValueChange, className, ...props }, ref) => {
316
- const [current, setCurrent] = useControllableState<string | undefined>(value, defaultValue, next => {
317
- if (next !== undefined) onValueChange?.(next)
318
- })
319
- const own = useRef<HTMLDivElement>(null)
320
- useRowSlot(own, undefined, true)
321
- const ctx = useMemo(() => ({ value: current, select: (next: string) => setCurrent(next) }), [current, setCurrent])
322
- return (
323
- <RadioValueContext.Provider value={ctx}>
324
- <DropdownGroupContext.Provider value={false}>
325
- <Menu.RadioGroup
326
- ref={mergeRefs(own, ref)}
327
- value={current ?? null}
328
- className={cn('flex flex-col', className)}
329
- {...props}
330
- />
331
- </DropdownGroupContext.Provider>
332
- </RadioValueContext.Provider>
333
- )
334
- },
335
- )
336
-
337
- DropdownRadioGroup.displayName = 'DropdownRadioGroup'
338
-
339
- interface DropdownRadioItemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> {
340
- /** The value this row stands for in its `Dropdown.RadioGroup`. */
341
- value: string
342
- /** Optional leading icon. */
343
- icon?: IconComponent
344
- /** The row text. Omit it to pass the row's content as `children`. */
345
- label?: string
346
- /** Typeahead text for a row whose content is more than a string (an icon beside markup): the key a press matches while the menu is open. Defaults to `label`, else the row's text `children`. */
347
- textValue?: string
348
- /** The row's content when there is no `label`. */
349
- children?: ReactNode
350
- /** Position among the panel's rows. Omitted, the row takes its place in document order. */
351
- index?: number
352
- /** Called when the row is picked, before the group's value changes. Call `event.preventDefault()` to keep the menu open. */
353
- onSelect?: (event: Event) => void
354
- /** Dims the row; the pointer and the keyboard skip it. Defaults to `false`. */
355
- disabled?: boolean
356
- /** Whether picking the row closes the menu. Defaults to `true`. */
357
- closeOnClick?: boolean
358
- /** Indents the row to the label column of rows with an icon. Defaults to `false`. */
359
- inset?: boolean
360
- /** A keyboard shortcut shown muted at the row's end. */
361
- shortcut?: ReactNode
362
- /** Extra classes for the row. */
363
- className?: string
364
- }
365
-
366
- /** A row of a `Dropdown.RadioGroup` (role="menuitemradio"), checked while the group's value is its `value`. */
367
- const DropdownRadioItem = forwardRef<HTMLDivElement, DropdownRadioItemProps>(({ value, onSelect, ...props }, ref) => {
368
- const group = useContext(RadioValueContext)
369
- return (
370
- <MenuItem
371
- ref={ref}
372
- kind="radio"
373
- value={value}
374
- checked={group?.value === value}
375
- onSelect={event => {
376
- onSelect?.(event)
377
- group?.select(value)
378
- }}
379
- {...props}
380
- />
381
- )
382
- })
383
-
384
- DropdownRadioItem.displayName = 'DropdownRadioItem'
385
-
386
- // ---------------------------------------------------------------------------
387
- // Dropdown.Sub + Dropdown.SubTrigger + Dropdown.SubContent
388
- // ---------------------------------------------------------------------------
389
-
390
- interface SubContextValue {
391
- open: boolean
392
- origin: RefObject<MorphOrigin>
393
- }
394
-
395
- const SubContext = createContext<SubContextValue | null>(null)
396
-
397
- function useSubContext() {
398
- const ctx = useContext(SubContext)
399
- if (!ctx) throw new Error('Dropdown.SubTrigger and Dropdown.SubContent must be inside <Dropdown.Sub>')
400
- return ctx
401
- }
402
-
403
- interface DropdownSubProps {
404
- /** `Dropdown.SubTrigger` and `Dropdown.SubContent`. */
405
- children: ReactNode
406
- /** Controlled open state. Pair with `onOpenChange`. */
407
- open?: boolean
408
- /** Initial open state, for an uncontrolled submenu. Defaults to `false`. */
409
- defaultOpen?: boolean
410
- /** Called when the submenu opens or closes, with Base UI's event details: `reason` and `cancel()`, which keeps the submenu as it is. */
411
- onOpenChange?: (open: boolean, details: MenuRootChangeEventDetails) => void
412
- /** Disables the submenu. Defaults to `false`. */
413
- disabled?: boolean
414
- }
415
-
416
- /** A submenu: its trigger row and its panel. Lives inside `Dropdown.Content` (or another submenu). */
417
- function DropdownSub({ children, open, defaultOpen = false, onOpenChange, disabled = false }: DropdownSubProps) {
418
- const [current, setCurrent] = useControllableState(open, defaultOpen)
419
- const { origin, capture } = useMorphOrigin()
420
- const ctx = useMemo(() => ({ open: current, origin }), [current, origin])
421
- return (
422
- <SubContext.Provider value={ctx}>
423
- <Menu.SubmenuRoot
424
- open={current}
425
- disabled={disabled}
426
- onOpenChange={(next, details) => {
427
- // Base UI re-reports a sub that is already closed as closed (reason `sibling-open`,
428
- // once per sibling that opens). The caller hears changes only, as it did through
429
- // useControllableState's no-op skip: a handler shared with the root must not see them.
430
- if (next === current) return
431
- onOpenChange?.(next, details)
432
- if (details.isCanceled) return
433
- if (next) capture(details)
434
- setCurrent(next)
435
- }}
436
- >
437
- {children}
438
- </Menu.SubmenuRoot>
439
- </SubContext.Provider>
440
- )
441
- }
442
-
443
- DropdownSub.displayName = 'DropdownSub'
444
-
445
- interface DropdownSubTriggerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> {
446
- /** Optional leading icon. */
447
- icon?: IconComponent
448
- /** The row text. Omit it to pass the row's content as `children`. */
449
- label?: string
450
- /** Typeahead text for a row whose content is more than a string (an icon beside markup): the key a press matches while the menu is open. Defaults to `label`, else the row's text `children`. */
451
- textValue?: string
452
- /** The row's content when there is no `label`. */
453
- children?: ReactNode
454
- /** Position among the panel's rows. Omitted, the row takes its place in document order. */
455
- index?: number
456
- /** Dims the row; the pointer and the keyboard skip it. Defaults to `false`. */
457
- disabled?: boolean
458
- /** Indents the row to the label column of rows with an icon. Defaults to `false`. */
459
- inset?: boolean
460
- /** Open the submenu when the pointer rests on the row. Defaults to `true`. */
461
- openOnHover?: boolean
462
- /** How long the pointer rests before it opens, in ms. Defaults to `100`. */
463
- delay?: number
464
- /** How long before a hover-opened submenu closes once the pointer leaves, in ms. Defaults to `0`. */
465
- closeDelay?: number
466
- /** Extra classes for the row. */
467
- className?: string
468
- }
469
-
470
- /**
471
- * The row that opens a submenu, with a trailing chevron: ArrowRight, a press
472
- * or a resting pointer opens it, ArrowLeft closes it. Its row stays lit while
473
- * the submenu is open.
474
- */
475
- const DropdownSubTrigger = forwardRef<HTMLDivElement, DropdownSubTriggerProps>(
476
- ({ openOnHover, delay, closeDelay, ...props }, ref) => {
477
- const { open, origin } = useSubContext()
478
- const parent = useDropdown()
479
- const Chevron = useIcon('chevron-right')
480
- const size = useSize()
481
-
482
- const ctx = useMemo<DropdownContextValue>(
483
- () => ({
484
- ...parent,
485
- renderMenuItem: ({ disabled, label, onClick, element, children }) => (
486
- <Menu.SubmenuTrigger
487
- disabled={disabled}
488
- label={label}
489
- onClick={onClick}
490
- openOnHover={openOnHover}
491
- delay={delay}
492
- closeDelay={closeDelay}
493
- render={element}
494
- >
495
- {children}
496
- <Chevron
497
- size={size.icon}
498
- strokeWidth={open ? 2 : 1.5}
499
- className={cn(
500
- 'ml-auto shrink-0 transition-[color,stroke-width] duration-fast',
501
- open ? 'text-foreground' : 'text-muted-foreground',
502
- )}
503
- />
504
- </Menu.SubmenuTrigger>
505
- ),
506
- }),
507
- [parent, openOnHover, delay, closeDelay, Chevron, size.icon, open],
508
- )
509
-
510
- // The submenu grows out of this row, whatever Base UI reports as the trigger.
511
- const setTrigger = useCallback(
512
- (node: HTMLDivElement | null) => {
513
- if (node) (origin as MutableRefObject<MorphOrigin>).current = { ...origin.current, trigger: node }
514
- },
515
- [origin],
516
- )
517
-
518
- return (
519
- <DropdownContext.Provider value={ctx}>
520
- <MenuItem ref={mergeRefs(setTrigger, ref)} pinned={open} {...props} />
521
- </DropdownContext.Provider>
522
- )
523
- },
524
- )
525
-
526
- DropdownSubTrigger.displayName = 'DropdownSubTrigger'
527
-
528
- interface DropdownSubContentProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {
529
- /** Rows: `Dropdown.Item`, `Dropdown.CheckboxItem`, `Dropdown.RadioGroup`, `Dropdown.Group`, `Dropdown.Label`, `Dropdown.Separator`, another `Dropdown.Sub`. */
530
- children: ReactNode
531
- /** Extra classes for the submenu surface — it is 14rem wide by default. */
532
- className?: string
533
- /** Classes for the portalled positioner element: a z utility here lifts the submenu above other fixed layers (the positioner is `z-50`). */
534
- positionerClassName?: string
535
- /** Side of the trigger row the submenu prefers. Defaults to `"inline-end"`. */
536
- side?: MenuPositionerProps['side']
537
- /** Alignment against the trigger row. Defaults to `"start"`. */
538
- align?: MenuPositionerProps['align']
539
- /** Gap to the parent menu, in px: the goo neck's length. Defaults to `8`. */
540
- sideOffset?: number
541
- /** Shift along the trigger row, in px; `-4` lines the first row up with the trigger. Defaults to `-4`. */
542
- alignOffset?: number
543
- /** Space to keep between the submenu and the edge of the collision boundary, in px (a number, or per side). Defaults to `5`. */
544
- collisionPadding?: MenuPositionerProps['collisionPadding']
545
- /** The element the portalled submenu mounts into. Defaults to `document.body`. */
546
- container?: MenuPortalProps['container']
547
- /** Where focus goes once the submenu has closed: `false` leaves it, a ref moves it there, a function picks by how it closed. Defaults to `undefined`: Base UI's own return to the trigger row. */
548
- finalFocus?: MenuPopupProps['finalFocus']
549
- /** An element to focus once the submenu has opened. The ref may be a fresh object each render: it is read when the submenu opens. Defaults to `undefined`: keyboard opens focus the first row, as Base UI does. */
550
- initialFocus?: RefObject<HTMLElement | null>
551
- /** Key handler on the popup, in the capture phase, ahead of the panel's own. `preventDefault` is harmless: navigation and typeahead still run. `stopPropagation` stops Base UI's key handling; the keyboard ring still runs. Defaults to `undefined`. */
552
- onKeyDownCapture?: HTMLAttributes<HTMLDivElement>['onKeyDownCapture']
553
- /** Where the submenu grows from (see Morph): its trigger row, its own center, a viewport edge, or a ref to any element. Defaults to `'trigger'`. */
554
- from?: 'trigger' | 'center' | 'top' | 'right' | 'bottom' | 'left' | RefObject<HTMLElement | null>
555
- /** How it grows (see Morph): with the liquid goo neck, a plain morph, a slide or a fade. Defaults to `'goo'`. */
556
- effect?: 'goo' | 'morph' | 'slide' | 'fade'
557
- /** Spring tier of a plain morph, slide or fade; goo runs on its own `spring.goo`. Defaults to `'moderate'`. */
558
- tier?: 'moderate' | 'slow'
559
- /** Keep the rows mounted (hidden) while the submenu is closed, so rows that run their own state keep it across opens. Defaults to `false`. */
560
- keepMounted?: boolean
561
- }
562
-
563
- /** The submenu's panel: the same rows and systems as `Dropdown.Content`, lifted 2 levels above the menu it came from. */
564
- const DropdownSubContent = forwardRef<HTMLDivElement, DropdownSubContentProps>(
565
- (
566
- {
567
- children,
568
- className,
569
- positionerClassName,
570
- side = 'inline-end',
571
- align = 'start',
572
- sideOffset = 8,
573
- alignOffset = -4,
574
- collisionPadding,
575
- container,
576
- finalFocus,
577
- initialFocus,
578
- from,
579
- effect,
580
- tier = 'moderate',
581
- keepMounted = false,
582
- onKeyDownCapture,
583
- onMouseEnter,
584
- onMouseMove,
585
- onMouseLeave,
586
- onClick,
587
- onFocus,
588
- onBlur,
589
- ...popupProps
590
- },
591
- ref,
592
- ) => {
593
- const { open, origin } = useSubContext()
594
- const morph = useMorph(open, origin, { from, effect, tier })
595
- useImperativeHandle(ref, () => morph.popup as HTMLDivElement, [morph.popup])
596
- const level = Math.min(useSurface() + 2, 8)
597
- const containerRef = useRef<HTMLDivElement>(null)
598
- const panel = useMenuPanel(containerRef, open)
599
- const { hover, focusRow, setFocusedIndex } = panel
600
- const { handlers, setActiveIndex, registerItem, itemRects, remeasure } = hover
601
-
602
- useEffect(() => {
603
- if (open) remeasure()
604
- }, [open, remeasure])
605
-
606
- // Base UI's Menu.Popup has no `initialFocus`: the element takes focus a frame after the open.
607
- // Read through a ref: a fresh `{ current }` object each render must not re-run the effect.
608
- const initialFocusRef = useRef(initialFocus)
609
- initialFocusRef.current = initialFocus
610
- const hasInitialFocus = Boolean(initialFocus)
611
- useEffect(() => {
612
- if (!open || !hasInitialFocus) return
613
- const frame = requestAnimationFrame(() => initialFocusRef.current?.current?.focus())
614
- return () => cancelAnimationFrame(frame)
615
- }, [open, hasInitialFocus])
616
-
617
- const runs = useSelectionRuns(panel.valueChecked)
618
- const blocks = useMergeSplitBlocks(runs, itemRects, shape.bgRadius)
619
-
620
- const ctx = useMemo<DropdownContextValue>(
621
- () => ({
622
- registerItem,
623
- activeIndex: panel.lit,
624
- inMenu: true,
625
- renderMenuItem: renderPopupItem,
626
- pin: panel.pin,
627
- reportChecked: panel.reportChecked,
628
- }),
629
- [registerItem, panel.lit, panel.pin, panel.reportChecked],
630
- )
631
-
632
- return (
633
- <Menu.Portal keepMounted={keepMounted} container={container}>
634
- <Menu.Positioner
635
- side={side}
636
- align={align}
637
- sideOffset={sideOffset}
638
- alignOffset={alignOffset}
639
- collisionPadding={collisionPadding}
640
- className={cn('z-50 outline-none', positionerClassName)}
641
- >
642
- <Menu.Popup
643
- {...popupProps}
644
- ref={morph.popupRef}
645
- finalFocus={finalFocus}
646
- onKeyDownCapture={chain(onKeyDownCapture, e => ownEvent(e) && panel.trackKeyboardNav(e))}
647
- onMouseEnter={chain(onMouseEnter, () => {
648
- handlers.onMouseEnter()
649
- setFocusedIndex(null)
650
- })}
651
- onMouseMove={chain(onMouseMove, e => ownEvent(e) && handlers.onMouseMove(e))}
652
- onMouseLeave={chain(onMouseLeave, handlers.onMouseLeave)}
653
- onClick={chain(onClick, e => ownEvent(e) && handlers.onClick(e))}
654
- onFocus={chain(onFocus, e => {
655
- if (!ownEvent(e) || focusRow(e)) return
656
- if (e.target !== e.currentTarget) setActiveIndex(null)
657
- })}
658
- onBlur={chain(onBlur, e => {
659
- if (!ownEvent(e) || e.currentTarget.contains(e.relatedTarget as Node)) return
660
- setFocusedIndex(null)
661
- setActiveIndex(null)
662
- })}
663
- className="relative select-none outline-none"
664
- >
665
- <SurfaceProvider value={level}>
666
- <MorphSurface
667
- morph={morph}
668
- bg={SURFACE_BG[level]}
669
- shadow={SURFACE_SHADOW[3]}
670
- radius={shape.container}
671
- className={cn(
672
- 'flex w-56 max-w-[var(--available-width)] max-h-[min(480px,var(--available-height))] flex-col overflow-hidden',
673
- shape.container,
674
- className,
675
- )}
676
- >
677
- <ScrollArea className={popupScrollAreaClass} viewportClassName={cn(popupViewportClass, 'scroll-fade')}>
678
- <div ref={containerRef} className="relative flex flex-col p-1">
679
- <SelectionBackgrounds blocks={blocks} />
680
- <FluidHoverHighlight hover={panel.shownHover} hidden={!open} className={shape.bg} />
681
- <FocusRing rect={open ? panel.focusRect : null} shape="rounded" />
682
- <RowOrderContext.Provider value={panel.rowOrder}>
683
- <DropdownContext.Provider value={ctx}>{children}</DropdownContext.Provider>
684
- </RowOrderContext.Provider>
685
- </div>
686
- </ScrollArea>
687
- </MorphSurface>
688
- </SurfaceProvider>
689
- </Menu.Popup>
690
- </Menu.Positioner>
691
- </Menu.Portal>
692
- )
693
- },
694
- )
695
-
696
- DropdownSubContent.displayName = 'DropdownSubContent'
697
-
698
- export type {
699
- DropdownCheckboxItemProps,
700
- DropdownGroupProps,
701
- DropdownRadioGroupProps,
702
- DropdownRadioItemProps,
703
- DropdownSubContentProps,
704
- DropdownSubProps,
705
- DropdownSubTriggerProps,
706
- MenuPopupProps,
707
- MenuPortalProps,
708
- MenuPositionerProps,
709
- }
710
- export {
711
- chain,
712
- DropdownCheckboxItem,
713
- DropdownGroup,
714
- DropdownGroupContext,
715
- DropdownRadioGroup,
716
- DropdownRadioItem,
717
- DropdownSub,
718
- DropdownSubContent,
719
- DropdownSubTrigger,
720
- mergeRefs,
721
- ownEvent,
722
- renderPopupItem,
723
- useMenuPanel,
724
- useValueChecked,
725
- }