@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
package/lib/field-classes.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Local addition (not part of Fluid Functionalism): the field ladder FF
|
|
3
|
-
* repeats across InputGroup, Combobox and Sidebar's input, as one recipe,
|
|
4
|
-
* and `useFieldBox`, the box every text field (Input, Textarea, Combobox,
|
|
5
|
-
* the date and time pickers) builds on.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { createContext, type MouseEvent, type RefObject, useContext } from 'react'
|
|
9
|
-
import { FIELD_PX, type FieldVariant, fieldVariants } from './field-variants'
|
|
10
|
-
import { useShape } from './shape-context'
|
|
11
|
-
import { type SizeVariant, useSize } from './size-context'
|
|
12
|
-
import { cn } from './utils'
|
|
13
|
-
|
|
14
|
-
// The pure tables live in `field-variants.ts` (callable from a server
|
|
15
|
-
// component); every name stays importable from here.
|
|
16
|
-
export {
|
|
17
|
-
FIELD_ACTION,
|
|
18
|
-
FIELD_ACTION_BOX,
|
|
19
|
-
FIELD_ACTION_END,
|
|
20
|
-
FIELD_ACTION_RADIUS,
|
|
21
|
-
FIELD_ADORNMENT_ICON,
|
|
22
|
-
FIELD_PX,
|
|
23
|
-
FIELD_TEXT_INSET,
|
|
24
|
-
type FieldVariant,
|
|
25
|
-
fieldActionClasses,
|
|
26
|
-
fieldAdornmentClasses,
|
|
27
|
-
fieldIconClasses,
|
|
28
|
-
fieldVariants,
|
|
29
|
-
} from './field-variants'
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* What every text field's box takes. Items re-declare these members in their
|
|
33
|
-
* own props interface (the docs read only same-file members), with this prose.
|
|
34
|
-
*/
|
|
35
|
-
export interface FieldBoxOptions {
|
|
36
|
-
/** Framed at rest, or invisible until hovered or focused. */
|
|
37
|
-
variant: FieldVariant
|
|
38
|
-
/** Turns the field destructive. */
|
|
39
|
-
invalid?: boolean
|
|
40
|
-
/** Frames and dims the field. */
|
|
41
|
-
disabled?: boolean
|
|
42
|
-
/** Lit from outside, e.g. a group's fluid hover. */
|
|
43
|
-
active?: boolean
|
|
44
|
-
/** Shows the value without letting it change: the ring answers, the fill never lifts. */
|
|
45
|
-
readOnly?: boolean
|
|
46
|
-
/** Marks the control required (`required` on the control). */
|
|
47
|
-
required?: boolean
|
|
48
|
-
/** Pins the field to one step of the size ladder. Defaults to the surrounding SizeProvider. */
|
|
49
|
-
size?: SizeVariant
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** What a field wrapper hands to the control it holds. */
|
|
53
|
-
export interface FieldState {
|
|
54
|
-
/** Lit by a group's fluid hover. */
|
|
55
|
-
active: boolean
|
|
56
|
-
invalid: boolean
|
|
57
|
-
disabled: boolean
|
|
58
|
-
readOnly?: boolean
|
|
59
|
-
required?: boolean
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* State a field wrapper (Field, InputGroup.Field) hands to whatever control
|
|
64
|
-
* it holds: lit by the group's fluid hover, its error, its disabled,
|
|
65
|
-
* read-only and required state. `useFieldBox` reads it, so any field built on
|
|
66
|
-
* the box joins in; the control's own props win.
|
|
67
|
-
*/
|
|
68
|
-
export const FieldStateContext = createContext<FieldState | null>(null)
|
|
69
|
-
|
|
70
|
-
/** The surrounding field's state, or `null` outside one. */
|
|
71
|
-
export function useFieldState() {
|
|
72
|
-
return useContext(FieldStateContext)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* The box around a text field's control: the field ladder in the chosen
|
|
77
|
-
* variant, the state attributes it reads, the shape's input radius and the
|
|
78
|
-
* horizontal inset. Spread `props` on the element around the control (or the
|
|
79
|
-
* control itself, for a button field); the height stays with the item, from
|
|
80
|
-
* the returned `size`. Inside a Field or InputGroup.Field, unset `active` / `invalid` /
|
|
81
|
-
* `disabled` / `readOnly` / `required` come from the field (`FieldStateContext`).
|
|
82
|
-
*/
|
|
83
|
-
export function useFieldBox({ variant, invalid, disabled, active, readOnly, required, size }: FieldBoxOptions) {
|
|
84
|
-
const field = useContext(FieldStateContext)
|
|
85
|
-
const shape = useShape()
|
|
86
|
-
const sizeClasses = useSize(size)
|
|
87
|
-
const isInvalid = invalid ?? field?.invalid ?? false
|
|
88
|
-
const isDisabled = disabled ?? field?.disabled ?? false
|
|
89
|
-
const isReadOnly = readOnly ?? field?.readOnly ?? false
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
size: sizeClasses,
|
|
93
|
-
/** Resolved with the field's state, for the control's `aria-invalid` / `disabled` / `readOnly` / `required`. */
|
|
94
|
-
invalid: isInvalid,
|
|
95
|
-
disabled: isDisabled,
|
|
96
|
-
readOnly: isReadOnly,
|
|
97
|
-
required: required ?? field?.required,
|
|
98
|
-
props: {
|
|
99
|
-
'data-active': (active ?? field?.active) || undefined,
|
|
100
|
-
'data-invalid': isInvalid || undefined,
|
|
101
|
-
'data-disabled': isDisabled || undefined,
|
|
102
|
-
'data-readonly': isReadOnly || undefined,
|
|
103
|
-
className: cn(fieldVariants({ variant }), shape.input, FIELD_PX[sizeClasses.variant]),
|
|
104
|
-
},
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* A press anywhere in the box (icon, padding) focuses the control, without
|
|
110
|
-
* disturbing the control's own caret placement. A press that only reaches the
|
|
111
|
-
* box through the React tree (a popup portalled out of an adornment, e.g. a
|
|
112
|
-
* searchable Dropdown) is left alone, so that popup can take focus itself.
|
|
113
|
-
*/
|
|
114
|
-
export function focusControlOnPress(control: RefObject<HTMLElement | null>) {
|
|
115
|
-
return (e: MouseEvent) => {
|
|
116
|
-
if (e.target === control.current) return
|
|
117
|
-
if (!e.currentTarget.contains(e.target as Node)) return
|
|
118
|
-
e.preventDefault()
|
|
119
|
-
control.current?.focus()
|
|
120
|
-
}
|
|
121
|
-
}
|
package/lib/field-variants.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Local addition (not part of Fluid Functionalism): the field ladder's pure
|
|
3
|
-
* class tables, split from `field-classes.ts` so they carry no hooks, JSX or
|
|
4
|
-
* contexts. A React Server Component can call them; `field-classes.ts`
|
|
5
|
-
* re-exports every name, so its imports keep working.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { cva } from 'class-variance-authority'
|
|
9
|
-
import type { ShapeVariant } from './shape-context'
|
|
10
|
-
import type { SizeVariant } from './size-context'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The ringed box of a text field. It steps from rest to a muted fill when lit
|
|
14
|
-
* (hovered, or `data-active` from a group's fluid hover) to the card fill
|
|
15
|
-
* when focused. `data-invalid` keeps a destructive ring in every state and
|
|
16
|
-
* tints the lit fill; `data-disabled` frames and dims it; `data-readonly`
|
|
17
|
-
* shows the ring when lit or focused but never lifts the fill. Put it on the
|
|
18
|
-
* element around the control and stamp the data attributes; Base UI parts
|
|
19
|
-
* stamp `data-invalid` / `data-disabled` themselves.
|
|
20
|
-
*/
|
|
21
|
-
export const fieldVariants = cva(
|
|
22
|
-
[
|
|
23
|
-
'group/field ring-1 cursor-text transition-[background-color,box-shadow,opacity] duration-fast',
|
|
24
|
-
'hover:bg-muted/50 hover:ring-border data-[active]:bg-muted/50 data-[active]:ring-border',
|
|
25
|
-
// `!`: Uno doesn't emit the state variants in a fixed order, so the
|
|
26
|
-
// states that must win (focus fill, invalid ring) win on importance.
|
|
27
|
-
'focus-within:!bg-card focus-within:ring-border',
|
|
28
|
-
'data-[invalid]:!ring-destructive/50 data-[invalid]:hover:bg-destructive-light/60 data-[invalid]:data-[active]:bg-destructive-light/60',
|
|
29
|
-
'data-[disabled]:ring-border data-[disabled]:opacity-50 data-[disabled]:pointer-events-none',
|
|
30
|
-
// A read-only value can be selected and copied but not changed: the ring
|
|
31
|
-
// still answers the pointer and the keyboard, the fill never lifts. The
|
|
32
|
-
// attribute selector outranks the focus fill's at equal importance.
|
|
33
|
-
'data-[readonly]:cursor-default data-[readonly]:hover:!bg-transparent data-[readonly]:data-[active]:!bg-transparent data-[readonly]:focus-within:!bg-transparent',
|
|
34
|
-
],
|
|
35
|
-
{
|
|
36
|
-
variants: {
|
|
37
|
-
variant: {
|
|
38
|
-
// Invisible until lit or focused.
|
|
39
|
-
borderless: 'bg-transparent ring-transparent',
|
|
40
|
-
// Framed at rest.
|
|
41
|
-
bordered: 'bg-transparent ring-border',
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
defaultVariants: {
|
|
45
|
-
variant: 'borderless',
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
/** A leading icon inside a `fieldVariants` box: muted at rest, it darkens and thickens with the field. Pass `strokeWidth={1.5}`. */
|
|
51
|
-
export const fieldIconClasses =
|
|
52
|
-
'shrink-0 text-muted-foreground transition-[color,stroke-width] duration-fast group-hover/field:text-foreground group-hover/field:stroke-[2] group-data-[active]/field:text-foreground group-data-[active]/field:stroke-[2] group-focus-within/field:text-foreground group-focus-within/field:stroke-[2]'
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Content beside a field's text (an adornment): muted, held to the ladder's
|
|
56
|
-
* glyph size, and lit with the field like a leading icon. Strings read as a
|
|
57
|
-
* prefix or a unit.
|
|
58
|
-
*/
|
|
59
|
-
export const fieldAdornmentClasses =
|
|
60
|
-
'flex shrink-0 items-center whitespace-nowrap text-muted-foreground transition-[color] duration-fast group-hover/field:text-foreground group-data-[active]/field:text-foreground group-focus-within/field:text-foreground'
|
|
61
|
-
|
|
62
|
-
/** Glyph size for an adornment's icons, per ladder step (16px default, 14px compact). */
|
|
63
|
-
export const FIELD_ADORNMENT_ICON: Record<SizeVariant, string> = {
|
|
64
|
-
default: '[&_svg]:size-4',
|
|
65
|
-
compact: '[&_svg]:size-3.5',
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* A small icon button inside a field box (a password reveal, a clear, a
|
|
70
|
-
* stepper): 4px inside the ring on every side (28px in a 36px field, 20px in
|
|
71
|
-
* a 28px one), its negative margin taking back the box's inset so the gap to
|
|
72
|
-
* the edge matches the gap above and below.
|
|
73
|
-
*/
|
|
74
|
-
export const FIELD_ACTION: Record<SizeVariant, string> = {
|
|
75
|
-
default: 'size-7 -mx-1.5 [&_svg]:size-4',
|
|
76
|
-
compact: 'size-5 -mx-1 [&_svg]:size-3.5',
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** A field action's box alone, without `FIELD_ACTION`'s margins, for actions set side by side (a stepper pair). */
|
|
80
|
-
export const FIELD_ACTION_BOX: Record<SizeVariant, string> = {
|
|
81
|
-
default: 'size-7 [&_svg]:size-4',
|
|
82
|
-
compact: 'size-5 [&_svg]:size-3.5',
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** The margin that pulls the last of several side-by-side actions to 4px inside the ring. */
|
|
86
|
-
export const FIELD_ACTION_END: Record<SizeVariant, string> = {
|
|
87
|
-
default: '-mr-1.5',
|
|
88
|
-
compact: '-mr-1',
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** A field action's corners, concentric with the box's (8px box, 4px gap) or round in pill mode. */
|
|
92
|
-
export const FIELD_ACTION_RADIUS: Record<ShapeVariant, string> = {
|
|
93
|
-
rounded: 'rounded-sm',
|
|
94
|
-
pill: 'rounded-full',
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** The classes every field action shares, beside its `FIELD_ACTION` size and radius. */
|
|
98
|
-
export const fieldActionClasses =
|
|
99
|
-
'relative inline-flex shrink-0 cursor-pointer items-center justify-center text-muted-foreground outline-none transition-[color,background-color,opacity] duration-fast hover:bg-hover hover:text-foreground active:bg-active focus-visible:ring-1 focus-visible:ring-focus-ring disabled:pointer-events-none disabled:opacity-50 data-[disabled]:pointer-events-none data-[disabled]:opacity-50'
|
|
100
|
-
|
|
101
|
-
// Literal tables: one notch tighter than the ladder's `px`, since the ring is
|
|
102
|
-
// invisible at rest and the roomier inset would read as a gap.
|
|
103
|
-
|
|
104
|
-
/** Horizontal inset of a field box. */
|
|
105
|
-
export const FIELD_PX: Record<SizeVariant, string> = {
|
|
106
|
-
default: 'px-2.5',
|
|
107
|
-
compact: 'px-2',
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/** Left inset of the text around a field (label, description, error), so it lines up with the text inside the box. */
|
|
111
|
-
export const FIELD_TEXT_INSET: Record<SizeVariant, string> = {
|
|
112
|
-
default: 'pl-2.5',
|
|
113
|
-
compact: 'pl-2',
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/** Framed at rest (`bordered`), or invisible until hovered or focused (`borderless`). */
|
|
117
|
-
export type FieldVariant = 'bordered' | 'borderless'
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Vendored from Fluid Functionalism — `registry/default/fluid-hover-highlight.tsx` at
|
|
3
|
-
* github.com/mickadesign/fluid-functionalism@b3587bdbd83fc66c2a6aae3817ffb856cb09260b
|
|
4
|
-
* (fluidfunctionalism.com). MIT License © 2026 Micka Touillaud — see
|
|
5
|
-
* LICENSE.fluid-functionalism in this package.
|
|
6
|
-
*
|
|
7
|
-
* Local modifications:
|
|
8
|
-
* - `"use client"` directive dropped (no RSC here).
|
|
9
|
-
* - `framer-motion` → `motion/react` (the package's current name).
|
|
10
|
-
* - `@/lib/*` and `@/hooks/*` imports rewritten to sibling `./*` paths.
|
|
11
|
-
* - The fill is a `GooIndicator` (`./goo-indicator`, local): it melts from row
|
|
12
|
-
* to row with a liquid neck instead of sliding as one box. The keyed fade,
|
|
13
|
-
* `from`, `hidden` and `transition` behave as before; a square highlight
|
|
14
|
-
* (no radius) has nothing to melt and slides as before.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { AnimatePresence, motion, type Transition, useReducedMotion } from 'motion/react'
|
|
18
|
-
import { GooIndicator } from './goo-indicator'
|
|
19
|
-
import { spring } from './springs'
|
|
20
|
-
import type { ItemRect, UseFluidHoverReturn } from './use-fluid-hover'
|
|
21
|
-
import { cn } from './utils'
|
|
22
|
-
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
// The one hover highlight every fluid hover list renders: an absolutely
|
|
25
|
-
// positioned fill that springs between the rects `useFluidHover` measures.
|
|
26
|
-
// Consumers used to hand-roll this motion.div; this is that block, once.
|
|
27
|
-
//
|
|
28
|
-
// const hover = useFluidHover(ref);
|
|
29
|
-
// <FluidHoverHighlight hover={hover} className={shape.bg} />
|
|
30
|
-
//
|
|
31
|
-
// It owns no layout opinion beyond `absolute`: radius, z-index, and the
|
|
32
|
-
// offsetParent (the container must be `relative`) are the consumer's.
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
|
-
|
|
35
|
-
/** What the highlight reads off the hook: the highlighted index, the
|
|
36
|
-
* measured rects, whether they are current, and the pointer session. */
|
|
37
|
-
export type FluidHoverSource = Pick<UseFluidHoverReturn, 'activeIndex' | 'itemRects' | 'isMeasured' | 'sessionRef'>
|
|
38
|
-
|
|
39
|
-
interface HighlightFromHook {
|
|
40
|
-
/** The hook's return value. The highlight sits on
|
|
41
|
-
* `itemRects[activeIndex]` once `isMeasured`, and re-keys on the session. */
|
|
42
|
-
hover: FluidHoverSource
|
|
43
|
-
/** Keep the list's state but show nothing (a closed popup, hover switched
|
|
44
|
-
* off). Runs the exit fade. */
|
|
45
|
-
hidden?: boolean
|
|
46
|
-
rect?: never
|
|
47
|
-
session?: never
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
interface HighlightFromRect {
|
|
51
|
-
/** For lists that resolve their own rect (the sidebar's unified scope):
|
|
52
|
-
* the rect to sit on, in the container's coordinate space. `null` hides
|
|
53
|
-
* the highlight (it fades out on `spring.fast.exit`). */
|
|
54
|
-
rect: ItemRect | null
|
|
55
|
-
/** `sessionRef.current` from `useFluidHover`. It increments when the
|
|
56
|
-
* cursor enters the container, which re-keys the highlight so it fades in
|
|
57
|
-
* at `from ?? rect` instead of sliding over from wherever it was last. */
|
|
58
|
-
session: number
|
|
59
|
-
hover?: never
|
|
60
|
-
hidden?: never
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export type FluidHoverHighlightProps = (HighlightFromHook | HighlightFromRect) & {
|
|
64
|
-
/** Where a fresh session fades in from. A dropdown passes its checked row,
|
|
65
|
-
* a nav menu its active route. Defaults to the rect itself. */
|
|
66
|
-
from?: ItemRect | null
|
|
67
|
-
/** Radius, z-index, anything else. Merged onto
|
|
68
|
-
* `absolute bg-hover pointer-events-none`. */
|
|
69
|
-
className?: string
|
|
70
|
-
/** The positional spring. Defaults to `spring.fast`. Pass `false` to snap
|
|
71
|
-
* to the new rect with no travel (a layout reflow that moved the rows
|
|
72
|
-
* underneath, not a hover change). The opacity fade is always 0.08s. */
|
|
73
|
-
transition?: Transition | false
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const fade: Transition = { duration: 0.08 }
|
|
77
|
-
const snap: Transition = { duration: 0 }
|
|
78
|
-
|
|
79
|
-
/** A measured rect as animation targets: position as a transform, size as
|
|
80
|
-
* layout. Exported for the unit test. */
|
|
81
|
-
export function toTarget(rect: ItemRect) {
|
|
82
|
-
return { x: rect.left, y: rect.top, width: rect.width, height: rect.height }
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Resolves the positional transition. Reduced motion keeps the opacity fade
|
|
87
|
-
* and drops the travel, per the motion guidelines: fewer and gentler, not
|
|
88
|
-
* none. Exported for the unit test.
|
|
89
|
-
*/
|
|
90
|
-
export function resolveHighlightTransition(
|
|
91
|
-
transition: Transition | false | undefined,
|
|
92
|
-
reduceMotion: boolean,
|
|
93
|
-
): Transition {
|
|
94
|
-
const positional = transition === false || reduceMotion ? snap : (transition ?? spring.fast)
|
|
95
|
-
return { ...positional, opacity: fade }
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** The rect and session a set of props resolves to. Exported for the test. */
|
|
99
|
-
export function resolveHighlightSource(props: FluidHoverHighlightProps): {
|
|
100
|
-
rect: ItemRect | null
|
|
101
|
-
session: number
|
|
102
|
-
} {
|
|
103
|
-
if (props.hover) {
|
|
104
|
-
const { activeIndex, itemRects, isMeasured, sessionRef } = props.hover
|
|
105
|
-
const rect = !props.hidden && isMeasured && activeIndex !== null ? (itemRects[activeIndex] ?? null) : null
|
|
106
|
-
return { rect, session: sessionRef.current }
|
|
107
|
-
}
|
|
108
|
-
return { rect: props.rect, session: props.session }
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function FluidHoverHighlight(props: FluidHoverHighlightProps) {
|
|
112
|
-
const { from, className, transition } = props
|
|
113
|
-
const { rect, session } = resolveHighlightSource(props)
|
|
114
|
-
// Reads the OS media query directly, so an installed copy honours reduced
|
|
115
|
-
// motion without the app wrapping its tree in MotionConfig.
|
|
116
|
-
const reduceMotion = useReducedMotion() ?? false
|
|
117
|
-
return (
|
|
118
|
-
<AnimatePresence>
|
|
119
|
-
{rect && (
|
|
120
|
-
<motion.div
|
|
121
|
-
key={session}
|
|
122
|
-
data-slot="fluid-hover-highlight"
|
|
123
|
-
className="pointer-events-none absolute top-0 left-0"
|
|
124
|
-
initial={{ opacity: 0 }}
|
|
125
|
-
animate={{ opacity: 1 }}
|
|
126
|
-
exit={{ opacity: 0, transition: spring.fast.exit }}
|
|
127
|
-
transition={fade}
|
|
128
|
-
>
|
|
129
|
-
<GooIndicator
|
|
130
|
-
rect={rect}
|
|
131
|
-
from={from}
|
|
132
|
-
className={cn('bg-hover', className)}
|
|
133
|
-
transition={transition === false || reduceMotion ? false : (transition ?? spring.fast)}
|
|
134
|
-
/>
|
|
135
|
-
</motion.div>
|
|
136
|
-
)}
|
|
137
|
-
</AnimatePresence>
|
|
138
|
-
)
|
|
139
|
-
}
|
package/lib/focus-ring.tsx
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Local addition (not part of Fluid Functionalism): the one keyboard ring a
|
|
3
|
-
* list panel draws (Dropdown and its submenus, NavigationMenu's panels,
|
|
4
|
-
* Select): 2px outside the focused row, springing between rows on
|
|
5
|
-
* `spring.fast` (a snap under reduced motion) and fading out on its exit.
|
|
6
|
-
* Its corners follow the surrounding shape's `focusRing` radius, concentric
|
|
7
|
-
* with the row; a popup that pins its own shape passes it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { AnimatePresence, motion } from 'motion/react'
|
|
11
|
-
import { useReduceMotion } from './reduced-motion'
|
|
12
|
-
import { type ShapeVariant, shapeMap, useShape } from './shape-context'
|
|
13
|
-
import { spring } from './springs'
|
|
14
|
-
import type { ItemRect } from './use-fluid-hover'
|
|
15
|
-
import { cn } from './utils'
|
|
16
|
-
|
|
17
|
-
interface FocusRingProps {
|
|
18
|
-
/** The focused row's rect in the panel's coordinates; nothing while none has keyboard focus. */
|
|
19
|
-
rect: ItemRect | null | undefined
|
|
20
|
-
/** Pins the radius to one shape (popups stay `rounded`); defaults to the surrounding ShapeProvider. */
|
|
21
|
-
shape?: ShapeVariant
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** The keyboard ring: 2px outside the focused row, springing between rows. */
|
|
25
|
-
function FocusRing({ rect, shape }: FocusRingProps) {
|
|
26
|
-
const surrounding = useShape()
|
|
27
|
-
const radius = (shape ? shapeMap[shape] : surrounding).focusRing
|
|
28
|
-
const reduced = useReduceMotion()
|
|
29
|
-
return (
|
|
30
|
-
<AnimatePresence>
|
|
31
|
-
{rect && (
|
|
32
|
-
<motion.div
|
|
33
|
-
aria-hidden="true"
|
|
34
|
-
className={cn('pointer-events-none absolute z-20 border border-focus-ring', radius)}
|
|
35
|
-
initial={false}
|
|
36
|
-
animate={{ left: rect.left - 2, top: rect.top - 2, width: rect.width + 4, height: rect.height + 4 }}
|
|
37
|
-
exit={{ opacity: 0, transition: spring.fast.exit }}
|
|
38
|
-
transition={reduced ? { duration: 0 } : { ...spring.fast, opacity: { duration: spring.fast.duration } }}
|
|
39
|
-
/>
|
|
40
|
-
)}
|
|
41
|
-
</AnimatePresence>
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type { FocusRingProps }
|
|
46
|
-
export { FocusRing }
|
package/lib/goo-indicator.tsx
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Local addition (not part of Fluid Functionalism): the liquid indicator, the
|
|
3
|
-
* morph style for everything that travels between items: a tab's active pill,
|
|
4
|
-
* a switch thumb, the fluid hover highlight and merged selection backgrounds.
|
|
5
|
-
* When the indicator leaves a rect it leaves a blob behind. The blob lingers
|
|
6
|
-
* for a third of the spring, then follows to the back of the new rect,
|
|
7
|
-
* shrinking, while the indicator springs on: the goo melts the two into one
|
|
8
|
-
* stretched drop that lets go, or, on a long move, a drop and a droplet that
|
|
9
|
-
* catches up. The filter runs only while a blob is alive; at rest nothing is
|
|
10
|
-
* filtered.
|
|
11
|
-
*
|
|
12
|
-
* The goo is the morph engine's (`GOO_MATRIX` and `GOO_BLUR_RATIO` in
|
|
13
|
-
* `lib/use-morph.ts`, after beUI's gooey popover and Sileo, notices
|
|
14
|
-
* LICENSE.beui and LICENSE.sileo). `GooFilter` lays the source over the
|
|
15
|
-
* thresholded blur, which only works for opaque fills: `bg-hover` and
|
|
16
|
-
* `bg-active` are a few percent alpha, under the threshold. `GooLayer`
|
|
17
|
-
* thresholds the shapes' coverage instead and fills the result with their own
|
|
18
|
-
* token, read from their fill class, so translucent and opaque fills melt
|
|
19
|
-
* alike.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import { animate, motion, type Transition, useMotionValue, type ValueAnimationTransition } from 'motion/react'
|
|
23
|
-
import { type ReactNode, useId, useLayoutEffect, useRef, useState } from 'react'
|
|
24
|
-
import { useReduceMotion } from './reduced-motion'
|
|
25
|
-
import { spring } from './springs'
|
|
26
|
-
import type { ItemRect } from './use-fluid-hover'
|
|
27
|
-
import { GOO_BLUR_RATIO, GOO_MATRIX } from './use-morph'
|
|
28
|
-
import { cn } from './utils'
|
|
29
|
-
|
|
30
|
-
// Any coverage counts as solid before the blur, so a 4%-alpha fill melts like an opaque one.
|
|
31
|
-
const COVERAGE = '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0'
|
|
32
|
-
// The share of its cross size a retracting blob keeps: it thins into a neck instead of a point.
|
|
33
|
-
const NECK = 0.5
|
|
34
|
-
|
|
35
|
-
function union(a: ItemRect | null, b: ItemRect): ItemRect {
|
|
36
|
-
if (!a) return b
|
|
37
|
-
const left = Math.min(a.left, b.left)
|
|
38
|
-
const top = Math.min(a.top, b.top)
|
|
39
|
-
return {
|
|
40
|
-
left,
|
|
41
|
-
top,
|
|
42
|
-
width: Math.max(a.left + a.width, b.left + b.width) - left,
|
|
43
|
-
height: Math.max(a.top + a.height, b.top + b.height) - top,
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function pad(rect: ItemRect, by: number): ItemRect {
|
|
48
|
-
return { left: rect.left - by, top: rect.top - by, width: rect.width + by * 2, height: rect.height + by * 2 }
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function center(rect: ItemRect) {
|
|
52
|
-
return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** A move worth a blob: the center travels more than half the indicator's size, not a resize in place. */
|
|
56
|
-
function travels(from: ItemRect, to: ItemRect) {
|
|
57
|
-
const a = center(from)
|
|
58
|
-
const b = center(to)
|
|
59
|
-
return (
|
|
60
|
-
Math.abs(b.x - a.x) > Math.min(from.width, to.width) / 2 ||
|
|
61
|
-
Math.abs(b.y - a.y) > Math.min(from.height, to.height) / 2
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Where the blob left at `from` goes: the back edge of `to` on each axis that
|
|
67
|
-
* moved, so it follows the indicator and is absorbed, and a neck on the other.
|
|
68
|
-
*/
|
|
69
|
-
function retract(from: ItemRect, to: ItemRect): ItemRect {
|
|
70
|
-
const axis = (start: number, size: number, toStart: number, toSize: number) => {
|
|
71
|
-
const delta = toStart + toSize / 2 - (start + size / 2)
|
|
72
|
-
if (Math.abs(delta) < 1) return [start + (size * (1 - NECK)) / 2, size * NECK] as const
|
|
73
|
-
return [delta > 0 ? toStart : toStart + toSize, 0] as const
|
|
74
|
-
}
|
|
75
|
-
const [left, width] = axis(from.left, from.width, to.left, to.width)
|
|
76
|
-
const [top, height] = axis(from.top, from.height, to.top, to.height)
|
|
77
|
-
return { left, top, width, height }
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function toTarget(rect: ItemRect) {
|
|
81
|
-
return { x: rect.left, y: rect.top, width: rect.width, height: rect.height }
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function blurOf(el: Element, rect: ItemRect) {
|
|
85
|
-
const r = Number.parseFloat(getComputedStyle(el).borderTopLeftRadius) || 0
|
|
86
|
-
return Math.min(r, rect.width / 2, rect.height / 2) * GOO_BLUR_RATIO
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
interface GooLayerProps {
|
|
90
|
-
/** Filter on: the shapes melt into one. Off at rest. */
|
|
91
|
-
active: boolean
|
|
92
|
-
/** Blur in px: the shapes' radius times `GOO_BLUR_RATIO`. */
|
|
93
|
-
blur: number
|
|
94
|
-
/** The layer's box in the container's coordinates, covering every shape; padded for the blur here. */
|
|
95
|
-
box: ItemRect | null
|
|
96
|
-
/** The shapes' classes (a bg token, a radius): the melted result is filled with their background. */
|
|
97
|
-
fill: string
|
|
98
|
-
/** The shapes, positioned in the container's coordinates. */
|
|
99
|
-
children?: ReactNode
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/** A box of shapes that melt into one while `active`. The filter's region follows the box, so keep it tight. */
|
|
103
|
-
export function GooLayer({ active, blur, box, fill, children }: GooLayerProps) {
|
|
104
|
-
const id = `goo-${useId().replace(/:/g, '')}`
|
|
105
|
-
const flood = useRef<SVGFEFloodElement>(null)
|
|
106
|
-
const probe = useRef<HTMLDivElement>(null)
|
|
107
|
-
const layer = box ? pad(box, blur * 3) : { left: 0, top: 0, width: 0, height: 0 }
|
|
108
|
-
|
|
109
|
-
// Resolved each time the goo starts, so it follows the scheme.
|
|
110
|
-
useLayoutEffect(() => {
|
|
111
|
-
if (!active || !probe.current) return
|
|
112
|
-
flood.current?.setAttribute('flood-color', getComputedStyle(probe.current).backgroundColor)
|
|
113
|
-
}, [active])
|
|
114
|
-
|
|
115
|
-
return (
|
|
116
|
-
<>
|
|
117
|
-
<svg aria-hidden className="absolute size-0">
|
|
118
|
-
<filter id={id} x="-50%" y="-50%" width="200%" height="200%" colorInterpolationFilters="sRGB">
|
|
119
|
-
<feColorMatrix in="SourceGraphic" values={COVERAGE} result="coverage" />
|
|
120
|
-
<feGaussianBlur in="coverage" stdDeviation={blur} result="blur" />
|
|
121
|
-
<feColorMatrix in="blur" values={GOO_MATRIX} result="goo" />
|
|
122
|
-
<feFlood ref={flood} />
|
|
123
|
-
<feComposite in2="goo" operator="in" />
|
|
124
|
-
</filter>
|
|
125
|
-
</svg>
|
|
126
|
-
<div
|
|
127
|
-
aria-hidden
|
|
128
|
-
className="pointer-events-none absolute"
|
|
129
|
-
// Geometry is the shapes' own; the filter is the effect itself, melting their token fill.
|
|
130
|
-
style={{ ...layer, filter: active ? `url(#${id})` : undefined }}
|
|
131
|
-
>
|
|
132
|
-
{/* Zero-sized, so it paints nothing: it carries the fill token for the flood and maps the shapes back to the container's coordinates. */}
|
|
133
|
-
<div ref={probe} className={cn(fill, 'absolute')} style={{ left: -layer.left, top: -layer.top }}>
|
|
134
|
-
{children}
|
|
135
|
-
</div>
|
|
136
|
-
</div>
|
|
137
|
-
</>
|
|
138
|
-
)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
interface Trail {
|
|
142
|
-
id: number
|
|
143
|
-
from: ItemRect
|
|
144
|
-
to: ItemRect
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
interface GooIndicatorProps {
|
|
148
|
-
/** The rect to sit on, in the container's coordinates (as `useFluidHover` measures them). */
|
|
149
|
-
rect: ItemRect
|
|
150
|
-
/** Where it first appears; it then travels to `rect`. Defaults to `rect`. */
|
|
151
|
-
from?: ItemRect | null
|
|
152
|
-
/** Fill and radius classes: a bg token and the shape's radius. */
|
|
153
|
-
className?: string
|
|
154
|
-
/** Shadow class. While it melts, the shapes are drawn again beneath the goo with it, since the filter flattens shadows. */
|
|
155
|
-
shadow?: string
|
|
156
|
-
/** The travel: a spring tier. `false` snaps (a reflow, reduced motion). Defaults to `spring.moderate`. */
|
|
157
|
-
transition?: Transition | false
|
|
158
|
-
/** Opacity of the whole indicator, faded on `spring.fast`. Defaults to `1`. */
|
|
159
|
-
opacity?: number
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* An indicator that travels between items with a liquid neck. Render it in the
|
|
164
|
-
* items' `relative` container, beneath them: the items' text stays above it,
|
|
165
|
-
* unfiltered.
|
|
166
|
-
*/
|
|
167
|
-
export function GooIndicator({
|
|
168
|
-
rect,
|
|
169
|
-
from,
|
|
170
|
-
className,
|
|
171
|
-
shadow,
|
|
172
|
-
transition = spring.moderate,
|
|
173
|
-
opacity = 1,
|
|
174
|
-
}: GooIndicatorProps) {
|
|
175
|
-
const reduced = useReduceMotion()
|
|
176
|
-
const start = from ?? rect
|
|
177
|
-
const x = useMotionValue(start.left)
|
|
178
|
-
const y = useMotionValue(start.top)
|
|
179
|
-
const width = useMotionValue(start.width)
|
|
180
|
-
const height = useMotionValue(start.height)
|
|
181
|
-
const lead = useRef<HTMLDivElement>(null)
|
|
182
|
-
const [trails, setTrails] = useState<Trail[]>([])
|
|
183
|
-
const [blur, setBlur] = useState(0)
|
|
184
|
-
const ids = useRef(0)
|
|
185
|
-
const travel = transition === false || reduced ? false : transition
|
|
186
|
-
const travelRef = useRef(travel)
|
|
187
|
-
travelRef.current = travel
|
|
188
|
-
const read = () => ({ left: x.get(), top: y.get(), width: width.get(), height: height.get() })
|
|
189
|
-
|
|
190
|
-
// Only a new rect moves it: the transition is often an inline object.
|
|
191
|
-
useLayoutEffect(() => {
|
|
192
|
-
const move = travelRef.current as ValueAnimationTransition<number> | false
|
|
193
|
-
const current = read()
|
|
194
|
-
if (!move) {
|
|
195
|
-
x.jump(rect.left)
|
|
196
|
-
y.jump(rect.top)
|
|
197
|
-
width.jump(rect.width)
|
|
198
|
-
height.jump(rect.height)
|
|
199
|
-
return
|
|
200
|
-
}
|
|
201
|
-
const goo = lead.current && travels(current, rect) ? blurOf(lead.current, current) : 0
|
|
202
|
-
// Square shapes have no radius to melt with.
|
|
203
|
-
if (goo >= 1) {
|
|
204
|
-
setBlur(goo)
|
|
205
|
-
setTrails(list => [...list, { id: ++ids.current, from: current, to: retract(current, rect) }])
|
|
206
|
-
}
|
|
207
|
-
animate(x, rect.left, move)
|
|
208
|
-
animate(y, rect.top, move)
|
|
209
|
-
animate(width, rect.width, move)
|
|
210
|
-
animate(height, rect.height, move)
|
|
211
|
-
}, [rect.left, rect.top, rect.width, rect.height])
|
|
212
|
-
|
|
213
|
-
const melting = trails.length > 0
|
|
214
|
-
const linger = travel ? { ...travel, delay: (travel.duration ?? 0) / 3 } : undefined
|
|
215
|
-
const shape = cn('pointer-events-none absolute top-0 left-0', className)
|
|
216
|
-
const box = trails.reduce<ItemRect>((all, trail) => union(all, trail.from), union(read(), rect))
|
|
217
|
-
const drop = (trail: Trail) => setTrails(list => list.filter(t => t.id !== trail.id))
|
|
218
|
-
|
|
219
|
-
return (
|
|
220
|
-
<motion.div
|
|
221
|
-
aria-hidden
|
|
222
|
-
className="pointer-events-none absolute top-0 left-0"
|
|
223
|
-
initial={false}
|
|
224
|
-
animate={{ opacity }}
|
|
225
|
-
transition={{ duration: spring.fast.duration }}
|
|
226
|
-
>
|
|
227
|
-
{shadow && (
|
|
228
|
-
<>
|
|
229
|
-
{/* Fading as it shrinks: the goo lets a sliver vanish, a crisp shadow would not. */}
|
|
230
|
-
{trails.map(trail => (
|
|
231
|
-
<motion.div
|
|
232
|
-
key={trail.id}
|
|
233
|
-
className={cn(shape, shadow)}
|
|
234
|
-
initial={{ ...toTarget(trail.from), opacity: 1 }}
|
|
235
|
-
animate={{ ...toTarget(trail.to), opacity: 0 }}
|
|
236
|
-
transition={linger}
|
|
237
|
-
/>
|
|
238
|
-
))}
|
|
239
|
-
<motion.div className={cn(shape, shadow, !melting && 'invisible')} style={{ x, y, width, height }} />
|
|
240
|
-
</>
|
|
241
|
-
)}
|
|
242
|
-
<GooLayer active={melting} blur={blur} box={box} fill={className ?? ''}>
|
|
243
|
-
{trails.map(trail => (
|
|
244
|
-
<motion.div
|
|
245
|
-
key={trail.id}
|
|
246
|
-
className={shape}
|
|
247
|
-
initial={toTarget(trail.from)}
|
|
248
|
-
animate={toTarget(trail.to)}
|
|
249
|
-
transition={linger}
|
|
250
|
-
onAnimationComplete={() => drop(trail)}
|
|
251
|
-
/>
|
|
252
|
-
))}
|
|
253
|
-
{/* At rest it wears its own shadow; melting, a shadow would count as coverage and swell the goo. */}
|
|
254
|
-
<motion.div ref={lead} className={cn(shape, !melting && shadow)} style={{ x, y, width, height }} />
|
|
255
|
-
</GooLayer>
|
|
256
|
-
</motion.div>
|
|
257
|
-
)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
export type { GooIndicatorProps, GooLayerProps }
|
|
261
|
-
export { union }
|