@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,581 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Local addition (not part of Fluid Functionalism): the field and panel every
|
|
3
|
-
* date and time picker shares. Not an item (a file in a group folder): the
|
|
4
|
-
* pickers import it.
|
|
5
|
-
*
|
|
6
|
-
* The field is a text field on the shared field box (`useFieldBox` in
|
|
7
|
-
* `lib/field-classes.ts`, `bordered` unless the picker's `variant` says
|
|
8
|
-
* otherwise) showing the formatted value. Pressed, it opens its panel through Base UI's
|
|
9
|
-
* Popover and the morph layer, with Combobox's options: goo out of the field
|
|
10
|
-
* by default, or in place over it (`effect="morph"` with `hideSource`), the
|
|
11
|
-
* panel's header landing where the field was. On a phone-width screen the
|
|
12
|
-
* panel is the Sheet item instead, from the bottom edge.
|
|
13
|
-
*
|
|
14
|
-
* With an `editor` (DatePicker's `editable`) the field is a box around that
|
|
15
|
-
* text control instead of a button, and only its leading icon, an
|
|
16
|
-
* `InputAction`, opens the panel; the panel still anchors to and grows out
|
|
17
|
-
* of the whole field. `readOnly` shows the value and never opens.
|
|
18
|
-
*
|
|
19
|
-
* Form wiring: `controlRef` / `controlProps` reach the field's button (an
|
|
20
|
-
* editable picker puts its own on its input), and `formValues` render
|
|
21
|
-
* visually hidden inputs carrying the value for a native form; one the
|
|
22
|
-
* browser reports as invalid hands focus to the field.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
import { Popover } from '@base-ui/react/popover'
|
|
26
|
-
import {
|
|
27
|
-
type AriaAttributes,
|
|
28
|
-
type ButtonHTMLAttributes,
|
|
29
|
-
type FocusEvent,
|
|
30
|
-
forwardRef,
|
|
31
|
-
type HTMLAttributes,
|
|
32
|
-
type ReactElement,
|
|
33
|
-
type ReactNode,
|
|
34
|
-
type Ref,
|
|
35
|
-
type RefObject,
|
|
36
|
-
useCallback,
|
|
37
|
-
useMemo,
|
|
38
|
-
useRef,
|
|
39
|
-
useState,
|
|
40
|
-
} from 'react'
|
|
41
|
-
import { type FieldVariant, fieldIconClasses, useFieldBox, useFieldState } from '../../../lib/field-classes'
|
|
42
|
-
import { type IconName, useIcon } from '../../../lib/icon-context'
|
|
43
|
-
import { MorphSurface } from '../../../lib/morph-layers'
|
|
44
|
-
import { useShape } from '../../../lib/shape-context'
|
|
45
|
-
import { type SizeVariant, useSize } from '../../../lib/size-context'
|
|
46
|
-
import { SURFACE_BG, SURFACE_SHADOW } from '../../../lib/surface-classes'
|
|
47
|
-
import { SurfaceProvider, useSurface } from '../../../lib/surface-context'
|
|
48
|
-
import { useControllableState } from '../../../lib/use-controllable-state'
|
|
49
|
-
import { useIsMobile } from '../../../lib/use-is-mobile'
|
|
50
|
-
import {
|
|
51
|
-
inPlaceOffset,
|
|
52
|
-
type MorphEffect,
|
|
53
|
-
type MorphFrom,
|
|
54
|
-
type MorphTier,
|
|
55
|
-
opensInPlace,
|
|
56
|
-
useMorph,
|
|
57
|
-
useMorphOrigin,
|
|
58
|
-
} from '../../../lib/use-morph'
|
|
59
|
-
import { cn } from '../../../lib/utils'
|
|
60
|
-
import { SizeProvider } from '../../../primitives/sizes'
|
|
61
|
-
import Button from '../../button'
|
|
62
|
-
import Sheet from '../../overlays/sheet'
|
|
63
|
-
import Input, { InputAction, InputAdornment, type InputProps } from '../input'
|
|
64
|
-
|
|
65
|
-
/** Attributes for the element a picker's field renders as its control (its button, or an editable field's input), `data-*` included. */
|
|
66
|
-
type PickerControlAttributes = Omit<
|
|
67
|
-
HTMLAttributes<HTMLElement>,
|
|
68
|
-
'children' | 'dangerouslySetInnerHTML' | 'defaultValue' | 'defaultChecked'
|
|
69
|
-
> & {
|
|
70
|
-
/** An editable field's input: browser autofill hint. Defaults to `"off"`. */
|
|
71
|
-
autoComplete?: string
|
|
72
|
-
[data: `data-${string}`]: string | number | boolean | undefined
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** The form and accessibility props every picker forwards to its field's control. */
|
|
76
|
-
interface PickerControlProps {
|
|
77
|
-
/** Marks the value required: a native form won't submit while it is empty (and an editable field's input carries `required`). Defaults to the surrounding Field's `required`. */
|
|
78
|
-
required?: boolean
|
|
79
|
-
/** Called when the field's control (its button, or an editable field's input) loses focus, as when the panel takes it. */
|
|
80
|
-
onBlur?: (event: FocusEvent<HTMLElement>) => void
|
|
81
|
-
/** Names the field's control for assistive tech, in place of its label. */
|
|
82
|
-
'aria-label'?: string
|
|
83
|
-
/** Ids of the elements naming the field's control, in place of its own label. */
|
|
84
|
-
'aria-labelledby'?: string
|
|
85
|
-
/** Ids of the elements describing the field's control (a hint, an error message). */
|
|
86
|
-
'aria-describedby'?: string
|
|
87
|
-
/** Marks the value invalid, as `invalid` does. */
|
|
88
|
-
'aria-invalid'?: AriaAttributes['aria-invalid']
|
|
89
|
-
/** Attributes for the field's control: the button that opens the panel, or an `editable` field's input (`data-*`, `autoFocus`, `tabIndex`, handlers, which run after the picker's own; an editable field's input also takes `autoComplete` and `inputMode`, which replace its defaults of `"off"` and `"numeric"`). On an editable field the masked input owns `onChange`, so a caller's one never runs; only `onFocus`, `onBlur` and `onKeyDown` chain, the caller's `onKeyDown` first, and its `preventDefault()` skips the mask's own key handling). */
|
|
90
|
-
controlProps?: PickerControlAttributes
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** `invalid`, or `true` when `aria-invalid` marks the value invalid (unset stays unset, for a surrounding Field). */
|
|
94
|
-
const invalidOf = (invalid: boolean | undefined, ariaInvalid: AriaAttributes['aria-invalid']) =>
|
|
95
|
-
ariaInvalid !== undefined && ariaInvalid !== false && ariaInvalid !== 'false' ? true : invalid
|
|
96
|
-
|
|
97
|
-
/** The control's attributes from a picker's props: `controlProps`, then the named props over them, `onBlur` after its own. */
|
|
98
|
-
function controlAttributes({
|
|
99
|
-
controlProps,
|
|
100
|
-
onBlur,
|
|
101
|
-
'aria-label': ariaLabel,
|
|
102
|
-
'aria-labelledby': ariaLabelledBy,
|
|
103
|
-
'aria-describedby': ariaDescribedBy,
|
|
104
|
-
}: PickerControlProps): PickerControlAttributes {
|
|
105
|
-
return {
|
|
106
|
-
...controlProps,
|
|
107
|
-
...(ariaLabel !== undefined && { 'aria-label': ariaLabel }),
|
|
108
|
-
...(ariaLabelledBy !== undefined && { 'aria-labelledby': ariaLabelledBy }),
|
|
109
|
-
...(ariaDescribedBy !== undefined && { 'aria-describedby': ariaDescribedBy }),
|
|
110
|
-
...(onBlur && {
|
|
111
|
-
onBlur: (event: FocusEvent<HTMLElement>) => {
|
|
112
|
-
controlProps?.onBlur?.(event)
|
|
113
|
-
onBlur(event)
|
|
114
|
-
},
|
|
115
|
-
}),
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** Hands an element to every ref given. */
|
|
120
|
-
function assignRefs<T>(...refs: (Ref<T> | RefObject<unknown> | undefined)[]) {
|
|
121
|
-
return (node: T | null) => {
|
|
122
|
-
for (const ref of refs) {
|
|
123
|
-
if (typeof ref === 'function') ref(node)
|
|
124
|
-
else if (ref) (ref as { current: T | null }).current = node
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/** The field's own classes with `controlProps`, whose `className` joins them. */
|
|
130
|
-
function fieldControl(className: string | undefined, controlProps: PickerControlAttributes | undefined) {
|
|
131
|
-
return { ...controlProps, className: cn(className, controlProps?.className) }
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/** One value a native form submits: `name` (when given) and the text it carries; `slot` tells the entries apart. */
|
|
135
|
-
interface PickerFormValue {
|
|
136
|
-
slot: 'value' | 'start' | 'end'
|
|
137
|
-
name?: string
|
|
138
|
-
value: string
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
interface PickerShellProps {
|
|
142
|
-
open?: boolean
|
|
143
|
-
defaultOpen?: boolean
|
|
144
|
-
onOpenChange?: (open: boolean) => void
|
|
145
|
-
size?: SizeVariant
|
|
146
|
-
variant?: FieldVariant
|
|
147
|
-
invalid?: boolean
|
|
148
|
-
disabled?: boolean
|
|
149
|
-
/** The field's leading icon. */
|
|
150
|
-
icon: IconName
|
|
151
|
-
/** The formatted value; empty shows the placeholder. */
|
|
152
|
-
display: ReactNode
|
|
153
|
-
placeholder?: string
|
|
154
|
-
/** The panel header's inputs; the shell adds the close button after them. */
|
|
155
|
-
header: ReactNode
|
|
156
|
-
/** What the panel focuses when it opens on a desktop (its header input). */
|
|
157
|
-
initialFocus?: RefObject<HTMLElement | null>
|
|
158
|
-
/** Accessible name of the close button. */
|
|
159
|
-
closeLabel?: string
|
|
160
|
-
id?: string
|
|
161
|
-
dir?: string
|
|
162
|
-
/** Classes for the field. */
|
|
163
|
-
className?: string
|
|
164
|
-
/** Classes for the panel on a desktop: its width. */
|
|
165
|
-
popupClassName?: string
|
|
166
|
-
/** The desktop panel's morph (see Morph); a phone's sheet grows from its edge. */
|
|
167
|
-
from?: MorphFrom
|
|
168
|
-
effect?: MorphEffect
|
|
169
|
-
hideSource?: boolean
|
|
170
|
-
tier?: MorphTier
|
|
171
|
-
/** The field's own text control (an editable picker): the field becomes a box around it, and its icon a button that opens the panel. */
|
|
172
|
-
editor?: ReactNode
|
|
173
|
-
/** Accessible name of that icon button. Defaults to `"Open calendar"`. */
|
|
174
|
-
triggerLabel?: string
|
|
175
|
-
/** Shows the value and never opens. */
|
|
176
|
-
readOnly?: boolean
|
|
177
|
-
/** Receives the field's button (a plain field; an editable picker refs its own input). */
|
|
178
|
-
controlRef?: Ref<HTMLButtonElement>
|
|
179
|
-
/** Attributes for the field's button (a plain field; an editable picker puts its own on its input). */
|
|
180
|
-
controlProps?: PickerControlAttributes
|
|
181
|
-
/** What a native form submits: a visually hidden input per entry, rendered once one has a `name` or the field is `required`. */
|
|
182
|
-
formValues?: PickerFormValue[]
|
|
183
|
-
/** Marks the hidden inputs required. Defaults to the surrounding Field's `required`. */
|
|
184
|
-
required?: boolean
|
|
185
|
-
/** The panel body under the header. */
|
|
186
|
-
children: ReactNode
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/** The field and its panel: a popover out of the field (or in place of it), or a bottom sheet on a phone. */
|
|
190
|
-
function PickerShell({
|
|
191
|
-
open: openProp,
|
|
192
|
-
defaultOpen = false,
|
|
193
|
-
onOpenChange,
|
|
194
|
-
size,
|
|
195
|
-
formValues,
|
|
196
|
-
required,
|
|
197
|
-
...props
|
|
198
|
-
}: PickerShellProps) {
|
|
199
|
-
const [open, setOpenState] = useControllableState(openProp, defaultOpen, onOpenChange)
|
|
200
|
-
const setOpen = (next: boolean) => {
|
|
201
|
-
if (next && props.readOnly) return
|
|
202
|
-
setOpenState(next)
|
|
203
|
-
}
|
|
204
|
-
const fieldRef = useRef<HTMLElement>(null)
|
|
205
|
-
const mobile = useIsMobile(640)
|
|
206
|
-
const shell = mobile ? (
|
|
207
|
-
<PickerSheet open={open} setOpen={setOpen} fieldRef={fieldRef} {...props} />
|
|
208
|
-
) : (
|
|
209
|
-
<PickerPopover open={open} setOpen={setOpen} fieldRef={fieldRef} {...props} />
|
|
210
|
-
)
|
|
211
|
-
const inputs = formValues && (
|
|
212
|
-
<PickerFormInputs values={formValues} required={required} disabled={props.disabled} fieldRef={fieldRef} />
|
|
213
|
-
)
|
|
214
|
-
const content = inputs ? (
|
|
215
|
-
<>
|
|
216
|
-
{shell}
|
|
217
|
-
{inputs}
|
|
218
|
-
</>
|
|
219
|
-
) : (
|
|
220
|
-
shell
|
|
221
|
-
)
|
|
222
|
-
// A size pins the field and the portalled panel (context crosses portals).
|
|
223
|
-
return size ? <SizeProvider size={size}>{content}</SizeProvider> : content
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* The value for a native form: visually hidden inputs, out of the tab order.
|
|
228
|
-
* They are real text inputs, not `type="hidden"`, so `required` stops a
|
|
229
|
-
* submit; when the browser reports one, focus goes to the field.
|
|
230
|
-
*/
|
|
231
|
-
function PickerFormInputs({
|
|
232
|
-
values,
|
|
233
|
-
required,
|
|
234
|
-
disabled,
|
|
235
|
-
fieldRef,
|
|
236
|
-
}: {
|
|
237
|
-
values: PickerFormValue[]
|
|
238
|
-
required?: boolean
|
|
239
|
-
disabled?: boolean
|
|
240
|
-
fieldRef: RefObject<HTMLElement>
|
|
241
|
-
}) {
|
|
242
|
-
const field = useFieldState()
|
|
243
|
-
const isRequired = required ?? field?.required ?? false
|
|
244
|
-
if (!isRequired && !values.some(v => v.name)) return null
|
|
245
|
-
const focusField = () => {
|
|
246
|
-
const el = fieldRef.current
|
|
247
|
-
;(el instanceof HTMLButtonElement ? el : el?.querySelector('input'))?.focus()
|
|
248
|
-
}
|
|
249
|
-
return values.map(({ slot, name, value }) => (
|
|
250
|
-
<input
|
|
251
|
-
key={slot}
|
|
252
|
-
aria-hidden
|
|
253
|
-
tabIndex={-1}
|
|
254
|
-
name={name}
|
|
255
|
-
value={value}
|
|
256
|
-
required={isRequired}
|
|
257
|
-
disabled={disabled ?? field?.disabled}
|
|
258
|
-
onChange={() => {}}
|
|
259
|
-
onFocus={focusField}
|
|
260
|
-
className="sr-only"
|
|
261
|
-
/>
|
|
262
|
-
))
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
type PanelProps = Omit<
|
|
266
|
-
PickerShellProps,
|
|
267
|
-
'open' | 'defaultOpen' | 'onOpenChange' | 'size' | 'formValues' | 'required'
|
|
268
|
-
> & {
|
|
269
|
-
open: boolean
|
|
270
|
-
setOpen: (open: boolean) => void
|
|
271
|
-
/** The field's element: its button, or an editable field's box. */
|
|
272
|
-
fieldRef: RefObject<HTMLElement>
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
type PickerFieldProps = Pick<
|
|
276
|
-
PanelProps,
|
|
277
|
-
'icon' | 'display' | 'placeholder' | 'variant' | 'invalid' | 'disabled' | 'readOnly' | 'id' | 'className'
|
|
278
|
-
> &
|
|
279
|
-
Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'>
|
|
280
|
-
|
|
281
|
-
// Forwards its ref: Base UI anchors the panel to the field through it.
|
|
282
|
-
const PickerField = forwardRef<HTMLButtonElement, PickerFieldProps>(
|
|
283
|
-
({ icon, display, placeholder, variant = 'bordered', invalid, disabled, readOnly, id, className, ...props }, ref) => {
|
|
284
|
-
const Icon = useIcon(icon)
|
|
285
|
-
const { size: sizeClasses, props: boxProps } = useFieldBox({ variant, invalid, disabled, readOnly })
|
|
286
|
-
|
|
287
|
-
return (
|
|
288
|
-
<button
|
|
289
|
-
ref={ref}
|
|
290
|
-
type="button"
|
|
291
|
-
id={id}
|
|
292
|
-
disabled={disabled}
|
|
293
|
-
aria-invalid={invalid || undefined}
|
|
294
|
-
{...boxProps}
|
|
295
|
-
// Base UI's trigger props (open state, handlers, aria) arrive here.
|
|
296
|
-
{...props}
|
|
297
|
-
className={cn(
|
|
298
|
-
boxProps.className,
|
|
299
|
-
'flex w-full min-w-0 items-center text-left outline-none focus-visible:ring-focus-ring',
|
|
300
|
-
// A read-only field never opens, and doesn't look like it would.
|
|
301
|
-
readOnly ? 'cursor-default' : 'cursor-pointer',
|
|
302
|
-
sizeClasses.gap,
|
|
303
|
-
sizeClasses.control,
|
|
304
|
-
className,
|
|
305
|
-
)}
|
|
306
|
-
>
|
|
307
|
-
<Icon size={sizeClasses.icon} strokeWidth={1.5} className={fieldIconClasses} />
|
|
308
|
-
<span
|
|
309
|
-
className={cn('flex-1 truncate', sizeClasses.text, display ? 'text-foreground' : 'text-muted-foreground')}
|
|
310
|
-
>
|
|
311
|
-
{display || placeholder}
|
|
312
|
-
</span>
|
|
313
|
-
</button>
|
|
314
|
-
)
|
|
315
|
-
},
|
|
316
|
-
)
|
|
317
|
-
PickerField.displayName = 'PickerField'
|
|
318
|
-
|
|
319
|
-
type EditableFieldProps = Pick<
|
|
320
|
-
PanelProps,
|
|
321
|
-
'icon' | 'variant' | 'invalid' | 'disabled' | 'readOnly' | 'className' | 'editor' | 'triggerLabel'
|
|
322
|
-
> & {
|
|
323
|
-
/** Wraps the icon button in the panel's trigger. */
|
|
324
|
-
trigger: (button: ReactNode) => ReactNode
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/** An editable picker's field: its text control, led by the icon button that opens the panel. */
|
|
328
|
-
const EditableField = forwardRef<HTMLElement, EditableFieldProps>(
|
|
329
|
-
(
|
|
330
|
-
{
|
|
331
|
-
icon,
|
|
332
|
-
variant = 'bordered',
|
|
333
|
-
invalid,
|
|
334
|
-
disabled,
|
|
335
|
-
readOnly,
|
|
336
|
-
className,
|
|
337
|
-
editor,
|
|
338
|
-
triggerLabel = 'Open calendar',
|
|
339
|
-
trigger,
|
|
340
|
-
},
|
|
341
|
-
ref,
|
|
342
|
-
) => {
|
|
343
|
-
const Icon = useIcon(icon)
|
|
344
|
-
const { size: sizeClasses, props: boxProps } = useFieldBox({ variant, invalid, disabled, readOnly })
|
|
345
|
-
return (
|
|
346
|
-
<div
|
|
347
|
-
ref={ref as Ref<HTMLDivElement>}
|
|
348
|
-
{...boxProps}
|
|
349
|
-
className={cn(
|
|
350
|
-
boxProps.className,
|
|
351
|
-
'flex w-full min-w-0 items-center',
|
|
352
|
-
sizeClasses.gap,
|
|
353
|
-
sizeClasses.control,
|
|
354
|
-
className,
|
|
355
|
-
)}
|
|
356
|
-
>
|
|
357
|
-
<InputAdornment>
|
|
358
|
-
{trigger(<InputAction label={triggerLabel} icon={Icon} disabled={disabled || readOnly} />)}
|
|
359
|
-
</InputAdornment>
|
|
360
|
-
{editor}
|
|
361
|
-
</div>
|
|
362
|
-
)
|
|
363
|
-
},
|
|
364
|
-
)
|
|
365
|
-
EditableField.displayName = 'EditableField'
|
|
366
|
-
|
|
367
|
-
function PanelHeader({
|
|
368
|
-
header,
|
|
369
|
-
closeLabel = 'Close',
|
|
370
|
-
close,
|
|
371
|
-
}: {
|
|
372
|
-
header: ReactNode
|
|
373
|
-
closeLabel?: string
|
|
374
|
-
close: () => void
|
|
375
|
-
}) {
|
|
376
|
-
const X = useIcon('x')
|
|
377
|
-
const sizeClasses = useSize()
|
|
378
|
-
return (
|
|
379
|
-
<div className="flex items-center gap-1 border-b border-border pb-1">
|
|
380
|
-
<div className="flex min-w-0 flex-1 items-center">{header}</div>
|
|
381
|
-
<Button variant="ghost" size="icon-sm" aria-label={closeLabel} onClick={close}>
|
|
382
|
-
<X size={sizeClasses.icon} strokeWidth={1.5} />
|
|
383
|
-
</Button>
|
|
384
|
-
</div>
|
|
385
|
-
)
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function PickerPopover({
|
|
389
|
-
open,
|
|
390
|
-
setOpen,
|
|
391
|
-
header,
|
|
392
|
-
initialFocus,
|
|
393
|
-
closeLabel,
|
|
394
|
-
dir,
|
|
395
|
-
popupClassName,
|
|
396
|
-
from,
|
|
397
|
-
effect,
|
|
398
|
-
hideSource,
|
|
399
|
-
tier = 'moderate',
|
|
400
|
-
children,
|
|
401
|
-
editor,
|
|
402
|
-
triggerLabel,
|
|
403
|
-
fieldRef,
|
|
404
|
-
controlRef,
|
|
405
|
-
controlProps,
|
|
406
|
-
...field
|
|
407
|
-
}: PanelProps) {
|
|
408
|
-
const triggerRef = useMemo(() => assignRefs<HTMLButtonElement>(fieldRef, controlRef), [fieldRef, controlRef])
|
|
409
|
-
const { origin, capture } = useMorphOrigin()
|
|
410
|
-
const morph = useMorph(open, origin, { from, effect, hideSource, tier })
|
|
411
|
-
const shape = useShape()
|
|
412
|
-
const level = Math.min(useSurface() + 2, 8)
|
|
413
|
-
|
|
414
|
-
const handleOpenChange = useCallback(
|
|
415
|
-
(next: boolean, details: { reason?: string; trigger?: Element; event?: Event }) => {
|
|
416
|
-
// Pressing or focusing the editable field's own text is no reason to
|
|
417
|
-
// close: the panel belongs to that field.
|
|
418
|
-
if (!next && editor && (details.reason === 'outside-press' || details.reason === 'focus-out')) {
|
|
419
|
-
const event = details.event as (Event & { relatedTarget?: EventTarget | null }) | undefined
|
|
420
|
-
const target = (event?.relatedTarget ?? event?.target) as Node | null | undefined
|
|
421
|
-
if (target && fieldRef.current?.contains(target)) return
|
|
422
|
-
}
|
|
423
|
-
// An editable field's panel grows out of the whole field, not its icon.
|
|
424
|
-
if (next) capture(editor ? { event: details.event, trigger: fieldRef.current ?? undefined } : details)
|
|
425
|
-
setOpen(next)
|
|
426
|
-
},
|
|
427
|
-
[capture, setOpen, editor],
|
|
428
|
-
)
|
|
429
|
-
|
|
430
|
-
return (
|
|
431
|
-
// Non-modal: the page keeps scrolling and the panel follows its field.
|
|
432
|
-
<Popover.Root open={open} onOpenChange={handleOpenChange} modal={false}>
|
|
433
|
-
{editor ? (
|
|
434
|
-
<EditableField
|
|
435
|
-
ref={fieldRef}
|
|
436
|
-
{...field}
|
|
437
|
-
editor={editor}
|
|
438
|
-
triggerLabel={triggerLabel}
|
|
439
|
-
trigger={button => <Popover.Trigger disabled={field.disabled} render={button as ReactElement} />}
|
|
440
|
-
/>
|
|
441
|
-
) : (
|
|
442
|
-
<Popover.Trigger
|
|
443
|
-
ref={triggerRef}
|
|
444
|
-
disabled={field.disabled}
|
|
445
|
-
render={<PickerField {...field} {...fieldControl(field.className, controlProps)} />}
|
|
446
|
-
/>
|
|
447
|
-
)}
|
|
448
|
-
<Popover.Portal>
|
|
449
|
-
<Popover.Positioner
|
|
450
|
-
anchor={editor ? fieldRef : undefined}
|
|
451
|
-
side="bottom"
|
|
452
|
-
align="start"
|
|
453
|
-
sideOffset={opensInPlace({ effect, hideSource }) ? inPlaceOffset : 6}
|
|
454
|
-
className="z-50 outline-none"
|
|
455
|
-
>
|
|
456
|
-
<Popover.Popup ref={morph.popupRef} initialFocus={initialFocus} className="relative outline-none">
|
|
457
|
-
<SurfaceProvider value={level}>
|
|
458
|
-
<MorphSurface
|
|
459
|
-
morph={morph}
|
|
460
|
-
bg={SURFACE_BG[level]}
|
|
461
|
-
shadow={SURFACE_SHADOW[3]}
|
|
462
|
-
radius={shape.container}
|
|
463
|
-
className={cn('flex max-w-[calc(100vw-1rem)] flex-col gap-1 p-1', popupClassName)}
|
|
464
|
-
>
|
|
465
|
-
<div dir={dir} className="flex min-h-0 flex-col gap-1">
|
|
466
|
-
<PanelHeader header={header} closeLabel={closeLabel} close={() => setOpen(false)} />
|
|
467
|
-
{children}
|
|
468
|
-
</div>
|
|
469
|
-
</MorphSurface>
|
|
470
|
-
</SurfaceProvider>
|
|
471
|
-
</Popover.Popup>
|
|
472
|
-
</Popover.Positioner>
|
|
473
|
-
</Popover.Portal>
|
|
474
|
-
</Popover.Root>
|
|
475
|
-
)
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
function PickerSheet({
|
|
479
|
-
open,
|
|
480
|
-
setOpen,
|
|
481
|
-
header,
|
|
482
|
-
closeLabel,
|
|
483
|
-
dir,
|
|
484
|
-
children,
|
|
485
|
-
editor,
|
|
486
|
-
triggerLabel,
|
|
487
|
-
fieldRef,
|
|
488
|
-
controlRef,
|
|
489
|
-
controlProps,
|
|
490
|
-
...field
|
|
491
|
-
}: PanelProps) {
|
|
492
|
-
const triggerRef = useMemo(() => assignRefs<HTMLButtonElement>(fieldRef, controlRef), [fieldRef, controlRef])
|
|
493
|
-
const {
|
|
494
|
-
initialFocus: _focus,
|
|
495
|
-
popupClassName: _width,
|
|
496
|
-
from: _from,
|
|
497
|
-
effect: _effect,
|
|
498
|
-
hideSource: _hide,
|
|
499
|
-
tier: _tier,
|
|
500
|
-
...fieldProps
|
|
501
|
-
} = field
|
|
502
|
-
return (
|
|
503
|
-
<Sheet open={open} onOpenChange={setOpen}>
|
|
504
|
-
{editor ? (
|
|
505
|
-
<EditableField
|
|
506
|
-
ref={fieldRef}
|
|
507
|
-
{...fieldProps}
|
|
508
|
-
editor={editor}
|
|
509
|
-
triggerLabel={triggerLabel}
|
|
510
|
-
trigger={button => <Sheet.Trigger disabled={field.disabled} render={button as ReactElement} />}
|
|
511
|
-
/>
|
|
512
|
-
) : (
|
|
513
|
-
<Sheet.Trigger
|
|
514
|
-
ref={triggerRef}
|
|
515
|
-
disabled={field.disabled}
|
|
516
|
-
render={<PickerField {...fieldProps} {...fieldControl(fieldProps.className, controlProps)} />}
|
|
517
|
-
/>
|
|
518
|
-
)}
|
|
519
|
-
<Sheet.Content className="gap-2 p-3 pt-3">
|
|
520
|
-
<div dir={dir} className="flex min-h-0 flex-col gap-2">
|
|
521
|
-
<PanelHeader header={header} closeLabel={closeLabel} close={() => setOpen(false)} />
|
|
522
|
-
{children}
|
|
523
|
-
</div>
|
|
524
|
-
</Sheet.Content>
|
|
525
|
-
</Sheet>
|
|
526
|
-
)
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
interface PickerInputProps extends Omit<InputProps, 'value' | 'defaultValue' | 'onChange'> {
|
|
530
|
-
/** The value as the field shows it, while nothing is being typed. */
|
|
531
|
-
formatted: string
|
|
532
|
-
/** Reads typed text and commits it; returns whether it could. */
|
|
533
|
-
onText: (text: string) => boolean
|
|
534
|
-
/** Enter, after a valid entry: the pickers close. */
|
|
535
|
-
onEnter?: () => void
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* A header input: shows the formatted value, selects it all on focus, and
|
|
540
|
-
* commits what is typed as soon as it reads as a value (marking it invalid
|
|
541
|
-
* until then). Leaving it restores the formatted value. Hover and focus fill
|
|
542
|
-
* it without the field ring.
|
|
543
|
-
*/
|
|
544
|
-
const PickerInput = forwardRef<HTMLInputElement, PickerInputProps>(
|
|
545
|
-
({ formatted, onText, onEnter, onFocus, onBlur, onKeyDown, className, ...props }, ref) => {
|
|
546
|
-
const [draft, setDraft] = useState<string | null>(null)
|
|
547
|
-
const [invalid, setInvalid] = useState(false)
|
|
548
|
-
return (
|
|
549
|
-
<Input
|
|
550
|
-
ref={ref}
|
|
551
|
-
{...props}
|
|
552
|
-
// The header is already framed by the panel: hover and focus change
|
|
553
|
-
// the fill only (an invalid entry keeps its destructive ring).
|
|
554
|
-
className={cn('hover:ring-transparent focus-within:ring-transparent data-[active]:ring-transparent', className)}
|
|
555
|
-
value={draft ?? formatted}
|
|
556
|
-
invalid={invalid}
|
|
557
|
-
onChange={text => {
|
|
558
|
-
setDraft(text)
|
|
559
|
-
setInvalid(!onText(text))
|
|
560
|
-
}}
|
|
561
|
-
onFocus={e => {
|
|
562
|
-
e.currentTarget.select()
|
|
563
|
-
onFocus?.(e)
|
|
564
|
-
}}
|
|
565
|
-
onBlur={e => {
|
|
566
|
-
setDraft(null)
|
|
567
|
-
setInvalid(false)
|
|
568
|
-
onBlur?.(e)
|
|
569
|
-
}}
|
|
570
|
-
onKeyDown={e => {
|
|
571
|
-
if (e.key === 'Enter' && !invalid) onEnter?.()
|
|
572
|
-
onKeyDown?.(e)
|
|
573
|
-
}}
|
|
574
|
-
/>
|
|
575
|
-
)
|
|
576
|
-
},
|
|
577
|
-
)
|
|
578
|
-
PickerInput.displayName = 'PickerInput'
|
|
579
|
-
|
|
580
|
-
export type { PickerControlAttributes, PickerControlProps, PickerFormValue, PickerShellProps }
|
|
581
|
-
export { assignRefs, controlAttributes, invalidOf, PickerInput, PickerShell }
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Local addition (not part of Fluid Functionalism): the hour column (its
|
|
3
|
-
* AM/PM folded in on a 12-hour clock) and the minute column the date picker
|
|
4
|
-
* (with time) and the time picker share. Not an item (a file in a group folder).
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { format, type Locale } from 'date-fns'
|
|
8
|
-
import { useMemo } from 'react'
|
|
9
|
-
import { fieldLabel, type HourCycle } from '../../../lib/date-locale'
|
|
10
|
-
import { ScrollColumn } from '../../../lib/scroll-column'
|
|
11
|
-
import { cn } from '../../../lib/utils'
|
|
12
|
-
|
|
13
|
-
interface Time {
|
|
14
|
-
hours: number
|
|
15
|
-
minutes: number
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface TimeColumnsProps {
|
|
19
|
-
value: Time | null
|
|
20
|
-
onValueChange: (time: Time) => void
|
|
21
|
-
hourCycle: HourCycle
|
|
22
|
-
minuteStep: number
|
|
23
|
-
locale: Locale
|
|
24
|
-
orientation: 'vertical' | 'horizontal'
|
|
25
|
-
/** Columns share the row's width equally instead of keeping their narrow fixed widths. Defaults to `false`. */
|
|
26
|
-
fill?: boolean
|
|
27
|
-
/** Accessible names of the columns. Default to the locale's names for the fields. */
|
|
28
|
-
labels?: { hour?: string; minute?: string }
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const pad = (n: number) => String(n).padStart(2, '0')
|
|
32
|
-
|
|
33
|
-
/** Columns for the hour (with its AM/PM on a 12-hour clock) and the minute; a row of them divides itself. */
|
|
34
|
-
function TimeColumns({
|
|
35
|
-
value,
|
|
36
|
-
onValueChange,
|
|
37
|
-
hourCycle,
|
|
38
|
-
minuteStep,
|
|
39
|
-
locale,
|
|
40
|
-
orientation,
|
|
41
|
-
fill = false,
|
|
42
|
-
labels,
|
|
43
|
-
}: TimeColumnsProps) {
|
|
44
|
-
const twelve = hourCycle === 'h12' || hourCycle === 'h11'
|
|
45
|
-
const hours = value?.hours ?? null
|
|
46
|
-
const minutes = value?.minutes ?? 0
|
|
47
|
-
|
|
48
|
-
const hourOptions = useMemo(
|
|
49
|
-
() =>
|
|
50
|
-
Array.from({ length: 24 }, (_, h) => ({
|
|
51
|
-
value: h,
|
|
52
|
-
// "12 AM" … "11 PM" (h11: "0 AM" … "11 PM"), in the locale's words.
|
|
53
|
-
label: twelve ? format(new Date(2000, 0, 1, h), hourCycle === 'h11' ? 'K a' : 'h a', { locale }) : pad(h),
|
|
54
|
-
})),
|
|
55
|
-
[twelve, hourCycle, locale],
|
|
56
|
-
)
|
|
57
|
-
const minuteOptions = useMemo(
|
|
58
|
-
() =>
|
|
59
|
-
Array.from({ length: Math.ceil(60 / minuteStep) }, (_, i) => ({
|
|
60
|
-
value: i * minuteStep,
|
|
61
|
-
label: pad(i * minuteStep),
|
|
62
|
-
})),
|
|
63
|
-
[minuteStep],
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
const vertical = orientation === 'vertical'
|
|
67
|
-
// Beside a calendar: narrower than its month and year columns, an hour
|
|
68
|
-
// with its AM/PM a little wider. On their own (`fill`): an equal share.
|
|
69
|
-
const width = (fixed: string) => (!vertical ? 'w-full' : fill ? 'min-w-0 flex-1' : cn('shrink-0', fixed))
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<>
|
|
73
|
-
<ScrollColumn
|
|
74
|
-
label={labels?.hour ?? fieldLabel(locale, 'hour')}
|
|
75
|
-
options={hourOptions}
|
|
76
|
-
value={hours}
|
|
77
|
-
onValueChange={h => onValueChange({ hours: h, minutes })}
|
|
78
|
-
orientation={orientation}
|
|
79
|
-
className={width(twelve ? 'w-15' : 'w-12')}
|
|
80
|
-
/>
|
|
81
|
-
<ScrollColumn
|
|
82
|
-
label={labels?.minute ?? fieldLabel(locale, 'minute')}
|
|
83
|
-
options={minuteOptions}
|
|
84
|
-
value={hours === null ? null : minutes}
|
|
85
|
-
onValueChange={m => onValueChange({ hours: hours ?? 0, minutes: m })}
|
|
86
|
-
orientation={orientation}
|
|
87
|
-
className={width('w-12')}
|
|
88
|
-
/>
|
|
89
|
-
</>
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export type { Time }
|
|
94
|
-
export { pad, TimeColumns }
|