@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,704 +0,0 @@
1
- /*
2
- * Local addition (not part of Fluid Functionalism): a site navigation bar
3
- * whose flyout panels grow out of their trigger through the morph engine
4
- * (`lib/use-morph.ts`), on Base UI's NavigationMenu. One panel is shared by
5
- * every item: moving to another trigger springs its size to the new content
6
- * while the content crossfades in from the side it came from. The strip has
7
- * one fluid hover highlight, and `NavigationMenu.Indicator` is a liquid
8
- * marker (`lib/goo-indicator.tsx`) under the open or current item. A panel
9
- * draws one keyboard ring (`lib/focus-ring.tsx`, on the surrounding shape).
10
- * The root forwards its ref and HTML attributes to the `<nav>`; `Trigger` and
11
- * `Content` also take Radix-style `asChild` (the child's element type and ref
12
- * are kept, its children become the part's content).
13
- */
14
-
15
- import { NavigationMenu as NavigationMenuPrimitive } from '@base-ui/react/navigation-menu'
16
- import { motion } from 'motion/react'
17
- import {
18
- type ComponentPropsWithoutRef,
19
- createContext,
20
- createElement,
21
- type ForwardRefExoticComponent,
22
- forwardRef,
23
- isValidElement,
24
- type MutableRefObject,
25
- type ReactElement,
26
- type ReactNode,
27
- type Ref,
28
- type RefAttributes,
29
- type RefObject,
30
- useCallback,
31
- useContext,
32
- useId,
33
- useLayoutEffect,
34
- useMemo,
35
- useRef,
36
- useState,
37
- version,
38
- } from 'react'
39
- import { FluidHoverHighlight } from '../../../lib/fluid-hover-highlight'
40
- import { FocusRing } from '../../../lib/focus-ring'
41
- import { GooIndicator } from '../../../lib/goo-indicator'
42
- import { type IconComponent, useIcon } from '../../../lib/icon-context'
43
- import { MorphSurface } from '../../../lib/morph-layers'
44
- import { useReduceMotion } from '../../../lib/reduced-motion'
45
- import { useShape } from '../../../lib/shape-context'
46
- import { type SizeVariant, useSize } from '../../../lib/size-context'
47
- import { spring } from '../../../lib/springs'
48
- import { SURFACE_BG, SURFACE_SHADOW } from '../../../lib/surface-classes'
49
- import { SurfaceProvider, useSurface } from '../../../lib/surface-context'
50
- import { useControllableState } from '../../../lib/use-controllable-state'
51
- import { type ItemRect, type UseFluidHoverReturn, useFluidHover } from '../../../lib/use-fluid-hover'
52
- import { useKeyboardNavGate } from '../../../lib/use-keyboard-nav-gate'
53
- import { useMorph, useMorphOrigin } from '../../../lib/use-morph'
54
- import { cn } from '../../../lib/utils'
55
- import { SizeProvider } from '../../../primitives/sizes'
56
-
57
- /* ─────────────────────── Shared ─────────────────────── */
58
-
59
- const TARGET = 'data-navigation-menu-target'
60
- const ROW = 'data-navigation-menu-row'
61
-
62
- interface PanelSize {
63
- width: number
64
- height: number
65
- }
66
-
67
- interface RootContextValue {
68
- value: string | null
69
- triggers: MutableRefObject<Map<string, HTMLElement>>
70
- setList: (el: HTMLElement | null) => void
71
- setPanelSize: (size: PanelSize) => void
72
- }
73
-
74
- const RootContext = createContext<RootContextValue | null>(null)
75
-
76
- function useRoot() {
77
- const ctx = useContext(RootContext)
78
- if (!ctx) throw new Error('NavigationMenu parts must be used within a NavigationMenu')
79
- return ctx
80
- }
81
-
82
- interface ListContextValue {
83
- hover: UseFluidHoverReturn
84
- indicatorRect: ItemRect | undefined
85
- }
86
-
87
- const ListContext = createContext<ListContextValue | null>(null)
88
-
89
- const ItemContext = createContext<string>('')
90
-
91
- // True inside a panel: links there are rows, not strip items.
92
- const InContentContext = createContext(false)
93
-
94
- /**
95
- * Registers every element matching `selector` inside the container with the
96
- * fluid hover, in document order, so parts need no `index`. Runs after every
97
- * render and only re-registers when the set changed.
98
- */
99
- function useRegisterBySelector(
100
- container: RefObject<HTMLElement | null>,
101
- selector: string,
102
- register: UseFluidHoverReturn['registerItem'],
103
- ) {
104
- const registered = useRef<HTMLElement[]>([])
105
- const [items, setItems] = useState<HTMLElement[]>([])
106
-
107
- useLayoutEffect(() => {
108
- const root = container.current
109
- if (!root) return
110
- const next = [...root.querySelectorAll<HTMLElement>(selector)]
111
- const previous = registered.current
112
- if (next.length === previous.length && next.every((el, i) => el === previous[i])) return
113
- for (let i = next.length; i < previous.length; i++) register(i, null)
114
- next.forEach((el, i) => {
115
- if (previous[i] !== el) register(i, el)
116
- })
117
- registered.current = next
118
- setItems(next)
119
- })
120
-
121
- return items
122
- }
123
-
124
- /** Writes a node into a forwarded ref as well as a local one. */
125
- function assignRef<T>(ref: Ref<T> | undefined, node: T | null) {
126
- if (typeof ref === 'function') ref(node)
127
- else if (ref) (ref as MutableRefObject<T | null>).current = node
128
- }
129
-
130
- const REACT_19 = parseInt(version, 10) >= 19
131
-
132
- /** An element's ref: `props.ref` on React 19, where `element.ref` warns on access; `element.ref` before (where `props.ref` warns). */
133
- function elementRef(element: ReactElement): Ref<HTMLElement> | undefined {
134
- if (REACT_19) return (element.props as { ref?: Ref<HTMLElement> }).ref
135
- return (element as ReactElement & { ref?: Ref<HTMLElement> }).ref
136
- }
137
-
138
- /**
139
- * What `asChild` makes of a part's single child: the element to render in its place (its own children
140
- * taken out, or they would win over the part's in the primitive, and its ref too, which the part merges
141
- * itself), that ref, and the content the child brought.
142
- */
143
- function slotParts(asChild: boolean | undefined, children: ReactNode) {
144
- if (!asChild || !isValidElement(children)) return { element: undefined, ref: undefined, content: children }
145
- const slot = children as ReactElement<{ children?: ReactNode; ref?: Ref<HTMLElement> }>
146
- const { children: content, ...props } = slot.props
147
- const ref = elementRef(slot)
148
- // On React 19 the ref rides in the props: the part merges it itself.
149
- if (REACT_19) delete props.ref
150
- return { element: createElement(slot.type, props), ref, content }
151
- }
152
-
153
- /* ─────────────────────── List ─────────────────────── */
154
-
155
- interface NavigationMenuListProps extends ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List> {
156
- /** `NavigationMenu.Item`s, and optionally a `NavigationMenu.Indicator`. */
157
- children?: ReactNode
158
- }
159
-
160
- const NavigationMenuList = forwardRef<HTMLUListElement, NavigationMenuListProps>(
161
- ({ className, children, ...props }, ref) => {
162
- const { value, setList } = useRoot()
163
- const containerRef = useRef<HTMLUListElement | null>(null)
164
- const hover = useFluidHover(containerRef, { axis: 'x' })
165
- const shape = useShape()
166
- const items = useRegisterBySelector(containerRef, `[${TARGET}]`, hover.registerItem)
167
-
168
- // The marker sits under the open item, else under the current page's item.
169
- const [marked, setMarked] = useState(-1)
170
- useLayoutEffect(() => {
171
- const open = value === null ? -1 : items.findIndex(el => el.dataset.navigationMenuValue === value)
172
- const next = open >= 0 ? open : items.findIndex(el => el.hasAttribute('data-active'))
173
- setMarked(next)
174
- })
175
- const indicatorRect = hover.isMeasured && marked >= 0 ? hover.itemRects[marked] : undefined
176
-
177
- const ctx = useMemo(() => ({ hover, indicatorRect }), [hover, indicatorRect])
178
-
179
- return (
180
- <ListContext.Provider value={ctx}>
181
- <NavigationMenuPrimitive.List
182
- ref={node => {
183
- containerRef.current = node as HTMLUListElement | null
184
- setList(node as HTMLElement | null)
185
- assignRef(ref, node as HTMLUListElement | null)
186
- }}
187
- {...hover.handlers}
188
- onFocus={event => {
189
- const index = items.indexOf(
190
- (event.target as HTMLElement).closest<HTMLElement>(`[${TARGET}]`) as HTMLElement,
191
- )
192
- if (index >= 0) hover.setActiveIndex(index)
193
- }}
194
- className={cn('relative m-0 flex list-none items-center p-0', className)}
195
- {...props}
196
- >
197
- <FluidHoverHighlight hover={hover} className={shape.bg} />
198
- {children}
199
- </NavigationMenuPrimitive.List>
200
- </ListContext.Provider>
201
- )
202
- },
203
- )
204
- NavigationMenuList.displayName = 'NavigationMenuList'
205
-
206
- /* ─────────────────────── Indicator ─────────────────────── */
207
-
208
- interface NavigationMenuIndicatorProps {
209
- /** Classes for the marker: its fill. Defaults to the `bg-active` overlay. */
210
- className?: string
211
- }
212
-
213
- /** A liquid marker under the open item, or the current page's item when nothing is open. */
214
- function NavigationMenuIndicator({ className }: NavigationMenuIndicatorProps) {
215
- const ctx = useContext(ListContext)
216
- const shape = useShape()
217
- const rect = ctx?.indicatorRect
218
- // Rendered as a list item so the list stays valid markup.
219
- return (
220
- <li aria-hidden="true" className="contents">
221
- {rect && <GooIndicator rect={rect} className={cn('bg-active', shape.bg, className)} />}
222
- </li>
223
- )
224
- }
225
-
226
- /* ─────────────────────── Item ─────────────────────── */
227
-
228
- interface NavigationMenuItemProps extends ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Item> {
229
- /** Identifies the item for a controlled `value`. Defaults to a generated id. */
230
- value?: string
231
- }
232
-
233
- const NavigationMenuItem = forwardRef<HTMLLIElement, NavigationMenuItemProps>(({ value, ...props }, ref) => {
234
- const generated = useId()
235
- const itemValue = value ?? generated
236
- return (
237
- <ItemContext.Provider value={itemValue}>
238
- <NavigationMenuPrimitive.Item ref={ref} value={itemValue} {...props} />
239
- </ItemContext.Provider>
240
- )
241
- })
242
- NavigationMenuItem.displayName = 'NavigationMenuItem'
243
-
244
- /* ─────────────────────── Strip label ─────────────────────── */
245
-
246
- /** The strip's label: semibold while open or current, with an invisible semibold copy holding its width. */
247
- function StripLabel({ emphasized, children }: { emphasized: boolean; children: ReactNode }) {
248
- const size = useSize()
249
- return (
250
- <span className={cn('inline-grid whitespace-nowrap', size.text)}>
251
- <span
252
- aria-hidden="true"
253
- className="invisible col-start-1 row-start-1 weight-semibold [text-box:trim-both_cap_alphabetic]"
254
- >
255
- {children}
256
- </span>
257
- <span
258
- className={cn(
259
- 'col-start-1 row-start-1 transition-[font-variation-settings] duration-fast [text-box:trim-both_cap_alphabetic]',
260
- emphasized ? 'weight-semibold' : 'weight-normal',
261
- )}
262
- >
263
- {children}
264
- </span>
265
- </span>
266
- )
267
- }
268
-
269
- const STRIP_ITEM =
270
- 'group/item relative z-10 flex cursor-pointer select-none items-center bg-transparent text-muted-foreground no-underline outline-none transition-[color] duration-fast focus-visible:ring-1 focus-visible:ring-focus-ring data-[fluid-hover-active]:text-foreground'
271
-
272
- /* ─────────────────────── Trigger ─────────────────────── */
273
-
274
- interface NavigationMenuTriggerProps extends ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger> {
275
- /** The trigger's label. With `asChild`, the single child element, whose own children are the label. */
276
- children?: ReactNode
277
- /** Compose onto the single child instead of `render`: it becomes the trigger and keeps its element type, props and ref. Defaults to `false`. */
278
- asChild?: boolean
279
- }
280
-
281
- const NavigationMenuTrigger = forwardRef<HTMLButtonElement, NavigationMenuTriggerProps>(
282
- ({ className, children, asChild, render, ...props }, ref) => {
283
- const { value, triggers } = useRoot()
284
- const itemValue = useContext(ItemContext)
285
- const size = useSize()
286
- const shape = useShape()
287
- const reduced = useReduceMotion()
288
- const Chevron = useIcon('chevron-down')
289
- const open = value === itemValue
290
- const slot = slotParts(asChild, children)
291
-
292
- const setRefs = useCallback(
293
- (node: HTMLButtonElement | null) => {
294
- if (node) triggers.current.set(itemValue, node)
295
- else triggers.current.delete(itemValue)
296
- assignRef(ref, node)
297
- assignRef(slot.ref, node)
298
- },
299
- [triggers, itemValue, ref, slot.ref],
300
- )
301
-
302
- return (
303
- <NavigationMenuPrimitive.Trigger
304
- ref={setRefs}
305
- render={slot.element ?? render}
306
- {...{ [TARGET]: '', 'data-navigation-menu-value': itemValue }}
307
- className={cn(STRIP_ITEM, size.control, size.px, size.gap, shape.button, open && 'text-foreground', className)}
308
- {...props}
309
- >
310
- <StripLabel emphasized={open}>{slot.content}</StripLabel>
311
- <motion.span
312
- aria-hidden="true"
313
- className="flex"
314
- initial={false}
315
- animate={{ rotate: open ? 180 : 0 }}
316
- transition={reduced ? { duration: 0 } : spring.moderate}
317
- >
318
- <Chevron
319
- size={size.icon}
320
- strokeWidth={1.5}
321
- className={cn(
322
- 'transition-[stroke-width] duration-fast group-[[data-fluid-hover-active]]/item:stroke-2',
323
- open && 'stroke-2',
324
- )}
325
- />
326
- </motion.span>
327
- </NavigationMenuPrimitive.Trigger>
328
- )
329
- },
330
- )
331
- NavigationMenuTrigger.displayName = 'NavigationMenuTrigger'
332
-
333
- /* ─────────────────────── Content ─────────────────────── */
334
-
335
- interface NavigationMenuContentProps extends ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content> {
336
- /** Classes for the panel's content: its width and layout (a grid of links, a feature column). */
337
- className?: string
338
- /** The panel: `NavigationMenu.Link`s and anything else. With `asChild`, the single child element, whose own children are the panel. */
339
- children?: ReactNode
340
- /** Compose onto the single child instead of `render`: it becomes the panel and keeps its element type, props and ref, so a `ul` stays a `ul`. Defaults to `false`. */
341
- asChild?: boolean
342
- }
343
-
344
- const NavigationMenuContent = forwardRef<HTMLDivElement, NavigationMenuContentProps>(
345
- ({ className, children, asChild, render, ...props }, ref) => {
346
- const { value, setPanelSize } = useRoot()
347
- const itemValue = useContext(ItemContext)
348
- const open = value === itemValue
349
- const reduced = useReduceMotion()
350
- const shape = useShape()
351
- const containerRef = useRef<HTMLDivElement | null>(null)
352
- const [element, setElement] = useState<HTMLDivElement | null>(null)
353
- const hover = useFluidHover(containerRef, { axis: 'xy' })
354
- const rows = useRegisterBySelector(containerRef, `[${ROW}]`, hover.registerItem)
355
- // Only keyboard focus earns the ring: Tab or an arrow key, or focus that arrived as :focus-visible.
356
- const { keyboardNavRef, trackKeyboardNav } = useKeyboardNavGate(open)
357
- const [focused, setFocused] = useState<number | null>(null)
358
-
359
- // The open panel tells the shared frame its natural size, and keeps telling it as it changes.
360
- useLayoutEffect(() => {
361
- if (!open || !element) return
362
- const report = () => setPanelSize({ width: element.offsetWidth, height: element.offsetHeight })
363
- report()
364
- const observer = new ResizeObserver(report)
365
- observer.observe(element)
366
- return () => observer.disconnect()
367
- }, [open, element, setPanelSize])
368
-
369
- const slot = slotParts(asChild, children)
370
- // One merged ref, stable while its parts are: the panel re-measures whenever its ref changes.
371
- const setRefs = useCallback(
372
- (node: HTMLDivElement | null) => {
373
- containerRef.current = node
374
- setElement(node)
375
- assignRef(ref, node)
376
- assignRef(slot.ref, node)
377
- },
378
- [ref, slot.ref],
379
- )
380
-
381
- // A list element can't hold the overlays' divs directly. A string tag tells at once, from the first paint;
382
- // a component or render function only once it has mounted.
383
- const host = slot.element ?? render
384
- const hostType = isValidElement(host) ? host.type : typeof host === 'function' ? undefined : 'div'
385
- const inList =
386
- typeof hostType === 'string'
387
- ? hostType === 'ul' || hostType === 'ol'
388
- : element?.tagName === 'UL' || element?.tagName === 'OL'
389
- const overlays = (
390
- <>
391
- <FluidHoverHighlight hover={hover} className={shape.bg} />
392
- <FocusRing rect={open && focused !== null ? hover.itemRects[focused] : undefined} />
393
- </>
394
- )
395
-
396
- return (
397
- <InContentContext.Provider value={true}>
398
- <NavigationMenuPrimitive.Content
399
- ref={setRefs}
400
- render={slot.element ?? render}
401
- {...hover.handlers}
402
- onKeyDown={event => {
403
- if (event.key === 'Tab') keyboardNavRef.current = true
404
- trackKeyboardNav(event)
405
- }}
406
- onFocus={event => {
407
- const target = event.target as HTMLElement
408
- const index = rows.indexOf(target.closest<HTMLElement>(`[${ROW}]`) as HTMLElement)
409
- if (index < 0) return
410
- hover.setActiveIndex(index)
411
- setFocused(keyboardNavRef.current || target.matches(':focus-visible') ? index : null)
412
- }}
413
- onBlur={event => {
414
- if (!event.currentTarget.contains(event.relatedTarget as Node | null)) setFocused(null)
415
- }}
416
- className={cn(
417
- 'relative w-max p-1 transition-[opacity,transform] duration-moderate data-[ending-style]:duration-moderate-exit data-[starting-style]:opacity-0 data-[ending-style]:opacity-0',
418
- !reduced &&
419
- 'data-[starting-style]:data-[activation-direction=right]:translate-x-4 data-[starting-style]:data-[activation-direction=left]:-translate-x-4 data-[ending-style]:data-[activation-direction=right]:-translate-x-4 data-[ending-style]:data-[activation-direction=left]:translate-x-4',
420
- className,
421
- )}
422
- {...props}
423
- >
424
- {inList ? (
425
- <li aria-hidden="true" className="contents">
426
- {overlays}
427
- </li>
428
- ) : (
429
- overlays
430
- )}
431
- {slot.content}
432
- </NavigationMenuPrimitive.Content>
433
- </InContentContext.Provider>
434
- )
435
- },
436
- )
437
- NavigationMenuContent.displayName = 'NavigationMenuContent'
438
-
439
- /* ─────────────────────── Link ─────────────────────── */
440
-
441
- interface NavigationMenuLinkProps extends ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Link> {
442
- /** Marks the link as the current page (`aria-current`); in the strip, the indicator rests under it. Defaults to `false`. */
443
- active?: boolean
444
- /** Leading icon of a link inside a panel. */
445
- icon?: IconComponent
446
- /** A muted line under the title of a link inside a panel. */
447
- description?: ReactNode
448
- /** Close the panel when the link is pressed. Defaults to `false`. */
449
- closeOnClick?: boolean
450
- /** The link's title. */
451
- children?: ReactNode
452
- }
453
-
454
- const NavigationMenuLink = forwardRef<HTMLAnchorElement, NavigationMenuLinkProps>(
455
- ({ active = false, icon: Icon, description, className, children, ...props }, ref) => {
456
- const inContent = useContext(InContentContext)
457
- const size = useSize()
458
- const shape = useShape()
459
-
460
- if (!inContent) {
461
- return (
462
- <NavigationMenuPrimitive.Link
463
- ref={ref}
464
- active={active}
465
- {...{ [TARGET]: '' }}
466
- className={cn(STRIP_ITEM, size.control, size.px, shape.button, active && 'text-foreground', className)}
467
- {...props}
468
- >
469
- <StripLabel emphasized={active}>{children}</StripLabel>
470
- </NavigationMenuPrimitive.Link>
471
- )
472
- }
473
-
474
- const compact = size.variant === 'compact'
475
- return (
476
- <NavigationMenuPrimitive.Link
477
- ref={ref}
478
- active={active}
479
- {...{ [ROW]: '' }}
480
- className={cn(
481
- 'group/row relative z-10 flex min-w-0 cursor-pointer items-start no-underline outline-none',
482
- description ? 'py-2' : cn(size.control, 'items-center'),
483
- size.itemPx,
484
- size.gap,
485
- shape.item,
486
- className,
487
- )}
488
- {...props}
489
- >
490
- {Icon && (
491
- <Icon
492
- size={size.icon}
493
- strokeWidth={1.5}
494
- className={cn(
495
- 'shrink-0 text-muted-foreground transition-[color,stroke-width] duration-fast group-[[data-fluid-hover-active]]/row:stroke-2 group-[[data-fluid-hover-active]]/row:text-foreground',
496
- description && 'mt-0.5',
497
- )}
498
- />
499
- )}
500
- <span className="flex min-w-0 flex-col gap-0.5">
501
- <span className={cn('truncate text-foreground', active ? 'weight-semibold' : 'weight-normal', size.text)}>
502
- {children}
503
- </span>
504
- {description && (
505
- <span className={cn('text-muted-foreground', compact ? 'text-caption-compact' : 'text-caption')}>
506
- {description}
507
- </span>
508
- )}
509
- </span>
510
- </NavigationMenuPrimitive.Link>
511
- )
512
- },
513
- )
514
- NavigationMenuLink.displayName = 'NavigationMenuLink'
515
-
516
- /* ─────────────────────── Root ─────────────────────── */
517
-
518
- interface NavigationMenuProps
519
- extends Omit<
520
- ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>,
521
- 'value' | 'defaultValue' | 'onValueChange' | 'delay' | 'closeDelay' | 'className' | 'children'
522
- > {
523
- /** Controlled open item (its `value`), or `null` when closed. Pair with `onValueChange`. */
524
- value?: string | null
525
- /** Initially open item, for an uncontrolled menu. Defaults to `null`. */
526
- defaultValue?: string | null
527
- /** Called with the open item's value, or `null` as the menu closes. */
528
- onValueChange?: (value: string | null) => void
529
- /** Hover delay before a panel opens, in ms. Defaults to `50`. */
530
- delay?: number
531
- /** Delay before the panel closes once the pointer leaves, in ms. Defaults to `50`. */
532
- closeDelay?: number
533
- /** Alignment of the panel along the strip. Defaults to `'start'`. */
534
- align?: 'start' | 'center' | 'end'
535
- /** Gap between strip and panel in px — the length of the goo neck. Defaults to `12`. */
536
- sideOffset?: number
537
- /** Where the panel grows from (see Morph): the pressed trigger, the press point, its own center, a viewport edge, or a ref to any element. Defaults to `'trigger'`. */
538
- from?: 'trigger' | 'pointer' | 'center' | 'top' | 'right' | 'bottom' | 'left' | RefObject<HTMLElement | null>
539
- /** How it grows (see Morph): with the liquid goo neck, a plain morph, a slide or a fade. Defaults to `'goo'`. */
540
- effect?: 'goo' | 'morph' | 'slide' | 'fade'
541
- /** Hide the trigger while open, so it reads as turning into the panel. Defaults to `false`. */
542
- hideSource?: boolean
543
- /** Spring tier of a plain morph, slide or fade; goo runs on its own `spring.goo`. Defaults to `'slow'`. */
544
- tier?: 'moderate' | 'slow'
545
- /** Pins the strip and its panels to one step of the size ladder (36px default, 28px compact). Defaults to the surrounding SizeProvider. */
546
- size?: SizeVariant
547
- /** Classes for the `nav` root. */
548
- className?: string
549
- /** A `NavigationMenu.List`. */
550
- children?: ReactNode
551
- }
552
-
553
- type NavigationMenuComponent = ForwardRefExoticComponent<NavigationMenuProps & RefAttributes<HTMLElement>> & {
554
- List: typeof NavigationMenuList
555
- Item: typeof NavigationMenuItem
556
- Trigger: typeof NavigationMenuTrigger
557
- Content: typeof NavigationMenuContent
558
- Link: typeof NavigationMenuLink
559
- Indicator: typeof NavigationMenuIndicator
560
- }
561
-
562
- /**
563
- * A site navigation bar whose items open flyout panels of links.
564
- *
565
- * The panel grows out of the trigger that opened it (see Morph) and closes
566
- * back into it. Moving to another trigger keeps the one panel open: it
567
- * springs to the new content's size while the content slides in from the
568
- * side the pointer came from. One fluid hover highlight runs along the
569
- * strip and another inside each panel, and `NavigationMenu.Indicator` melts
570
- * from item to item under the open one, or under the current page's link.
571
- * The panel lifts 2 surface levels off its substrate. Built on Base UI's
572
- * NavigationMenu: panels open on hover or press, arrow keys move between
573
- * items, Escape closes; controlled with `value` + `onValueChange`. The root
574
- * is the `<nav>`: it takes a ref and HTML attributes such as `aria-label`.
575
- *
576
- * Statics:
577
- * - `NavigationMenu.List` — the strip.
578
- * - `NavigationMenu.Item` — one entry: a Trigger + Content pair, or a Link;
579
- * `value`.
580
- * - `NavigationMenu.Trigger` — opens its item's panel; the chevron turns and
581
- * the label turns semibold while open; `asChild`.
582
- * - `NavigationMenu.Content` — the item's panel; size it with `className`;
583
- * `asChild` makes it the child (a `ul`, say).
584
- * - `NavigationMenu.Link` — a link: in the strip, a top-level item; in a
585
- * panel, a row with `icon` and `description`. `active` marks the current
586
- * page; `closeOnClick`.
587
- * - `NavigationMenu.Indicator` — the liquid marker; put it in the List.
588
- *
589
- * @example {@include ./examples.mdx}
590
- */
591
- const NavigationMenu = forwardRef<HTMLElement, NavigationMenuProps>(function NavigationMenu(
592
- {
593
- value,
594
- defaultValue = null,
595
- onValueChange,
596
- delay,
597
- closeDelay,
598
- align = 'start',
599
- sideOffset = 12,
600
- from,
601
- effect,
602
- hideSource,
603
- tier,
604
- size,
605
- className,
606
- children,
607
- ...props
608
- },
609
- ref,
610
- ) {
611
- const [current, setCurrent] = useControllableState<string | null>(value, defaultValue, onValueChange)
612
- const { origin, capture } = useMorphOrigin()
613
- const triggers = useRef(new Map<string, HTMLElement>())
614
- const [list, setList] = useState<HTMLElement | null>(null)
615
- const [panelSize, setPanelSize] = useState<PanelSize | null>(null)
616
- const open = current !== null
617
- const morph = useMorph(open, origin, { from, effect, hideSource, tier })
618
- const reduced = useReduceMotion()
619
- const shape = useShape()
620
- const level = Math.min(useSurface() + 2, 8)
621
-
622
- // A fresh open measures the panel at its natural size.
623
- if (!open && panelSize) setPanelSize(null)
624
-
625
- const ctx = useMemo(() => ({ value: current, triggers, setList, setPanelSize }), [current])
626
-
627
- const root = (
628
- <RootContext.Provider value={ctx}>
629
- <NavigationMenuPrimitive.Root
630
- {...props}
631
- ref={ref}
632
- value={current}
633
- onValueChange={(next, details) => {
634
- const nextValue = (next as string | null) ?? null
635
- // Every switch re-points the origin, so the panel closes into the trigger that is open.
636
- if (nextValue !== null) capture({ trigger: triggers.current.get(nextValue), event: details.event })
637
- setCurrent(nextValue)
638
- }}
639
- delay={delay}
640
- closeDelay={closeDelay}
641
- className={cn('relative', className)}
642
- >
643
- {children}
644
- <NavigationMenuPrimitive.Portal>
645
- <NavigationMenuPrimitive.Positioner
646
- anchor={list}
647
- side="bottom"
648
- align={align}
649
- sideOffset={sideOffset}
650
- collisionPadding={8}
651
- className="z-50 outline-none"
652
- >
653
- <NavigationMenuPrimitive.Popup ref={morph.popupRef} className="relative outline-none">
654
- <SurfaceProvider value={level}>
655
- <MorphSurface morph={morph} bg={SURFACE_BG[level]} shadow={SURFACE_SHADOW[3]} radius={shape.container}>
656
- <motion.div
657
- className="relative overflow-hidden"
658
- initial={false}
659
- animate={panelSize ? { width: panelSize.width, height: panelSize.height } : undefined}
660
- transition={reduced ? { duration: 0 } : spring.moderate}
661
- >
662
- <NavigationMenuPrimitive.Viewport className="relative" />
663
- </motion.div>
664
- </MorphSurface>
665
- </SurfaceProvider>
666
- </NavigationMenuPrimitive.Popup>
667
- </NavigationMenuPrimitive.Positioner>
668
- </NavigationMenuPrimitive.Portal>
669
- </NavigationMenuPrimitive.Root>
670
- </RootContext.Provider>
671
- )
672
-
673
- // A size prop pins the strip and its panels to one ladder step.
674
- return size ? <SizeProvider size={size}>{root}</SizeProvider> : root
675
- }) as NavigationMenuComponent
676
-
677
- NavigationMenu.displayName = 'NavigationMenu'
678
- NavigationMenu.List = NavigationMenuList
679
- NavigationMenu.Item = NavigationMenuItem
680
- NavigationMenu.Trigger = NavigationMenuTrigger
681
- NavigationMenu.Content = NavigationMenuContent
682
- NavigationMenu.Link = NavigationMenuLink
683
- NavigationMenu.Indicator = NavigationMenuIndicator
684
-
685
- export type {
686
- NavigationMenuContentProps,
687
- NavigationMenuIndicatorProps,
688
- NavigationMenuItemProps,
689
- NavigationMenuLinkProps,
690
- NavigationMenuListProps,
691
- NavigationMenuProps,
692
- NavigationMenuTriggerProps,
693
- }
694
- export {
695
- NavigationMenu,
696
- NavigationMenuContent,
697
- NavigationMenuIndicator,
698
- NavigationMenuItem,
699
- NavigationMenuLink,
700
- NavigationMenuList,
701
- NavigationMenuTrigger,
702
- }
703
-
704
- export default NavigationMenu