@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,105 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Local addition (not part of Fluid Functionalism): the docs stage of the
|
|
3
|
-
* Combobox page's remote example. A fake server answers each query after a
|
|
4
|
-
* beat, a page at a time, so the example stays hook-free.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { useEffect, useState } from 'react'
|
|
8
|
-
import Button from '../../button'
|
|
9
|
-
import Combobox from './index'
|
|
10
|
-
|
|
11
|
-
const CITIES = [
|
|
12
|
-
'Amsterdam',
|
|
13
|
-
'Athens',
|
|
14
|
-
'Barcelona',
|
|
15
|
-
'Berlin',
|
|
16
|
-
'Bratislava',
|
|
17
|
-
'Brussels',
|
|
18
|
-
'Bucharest',
|
|
19
|
-
'Budapest',
|
|
20
|
-
'Copenhagen',
|
|
21
|
-
'Dublin',
|
|
22
|
-
'Helsinki',
|
|
23
|
-
'Kyiv',
|
|
24
|
-
'Lisbon',
|
|
25
|
-
'Ljubljana',
|
|
26
|
-
'London',
|
|
27
|
-
'Madrid',
|
|
28
|
-
'Oslo',
|
|
29
|
-
'Paris',
|
|
30
|
-
'Prague',
|
|
31
|
-
'Riga',
|
|
32
|
-
'Rome',
|
|
33
|
-
'Sofia',
|
|
34
|
-
'Stockholm',
|
|
35
|
-
'Tallinn',
|
|
36
|
-
'Vienna',
|
|
37
|
-
'Vilnius',
|
|
38
|
-
'Warsaw',
|
|
39
|
-
'Zagreb',
|
|
40
|
-
]
|
|
41
|
-
|
|
42
|
-
const PAGE = 6
|
|
43
|
-
|
|
44
|
-
interface RemoteDemoProps {
|
|
45
|
-
/** How long the fake server takes, in ms. Defaults to `600`. */
|
|
46
|
-
latency?: number
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export default function RemoteDemo({ latency = 600 }: RemoteDemoProps) {
|
|
50
|
-
const [query, setQuery] = useState('')
|
|
51
|
-
const [limit, setLimit] = useState(PAGE)
|
|
52
|
-
const [items, setItems] = useState<string[]>([])
|
|
53
|
-
const [total, setTotal] = useState(0)
|
|
54
|
-
const [loading, setLoading] = useState(true)
|
|
55
|
-
// Base UI's change details tell typing from a pick that rewrites the field.
|
|
56
|
-
const [reason, setReason] = useState<string>()
|
|
57
|
-
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
setLoading(true)
|
|
60
|
-
const timer = setTimeout(() => {
|
|
61
|
-
const matches = CITIES.filter(city => city.toLowerCase().includes(query.trim().toLowerCase()))
|
|
62
|
-
setItems(matches.slice(0, limit))
|
|
63
|
-
setTotal(matches.length)
|
|
64
|
-
setLoading(false)
|
|
65
|
-
}, latency)
|
|
66
|
-
return () => clearTimeout(timer)
|
|
67
|
-
}, [query, limit, latency])
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<div className="w-72 max-w-full">
|
|
71
|
-
<Combobox
|
|
72
|
-
items={items}
|
|
73
|
-
filter={null}
|
|
74
|
-
loading={loading}
|
|
75
|
-
inputValue={query}
|
|
76
|
-
onInputValueChange={(next, details) => {
|
|
77
|
-
setQuery(next)
|
|
78
|
-
setLimit(PAGE)
|
|
79
|
-
setReason(details.reason)
|
|
80
|
-
}}
|
|
81
|
-
>
|
|
82
|
-
<Combobox.Input placeholder="Search a city…" />
|
|
83
|
-
<Combobox.Content
|
|
84
|
-
footer={
|
|
85
|
-
items.length < total ? (
|
|
86
|
-
<Button variant="ghost" size="compact" className="w-full" onClick={() => setLimit(limit + PAGE)}>
|
|
87
|
-
Load more ({total - items.length})
|
|
88
|
-
</Button>
|
|
89
|
-
) : undefined
|
|
90
|
-
}
|
|
91
|
-
>
|
|
92
|
-
<Combobox.Empty>No city matches.</Combobox.Empty>
|
|
93
|
-
<Combobox.List>
|
|
94
|
-
{item => (
|
|
95
|
-
<Combobox.Item key={String(item)} value={String(item)}>
|
|
96
|
-
{String(item)}
|
|
97
|
-
</Combobox.Item>
|
|
98
|
-
)}
|
|
99
|
-
</Combobox.List>
|
|
100
|
-
</Combobox.Content>
|
|
101
|
-
</Combobox>
|
|
102
|
-
{reason && <p className="mt-1 pl-3 text-caption text-muted-foreground">Last text change: {reason}</p>}
|
|
103
|
-
</div>
|
|
104
|
-
)
|
|
105
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import Calendar from './index'
|
|
2
|
-
import { de } from 'react-day-picker/locale'
|
|
3
|
-
|
|
4
|
-
# Single day
|
|
5
|
-
|
|
6
|
-
Scroll through the months, or jump with the month and year columns.
|
|
7
|
-
|
|
8
|
-
<Calendar mode="single" selected={new Date(2026, 9, 9)} />
|
|
9
|
-
|
|
10
|
-
# Range
|
|
11
|
-
|
|
12
|
-
`mode="range"` picks a span of days.
|
|
13
|
-
|
|
14
|
-
<Calendar mode="range" selected={{ from: new Date(2026, 9, 9), to: new Date(2026, 9, 15) }} />
|
|
15
|
-
|
|
16
|
-
# German
|
|
17
|
-
|
|
18
|
-
A react-day-picker locale names the months and weekdays and starts the week on its first day.
|
|
19
|
-
|
|
20
|
-
<Calendar mode="single" locale={de} selected={new Date(2026, 9, 9)} />
|
|
21
|
-
|
|
22
|
-
# Columns first
|
|
23
|
-
|
|
24
|
-
`columnsSide="start"` stands the year and month columns before the days.
|
|
25
|
-
|
|
26
|
-
<Calendar mode="single" columnsSide="start" selected={new Date(2026, 9, 9)} />
|
|
27
|
-
|
|
28
|
-
# Narrow
|
|
29
|
-
|
|
30
|
-
Without room for the columns, they turn into strips above the days.
|
|
31
|
-
|
|
32
|
-
<div className="w-72 max-w-full">
|
|
33
|
-
<Calendar mode="single" selected={new Date(2026, 9, 9)} />
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
# Fixed height
|
|
37
|
-
|
|
38
|
-
A height class on the calendar sets its height in both layouts, with the columns beside the days or above them. The calendar needs a bounded height for this: without one every month in the window renders and it opens on the window start.
|
|
39
|
-
|
|
40
|
-
<div className="flex flex-wrap items-start gap-4">
|
|
41
|
-
<Calendar mode="single" className="h-72" selected={new Date(2026, 9, 9)} />
|
|
42
|
-
<div className="w-72 max-w-full">
|
|
43
|
-
<Calendar mode="single" className="h-72" selected={new Date(2026, 9, 9)} />
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Local addition (not part of Fluid Functionalism): a scrolling calendar on
|
|
3
|
-
* react-day-picker (daypicker.dev), styled through its `classNames` and
|
|
4
|
-
* custom components with DS utilities (its stylesheet isn't loaded). Props
|
|
5
|
-
* pass through to DayPicker, the way shadcn's Calendar does.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
addDays,
|
|
10
|
-
addYears,
|
|
11
|
-
endOfYear,
|
|
12
|
-
format,
|
|
13
|
-
isSameYear,
|
|
14
|
-
type Locale,
|
|
15
|
-
startOfMonth,
|
|
16
|
-
startOfWeek,
|
|
17
|
-
startOfYear,
|
|
18
|
-
} from 'date-fns'
|
|
19
|
-
import {
|
|
20
|
-
Fragment,
|
|
21
|
-
type ReactElement,
|
|
22
|
-
type ReactNode,
|
|
23
|
-
useCallback,
|
|
24
|
-
useEffect,
|
|
25
|
-
useLayoutEffect,
|
|
26
|
-
useMemo,
|
|
27
|
-
useRef,
|
|
28
|
-
useState,
|
|
29
|
-
} from 'react'
|
|
30
|
-
import { type DayButtonProps, DayPicker, type DayPickerProps, type DayProps, type MonthProps } from 'react-day-picker'
|
|
31
|
-
import { defaultLocale, fieldLabel } from '../../../../lib/date-locale'
|
|
32
|
-
import { dividedColumns, ScrollColumn } from '../../../../lib/scroll-column'
|
|
33
|
-
import { useShape } from '../../../../lib/shape-context'
|
|
34
|
-
import { type SizeVariant, useSize } from '../../../../lib/size-context'
|
|
35
|
-
import { cn } from '../../../../lib/utils'
|
|
36
|
-
import { SizeProvider } from '../../../../primitives/sizes'
|
|
37
|
-
import { monthKey, useMonthWindow } from './use-month-window'
|
|
38
|
-
|
|
39
|
-
const WEEKEND = { dayOfWeek: [0, 6] }
|
|
40
|
-
|
|
41
|
-
/** The day picked for the columns' dot and the first scroll: a single date, or a range's start. */
|
|
42
|
-
function pickedDate(props: DayPickerProps): Date | undefined {
|
|
43
|
-
if (props.mode === 'single') return props.selected
|
|
44
|
-
if (props.mode === 'range') return props.selected?.from
|
|
45
|
-
return undefined
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Stamps each month with its key, so the window can find and measure it. */
|
|
49
|
-
function Month({ calendarMonth, displayIndex: _, ...props }: MonthProps) {
|
|
50
|
-
return <div {...props} data-calendar-month={monthKey(calendarMonth.date)} />
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** The day's cell: draws a range's band behind the pills. */
|
|
54
|
-
function Day({ day: _, modifiers, className, ...props }: DayProps) {
|
|
55
|
-
const start = modifiers.range_start && !modifiers.range_end
|
|
56
|
-
const end = modifiers.range_end && !modifiers.range_start
|
|
57
|
-
return (
|
|
58
|
-
<td
|
|
59
|
-
{...props}
|
|
60
|
-
className={cn(
|
|
61
|
-
'relative p-0',
|
|
62
|
-
// FF's fills: a committed span is `bg-active` (Checkbox's merged
|
|
63
|
-
// rows), the preview one step lighter at `bg-hover`.
|
|
64
|
-
!modifiers.hidden && modifiers.range_middle && 'bg-active',
|
|
65
|
-
!modifiers.hidden && modifiers.preview && !modifiers.selected && 'bg-hover',
|
|
66
|
-
(start || end) && 'before:absolute before:inset-y-0 before:bg-active',
|
|
67
|
-
start && 'before:start-1/2 before:end-0',
|
|
68
|
-
end && 'before:start-0 before:end-1/2',
|
|
69
|
-
className,
|
|
70
|
-
)}
|
|
71
|
-
/>
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function DayButton({ day: _, modifiers, className, ...props }: DayButtonProps) {
|
|
76
|
-
const ref = useRef<HTMLButtonElement>(null)
|
|
77
|
-
// DayPicker's own DayButton does this: keyboard focus follows `focused`.
|
|
78
|
-
useEffect(() => {
|
|
79
|
-
if (modifiers.focused) ref.current?.focus()
|
|
80
|
-
}, [modifiers.focused])
|
|
81
|
-
const shape = useShape()
|
|
82
|
-
const sizeClasses = useSize()
|
|
83
|
-
const pill = modifiers.selected && !modifiers.range_middle
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<button
|
|
87
|
-
ref={ref}
|
|
88
|
-
{...props}
|
|
89
|
-
className={cn(
|
|
90
|
-
'relative flex items-center justify-center tabular-nums outline-none cursor-pointer',
|
|
91
|
-
'transition-[color,background-color] duration-fast focus-visible:ring-1 focus-visible:ring-focus-ring',
|
|
92
|
-
'disabled:opacity-50 disabled:cursor-default',
|
|
93
|
-
sizeClasses.variant === 'compact' ? 'size-7' : 'size-9',
|
|
94
|
-
sizeClasses.text,
|
|
95
|
-
shape.item,
|
|
96
|
-
// FF keeps red for errors: weekends step back to the muted text.
|
|
97
|
-
modifiers.weekend && 'text-muted-foreground',
|
|
98
|
-
modifiers.today &&
|
|
99
|
-
'after:absolute after:bottom-1 after:left-1/2 after:size-1 after:-translate-x-1/2 after:rounded-full after:bg-current',
|
|
100
|
-
// Foreground is FF's primary (its primary button's fill), text-background on it.
|
|
101
|
-
pill ? 'bg-foreground text-background weight-semibold hover:bg-foreground/90' : 'enabled:hover:bg-hover',
|
|
102
|
-
className,
|
|
103
|
-
)}
|
|
104
|
-
/>
|
|
105
|
-
)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** The Calendar's own props, beside DayPicker's. */
|
|
109
|
-
interface CalendarOwnProps {
|
|
110
|
-
/** The locale: a react-day-picker / date-fns locale (`import { de } from 'react-day-picker/locale'`). Names months and weekdays, picks the first day of the week. Defaults to `enUS`. */
|
|
111
|
-
locale?: Locale
|
|
112
|
-
/** Pins the calendar to one step of the size ladder (36px days, compact 28px). Defaults to the surrounding SizeProvider. */
|
|
113
|
-
size?: SizeVariant
|
|
114
|
-
/** Which side of the days the month and year columns stand on; the month column keeps next to the days. Defaults to `'end'`. */
|
|
115
|
-
columnsSide?: 'start' | 'end'
|
|
116
|
-
/** Accessible names of the month and year columns (`{ month, year }`). Default to the locale's names for the fields. */
|
|
117
|
-
columnLabels?: { month?: string; year?: string }
|
|
118
|
-
/** More columns, given the layout's orientation — the date picker's hours and minutes. */
|
|
119
|
-
extraColumns?: (orientation: 'vertical' | 'horizontal') => ReactNode
|
|
120
|
-
/** Which side of the days the extra columns stand on, outside the month and year columns when they share it. Defaults to `'end'`. */
|
|
121
|
-
extraColumnsSide?: 'start' | 'end'
|
|
122
|
-
/** Classes for the calendar's box. */
|
|
123
|
-
className?: string
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/** DayPicker's props (`mode`, `selected`, `onSelect`, matchers…) and the Calendar's own. */
|
|
127
|
-
type CalendarProps = DayPickerProps & CalendarOwnProps
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* A calendar that scrolls through the months instead of paging, with month
|
|
131
|
-
* and year columns to jump by.
|
|
132
|
-
*
|
|
133
|
-
* Months run on in one list, each under its name, with the weekday row pinned
|
|
134
|
-
* above them; weekends step back to the muted text and today carries a dot. The month column
|
|
135
|
-
* marks the month being read and the year column its year, so either works
|
|
136
|
-
* as a scrollbar you can click: a month or a year scrolls the calendar there.
|
|
137
|
-
* The picked day, month and year show a filled pill or a dot. The columns
|
|
138
|
-
* stand after the days by default; `columnsSide="start"` puts them before
|
|
139
|
-
* (and `extraColumnsSide` places any extra ones). When the calendar is too
|
|
140
|
-
* narrow for them, they turn into strips above it. The list renders a window of months and moves it as you scroll, so the
|
|
141
|
-
* range is as long as `startMonth` / `endMonth` allow (100 years back and 50
|
|
142
|
-
* ahead by default).
|
|
143
|
-
*
|
|
144
|
-
* It is react-day-picker's DayPicker underneath: `mode` (`'single'`,
|
|
145
|
-
* `'range'`), `selected` / `onSelect`, `disabled` and `hidden` matchers,
|
|
146
|
-
* `modifiers`, `weekStartsOn`, `dir` and the other DayPicker props pass
|
|
147
|
-
* through. Its navigation props don't apply: the calendar scrolls.
|
|
148
|
-
* DatePicker and DateRangePicker put it in a field.
|
|
149
|
-
*
|
|
150
|
-
* @example {@include ./examples.mdx}
|
|
151
|
-
*/
|
|
152
|
-
function Calendar({
|
|
153
|
-
locale = defaultLocale,
|
|
154
|
-
size,
|
|
155
|
-
columnsSide = 'end',
|
|
156
|
-
columnLabels,
|
|
157
|
-
extraColumns,
|
|
158
|
-
extraColumnsSide = 'end',
|
|
159
|
-
className,
|
|
160
|
-
...props
|
|
161
|
-
}: CalendarProps): ReactElement {
|
|
162
|
-
const sizeClasses = useSize(size)
|
|
163
|
-
const picked = pickedDate(props)
|
|
164
|
-
const today = useMemo(() => new Date(), [])
|
|
165
|
-
const start = startOfMonth(props.startMonth ?? startOfYear(addYears(today, -100)))
|
|
166
|
-
const end = startOfMonth(props.endMonth ?? endOfYear(addYears(today, 50)))
|
|
167
|
-
const anchor = picked ?? props.month ?? props.defaultMonth ?? today
|
|
168
|
-
const scroll = useMonthWindow(start, end, anchor)
|
|
169
|
-
const { jumpTo, visible } = scroll
|
|
170
|
-
|
|
171
|
-
// Before the first measure, the month the list opens on.
|
|
172
|
-
const currentKey = scroll.current ?? monthKey(anchor)
|
|
173
|
-
const yearInView = Number(currentKey.slice(0, 4))
|
|
174
|
-
const monthInView = Number(currentKey.slice(5, 7)) - 1
|
|
175
|
-
|
|
176
|
-
// A pick from outside the calendar (typed into a picker's field) scrolls to it.
|
|
177
|
-
const pickedTime = picked?.getTime()
|
|
178
|
-
const pickedRef = useRef(pickedTime)
|
|
179
|
-
useEffect(() => {
|
|
180
|
-
if (pickedTime === pickedRef.current) return
|
|
181
|
-
pickedRef.current = pickedTime
|
|
182
|
-
if (pickedTime !== undefined && !visible.includes(monthKey(new Date(pickedTime)))) jumpTo(new Date(pickedTime))
|
|
183
|
-
}, [pickedTime, jumpTo, visible])
|
|
184
|
-
|
|
185
|
-
// The columns stand beside the grid while they fit, and turn into strips
|
|
186
|
-
// above it when they don't. The width they need is remembered, so the
|
|
187
|
-
// strips only turn back once there is room again.
|
|
188
|
-
const rootRef = useRef<HTMLDivElement>(null)
|
|
189
|
-
const [wide, setWide] = useState(true)
|
|
190
|
-
const needed = useRef(0)
|
|
191
|
-
useLayoutEffect(() => {
|
|
192
|
-
const root = rootRef.current
|
|
193
|
-
if (!root) return
|
|
194
|
-
const check = () => {
|
|
195
|
-
if (wide && root.scrollWidth > root.clientWidth + 1) {
|
|
196
|
-
needed.current = root.scrollWidth
|
|
197
|
-
setWide(false)
|
|
198
|
-
} else if (!wide && root.clientWidth >= needed.current) setWide(true)
|
|
199
|
-
}
|
|
200
|
-
check()
|
|
201
|
-
const observer = new ResizeObserver(check)
|
|
202
|
-
observer.observe(root)
|
|
203
|
-
return () => observer.disconnect()
|
|
204
|
-
}, [wide])
|
|
205
|
-
|
|
206
|
-
// Turning changes the grid's height: put the picked day (or today) back in the middle.
|
|
207
|
-
const turned = useRef(wide)
|
|
208
|
-
useLayoutEffect(() => {
|
|
209
|
-
if (turned.current === wide) return
|
|
210
|
-
turned.current = wide
|
|
211
|
-
scroll.centreDay(picked ?? today)
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
// Range picking previews the span under the pointer before the second click.
|
|
215
|
-
const [hovered, setHovered] = useState<Date>()
|
|
216
|
-
const from = props.mode === 'range' ? props.selected?.from : undefined
|
|
217
|
-
const previewing = from && props.mode === 'range' && !props.selected?.to && hovered
|
|
218
|
-
const preview = previewing ? (hovered < from ? { from: hovered, to: from } : { from, to: hovered }) : false
|
|
219
|
-
|
|
220
|
-
const weekStartsOn = props.weekStartsOn ?? locale.options?.weekStartsOn ?? 0
|
|
221
|
-
const weekdays = useMemo(() => {
|
|
222
|
-
const first = startOfWeek(today, { weekStartsOn })
|
|
223
|
-
return Array.from({ length: 7 }, (_, i) => addDays(first, i))
|
|
224
|
-
}, [today, weekStartsOn])
|
|
225
|
-
|
|
226
|
-
const months = useMemo(
|
|
227
|
-
() =>
|
|
228
|
-
Array.from({ length: 12 }, (_, m) => ({
|
|
229
|
-
value: m,
|
|
230
|
-
label: format(new Date(2000, m, 1), 'LLL', { locale }),
|
|
231
|
-
disabled: new Date(yearInView, m, 1) < start || new Date(yearInView, m, 1) > end,
|
|
232
|
-
})),
|
|
233
|
-
[locale, yearInView, start.getTime(), end.getTime()],
|
|
234
|
-
)
|
|
235
|
-
const years = useMemo(
|
|
236
|
-
() =>
|
|
237
|
-
Array.from({ length: end.getFullYear() - start.getFullYear() + 1 }, (_, i) => {
|
|
238
|
-
const year = start.getFullYear() + i
|
|
239
|
-
return { value: year, label: String(year) }
|
|
240
|
-
}),
|
|
241
|
-
[start.getFullYear(), end.getFullYear()],
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
const jumpToYear = useCallback((year: number) => jumpTo(new Date(year, monthInView, 1)), [jumpTo, monthInView])
|
|
245
|
-
const orientation = wide ? 'vertical' : 'horizontal'
|
|
246
|
-
const column = wide ? 'w-16 shrink-0' : 'w-full'
|
|
247
|
-
|
|
248
|
-
const monthColumn = (
|
|
249
|
-
<ScrollColumn
|
|
250
|
-
key="month"
|
|
251
|
-
label={columnLabels?.month ?? fieldLabel(locale, 'month')}
|
|
252
|
-
options={months}
|
|
253
|
-
value={picked && isSameYear(picked, new Date(yearInView, 0, 1)) ? picked.getMonth() : null}
|
|
254
|
-
follow={monthInView}
|
|
255
|
-
inView={m => m === monthInView}
|
|
256
|
-
onValueChange={m => jumpTo(new Date(yearInView, m, 1))}
|
|
257
|
-
orientation={orientation}
|
|
258
|
-
className={column}
|
|
259
|
-
/>
|
|
260
|
-
)
|
|
261
|
-
const yearColumn = (
|
|
262
|
-
<ScrollColumn
|
|
263
|
-
key="year"
|
|
264
|
-
label={columnLabels?.year ?? fieldLabel(locale, 'year')}
|
|
265
|
-
options={years}
|
|
266
|
-
value={picked?.getFullYear() ?? null}
|
|
267
|
-
follow={yearInView}
|
|
268
|
-
inView={y => y === yearInView}
|
|
269
|
-
onValueChange={jumpToYear}
|
|
270
|
-
orientation={orientation}
|
|
271
|
-
className={column}
|
|
272
|
-
/>
|
|
273
|
-
)
|
|
274
|
-
const extras = extraColumns?.(orientation)
|
|
275
|
-
// Outward from the days: the month column, the year column, then the extras.
|
|
276
|
-
// Keyed fragments, so a side's children keep their identity as the extras come and go.
|
|
277
|
-
const extrasPart = extras ? <Fragment key="extras">{extras}</Fragment> : null
|
|
278
|
-
const before = [extraColumnsSide === 'start' && extrasPart, columnsSide === 'start' && [yearColumn, monthColumn]]
|
|
279
|
-
const after = [columnsSide === 'end' && [monthColumn, yearColumn], extraColumnsSide === 'end' && extrasPart]
|
|
280
|
-
const side = (place: 'start' | 'end') =>
|
|
281
|
-
wide
|
|
282
|
-
? cn(dividedColumns, 'h-full shrink-0 border-border', place === 'start' ? 'border-e' : 'border-s')
|
|
283
|
-
: 'order-first flex w-full flex-col [&>*]:border-b [&>*]:border-border'
|
|
284
|
-
|
|
285
|
-
const grid = (
|
|
286
|
-
<div className={cn('flex min-h-0 shrink-0 flex-col', wide ? 'h-full' : 'flex-1 self-center')}>
|
|
287
|
-
<div aria-hidden className="flex border-b border-border px-1 pb-1">
|
|
288
|
-
{weekdays.map(day => (
|
|
289
|
-
<span
|
|
290
|
-
key={day.getDay()}
|
|
291
|
-
className={cn(
|
|
292
|
-
'flex items-center justify-center text-caption',
|
|
293
|
-
sizeClasses.variant === 'compact' ? 'w-7' : 'w-9',
|
|
294
|
-
'text-muted-foreground',
|
|
295
|
-
)}
|
|
296
|
-
>
|
|
297
|
-
{format(day, 'EEEEEE', { locale })}
|
|
298
|
-
</span>
|
|
299
|
-
))}
|
|
300
|
-
</div>
|
|
301
|
-
<div
|
|
302
|
-
ref={scroll.scrollerRef}
|
|
303
|
-
onScroll={scroll.measure}
|
|
304
|
-
className="relative min-h-0 flex-1 overflow-y-auto overflow-x-hidden px-1 scrollbar-hide scroll-fade [--scroll-fade-size:16px] [overflow-anchor:none]"
|
|
305
|
-
>
|
|
306
|
-
<DayPicker
|
|
307
|
-
{...props}
|
|
308
|
-
locale={locale}
|
|
309
|
-
month={scroll.first}
|
|
310
|
-
numberOfMonths={scroll.count}
|
|
311
|
-
startMonth={start}
|
|
312
|
-
endMonth={end}
|
|
313
|
-
onMonthChange={scroll.recentre}
|
|
314
|
-
hideNavigation
|
|
315
|
-
hideWeekdays
|
|
316
|
-
showOutsideDays={false}
|
|
317
|
-
modifiers={{ weekend: WEEKEND, preview, ...props.modifiers }}
|
|
318
|
-
onDayMouseEnter={(date, modifiers, e) => {
|
|
319
|
-
setHovered(date)
|
|
320
|
-
props.onDayMouseEnter?.(date, modifiers, e)
|
|
321
|
-
}}
|
|
322
|
-
onDayMouseLeave={(date, modifiers, e) => {
|
|
323
|
-
setHovered(undefined)
|
|
324
|
-
props.onDayMouseLeave?.(date, modifiers, e)
|
|
325
|
-
}}
|
|
326
|
-
formatters={{
|
|
327
|
-
// The current year's months go by name alone, the rest with their year.
|
|
328
|
-
formatCaption: month => format(month, isSameYear(month, today) ? 'LLLL' : 'LLLL y', { locale }),
|
|
329
|
-
...props.formatters,
|
|
330
|
-
}}
|
|
331
|
-
components={{ Month, Day, DayButton, ...props.components }}
|
|
332
|
-
classNames={{
|
|
333
|
-
months: 'flex flex-col',
|
|
334
|
-
month: 'pb-2',
|
|
335
|
-
month_caption: cn(
|
|
336
|
-
'px-2 pt-2 pb-1 text-subtitle weight-semibold',
|
|
337
|
-
sizeClasses.variant === 'compact' && 'text-subtitle-compact',
|
|
338
|
-
),
|
|
339
|
-
month_grid: 'border-collapse',
|
|
340
|
-
...props.classNames,
|
|
341
|
-
}}
|
|
342
|
-
/>
|
|
343
|
-
</div>
|
|
344
|
-
</div>
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
const content = (
|
|
348
|
-
<div
|
|
349
|
-
ref={rootRef}
|
|
350
|
-
dir={props.dir}
|
|
351
|
-
className={cn(
|
|
352
|
-
'flex w-max max-w-full overflow-hidden',
|
|
353
|
-
wide ? 'h-80 flex-row' : 'h-[min(30rem,65dvh)] flex-col',
|
|
354
|
-
className,
|
|
355
|
-
)}
|
|
356
|
-
>
|
|
357
|
-
{/* Strips are reordered by CSS, not in the tree, so turning doesn't remount the grid. */}
|
|
358
|
-
{before.some(Boolean) ? <div className={side('start')}>{before}</div> : null}
|
|
359
|
-
{grid}
|
|
360
|
-
{after.some(Boolean) ? <div className={side('end')}>{after}</div> : null}
|
|
361
|
-
</div>
|
|
362
|
-
)
|
|
363
|
-
|
|
364
|
-
return size ? <SizeProvider size={size}>{content}</SizeProvider> : content
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
export type { CalendarProps }
|
|
368
|
-
export { Calendar }
|
|
369
|
-
|
|
370
|
-
export default Calendar
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { addMonths, differenceInCalendarMonths, format, startOfMonth } from 'date-fns'
|
|
2
|
-
import { useCallback, useLayoutEffect, useRef, useState } from 'react'
|
|
3
|
-
|
|
4
|
-
/** Months rendered at once, and how far the window moves when the reader nears its edge. */
|
|
5
|
-
const WINDOW = 25
|
|
6
|
-
const SHIFT = 12
|
|
7
|
-
|
|
8
|
-
const monthKey = (date: Date) => format(date, 'yyyy-MM')
|
|
9
|
-
|
|
10
|
-
/** A rendered month's element in the scroller (the Calendar's `Month` stamps the key). */
|
|
11
|
-
const findMonth = (scroller: HTMLElement, key: string) =>
|
|
12
|
-
scroller.querySelector<HTMLElement>(`[data-calendar-month="${key}"]`)
|
|
13
|
-
|
|
14
|
-
/** What the next layout pass scrolls to: back to where the reader was, a month's top, or a day in the middle. */
|
|
15
|
-
interface Pending {
|
|
16
|
-
keep?: { key: string; delta: number }
|
|
17
|
-
month?: string
|
|
18
|
-
day?: Date
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* The calendar's scroll: an endless-feeling list of months between `start` and
|
|
23
|
-
* `end` that renders only `WINDOW` of them. Nearing either rendered edge moves
|
|
24
|
-
* the window by `SHIFT` months and puts the reader back on the month they were
|
|
25
|
-
* reading. Also reports the months in view, for the month and year columns.
|
|
26
|
-
*/
|
|
27
|
-
function useMonthWindow(start: Date, end: Date, anchor: Date) {
|
|
28
|
-
const total = differenceInCalendarMonths(end, start) + 1
|
|
29
|
-
const count = Math.min(WINDOW, total)
|
|
30
|
-
const startTime = start.getTime()
|
|
31
|
-
|
|
32
|
-
const clamp = useCallback(
|
|
33
|
-
(first: Date) => {
|
|
34
|
-
const from = new Date(startTime)
|
|
35
|
-
const last = addMonths(from, total - count)
|
|
36
|
-
return first < from ? from : first > last ? last : startOfMonth(first)
|
|
37
|
-
},
|
|
38
|
-
[startTime, total, count],
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
const [first, setFirst] = useState(() => clamp(addMonths(startOfMonth(anchor), -Math.floor(WINDOW / 2))))
|
|
42
|
-
const [visible, setVisible] = useState<string[]>([])
|
|
43
|
-
// The month taking up most of the view: the one the columns mark.
|
|
44
|
-
const [current, setCurrent] = useState<string>()
|
|
45
|
-
const scrollerRef = useRef<HTMLDivElement>(null)
|
|
46
|
-
const firstRef = useRef(first)
|
|
47
|
-
firstRef.current = first
|
|
48
|
-
const pending = useRef<Pending | null>({ day: anchor })
|
|
49
|
-
// Set while a smooth jump runs: moving the window under it would cut it short.
|
|
50
|
-
const settling = useRef(false)
|
|
51
|
-
|
|
52
|
-
const topMonth = useCallback(() => {
|
|
53
|
-
const scroller = scrollerRef.current
|
|
54
|
-
if (!scroller) return undefined
|
|
55
|
-
const top = scroller.scrollTop
|
|
56
|
-
return [...scroller.querySelectorAll<HTMLElement>('[data-calendar-month]')].find(
|
|
57
|
-
el => el.offsetTop + el.offsetHeight > top,
|
|
58
|
-
)
|
|
59
|
-
}, [])
|
|
60
|
-
|
|
61
|
-
const moveWindow = useCallback(
|
|
62
|
-
(nextFirst: Date, target?: string) => {
|
|
63
|
-
const next = clamp(nextFirst)
|
|
64
|
-
if (next.getTime() === firstRef.current.getTime()) return
|
|
65
|
-
const scroller = scrollerRef.current
|
|
66
|
-
const top = topMonth()
|
|
67
|
-
pending.current = {
|
|
68
|
-
month: target,
|
|
69
|
-
keep:
|
|
70
|
-
scroller && top
|
|
71
|
-
? { key: top.dataset.calendarMonth ?? '', delta: top.offsetTop - scroller.scrollTop }
|
|
72
|
-
: undefined,
|
|
73
|
-
}
|
|
74
|
-
setFirst(next)
|
|
75
|
-
},
|
|
76
|
-
[clamp, topMonth],
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
/** Scrolls a rendered day into the middle of the list, at once. */
|
|
80
|
-
const centreDay = useCallback((date: Date) => {
|
|
81
|
-
const scroller = scrollerRef.current
|
|
82
|
-
const day = scroller?.querySelector<HTMLElement>(`[data-day="${format(date, 'yyyy-MM-dd')}"]`)
|
|
83
|
-
if (!scroller || !day) return
|
|
84
|
-
const s = scroller.getBoundingClientRect()
|
|
85
|
-
const d = day.getBoundingClientRect()
|
|
86
|
-
// In layout pixels: the panel may still be scaled by its opening morph.
|
|
87
|
-
const scale = s.height / scroller.offsetHeight || 1
|
|
88
|
-
scroller.scrollTop += (d.top - s.top) / scale - (scroller.clientHeight - day.offsetHeight) / 2
|
|
89
|
-
}, [])
|
|
90
|
-
|
|
91
|
-
/** Reports the months in view and, when `move` is set, shifts the window if the reader is near its edge. */
|
|
92
|
-
const read = useCallback(
|
|
93
|
-
(move: boolean) => {
|
|
94
|
-
const scroller = scrollerRef.current
|
|
95
|
-
if (!scroller) return
|
|
96
|
-
const top = scroller.scrollTop
|
|
97
|
-
const bottom = top + scroller.clientHeight
|
|
98
|
-
const shown = [...scroller.querySelectorAll<HTMLElement>('[data-calendar-month]')]
|
|
99
|
-
.map(el => ({
|
|
100
|
-
key: el.dataset.calendarMonth ?? '',
|
|
101
|
-
height: Math.min(bottom, el.offsetTop + el.offsetHeight) - Math.max(top, el.offsetTop),
|
|
102
|
-
}))
|
|
103
|
-
.filter(m => m.height > 0)
|
|
104
|
-
const inView = shown.map(m => m.key)
|
|
105
|
-
setVisible(prev => (prev.join() === inView.join() ? prev : inView))
|
|
106
|
-
setCurrent(
|
|
107
|
-
shown.reduce<(typeof shown)[number] | undefined>((a, m) => (a && a.height >= m.height ? a : m), undefined)?.key,
|
|
108
|
-
)
|
|
109
|
-
if (!move || settling.current) return
|
|
110
|
-
|
|
111
|
-
// A reader this close to an edge moves the window. The margin is capped well inside what a shift
|
|
112
|
-
// gives back, so a list with no height of its own (a height class the stylesheet lacks, `h-auto`)
|
|
113
|
-
// can't keep the reader "near" an edge after every move and walk the window to the end of the range.
|
|
114
|
-
const margin = Math.min(scroller.clientHeight, scroller.scrollHeight / 4)
|
|
115
|
-
if (top < margin) moveWindow(addMonths(firstRef.current, -SHIFT))
|
|
116
|
-
else if (scroller.scrollHeight - bottom < margin) moveWindow(addMonths(firstRef.current, SHIFT))
|
|
117
|
-
},
|
|
118
|
-
[moveWindow],
|
|
119
|
-
)
|
|
120
|
-
const measure = useCallback(() => read(true), [read])
|
|
121
|
-
|
|
122
|
-
// Runs after the window moves (and on mount) to restore the reader's place.
|
|
123
|
-
useLayoutEffect(() => {
|
|
124
|
-
const scroller = scrollerRef.current
|
|
125
|
-
const p = pending.current
|
|
126
|
-
pending.current = null
|
|
127
|
-
if (!scroller || !p) return
|
|
128
|
-
const target = p.month && findMonth(scroller, p.month)
|
|
129
|
-
const kept = p.keep && findMonth(scroller, p.keep.key)
|
|
130
|
-
if (target) scroller.scrollTop = target.offsetTop
|
|
131
|
-
else if (kept && p.keep) scroller.scrollTop = kept.offsetTop - p.keep.delta
|
|
132
|
-
else if (p.day) centreDay(p.day)
|
|
133
|
-
// Reports only: moving the window from here would nest one update inside the last, and
|
|
134
|
-
// the scroll the restore causes calls `measure` for the next shift.
|
|
135
|
-
read(false)
|
|
136
|
-
}, [first])
|
|
137
|
-
|
|
138
|
-
/** Scrolls a month to the top: smoothly when it is rendered, else by moving the window to it. */
|
|
139
|
-
const jumpTo = useCallback(
|
|
140
|
-
(month: Date, behavior: ScrollBehavior = 'smooth') => {
|
|
141
|
-
const scroller = scrollerRef.current
|
|
142
|
-
const key = monthKey(month)
|
|
143
|
-
const el = scroller && findMonth(scroller, key)
|
|
144
|
-
if (!scroller || !el) {
|
|
145
|
-
moveWindow(addMonths(startOfMonth(month), -Math.floor(WINDOW / 2)), key)
|
|
146
|
-
return
|
|
147
|
-
}
|
|
148
|
-
if (behavior === 'smooth') {
|
|
149
|
-
settling.current = true
|
|
150
|
-
const done = () => {
|
|
151
|
-
settling.current = false
|
|
152
|
-
scroller.removeEventListener('scrollend', done)
|
|
153
|
-
measure()
|
|
154
|
-
}
|
|
155
|
-
scroller.addEventListener('scrollend', done)
|
|
156
|
-
// Browsers without `scrollend` (and a jump that doesn't move) still settle.
|
|
157
|
-
setTimeout(done, 600)
|
|
158
|
-
}
|
|
159
|
-
scroller.scrollTo({ top: el.offsetTop, behavior })
|
|
160
|
-
},
|
|
161
|
-
[measure, moveWindow],
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
/** Keyboard focus left the window: recentre it on that month and keep the reader's place. */
|
|
165
|
-
const recentre = useCallback(
|
|
166
|
-
(month: Date) => moveWindow(addMonths(startOfMonth(month), -Math.floor(WINDOW / 2))),
|
|
167
|
-
[moveWindow],
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
return { first, count, visible, current, scrollerRef, measure, jumpTo, recentre, centreDay }
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export { monthKey, useMonthWindow }
|