@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.
- package/README.md +66 -164
- package/dist/base.css +4 -141
- package/dist/blocks/sidebar-app/index.js +26 -40
- package/dist/components/AI/input-message/index.js +16 -23
- package/dist/components/AI/thinking-indicator/index.js +6 -9
- package/dist/components/accordion/index.d.ts +11 -39
- package/dist/components/accordion/index.js +13 -18
- package/dist/components/badge/index.d.ts +11 -18
- package/dist/components/badge/index.js +7 -12
- package/dist/components/button/index.d.ts +17 -53
- package/dist/components/button/index.js +6 -11
- package/dist/components/card/index.d.ts +9 -32
- package/dist/components/card/index.js +11 -17
- package/dist/components/copy/index.d.ts +8 -41
- package/dist/components/copy/index.js +9 -15
- package/dist/components/inputs/checkbox/index.d.ts +9 -28
- package/dist/components/inputs/checkbox/index.js +13 -18
- package/dist/components/inputs/color-picker/index.d.ts +14 -22
- package/dist/components/inputs/color-picker/index.js +18 -26
- package/dist/components/inputs/combobox/index.d.ts +20 -85
- package/dist/components/inputs/combobox/index.js +18 -27
- package/dist/components/inputs/date-time/calendar/index.d.ts +18 -24
- package/dist/components/inputs/date-time/calendar/index.js +11 -15
- package/dist/components/inputs/date-time/date-picker/index.d.ts +16 -105
- package/dist/components/inputs/date-time/date-picker/index.js +25 -35
- package/dist/components/inputs/date-time/date-range-picker/index.d.ts +12 -106
- package/dist/components/inputs/date-time/date-range-picker/index.js +24 -35
- package/dist/components/inputs/date-time/duration-picker/index.d.ts +13 -66
- package/dist/components/inputs/date-time/duration-picker/index.js +24 -33
- package/dist/components/inputs/date-time/month-picker/index.d.ts +10 -60
- package/dist/components/inputs/date-time/month-picker/index.js +23 -32
- package/dist/components/inputs/date-time/time-picker/index.d.ts +10 -58
- package/dist/components/inputs/date-time/time-picker/index.js +24 -33
- package/dist/components/inputs/input/index.d.ts +13 -95
- package/dist/components/inputs/input/index.js +9 -18
- package/dist/components/inputs/radio/index.d.ts +5 -20
- package/dist/components/inputs/radio/index.js +12 -16
- package/dist/components/inputs/search/index.d.ts +3 -3
- package/dist/components/inputs/search/index.js +18 -26
- package/dist/components/inputs/select/index.d.ts +23 -99
- package/dist/components/inputs/select/index.js +14 -29
- package/dist/components/inputs/slider/index.d.ts +0 -9
- package/dist/components/inputs/slider/index.js +5 -8
- package/dist/components/inputs/switch/index.d.ts +2 -8
- package/dist/components/inputs/switch/index.js +12 -15
- package/dist/components/inputs/textarea/index.d.ts +1 -20
- package/dist/components/inputs/textarea/index.js +6 -9
- package/dist/components/navigation/sidebar/index.d.ts +21 -44
- package/dist/components/navigation/sidebar/index.js +31 -42
- package/dist/components/navigation/tabs/index.d.ts +2 -8
- package/dist/components/navigation/tabs/index.js +10 -15
- package/dist/components/navigation/tabs-subtle/index.js +10 -13
- package/dist/components/overlays/alert-dialog/index.d.ts +16 -135
- package/dist/components/overlays/alert-dialog/index.js +13 -23
- package/dist/components/overlays/command/index.d.ts +20 -25
- package/dist/components/overlays/command/index.js +17 -25
- package/dist/components/overlays/context-menu/index.d.ts +17 -39
- package/dist/components/overlays/context-menu/index.js +18 -29
- package/dist/components/overlays/dialog/index.d.ts +16 -42
- package/dist/components/overlays/dialog/index.js +12 -20
- package/dist/components/overlays/dropdown/index.d.ts +34 -304
- package/dist/components/overlays/dropdown/index.js +17 -44
- package/dist/components/overlays/popover/index.d.ts +12 -38
- package/dist/components/overlays/popover/index.js +9 -13
- package/dist/components/overlays/preview-card/index.js +8 -12
- package/dist/components/overlays/sheet/index.d.ts +8 -25
- package/dist/components/overlays/sheet/index.js +13 -19
- package/dist/components/overlays/toast/index.d.ts +50 -209
- package/dist/components/overlays/toast/index.js +10 -23
- package/dist/components/overlays/tooltip/index.d.ts +21 -123
- package/dist/components/overlays/tooltip/index.js +6 -16
- package/dist/components/table/index.d.ts +8 -63
- package/dist/components/table/index.js +9 -20
- package/dist/index.d.ts +1048 -2999
- package/dist/index.js +82 -231
- package/dist/preset.d.ts +0 -22
- package/dist/preset.js +2 -24
- package/dist/primitives/code/index.js +5 -8
- package/dist/primitives/craft/index.js +6 -10
- package/dist/primitives/fluid-hover/index.js +8 -10
- package/dist/primitives/morph/index.js +10 -16
- package/dist/primitives/motion/index.js +8 -11
- package/dist/primitives/scroll-area/index.js +3 -5
- package/dist/primitives/sizes/index.js +4 -6
- package/dist/primitives/surface/index.js +4 -6
- package/dist/shared/{components-4y816hwp.js → components-0q0sqfh4.js} +49 -27
- package/dist/shared/components-0sn7ypjw.js +61 -0
- package/dist/shared/{components-vc864c51.js → components-11da9ajg.js} +5 -8
- package/dist/shared/components-1434p1mh.js +123 -0
- package/dist/shared/{components-t2a3qmy9.js → components-1z6tdadk.js} +24 -40
- package/dist/shared/{components-qs4rkqsj.js → components-27nnvrwe.js} +14 -15
- package/dist/shared/{components-av5t26rc.js → components-2dxkv6zm.js} +7 -8
- package/dist/shared/{components-wqrvqq5p.js → components-2ecg8svx.js} +152 -234
- package/dist/shared/{components-3ydr2fqe.js → components-2ph6t61s.js} +34 -37
- package/dist/shared/{components-6gk118w3.js → components-39jq9va1.js} +24 -29
- package/dist/shared/components-3ky44908.js +9 -0
- package/dist/shared/{components-y1qvbawa.js → components-3mkepka5.js} +25 -28
- package/dist/shared/{components-xqszvkj4.js → components-4700p9kz.js} +22 -24
- package/dist/shared/{components-yhgq0qxx.js → components-59efxjd9.js} +12 -13
- package/dist/shared/{components-9j9abkct.js → components-5vgpnxgy.js} +27 -51
- package/dist/shared/{components-8tt3xbb5.js → components-5xc2j8jz.js} +18 -19
- package/dist/shared/{components-jymmaevv.js → components-6p8tfcd6.js} +29 -57
- package/dist/shared/{components-4nck8acq.js → components-7r3etddy.js} +54 -19
- package/dist/shared/{components-skfd7kff.js → components-8snj490h.js} +32 -78
- package/dist/shared/{components-ctqmge8t.js → components-b0eac83j.js} +30 -9
- package/dist/shared/{components-9sttq78t.js → components-b2wyq2cq.js} +59 -41
- package/dist/shared/{components-vkwq2k96.js → components-b3c5et5b.js} +38 -49
- package/dist/shared/{components-rrbpmfx4.js → components-c6s6b43g.js} +2 -3
- package/dist/shared/{components-pw06rbxq.js → components-chacnk61.js} +19 -19
- package/dist/shared/{components-71nbt03m.js → components-cv16mryv.js} +7 -26
- package/dist/shared/{components-eqze3y30.js → components-d6xtjht3.js} +30 -35
- package/dist/shared/{components-5y5shqfd.js → components-dk0gjr5a.js} +18 -19
- package/dist/shared/{components-khspp26b.js → components-fzrq6tr3.js} +34 -37
- package/dist/shared/{components-km7fhgbk.js → components-gc5vtq2f.js} +30 -66
- package/dist/shared/components-gf5s6ap9.js +42 -0
- package/dist/shared/{components-qqcmtrbv.js → components-gz8zf3ec.js} +55 -56
- package/dist/shared/{components-mattt5jp.js → components-h2ajmhwn.js} +35 -107
- package/dist/shared/{components-awra5sff.js → components-hqeq3w9q.js} +16 -24
- package/dist/shared/{components-5tzhqbcw.js → components-hw9yk32z.js} +24 -36
- package/dist/shared/components-hyq23phv.js +310 -0
- package/dist/shared/{components-8mt5bsv6.js → components-jbbmdr74.js} +22 -41
- package/dist/shared/{components-dcc02hs2.js → components-jjw69c4c.js} +4 -7
- package/dist/shared/{components-2syq4mwc.js → components-jthe1pwb.js} +420 -139
- package/dist/shared/{components-r7q1zm7r.js → components-jwst3vtj.js} +76 -224
- package/dist/shared/{components-qdm3yh26.js → components-kvr7f9hy.js} +10 -19
- package/dist/shared/{components-s8yqk2dc.js → components-kwa6mrf9.js} +11 -46
- package/dist/shared/{components-de99ykt7.js → components-men63rwj.js} +2 -3
- package/dist/shared/{components-6b0zb8z3.js → components-mjthm1kf.js} +9 -13
- package/dist/shared/{components-2c64r8c9.js → components-n42c79bz.js} +22 -23
- package/dist/shared/{components-tz1fv35x.js → components-n7mjr357.js} +2 -3
- package/dist/shared/components-ng72k97e.js +128 -0
- package/dist/shared/{components-dyae0y7h.js → components-pbmqctfa.js} +65 -169
- package/dist/shared/{components-px2zm7dc.js → components-q5xj5c16.js} +8 -9
- package/dist/shared/components-raknhppb.js +64 -0
- package/dist/shared/{components-8rb25gbe.js → components-rr7a6ja9.js} +27 -59
- package/dist/shared/{components-5012r6gr.js → components-s083f38z.js} +34 -164
- package/dist/shared/components-s5ngg32c.js +267 -0
- package/dist/shared/components-sn1rxx1d.js +143 -0
- package/dist/shared/{components-r8eqs7gz.js → components-ta7shw28.js} +4 -4
- package/dist/shared/{components-9as3rf68.js → components-vc7vq5nz.js} +3 -6
- package/dist/shared/{components-ft3zdc79.js → components-vfbhxf5r.js} +5 -6
- package/dist/shared/components-vynjtrk6.js +19 -0
- package/dist/shared/{components-w0xq6q9k.js → components-w1r67ag9.js} +149 -294
- package/dist/shared/{components-z0bqtvcp.js → components-w90endve.js} +72 -71
- package/dist/shared/{components-t5pk5nmc.js → components-wvp1m52g.js} +102 -149
- package/dist/shared/components-wy9jpqny.js +146 -0
- package/dist/shared/{components-5sxjeh6h.js → components-y9y0g8er.js} +28 -52
- package/dist/shared/components-ypp01w3p.js +986 -0
- package/dist/shared/{components-t50hrswb.js → components-zfnmn5d4.js} +36 -82
- package/dist/shared/{components-jqpefjsn.js → components-zrkzcayz.js} +6 -54
- package/dist/shared/{components-vf45j12c.js → components-zx6b6yby.js} +18 -4
- package/dist/styles.css +32 -320
- package/dist/tailwind.css +0 -16
- package/dist/tokens.css +0 -67
- package/package.json +4 -227
- package/DESIGN.md +0 -623
- package/blocks/sidebar-app/examples.mdx +0 -33
- package/blocks/sidebar-app/index.tsx +0 -218
- package/blocks/sidebar-app/inset-topbar.tsx +0 -25
- package/blocks/sidebar-app/menu-grid.ts +0 -26
- package/blocks/sidebar-app/nav-data.ts +0 -36
- package/blocks/sidebar-app/search-field.tsx +0 -48
- package/blocks/sidebar-app/user-footer.tsx +0 -67
- package/blocks/sidebar-app/workspace-header.tsx +0 -129
- package/components/AI/input-message/examples.mdx +0 -130
- package/components/AI/input-message/file-thumbnail.tsx +0 -173
- package/components/AI/input-message/index.tsx +0 -1385
- package/components/AI/thinking-indicator/examples.mdx +0 -27
- package/components/AI/thinking-indicator/index.tsx +0 -210
- package/components/accordion/examples.mdx +0 -233
- package/components/accordion/index.tsx +0 -1071
- package/components/avatar/examples.mdx +0 -95
- package/components/avatar/index.tsx +0 -129
- package/components/badge/change-demo.tsx +0 -29
- package/components/badge/examples.mdx +0 -124
- package/components/badge/index.tsx +0 -225
- package/components/badge/variants.ts +0 -73
- package/components/button/examples.mdx +0 -168
- package/components/button/index.tsx +0 -424
- package/components/button/loading-demo.tsx +0 -25
- package/components/button/variants.ts +0 -168
- package/components/card/examples.mdx +0 -251
- package/components/card/index.tsx +0 -1070
- package/components/copy/examples.mdx +0 -125
- package/components/copy/index.tsx +0 -662
- package/components/inputs/checkbox/examples.mdx +0 -87
- package/components/inputs/checkbox/index.tsx +0 -611
- package/components/inputs/checkbox/select-all-demo.tsx +0 -48
- package/components/inputs/color-picker/examples.mdx +0 -111
- package/components/inputs/color-picker/index.tsx +0 -1981
- package/components/inputs/color-picker/variants.ts +0 -401
- package/components/inputs/combobox/examples.mdx +0 -366
- package/components/inputs/combobox/index.tsx +0 -1527
- package/components/inputs/combobox/remote-demo.tsx +0 -105
- package/components/inputs/date-time/calendar/examples.mdx +0 -45
- package/components/inputs/date-time/calendar/index.tsx +0 -370
- package/components/inputs/date-time/calendar/use-month-window.ts +0 -173
- package/components/inputs/date-time/date-picker/examples.mdx +0 -243
- package/components/inputs/date-time/date-picker/index.tsx +0 -476
- package/components/inputs/date-time/date-picker/masked-date-input.tsx +0 -348
- package/components/inputs/date-time/date-range-picker/examples.mdx +0 -93
- package/components/inputs/date-time/date-range-picker/index.tsx +0 -525
- package/components/inputs/date-time/duration-picker/examples.mdx +0 -40
- package/components/inputs/date-time/duration-picker/index.tsx +0 -253
- package/components/inputs/date-time/month-picker/examples.mdx +0 -45
- package/components/inputs/date-time/month-picker/index.tsx +0 -254
- package/components/inputs/date-time/picker-shell.tsx +0 -581
- package/components/inputs/date-time/time-columns.tsx +0 -94
- package/components/inputs/date-time/time-picker/examples.mdx +0 -57
- package/components/inputs/date-time/time-picker/index.tsx +0 -227
- package/components/inputs/field/examples.mdx +0 -117
- package/components/inputs/field/index.tsx +0 -268
- package/components/inputs/file-dropzone/examples.mdx +0 -83
- package/components/inputs/file-dropzone/file-row.tsx +0 -201
- package/components/inputs/file-dropzone/index.tsx +0 -316
- package/components/inputs/file-dropzone/upload-demo.tsx +0 -67
- package/components/inputs/file-dropzone/variants.ts +0 -94
- package/components/inputs/input/examples.mdx +0 -166
- package/components/inputs/input/index.tsx +0 -494
- package/components/inputs/input/password-demo.tsx +0 -30
- package/components/inputs/label/examples.mdx +0 -67
- package/components/inputs/label/index.tsx +0 -85
- package/components/inputs/number-input/examples.mdx +0 -69
- package/components/inputs/number-input/index.tsx +0 -221
- package/components/inputs/radio/examples.mdx +0 -77
- package/components/inputs/radio/index.tsx +0 -636
- package/components/inputs/search/examples.mdx +0 -74
- package/components/inputs/search/index.tsx +0 -333
- package/components/inputs/select/examples.mdx +0 -296
- package/components/inputs/select/index.tsx +0 -1044
- package/components/inputs/select/variants.ts +0 -32
- package/components/inputs/slider/examples.mdx +0 -153
- package/components/inputs/slider/index.tsx +0 -1867
- package/components/inputs/switch/examples.mdx +0 -96
- package/components/inputs/switch/index.tsx +0 -504
- package/components/inputs/textarea/examples.mdx +0 -126
- package/components/inputs/textarea/index.tsx +0 -207
- package/components/navigation/navigation-menu/examples.mdx +0 -136
- package/components/navigation/navigation-menu/index.tsx +0 -704
- package/components/navigation/pagination/examples.mdx +0 -74
- package/components/navigation/pagination/index.tsx +0 -401
- package/components/navigation/sidebar/examples.mdx +0 -325
- package/components/navigation/sidebar/index.tsx +0 -453
- package/components/navigation/sidebar/sidebar-core.tsx +0 -1408
- package/components/navigation/sidebar/sidebar-menu.tsx +0 -1495
- package/components/navigation/sidebar/sidebar.css +0 -74
- package/components/navigation/sidebar/variants.ts +0 -55
- package/components/navigation/tabs/examples.mdx +0 -89
- package/components/navigation/tabs/index.tsx +0 -494
- package/components/navigation/tabs-subtle/examples.mdx +0 -49
- package/components/navigation/tabs-subtle/index.tsx +0 -512
- package/components/overlays/alert-dialog/examples.mdx +0 -123
- package/components/overlays/alert-dialog/index.tsx +0 -276
- package/components/overlays/alert-dialog/pending-demo.tsx +0 -36
- package/components/overlays/command/examples.mdx +0 -113
- package/components/overlays/command/index.tsx +0 -425
- package/components/overlays/context-menu/examples.mdx +0 -56
- package/components/overlays/context-menu/index.tsx +0 -279
- package/components/overlays/dialog/examples.mdx +0 -165
- package/components/overlays/dialog/index.tsx +0 -451
- package/components/overlays/dropdown/dropdown-search.tsx +0 -395
- package/components/overlays/dropdown/examples.mdx +0 -444
- package/components/overlays/dropdown/index.tsx +0 -1241
- package/components/overlays/dropdown/menu-item.tsx +0 -510
- package/components/overlays/dropdown/menu-parts.tsx +0 -725
- package/components/overlays/popover/anchored-demo.tsx +0 -59
- package/components/overlays/popover/examples.mdx +0 -203
- package/components/overlays/popover/index.tsx +0 -317
- package/components/overlays/preview-card/examples.mdx +0 -61
- package/components/overlays/preview-card/index.tsx +0 -204
- package/components/overlays/sheet/examples.mdx +0 -101
- package/components/overlays/sheet/index.tsx +0 -307
- package/components/overlays/toast/examples.mdx +0 -85
- package/components/overlays/toast/global-demo.tsx +0 -72
- package/components/overlays/toast/index.tsx +0 -544
- package/components/overlays/toast/manager.ts +0 -193
- package/components/overlays/tooltip/examples.mdx +0 -106
- package/components/overlays/tooltip/index.tsx +0 -539
- package/components/progress/examples.mdx +0 -59
- package/components/progress/index.tsx +0 -174
- package/components/progress/progress.css +0 -49
- package/components/progress/step-demo.tsx +0 -27
- package/components/table/examples.mdx +0 -188
- package/components/table/index.tsx +0 -535
- package/components/table/sort-demo.tsx +0 -61
- package/dist/components/avatar/index.d.ts +0 -46
- package/dist/components/avatar/index.js +0 -19
- package/dist/components/badge/variants.d.ts +0 -33
- package/dist/components/badge/variants.js +0 -10
- package/dist/components/button/variants.d.ts +0 -39
- package/dist/components/button/variants.js +0 -8
- package/dist/components/inputs/color-picker/variants.d.ts +0 -61
- package/dist/components/inputs/color-picker/variants.js +0 -28
- package/dist/components/inputs/field/index.d.ts +0 -116
- package/dist/components/inputs/field/index.js +0 -29
- package/dist/components/inputs/file-dropzone/index.d.ts +0 -167
- package/dist/components/inputs/file-dropzone/index.js +0 -33
- package/dist/components/inputs/file-dropzone/variants.d.ts +0 -35
- package/dist/components/inputs/file-dropzone/variants.js +0 -12
- package/dist/components/inputs/label/index.d.ts +0 -32
- package/dist/components/inputs/label/index.js +0 -11
- package/dist/components/inputs/number-input/index.d.ts +0 -87
- package/dist/components/inputs/number-input/index.js +0 -21
- package/dist/components/inputs/select/variants.d.ts +0 -5
- package/dist/components/inputs/select/variants.js +0 -6
- package/dist/components/navigation/navigation-menu/index.d.ts +0 -126
- package/dist/components/navigation/navigation-menu/index.js +0 -41
- package/dist/components/navigation/pagination/index.d.ts +0 -75
- package/dist/components/navigation/pagination/index.js +0 -41
- package/dist/components/navigation/sidebar/variants.d.ts +0 -25
- package/dist/components/navigation/sidebar/variants.js +0 -28
- package/dist/components/progress/index.d.ts +0 -56
- package/dist/components/progress/index.js +0 -15
- package/dist/docs/index.d.ts +0 -83
- package/dist/docs/index.js +0 -288
- package/dist/docs/vite.d.ts +0 -31
- package/dist/docs/vite.js +0 -45
- package/dist/lib/date-locale.d.ts +0 -26
- package/dist/lib/date-locale.js +0 -24
- package/dist/lib/field-classes.d.ts +0 -149
- package/dist/lib/field-classes.js +0 -41
- package/dist/lib/field-variants.d.ts +0 -47
- package/dist/lib/field-variants.js +0 -26
- package/dist/lib/fluid-hover-highlight.d.ts +0 -112
- package/dist/lib/fluid-hover-highlight.js +0 -17
- package/dist/lib/focus-ring.d.ts +0 -18
- package/dist/lib/focus-ring.js +0 -11
- package/dist/lib/goo-indicator.d.ts +0 -46
- package/dist/lib/goo-indicator.js +0 -14
- package/dist/lib/icon-context.d.ts +0 -30
- package/dist/lib/icon-context.js +0 -12
- package/dist/lib/inert.d.ts +0 -9
- package/dist/lib/inert.js +0 -8
- package/dist/lib/morph-layers.d.ts +0 -93
- package/dist/lib/morph-layers.js +0 -13
- package/dist/lib/morph-part.d.ts +0 -21
- package/dist/lib/morph-part.js +0 -12
- package/dist/lib/popup.d.ts +0 -20
- package/dist/lib/popup.js +0 -12
- package/dist/lib/reduced-motion.d.ts +0 -9
- package/dist/lib/reduced-motion.js +0 -6
- package/dist/lib/row-index.d.ts +0 -10
- package/dist/lib/row-index.js +0 -8
- package/dist/lib/row-order.d.ts +0 -28
- package/dist/lib/row-order.js +0 -10
- package/dist/lib/scroll-column.d.ts +0 -31
- package/dist/lib/scroll-column.js +0 -19
- package/dist/lib/shape-context.d.ts +0 -30
- package/dist/lib/shape-context.js +0 -13
- package/dist/lib/shape-radius.d.ts +0 -19
- package/dist/lib/shape-radius.js +0 -6
- package/dist/lib/size-context.d.ts +0 -94
- package/dist/lib/size-context.js +0 -20
- package/dist/lib/size-scale.d.ts +0 -79
- package/dist/lib/size-scale.js +0 -8
- package/dist/lib/slot.d.ts +0 -39
- package/dist/lib/slot.js +0 -14
- package/dist/lib/springs.d.ts +0 -44
- package/dist/lib/springs.js +0 -8
- package/dist/lib/surface-classes.d.ts +0 -19
- package/dist/lib/surface-classes.js +0 -10
- package/dist/lib/surface-context.d.ts +0 -9
- package/dist/lib/surface-context.js +0 -8
- package/dist/lib/use-controllable-state.d.ts +0 -2
- package/dist/lib/use-controllable-state.js +0 -6
- package/dist/lib/use-fluid-hover.d.ts +0 -138
- package/dist/lib/use-fluid-hover.js +0 -14
- package/dist/lib/use-is-mobile.d.ts +0 -2
- package/dist/lib/use-is-mobile.js +0 -6
- package/dist/lib/use-keyboard-nav-gate.d.ts +0 -20
- package/dist/lib/use-keyboard-nav-gate.js +0 -7
- package/dist/lib/use-merge-split.d.ts +0 -47
- package/dist/lib/use-merge-split.js +0 -15
- package/dist/lib/use-morph.d.ts +0 -101
- package/dist/lib/use-morph.js +0 -20
- package/dist/lib/use-touch-primary.d.ts +0 -2
- package/dist/lib/use-touch-primary.js +0 -6
- package/dist/lib/utils.d.ts +0 -3
- package/dist/lib/utils.js +0 -6
- package/dist/primitives/separator/index.d.ts +0 -25
- package/dist/primitives/separator/index.js +0 -9
- package/dist/primitives/skeleton/index.d.ts +0 -35
- package/dist/primitives/skeleton/index.js +0 -13
- package/dist/shared/components-124epb7f.js +0 -53
- package/dist/shared/components-1kab3j44.js +0 -337
- package/dist/shared/components-26snnbs9.js +0 -322
- package/dist/shared/components-34txk9rj.js +0 -35
- package/dist/shared/components-3h92d94m.js +0 -23
- package/dist/shared/components-4vfm04wq.js +0 -82
- package/dist/shared/components-54nq988h.js +0 -123
- package/dist/shared/components-7s7pykk5.js +0 -281
- package/dist/shared/components-7zkhz3r8.js +0 -399
- package/dist/shared/components-8v644a0s.js +0 -298
- package/dist/shared/components-a4evvq8h.js +0 -271
- package/dist/shared/components-adkarj8n.js +0 -35
- package/dist/shared/components-b1e239g3.js +0 -28
- package/dist/shared/components-b94t6qtj.js +0 -143
- package/dist/shared/components-c9yr4ed1.js +0 -44
- package/dist/shared/components-cwg1d0w6.js +0 -254
- package/dist/shared/components-d3shbwqq.js +0 -95
- package/dist/shared/components-dhgk6mbt.js +0 -16
- package/dist/shared/components-drxrtnp2.js +0 -25
- package/dist/shared/components-ej4r7wmj.js +0 -482
- package/dist/shared/components-f7h57m6t.js +0 -59
- package/dist/shared/components-fejdzvqc.js +0 -448
- package/dist/shared/components-gx4h5rbb.js +0 -40
- package/dist/shared/components-gyt7my41.js +0 -328
- package/dist/shared/components-h6p86be3.js +0 -19
- package/dist/shared/components-h83az0bz.js +0 -33
- package/dist/shared/components-hdzrqqpx.js +0 -55
- package/dist/shared/components-krtx3m5b.js +0 -84
- package/dist/shared/components-kswxnm3h.js +0 -24
- package/dist/shared/components-mpa2y6x8.js +0 -277
- package/dist/shared/components-mrbaxt8q.js +0 -62
- package/dist/shared/components-pt5ftm4p.js +0 -38
- package/dist/shared/components-rpw4md2b.js +0 -179
- package/dist/shared/components-rtadhd9j.js +0 -64
- package/dist/shared/components-tz4gaf1v.js +0 -23
- package/dist/shared/components-wbbckbw8.js +0 -34
- package/dist/shared/components-xdqmt6ed.js +0 -20
- package/dist/shared/components-xjkdvnbg.js +0 -107
- package/dist/shared/components-z3v0n0de.js +0 -11
- package/dist/shared/components-z6dfqtyt.js +0 -1545
- package/dist/tokens/colors.css +0 -230
- package/dist/tokens/motion.css +0 -40
- package/dist/tokens/radius.css +0 -10
- package/dist/tokens/spacing.css +0 -9
- package/dist/tokens/typography.css +0 -119
- package/docs/chrome.css +0 -120
- package/docs/chrome.tsx +0 -283
- package/docs/index.ts +0 -9
- package/docs/vite.ts +0 -85
- package/index.ts +0 -60
- package/lib/date-locale.ts +0 -195
- package/lib/field-classes.ts +0 -121
- package/lib/field-variants.ts +0 -117
- package/lib/fluid-hover-highlight.tsx +0 -139
- package/lib/focus-ring.tsx +0 -46
- package/lib/goo-indicator.tsx +0 -261
- package/lib/icon-context.tsx +0 -310
- package/lib/inert.ts +0 -22
- package/lib/morph-layers.tsx +0 -102
- package/lib/morph-part.tsx +0 -49
- package/lib/popup.ts +0 -52
- package/lib/reduced-motion.ts +0 -19
- package/lib/row-index.tsx +0 -29
- package/lib/row-order.tsx +0 -126
- package/lib/scroll-column.tsx +0 -273
- package/lib/shape-context.tsx +0 -138
- package/lib/shape-radius.ts +0 -67
- package/lib/size-context.tsx +0 -66
- package/lib/size-scale.ts +0 -115
- package/lib/slot.ts +0 -115
- package/lib/springs.ts +0 -62
- package/lib/surface-classes.ts +0 -58
- package/lib/surface-context.tsx +0 -21
- package/lib/use-controllable-state.ts +0 -44
- package/lib/use-fluid-hover.ts +0 -541
- package/lib/use-is-mobile.ts +0 -25
- package/lib/use-keyboard-nav-gate.ts +0 -45
- package/lib/use-merge-split.tsx +0 -209
- package/lib/use-morph.ts +0 -557
- package/lib/use-touch-primary.tsx +0 -43
- package/lib/utils.ts +0 -37
- package/preset.ts +0 -199
- package/primitives/code/examples.mdx +0 -27
- package/primitives/code/index.tsx +0 -80
- package/primitives/craft/demos.tsx +0 -173
- package/primitives/craft/examples.mdx +0 -142
- package/primitives/craft/index.tsx +0 -76
- package/primitives/fluid-hover/examples.mdx +0 -84
- package/primitives/fluid-hover/index.tsx +0 -316
- package/primitives/morph/examples.mdx +0 -139
- package/primitives/morph/index.tsx +0 -192
- package/primitives/motion/examples.mdx +0 -100
- package/primitives/motion/index.tsx +0 -160
- package/primitives/scroll-area/examples.mdx +0 -58
- package/primitives/scroll-area/index.tsx +0 -204
- package/primitives/separator/examples.mdx +0 -30
- package/primitives/separator/index.tsx +0 -53
- package/primitives/sizes/examples.mdx +0 -167
- package/primitives/sizes/index.tsx +0 -89
- package/primitives/skeleton/examples.mdx +0 -51
- package/primitives/skeleton/index.tsx +0 -72
- package/primitives/skeleton/skeleton.css +0 -15
- package/primitives/surface/examples.mdx +0 -173
- package/primitives/surface/index.tsx +0 -109
- package/primitives/surface/surface.css +0 -176
- /package/dist/shared/{components-3ey0hzpb.js → components-1v7rxytx.js} +0 -0
- /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
|