@yewdiel21/motion-kit 0.9.0 → 0.10.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/NOTICE +3 -35
- package/README.md +93 -81
- package/dist/auto/index.d.ts +22 -3
- package/dist/auto/index.js +43 -5
- package/dist/auto/index.js.map +1 -1
- package/dist/{chunk-KLY5BRRI.js → chunk-34EZ7DF4.js} +1 -1
- package/dist/chunk-34EZ7DF4.js.map +1 -0
- package/dist/{chunk-RFDIZYFX.js → chunk-DOOMULVV.js} +20 -20
- package/dist/chunk-DOOMULVV.js.map +1 -0
- package/dist/{chunk-ABNRDDO7.js → chunk-I3DXF2KQ.js} +2 -2
- package/dist/{chunk-Q4LVFNLN.js → chunk-IKQ5FODN.js} +4 -4
- package/dist/chunk-IKQ5FODN.js.map +1 -0
- package/dist/{chunk-2BQGFOA7.js → chunk-J6OCFNGU.js} +2 -2
- package/dist/chunk-J6OCFNGU.js.map +1 -0
- package/dist/{chunk-6OJAP6ZL.js → chunk-QFBOHPWZ.js} +3 -3
- package/dist/chunk-QFBOHPWZ.js.map +1 -0
- package/dist/{chunk-J27KH2A2.js → chunk-RVSKEBIC.js} +1 -1
- package/dist/chunk-RVSKEBIC.js.map +1 -0
- package/dist/{chunk-34XYOXHG.js → chunk-TFNRIZHU.js} +1615 -12
- package/dist/chunk-TFNRIZHU.js.map +1 -0
- package/dist/{chunk-FS2HJVVY.js → chunk-XAKC2QY7.js} +1204 -5
- package/dist/chunk-XAKC2QY7.js.map +1 -0
- package/dist/css/components/calendar.css +159 -0
- package/dist/css/components/chat-background.css +2 -2
- package/dist/css/components/chat.css +1 -1
- package/dist/css/components/cursor.css +3 -3
- package/dist/css/components/dialog.css +3 -3
- package/dist/css/components/hover-card.css +14 -0
- package/dist/css/components/input-otp.css +10 -0
- package/dist/css/components/island.css +1 -1
- package/dist/css/components/menu.css +1 -1
- package/dist/css/components/nav.css +1 -5
- package/dist/css/components/pagination.css +11 -0
- package/dist/css/components/quantity.css +16 -0
- package/dist/css/components/slot-picker.css +126 -0
- package/dist/css/components/steps.css +2 -2
- package/dist/css/components/studio-dock.css +35 -0
- package/dist/css/components/theme-picker.css +1 -1
- package/dist/css/components/toast.css +1 -1
- package/dist/css/components/trailer.css +37 -0
- package/dist/css/controls.css +78 -13
- package/dist/css/effects.css +8 -8
- package/dist/css/fonts.css +1 -1
- package/dist/css/themes/black-green.css +1 -1
- package/dist/css/themes/black.css +1 -1
- package/dist/css/themes/blue.css +1 -1
- package/dist/css/themes/brown.css +1 -1
- package/dist/css/themes/cold-blue.css +1 -1
- package/dist/css/themes/funny.css +1 -1
- package/dist/css/themes/gray.css +1 -1
- package/dist/css/themes/green.css +1 -1
- package/dist/css/themes/modern-1.css +1 -1
- package/dist/css/themes/neogreen.css +1 -1
- package/dist/css/themes/new.css +1 -1
- package/dist/css/themes/new2.css +1 -1
- package/dist/css/themes/oled.css +1 -1
- package/dist/css/themes/orange.css +1 -1
- package/dist/css/themes/pastel-pink.css +1 -1
- package/dist/css/themes/pink.css +1 -1
- package/dist/css/themes/purple.css +1 -1
- package/dist/css/themes/red.css +1 -1
- package/dist/css/themes/super-blue.css +1 -1
- package/dist/css/themes.css +19 -19
- package/dist/css/tokens.css +9 -9
- package/dist/elements/index.d.ts +75 -7
- package/dist/elements/index.js +172 -6
- package/dist/elements/index.js.map +1 -1
- package/dist/{engine-CUr9QijM.d.ts → engine-GDGwQnJE.d.ts} +2 -2
- package/dist/gl/index.js +3 -3
- package/dist/index.css +1076 -63
- package/dist/index.d.ts +17 -17
- package/dist/index.js +49 -7
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.ts +139 -40
- package/dist/react/index.js +355 -8
- package/dist/react/index.js.map +1 -1
- package/dist/{reduced-BM4Ls0g5.d.ts → reduced-BmBzKH94.d.ts} +215 -18
- package/dist/{reveal-WFUWDrei.d.ts → reveal-jsX-uwUz.d.ts} +233 -24
- package/dist/{store-Bqy_obnD.d.ts → store-DYb3tTsZ.d.ts} +5 -5
- package/dist/theme/generate.d.ts +1 -1
- package/dist/theme/generate.js +2 -2
- package/dist/theme/generate.js.map +1 -1
- package/dist/theme/index.d.ts +2 -2
- package/dist/theme/index.js +2 -2
- package/dist/{theme-BFMoCzi6.d.ts → theme-Bjf9qIIy.d.ts} +1 -1
- package/package.json +2 -2
- package/registry.json +230 -156
- package/skills/motion-kit/SKILL.md +209 -189
- package/skills/motion-kit/reference/components.md +5 -5
- package/skills/motion-kit/reference/design.md +14 -14
- package/skills/motion-kit/reference/recipes.md +48 -49
- package/src/auto/auto-init.ts +38 -0
- package/src/components/calendar/README.md +82 -0
- package/src/components/calendar/calendar.css +158 -0
- package/src/components/calendar/element.ts +27 -0
- package/src/components/calendar/engine.ts +412 -0
- package/src/components/calendar/react.tsx +69 -0
- package/src/components/chat/README.md +1 -3
- package/src/components/chat/chat.css +1 -1
- package/src/components/chat/engine.ts +1 -1
- package/src/components/chat/react.tsx +1 -1
- package/src/components/chat-background/README.md +1 -3
- package/src/components/chat-background/audio.ts +1 -1
- package/src/components/chat-background/chat-background.css +2 -2
- package/src/components/chat-background/engine.ts +1 -1
- package/src/components/chat-background/react.tsx +1 -1
- package/src/components/cursor/README.md +3 -5
- package/src/components/cursor/cursor.css +3 -3
- package/src/components/cursor/element.ts +2 -2
- package/src/components/cursor/engine.ts +5 -5
- package/src/components/cursor/react.tsx +1 -1
- package/src/components/dialog/README.md +4 -8
- package/src/components/dialog/dialog.css +3 -3
- package/src/components/dialog/engine.ts +2 -2
- package/src/components/dialog/react.tsx +1 -1
- package/src/components/hover-card/README.md +16 -0
- package/src/components/hover-card/element.ts +8 -0
- package/src/components/hover-card/engine.ts +69 -0
- package/src/components/hover-card/hover-card.css +13 -0
- package/src/components/hover-card/react.tsx +19 -0
- package/src/components/input-otp/README.md +18 -0
- package/src/components/input-otp/element.ts +14 -0
- package/src/components/input-otp/engine.ts +106 -0
- package/src/components/input-otp/input-otp.css +9 -0
- package/src/components/input-otp/react.tsx +21 -0
- package/src/components/island/README.md +7 -7
- package/src/components/island/engine.ts +3 -3
- package/src/components/island/island.css +1 -1
- package/src/components/island/react.tsx +3 -3
- package/src/components/menu/README.md +2 -4
- package/src/components/menu/engine.ts +1 -1
- package/src/components/menu/menu.css +1 -1
- package/src/components/menu/react.tsx +1 -1
- package/src/components/nav/README.md +12 -14
- package/src/components/nav/engine.ts +5 -5
- package/src/components/nav/nav.css +1 -5
- package/src/components/nav/react.tsx +3 -3
- package/src/components/pagination/README.md +17 -0
- package/src/components/pagination/element.ts +14 -0
- package/src/components/pagination/engine.ts +102 -0
- package/src/components/pagination/pagination.css +10 -0
- package/src/components/pagination/react.tsx +22 -0
- package/src/components/quantity/README.md +20 -0
- package/src/components/quantity/element.ts +14 -0
- package/src/components/quantity/engine.ts +85 -0
- package/src/components/quantity/quantity.css +15 -0
- package/src/components/quantity/react.tsx +21 -0
- package/src/components/slot-picker/README.md +68 -0
- package/src/components/slot-picker/element.ts +27 -0
- package/src/components/slot-picker/engine.ts +412 -0
- package/src/components/slot-picker/react.tsx +76 -0
- package/src/components/slot-picker/slot-picker.css +125 -0
- package/src/components/steps/README.md +1 -3
- package/src/components/steps/engine.ts +3 -3
- package/src/components/steps/react.tsx +2 -2
- package/src/components/steps/steps.css +2 -2
- package/src/components/studio-dock/README.md +44 -0
- package/src/components/studio-dock/element.ts +11 -0
- package/src/components/studio-dock/engine.ts +212 -0
- package/src/components/studio-dock/react.tsx +23 -0
- package/src/components/studio-dock/studio-dock.css +34 -0
- package/src/components/theme-picker/README.md +3 -5
- package/src/components/theme-picker/engine.ts +2 -2
- package/src/components/theme-picker/react.tsx +1 -1
- package/src/components/theme-picker/theme-picker.css +1 -1
- package/src/components/toast/README.md +1 -3
- package/src/components/toast/engine.ts +2 -2
- package/src/components/toast/react.tsx +1 -1
- package/src/components/toast/store.ts +1 -2
- package/src/components/toast/toast.css +1 -1
- package/src/components/trailer/README.md +28 -0
- package/src/components/trailer/element.ts +13 -0
- package/src/components/trailer/engine.ts +189 -0
- package/src/components/trailer/react.tsx +16 -0
- package/src/components/trailer/trailer.css +36 -0
- package/src/core/channels.ts +3 -3
- package/src/core/curves.ts +3 -3
- package/src/core/dates.ts +98 -0
- package/src/core/gsap.ts +2 -2
- package/src/core/loop.ts +1 -1
- package/src/core/math.ts +1 -1
- package/src/core/physics-spring.ts +2 -2
- package/src/core/scroll-track.ts +2 -4
- package/src/core/spring.ts +1 -1
- package/src/core/timing.ts +21 -22
- package/src/css/controls/README.md +24 -20
- package/src/css/controls/burger.css +1 -1
- package/src/css/controls/button.css +4 -4
- package/src/css/controls/checkbox.css +1 -1
- package/src/css/controls/chip.css +1 -1
- package/src/css/controls/field.css +2 -2
- package/src/css/controls/glass.css +4 -4
- package/src/css/controls/status.css +63 -0
- package/src/css/default-theme.css +1 -1
- package/src/css/effects/README.md +19 -21
- package/src/css/effects/anim.css +1 -1
- package/src/css/effects/fade.css +1 -1
- package/src/css/effects/float.css +1 -1
- package/src/css/effects/frost.css +1 -1
- package/src/css/effects/grain.css +1 -1
- package/src/css/effects/loading.css +1 -1
- package/src/css/effects/success.css +1 -1
- package/src/css/effects/text.css +1 -1
- package/src/css/fonts.css +1 -1
- package/src/css/states.css +1 -1
- package/src/css/themes/black-green.css +1 -1
- package/src/css/themes/black.css +1 -1
- package/src/css/themes/blue.css +1 -1
- package/src/css/themes/brown.css +1 -1
- package/src/css/themes/cold-blue.css +1 -1
- package/src/css/themes/funny.css +1 -1
- package/src/css/themes/gray.css +1 -1
- package/src/css/themes/green.css +1 -1
- package/src/css/themes/modern-1.css +1 -1
- package/src/css/themes/neogreen.css +1 -1
- package/src/css/themes/new.css +1 -1
- package/src/css/themes/new2.css +1 -1
- package/src/css/themes/oled.css +1 -1
- package/src/css/themes/orange.css +1 -1
- package/src/css/themes/pastel-pink.css +1 -1
- package/src/css/themes/pink.css +1 -1
- package/src/css/themes/purple.css +1 -1
- package/src/css/themes/red.css +1 -1
- package/src/css/themes/super-blue.css +1 -1
- package/src/css/tokens.css +8 -8
- package/src/elements/index.ts +24 -0
- package/src/gl/liquid-blend/README.md +3 -3
- package/src/gl/matcap/README.md +3 -3
- package/src/gl/particle-hero/README.md +1 -1
- package/src/gl/particle-hero/create-particle-hero.ts +3 -5
- package/src/gl/particle-hero/shaders.ts +1 -1
- package/src/gl/shader-blur/README.md +3 -3
- package/src/gl/shader-grain/README.md +3 -3
- package/src/index.ts +25 -0
- package/src/motion/chat.ts +2 -2
- package/src/motion/confetti.ts +1 -1
- package/src/motion/count.ts +1 -1
- package/src/motion/details.ts +1 -1
- package/src/motion/drag-dismiss.ts +1 -1
- package/src/motion/effects.ts +1 -1
- package/src/motion/entrances.ts +1 -1
- package/src/motion/floating.ts +1 -1
- package/src/motion/flow.ts +2 -2
- package/src/motion/indicator.ts +1 -1
- package/src/motion/layout.ts +1 -1
- package/src/motion/liquid.ts +1 -1
- package/src/motion/morph.ts +2 -2
- package/src/motion/reveal.ts +1 -1
- package/src/motion/sheet.ts +1 -1
- package/src/motion/surface.ts +1 -1
- package/src/react/animated-number.tsx +2 -2
- package/src/react/flip-group.tsx +1 -1
- package/src/react/frost.tsx +1 -1
- package/src/react/index.ts +21 -0
- package/src/react/slot-text.tsx +1 -1
- package/src/react/use-action-button.ts +6 -0
- package/src/react/use-card-dock.ts +1 -1
- package/src/react/use-cascade.ts +1 -1
- package/src/react/use-contrast.ts +1 -1
- package/src/react/use-depth-grid.ts +1 -1
- package/src/react/use-editorial-reveal.ts +7 -0
- package/src/react/use-fill-text.ts +1 -1
- package/src/react/use-film-hero.ts +6 -0
- package/src/react/use-font-cycle.ts +7 -0
- package/src/react/use-frame-zoom.ts +1 -1
- package/src/react/use-image-zoom.ts +5 -0
- package/src/react/use-joined-cta.ts +5 -0
- package/src/react/use-letters.ts +1 -1
- package/src/react/use-local-clock.ts +5 -0
- package/src/react/use-marquee.ts +1 -1
- package/src/react/use-mask-text.ts +1 -1
- package/src/react/use-parallax.ts +1 -1
- package/src/react/use-particle-hero.ts +1 -1
- package/src/react/use-scroll-dock.ts +5 -0
- package/src/react/use-snap-strip.ts +1 -1
- package/src/react/use-sticker.ts +5 -0
- package/src/react/use-studio-dock.ts +8 -0
- package/src/react/use-text-roll.ts +1 -1
- package/src/react/use-thumbnail-nav.ts +7 -0
- package/src/react/use-trailer.ts +6 -0
- package/src/react/use-weight-hover.ts +5 -0
- package/src/recipes/action-button/README.md +31 -0
- package/src/recipes/action-button/action-button.css +113 -0
- package/src/recipes/action-button/create-action-button.ts +56 -0
- package/src/recipes/card-dock/README.md +1 -1
- package/src/recipes/card-dock/card-dock.css +1 -1
- package/src/recipes/card-dock/create-card-dock.ts +2 -2
- package/src/recipes/cascade/README.md +1 -3
- package/src/recipes/cascade/create-cascade.ts +3 -3
- package/src/recipes/contrast/README.md +0 -2
- package/src/recipes/contrast/create-contrast.ts +1 -1
- package/src/recipes/counter/README.md +0 -2
- package/src/recipes/counter/create-counter.ts +1 -1
- package/src/recipes/curved-carousel/README.md +0 -2
- package/src/recipes/curved-carousel/create-curved-carousel.ts +2 -2
- package/src/recipes/curved-carousel/curved-carousel.css +1 -1
- package/src/recipes/depth-grid/README.md +0 -2
- package/src/recipes/depth-grid/create-depth-grid.ts +3 -4
- package/src/recipes/details/README.md +0 -2
- package/src/recipes/details/create-details.ts +1 -1
- package/src/recipes/dock-pill/README.md +3 -3
- package/src/recipes/drag-ruler/README.md +3 -3
- package/src/recipes/editorial-reveal/README.md +35 -0
- package/src/recipes/editorial-reveal/create-editorial-reveal.ts +91 -0
- package/src/recipes/editorial-reveal/editorial-reveal.css +17 -0
- package/src/recipes/fill-text/README.md +1 -1
- package/src/recipes/fill-text/create-fill-text.ts +1 -1
- package/src/recipes/film-hero/README.md +23 -0
- package/src/recipes/film-hero/create-film-hero.ts +65 -0
- package/src/recipes/film-hero/film-hero.css +29 -0
- package/src/recipes/fit-text/README.md +0 -2
- package/src/recipes/flow/README.md +0 -2
- package/src/recipes/flow/create-flow.ts +1 -1
- package/src/recipes/font-cycle/README.md +11 -0
- package/src/recipes/font-cycle/create-font-cycle.ts +126 -0
- package/src/recipes/font-cycle/font-cycle.css +36 -0
- package/src/recipes/frame-zoom/README.md +1 -3
- package/src/recipes/frame-zoom/create-frame-zoom.ts +2 -2
- package/src/recipes/image-zoom/README.md +16 -0
- package/src/recipes/image-zoom/create-image-zoom.ts +27 -0
- package/src/recipes/image-zoom/image-zoom.css +7 -0
- package/src/recipes/infinite-reel/README.md +3 -3
- package/src/recipes/joined-cta/README.md +13 -0
- package/src/recipes/joined-cta/create-joined-cta.ts +22 -0
- package/src/recipes/joined-cta/joined-cta.css +17 -0
- package/src/recipes/letters/README.md +2 -4
- package/src/recipes/letters/create-letters.ts +3 -3
- package/src/recipes/local-clock/README.md +31 -0
- package/src/recipes/local-clock/create-local-clock.ts +61 -0
- package/src/recipes/marquee/README.md +0 -2
- package/src/recipes/marquee/create-marquee.ts +3 -3
- package/src/recipes/marquee/marquee.css +1 -1
- package/src/recipes/mask-text/README.md +3 -5
- package/src/recipes/mask-text/create-mask-text.ts +4 -4
- package/src/recipes/parallax/README.md +1 -3
- package/src/recipes/parallax/create-parallax.ts +1 -1
- package/src/recipes/pile/README.md +0 -2
- package/src/recipes/pile/create-pile.ts +1 -1
- package/src/recipes/pile/pile-math.ts +1 -1
- package/src/recipes/pile/pile.css +1 -1
- package/src/recipes/pill/README.md +0 -2
- package/src/recipes/pill/pill.css +2 -2
- package/src/recipes/pop/README.md +0 -2
- package/src/recipes/pop/create-pop.ts +1 -1
- package/src/recipes/radial-menu/README.md +0 -2
- package/src/recipes/radial-menu/create-radial-menu.ts +1 -1
- package/src/recipes/radial-menu/radial-menu.css +1 -1
- package/src/recipes/reflow/README.md +3 -5
- package/src/recipes/reflow/create-reflow.ts +1 -1
- package/src/recipes/repel-bento/README.md +3 -3
- package/src/recipes/reveal/README.md +0 -2
- package/src/recipes/reveal/create-reveal.ts +1 -1
- package/src/recipes/rotator/README.md +3 -3
- package/src/recipes/scroll-dock/README.md +46 -0
- package/src/recipes/scroll-dock/create-scroll-dock.ts +72 -0
- package/src/recipes/scroll-dock/scroll-dock.css +70 -0
- package/src/recipes/slot-text/README.md +0 -2
- package/src/recipes/slot-text/create-slot-text.ts +1 -1
- package/src/recipes/snap-strip/README.md +1 -1
- package/src/recipes/snap-strip/create-snap-strip.ts +5 -6
- package/src/recipes/snap-strip/snap-strip.css +1 -1
- package/src/recipes/sortable/README.md +3 -5
- package/src/recipes/sortable/create-sortable.ts +4 -4
- package/src/recipes/sortable/sortable.css +1 -1
- package/src/recipes/spring-cards/README.md +0 -2
- package/src/recipes/spring-cards/create-spring-cards.ts +1 -1
- package/src/recipes/spring-cards/spring-cards.css +1 -1
- package/src/recipes/sticker/README.md +59 -0
- package/src/recipes/sticker/create-sticker.ts +490 -0
- package/src/recipes/sticker/sticker.css +112 -0
- package/src/recipes/stretch-footer/README.md +0 -2
- package/src/recipes/stretch-footer/create-stretch-footer.ts +1 -1
- package/src/recipes/stretch-footer/stretch-footer.css +1 -1
- package/src/recipes/tabs/README.md +0 -2
- package/src/recipes/tabs/create-tabs.ts +1 -1
- package/src/recipes/text-roll/README.md +1 -3
- package/src/recipes/text-roll/create-text-roll.ts +3 -3
- package/src/recipes/text-roll/text-roll.css +1 -1
- package/src/recipes/thumbnail-nav/README.md +16 -0
- package/src/recipes/thumbnail-nav/create-thumbnail-nav.ts +165 -0
- package/src/recipes/thumbnail-nav/thumbnail-nav.css +108 -0
- package/src/recipes/ticket-menu/README.md +3 -3
- package/src/recipes/weight-hover/README.md +37 -0
- package/src/recipes/weight-hover/create-weight-hover.ts +136 -0
- package/src/recipes/weight-hover/weight-hover.css +7 -0
- package/src/recipes/words/README.md +0 -2
- package/src/recipes/words/create-words.ts +1 -1
- package/src/theme/generate.ts +1 -1
- package/src/theme/presets.ts +2 -2
- package/src/theme/theme.ts +1 -2
- package/dist/chunk-2BQGFOA7.js.map +0 -1
- package/dist/chunk-34XYOXHG.js.map +0 -1
- package/dist/chunk-6OJAP6ZL.js.map +0 -1
- package/dist/chunk-FS2HJVVY.js.map +0 -1
- package/dist/chunk-J27KH2A2.js.map +0 -1
- package/dist/chunk-KLY5BRRI.js.map +0 -1
- package/dist/chunk-Q4LVFNLN.js.map +0 -1
- package/dist/chunk-RFDIZYFX.js.map +0 -1
- /package/dist/{chunk-ABNRDDO7.js.map → chunk-I3DXF2KQ.js.map} +0 -0
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
# Recipe parameters
|
|
1
|
+
# Recipe parameters
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Parameters, defaults and behavior for the motion recipes.
|
|
4
4
|
|
|
5
5
|
## Shared
|
|
6
6
|
|
|
7
|
-
| Name | Value |
|
|
8
|
-
|
|
9
|
-
| Spring | `v = v·friction^dt + (target − x)·stiffness·dt; x += v·dt`, stiffness .05, friction .8 |
|
|
10
|
-
| Frame loop | one `gsap.ticker` callback, `dt = Δms / (1000/60)`, capped at 3; recipes subscribe only while visible |
|
|
11
|
-
| `--mk-ease-elastic` | `linear(0, .5737 7.6%, … 1.0011 81.26%, 1)` |
|
|
12
|
-
| `--mk-ease-elastic-hover` | `linear(0, .2178 2.1%, … .9981 86.66%, 1)` |
|
|
13
|
-
| `ELASTIC` (GSAP) | `elastic.out(1, 0.45)` |
|
|
14
|
-
| `mk-signature` | `M0,0 C0.308,0.19 0.107,0.633 0.288,0.866 0.382,0.987 0.656,1 1,1` |
|
|
15
|
-
| `mk-flow` | `M0,0 C0.25,0.1 0.25,1 1,1` |
|
|
16
|
-
| `mk-close` | `.56,.27,0,1` |
|
|
17
|
-
| `--mk-shadow` | `0 9px 21px rgb(0 0 0/.1), 0 38px 38px rgb(0 0 0/.09), 0 85px 51px rgb(0 0 0/.05)` |
|
|
7
|
+
| Name | Value |
|
|
8
|
+
|---|---|
|
|
9
|
+
| Spring | `v = v·friction^dt + (target − x)·stiffness·dt; x += v·dt`, stiffness .05, friction .8 |
|
|
10
|
+
| Frame loop | one `gsap.ticker` callback, `dt = Δms / (1000/60)`, capped at 3; recipes subscribe only while visible |
|
|
11
|
+
| `--mk-ease-elastic` | `linear(0, .5737 7.6%, … 1.0011 81.26%, 1)` |
|
|
12
|
+
| `--mk-ease-elastic-hover` | `linear(0, .2178 2.1%, … .9981 86.66%, 1)` |
|
|
13
|
+
| `ELASTIC` (GSAP) | `elastic.out(1, 0.45)` |
|
|
14
|
+
| `mk-signature` | `M0,0 C0.308,0.19 0.107,0.633 0.288,0.866 0.382,0.987 0.656,1 1,1` |
|
|
15
|
+
| `mk-flow` | `M0,0 C0.25,0.1 0.25,1 1,1` |
|
|
16
|
+
| `mk-close` | `.56,.27,0,1` |
|
|
17
|
+
| `--mk-shadow` | `0 9px 21px rgb(0 0 0/.1), 0 38px 38px rgb(0 0 0/.09), 0 85px 51px rgb(0 0 0/.05)` |
|
|
18
18
|
|
|
19
19
|
## spring-cards
|
|
20
20
|
|
|
@@ -22,12 +22,12 @@ Values were read from the public bundles of spencergabor.com (Nuxt 3, analysed w
|
|
|
22
22
|
- Pointer push: `dx = (px − cx)/innerWidth·2`, `dy = (py − cy)/innerHeight·2`, `k = max(0, 1 − hypot(dx, dy))^6 · .4`, `push += movement·k`, `push *= .9^dt`.
|
|
23
23
|
- CSS: `rotate: calc(tilt − velocity·.25deg)`; tilts 2°, −3°, 6°, −2°; vertical offsets 5 %, −6 %, 5 %, −4 %.
|
|
24
24
|
- Entrance: `scale 0 → 1`, 1 s, elastic, `i·.08s + .4s`.
|
|
25
|
-
-
|
|
25
|
+
- Layout: 4:3 cards and −1.5 % overlap so text on covers stays readable.
|
|
26
26
|
|
|
27
27
|
## curved-carousel
|
|
28
28
|
|
|
29
29
|
- Friction .85; drag velocity = pointer movement per frame; on release `v·2`, rest `x − v·f/(1−f)`, snap to the nearest slide, approach `x += (target − x)(1 − f^dt)`.
|
|
30
|
-
- Tap: under 6 px of travel
|
|
30
|
+
- Tap: under 6 px of travel.
|
|
31
31
|
- Wheel: `v −= deltaX·.2` when horizontal; snap 150 ms after the last wheel event.
|
|
32
32
|
- Arc: `rotate: t·.03deg`, origin `50% 70vw`, `translateY: cos(t·π/1000)·−3rem + 3rem`, title opacity `cos(t·π/600)`; `t` = slide centre − viewport centre in px.
|
|
33
33
|
- Entrance: media from `scale .8; translate 0 20%`, 1.4 s elastic, delay `sin(k·π/2)·.12s`.
|
|
@@ -35,15 +35,15 @@ Values were read from the public bundles of spencergabor.com (Nuxt 3, analysed w
|
|
|
35
35
|
## pile
|
|
36
36
|
|
|
37
37
|
- Layers: `rotation = rand(2,5)·(±1 alternating)`, `offsetX = rand(4,10)·random sign`, `offsetY = (n − i)·5`; seeded (mulberry32) so SSR and client match.
|
|
38
|
-
- CSS: `rotate: rot·.6deg`, `translate: px·.3% py·.3
|
|
38
|
+
- CSS: `rotate: rot·.6deg`, `translate: px·.3% py·.3%`.
|
|
39
39
|
- In view: media `scale .7 → 1`, shadow `0 → 1`, .8 s elastic; hover 1.01/1.02/1.03, active .97/.98/.99.
|
|
40
40
|
|
|
41
41
|
## words
|
|
42
42
|
|
|
43
43
|
- `scaleY 0 → 1`, `yPercent 25 → 0`, origin bottom, .8 s, `ELASTIC`, 100 ms between words, 60 ms between letters.
|
|
44
|
-
-
|
|
44
|
+
- Uses GSAP SplitText with reduced-motion support and text replacement.
|
|
45
45
|
|
|
46
|
-
## flow
|
|
46
|
+
## flow
|
|
47
47
|
|
|
48
48
|
- From `y −20`, `blur(16px)`, opacity 0 → 0, 0.5 s, 50 ms stagger, `mk-flow`.
|
|
49
49
|
|
|
@@ -62,21 +62,21 @@ Values were read from the public bundles of spencergabor.com (Nuxt 3, analysed w
|
|
|
62
62
|
|
|
63
63
|
## radial-menu
|
|
64
64
|
|
|
65
|
-
- Item position: `translate(sin(i·.9 + 1.5708)·−r, cos(i·.9 + 1.5708)·r)`, r = 3.6rem
|
|
65
|
+
- Item position: `translate(sin(i·.9 + 1.5708)·−r, cos(i·.9 + 1.5708)·r)`, r = 3.6rem.
|
|
66
66
|
- Open: `scale .5 → 1`, .5 s elastic, `i·.05s`; close: .15 s `cubic-bezier(.55,.055,.675,.19)`.
|
|
67
67
|
|
|
68
68
|
## pill
|
|
69
69
|
|
|
70
70
|
- Hover `scale 1.05` + shadow, active `.95`, .8 s elastic; `.mk-stretch` hover `scaleY(1.2)`, 1 s elastic-hover.
|
|
71
71
|
|
|
72
|
-
##
|
|
72
|
+
## Core motion and surfaces
|
|
73
73
|
|
|
74
|
-
| Name | Value |
|
|
75
|
-
|
|
76
|
-
| `mk-fade-away` / `mk-blur-away` | `.56,.27,0,1` / `.37,.35,0,1` |
|
|
77
|
-
| `mk-chat-scroll` | `M0,0 C0.308,0.19 0.318,0.567 0.5,0.8 0.593,0.921 0.656,1 1,1` |
|
|
78
|
-
| `mk-layout-reflow` / `mk-sortable-land` | spring path `FA(.52)` / `FA(.62)` (stiffness 5.6, sampled 72 steps) |
|
|
79
|
-
| `--mk-ease-signature` |
|
|
74
|
+
| Name | Value |
|
|
75
|
+
|---|---|
|
|
76
|
+
| `mk-fade-away` / `mk-blur-away` | `.56,.27,0,1` / `.37,.35,0,1` |
|
|
77
|
+
| `mk-chat-scroll` | `M0,0 C0.308,0.19 0.318,0.567 0.5,0.8 0.593,0.921 0.656,1 1,1` |
|
|
78
|
+
| `mk-layout-reflow` / `mk-sortable-land` | spring path `FA(.52)` / `FA(.62)` (stiffness 5.6, sampled 72 steps) |
|
|
79
|
+
| `--mk-ease-signature` | own `linear()` sampling of the signature (its backdrop tint) |
|
|
80
80
|
|
|
81
81
|
### flowIn / flowOut / stepChange
|
|
82
82
|
|
|
@@ -86,7 +86,7 @@ Values were read from the public bundles of spencergabor.com (Nuxt 3, analysed w
|
|
|
86
86
|
|
|
87
87
|
### tabs
|
|
88
88
|
|
|
89
|
-
- Indicator to the selected tab's box
|
|
89
|
+
- Indicator to the selected tab's box, 0.45 s, signature; centres a scrolling list; reduced: instant.
|
|
90
90
|
|
|
91
91
|
### counter
|
|
92
92
|
|
|
@@ -115,48 +115,47 @@ Values were read from the public bundles of spencergabor.com (Nuxt 3, analysed w
|
|
|
115
115
|
|
|
116
116
|
### sortable
|
|
117
117
|
|
|
118
|
-
-
|
|
118
|
+
- Drag threshold 6 px; floating copy (cloned into the item's own list, `position: fixed`, so the list's CSS still styles it) follows a spring 1100/38 with mass `clamp(√(w·h / 24000), 1, 2.5)`; tilt spring 170/13 toward `14·tanh(torque / 14)`, torque from smoothed velocity (×2e-3) and acceleration (×45e-5) about the grab point (arm Y ≥ .4). Lift 0.18 s `power2.out`, scale `1 + .03·lift`, shadow `0 12·lift 32·lift rgb(0 0 0 / .22·lift)`.
|
|
119
119
|
- Neighbours: `y` by the item's height + the space to its neighbour, 0.62 s `mk-layout-reflow` (FA .52); insertion index by the pointer against item midpoints; group by pointer x (then y). Land 0.42 s `mk-sortable-land` (FA .62) to the slot, cross-fade 0.277 s `power1.inOut` to a copy styled by the destination list.
|
|
120
120
|
- Auto-scroll: scrollable ancestors (and the page) within 56 px of an edge, `ceil(16 · min(1, d / 56))` px a frame. Touch (`pointer: coarse`): handle only. Escape / pointercancel: back. Keyboard (added): Space/Enter, arrows, Escape; reflow 0.62 s; `aria-live` announcements.
|
|
121
121
|
|
|
122
|
-
##
|
|
122
|
+
## Floating navigation and cards
|
|
123
123
|
|
|
124
|
-
### island
|
|
124
|
+
### island
|
|
125
125
|
|
|
126
126
|
- Shell fixed top 2rem, 23.5rem wide (28rem ≥ 1920 px; 1rem / 5vw side margins ≤ 767 / 479 px), radius 3em → 2em (0.4 s `cubic-bezier(.4,0,.2,1)`, closing 0.45 s late). Glass `blur(20px)` on `#38383899` + `linear-gradient(141deg, #a9c2f214, #62718c24)`.
|
|
127
127
|
- Content `grid-template-rows 0fr → 1fr`, 0.6 s `cubic-bezier(.625,.05,0,1)`, 0.125 s late. Backdrop black 0 → .4, 0.7 s `cubic-bezier(.5,.5,0,1)`, 0.1 s late. Rows `opacity 0 → 1`, `translateY 3em → 0`, 0.6 s, delay `0.15 + i·0.025` s.
|
|
128
128
|
- Entrance `yPercent −300 → 0`, 1.8 s (no ease given, so GSAP's `power1.out`). Card hover: siblings 20 % (0.15 s ease-out), picture 1.04 (0.4 s, back 0.3 s `cubic-bezier(.25,.46,.45,.94)`). Closes on a scroll > 1 px after wheel / touchmove.
|
|
129
129
|
|
|
130
|
-
### card-dock
|
|
130
|
+
### card-dock
|
|
131
131
|
|
|
132
132
|
- Stack, from the end: `translateY(90 % / 180 % / 270 % / 360 %) scale(.93 / .87 / .8 / .73)`; open 0.8 s, close 0.64 s, `cubic-bezier(.48,.01,0,1.08)`. Card 4rem → 4.5rem, 0.6 s `cubic-bezier(.77,0,.175,1)`; surface `#38383899 → #555555b0` 0.3 s `cubic-bezier(.65,0,.35,1)`; `blur(19px)`, border `#8a8a8a1a`, radius .9rem.
|
|
133
133
|
- Title opacity 0.5 s, `translateX(−15 % → −120 %)` 0.4 s. Intro: spread 1600 ms from the call, then the CTA fades in. Tablet (768–1024 px, `hover: none`): the first tap opens.
|
|
134
134
|
|
|
135
|
-
### snap-strip
|
|
135
|
+
### snap-strip
|
|
136
136
|
|
|
137
|
-
- 5000 ms a card, 2000 ms wait after mousedown / touchstart / wheel, `data-delay 500`, cards 68vw.
|
|
137
|
+
- 5000 ms a card, 2000 ms wait after mousedown / touchstart / wheel, `data-delay 500`, cards 68vw. Uses native scroll-snap.
|
|
138
138
|
|
|
139
|
-
### fill-text
|
|
139
|
+
### fill-text
|
|
140
140
|
|
|
141
141
|
- SplitText `words, chars`; `fromTo(chars, { autoAlpha: .2 }, { autoAlpha: 1, stagger: .1, ease: 'linear' })` (0.5 s each), scrubbed `top 90%` → `center 40%`.
|
|
142
142
|
|
|
143
|
-
### particle-hero
|
|
143
|
+
### particle-hero
|
|
144
144
|
|
|
145
|
-
-
|
|
146
|
-
- Kit: own shaders, size² points (128² by default), damping .91, pointer radius .28, words drawn locally (dark pixels < 120 of a 640 × 320 canvas), Canvas2D fallback (~1800 points).
|
|
145
|
+
- GPU simulation: `size²` points (128² by default), damping .91, pointer radius .28, Chladni modes 3/5/7 and word morph cycles, words drawn locally (dark pixels < 120 of a 640 × 320 canvas), Canvas2D fallback (~1800 points).
|
|
147
146
|
|
|
148
147
|
## Collections and menu (v0.8)
|
|
149
148
|
|
|
150
149
|
All six have a `createX(root, options)` factory in the main entry, `useX(ref, options, deps)` in `/react`, CLI entry and vanilla/React playground page. `autoInit()` supports all six. Destroy restores the host and clears timers, tweens, listeners, observers and generated markup.
|
|
151
150
|
|
|
152
|
-
| Name | Markup | Options and controls |
|
|
151
|
+
| Name | Markup | Options and controls | Motion |
|
|
153
152
|
|---|---|---|---|
|
|
154
|
-
| ticket-menu | `.mk-dialog.mk-menu` dialog with `[data-mk-item]` | `MenuOptions`; `open`, `close`, `toggle`, `items`, `isOpen`; also `<Menu.Root ticket>` / `<mk-menu ticket>` |
|
|
155
|
-
| infinite-reel | `.mk-infinite-reel > [data-mk-reel-track]` | `axis x/y`, `speed 0`, `friction .95`; `moveBy`, `position`, `pause`, `resume` |
|
|
156
|
-
| repel-bento | `.mk-repel-bento` with cards | `distance 30`, `breakpoint 1024`; `play`, `reset` |
|
|
157
|
-
| rotator | `.mk-rotator` with one item per child | `interval 8000`, `autoplay true`, `index`, `onChange`; `select`, `next`, `previous`, `index` |
|
|
158
|
-
| drag-ruler | `.mk-drag-ruler[aria-label]` | `min 0`, `max 8`, `step .1`, `value max`, `pixelsPerUnit 60`, `onChange`; `set`, `value`; `mk:change` |
|
|
159
|
-
| dock-pill | `.mk-dock-pill` with `[data-mk-dock-item]` links/buttons | `index`, `onSelect`; `select`, `index`; `mk:select` |
|
|
153
|
+
| ticket-menu | `.mk-dialog.mk-menu` dialog with `[data-mk-item]` | `MenuOptions`; `open`, `close`, `toggle`, `items`, `isOpen`; also `<Menu.Root ticket>` / `<mk-menu ticket>` | .9 s opening, 1.1 s rows from 150%, stagger .02 |
|
|
154
|
+
| infinite-reel | `.mk-infinite-reel > [data-mk-reel-track]` | `axis x/y`, `speed 0`, `friction .95`; `moveBy`, `position`, `pause`, `resume` | Continuous DOM track with inertial scrolling |
|
|
155
|
+
| repel-bento | `.mk-repel-bento` with cards | `distance 30`, `breakpoint 1024`; `play`, `reset` | Entry spring 60/15, stagger .006, .6 vector; neighbours min(5000/d,30), spring 300/25 |
|
|
156
|
+
| rotator | `.mk-rotator` with one item per child | `interval 8000`, `autoplay true`, `index`, `onChange`; `select`, `next`, `previous`, `index` | .25 s, y 5→0 |
|
|
157
|
+
| drag-ruler | `.mk-drag-ruler[aria-label]` | `min 0`, `max 8`, `step .1`, `value max`, `pixelsPerUnit 60`, `onChange`; `set`, `value`; `mk:change` | Numeric marks with drag and keyboard input |
|
|
158
|
+
| dock-pill | `.mk-dock-pill` with `[data-mk-dock-item]` links/buttons | `index`, `onSelect`; `select`, `index`; `mk:select` | Spring 380/30 |
|
|
160
159
|
|
|
161
160
|
Reduced motion disables inertia, autoplay, entry and repulsion, keeping manual navigation. Reel copies are inert, aria-hidden and have no duplicate IDs. Ruler supports arrows, Home/End and PageUp/PageDown. Dock supports arrows/Home/End and skips disabled items. Keep rotator controls outside its child list.
|
|
162
161
|
|
|
@@ -164,9 +163,9 @@ Reduced motion disables inertia, autoplay, entry and repulsion, keeping manual n
|
|
|
164
163
|
|
|
165
164
|
`createLiquidBlend`, `createMatcap`, `createShaderGrain`, `createShaderBlur` share `{ images?, progress?, amount?, maxDpr? }` and return `{ setProgress, setAmount, pause, resume, mode, destroy }`. Images default to the host's first two `<img>` elements; one image is repeated. Same-origin or CORS-enabled images; loading is observed. A host with explicit dimensions is required. React hooks have the corresponding `use…` names. These factories are not exported from the main entry or registered with autoInit.
|
|
166
165
|
|
|
167
|
-
- Liquid: `amount .15`, progress 0→1 blends the two textures with centre-weighted UV waves.
|
|
168
|
-
- Matcap: analytic sphere, normal UV .495+.5, hemispheric light and gain .15; optional image used as matcap.
|
|
169
|
-
- Grain: own temporal hash, amount .07 from
|
|
170
|
-
- Blur: amount 5 image pixels, seven weighted samples with
|
|
166
|
+
- Liquid: `amount .15`, progress 0→1 blends the two textures with centre-weighted UV waves.
|
|
167
|
+
- Matcap: analytic sphere, normal UV .495+.5, hemispheric light and gain .15; optional image used as matcap. It does not load models.
|
|
168
|
+
- Grain: own temporal hash, amount .07 from postprocess; 24 Hz grain, fixed frame for reduced motion.
|
|
169
|
+
- Blur: amount 5 image pixels, seven weighted samples with .19648255/.29690696/.09447040/.01038136 weights and 1.41176471/3.29411765/5.17647059 offsets. Progress rotates the direction x→y.
|
|
171
170
|
|
|
172
|
-
WebGL unsupported, compilation/texture error or context loss leaves the original HTML available. Context restoration rebuilds resources. The canvas is decorative; loops pause offscreen and in hidden tabs. No
|
|
171
|
+
WebGL unsupported, compilation/texture error or context loss leaves the original HTML available. Context restoration rebuilds resources. The canvas is decorative; loops pause offscreen and in hidden tabs. No additional rendering library is required.
|
package/src/auto/auto-init.ts
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
import { createQuantity } from '../components/quantity/engine';
|
|
2
|
+
import { createPagination } from '../components/pagination/engine';
|
|
3
|
+
import { createHoverCard } from '../components/hover-card/engine';
|
|
4
|
+
import { createInputOtp } from '../components/input-otp/engine';
|
|
5
|
+
import { createJoinedCta } from '../recipes/joined-cta/create-joined-cta';
|
|
6
|
+
import { createImageZoom } from '../recipes/image-zoom/create-image-zoom';
|
|
7
|
+
import { createFontCycle } from '../recipes/font-cycle/create-font-cycle';
|
|
8
|
+
import { createThumbnailNav } from '../recipes/thumbnail-nav/create-thumbnail-nav';
|
|
9
|
+
import { createActionButton } from '../recipes/action-button/create-action-button';
|
|
10
|
+
import { createFilmHero } from '../recipes/film-hero/create-film-hero';
|
|
11
|
+
import { createEditorialReveal } from '../recipes/editorial-reveal/create-editorial-reveal';
|
|
12
|
+
import { createStudioDock } from '../components/studio-dock/engine';
|
|
13
|
+
import { createCalendar } from '../components/calendar/engine';
|
|
14
|
+
import { createSlotPicker } from '../components/slot-picker/engine';
|
|
15
|
+
import { createWeightHover } from '../recipes/weight-hover/create-weight-hover';
|
|
16
|
+
import { createSticker } from '../recipes/sticker/create-sticker';
|
|
17
|
+
import { createScrollDock } from '../recipes/scroll-dock/create-scroll-dock';
|
|
18
|
+
import { createLocalClock } from '../recipes/local-clock/create-local-clock';
|
|
19
|
+
import { createTrailer } from '../components/trailer/engine';
|
|
1
20
|
import { ScrollTrigger } from '../core/gsap';
|
|
2
21
|
import { warnOnce, type Instance } from '../core/types';
|
|
3
22
|
import { createSpringCards } from '../recipes/spring-cards/create-spring-cards';
|
|
@@ -39,6 +58,25 @@ import { createDockPill } from '../recipes/dock-pill/create-dock-pill';
|
|
|
39
58
|
type Factory = (el: HTMLElement, options: Record<string, unknown>) => Instance;
|
|
40
59
|
|
|
41
60
|
const factories = {
|
|
61
|
+
'joined-cta': createJoinedCta,
|
|
62
|
+
'image-zoom': createImageZoom,
|
|
63
|
+
'font-cycle': createFontCycle,
|
|
64
|
+
'thumbnail-nav': createThumbnailNav,
|
|
65
|
+
'action-button': createActionButton,
|
|
66
|
+
'film-hero': createFilmHero,
|
|
67
|
+
'editorial-reveal': createEditorialReveal,
|
|
68
|
+
'studio-dock': createStudioDock,
|
|
69
|
+
'trailer': createTrailer,
|
|
70
|
+
'quantity': createQuantity,
|
|
71
|
+
'pagination': createPagination,
|
|
72
|
+
'hover-card': createHoverCard,
|
|
73
|
+
'input-otp': createInputOtp,
|
|
74
|
+
'calendar': createCalendar,
|
|
75
|
+
'slot-picker': createSlotPicker,
|
|
76
|
+
'weight-hover': createWeightHover,
|
|
77
|
+
'sticker': createSticker,
|
|
78
|
+
'scroll-dock': createScrollDock,
|
|
79
|
+
'local-clock': createLocalClock,
|
|
42
80
|
'spring-cards': createSpringCards,
|
|
43
81
|
'curved-carousel': (el, options) =>
|
|
44
82
|
createCurvedCarousel(el, {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# calendar
|
|
2
|
+
|
|
3
|
+
El calendario de Melon Mind. Tiene vista de mes y de semana, día de hoy marcado y eventos como chips con estado (pendiente, completado o cancelado), hora y color propio.
|
|
4
|
+
|
|
5
|
+
- **Al cargar:** los días entran desde arriba con blur (y −20 px, blur 16 → 0, 0.5 s), 5 ms uno tras otro, y después los eventos, 20 ms uno tras otro. Es el `flowChilds` del `CalendarComponent` original.
|
|
6
|
+
- **Cambiar de mes o semana:** la rejilla vieja sale 30 px hacia un lado (0.12 s) y, cuando ya casi no se ve, la nueva entra 30 px desde el otro (0.25 s `ease-out`), como los horarios de su selector de citas. Van en secuencia, sin fundido cruzado, para que no se mezclen dos meses llenos de eventos. Luego vuelven a entrar los eventos.
|
|
7
|
+
- **Hover:** el fondo del día cambia en 0.3 s y el número tiene resorte de radio y escala (`cubic-bezier(.38,.49,0,2)`).
|
|
8
|
+
|
|
9
|
+
Origen: patrón observado en la app de Melon Mind.
|
|
10
|
+
|
|
11
|
+
## HTML / Astro
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<mk-calendar class="mk-calendar" locale="es" first-day="0"
|
|
15
|
+
events='[{"id":1,"title":"Ana","start":"2026-10-23T10:00","status":"pending"}]'>
|
|
16
|
+
<div class="mk-calendar__header">
|
|
17
|
+
<h3 class="mk-calendar__title" data-mk-calendar-title>Calendario</h3>
|
|
18
|
+
<div class="mk-calendar__views" role="group" aria-label="Vista">
|
|
19
|
+
<button type="button" data-mk-calendar-view="month">Mes</button>
|
|
20
|
+
<button type="button" data-mk-calendar-view="week">Semana</button>
|
|
21
|
+
</div>
|
|
22
|
+
<button type="button" class="mk-calendar__nav" data-mk-calendar-prev aria-label="Anterior">←</button>
|
|
23
|
+
<button type="button" class="mk-calendar__nav" data-mk-calendar-today>Hoy</button>
|
|
24
|
+
<button type="button" class="mk-calendar__nav" data-mk-calendar-next aria-label="Siguiente">→</button>
|
|
25
|
+
</div>
|
|
26
|
+
<div data-mk-calendar-grid></div>
|
|
27
|
+
</mk-calendar>
|
|
28
|
+
<script>
|
|
29
|
+
import { defineElements } from '@yewdiel21/motion-kit/elements';
|
|
30
|
+
defineElements(['mk-calendar']);
|
|
31
|
+
</script>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Sólo `[data-mk-calendar-grid]` es obligatorio. Las demás piezas del header son opcionales. Si cambias el atributo `events`, los eventos se actualizan sin perder el mes ni el foco. Sin custom element: `createCalendar(root, opciones)`.
|
|
35
|
+
|
|
36
|
+
## React
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
<Calendar
|
|
40
|
+
events={citas}
|
|
41
|
+
onSelect={(day) => abrirDia(day)}
|
|
42
|
+
onEventClick={(event) => abrirCita(event.id)}
|
|
43
|
+
/>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`events` y `selected` se actualizan en el sitio. `date` y `view` son iniciales: el usuario navega libremente.
|
|
47
|
+
|
|
48
|
+
## Opciones
|
|
49
|
+
|
|
50
|
+
| Opción | Atributo | Por defecto | Qué hace |
|
|
51
|
+
|---|---|---|---|
|
|
52
|
+
| `date` | `date` | hoy | Mes o semana inicial (`Date` o `"2026-10-23"`) |
|
|
53
|
+
| `view` | `view` | `'month'` | `'month'` o `'week'` |
|
|
54
|
+
| `firstDay` | `first-day` | `0` | Primer día de la semana (0 = domingo) |
|
|
55
|
+
| `locale` | `locale` | `'es'` | Nombres de mes y día, formato de hora |
|
|
56
|
+
| `events` | `events` (JSON) | `[]` | `{ id, title, start, end?, allDay?, status?, color? }` |
|
|
57
|
+
| `maxEvents` | `max-events` | `3` | Chips por día en la vista de mes antes de «+N más» |
|
|
58
|
+
| `selected` | `selected` | — | Día seleccionado |
|
|
59
|
+
| `today` | `today` | — | Fija «hoy» (demos, pruebas) |
|
|
60
|
+
| `labels` | — | español | `more(n)`, `events(n)`, `status` |
|
|
61
|
+
| `onSelect(date)`, `onEventClick(event)`, `onNavigate({start, end, view})` | — | — | Callbacks |
|
|
62
|
+
|
|
63
|
+
API: `next()`, `prev()`, `goToday()`, `setDate(d)`, `setView(v)`, `setEvents(list)`, `select(d | null, notify)`, `date`, `view`, `selected`, `range`, `destroy()`. Eventos DOM: `mk:select` `{date, key}`, `mk:event` `{event}` y `mk:navigate` `{start, end, view}`.
|
|
64
|
+
|
|
65
|
+
Un evento con `end` en otro día aparece en cada día que cubre, hasta dos meses.
|
|
66
|
+
|
|
67
|
+
## Variables CSS
|
|
68
|
+
|
|
69
|
+
`--mk-calendar-gap`, `--mk-calendar-radius`, `--mk-calendar-day-height` y `--mk-calendar-event-color` (por evento, con `color`).
|
|
70
|
+
|
|
71
|
+
## Accesibilidad
|
|
72
|
+
|
|
73
|
+
Rejilla ARIA (`grid` / `row` / `columnheader` / `gridcell`) con un solo botón de día en el orden de tabulación:
|
|
74
|
+
|
|
75
|
+
| Tecla | Acción |
|
|
76
|
+
|---|---|
|
|
77
|
+
| Flechas | Día anterior/siguiente, misma semana anterior/siguiente |
|
|
78
|
+
| Inicio / Fin | Principio/fin de semana |
|
|
79
|
+
| RePág / AvPág | Mes anterior/siguiente (con Mayúsculas, año) |
|
|
80
|
+
| Enter / Espacio | Seleccionar el día |
|
|
81
|
+
|
|
82
|
+
Cada día anuncia la fecha completa y cuántos eventos tiene. Hoy lleva `aria-current="date"`. Los chips son botones con título, hora y estado. En móvil (< 680 px) los chips del mes se reducen a puntos de color. Con movimiento reducido no hay entradas, deslizamiento ni transiciones.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/* calendar — Melon Mind's month/week grid on the --mk-* tokens; parts are .mk-calendar__*. */
|
|
2
|
+
.mk-calendar,
|
|
3
|
+
mk-calendar {
|
|
4
|
+
--mk-calendar-gap: 6px;
|
|
5
|
+
--mk-calendar-radius: var(--mk-radius-lg);
|
|
6
|
+
--mk-calendar-day-height: 112px;
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: var(--mk-space-3);
|
|
10
|
+
color: var(--mk-text);
|
|
11
|
+
}
|
|
12
|
+
.mk-calendar__header {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-wrap: wrap;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: var(--mk-space-2);
|
|
17
|
+
}
|
|
18
|
+
.mk-calendar__title { margin: 0 auto 0 0; font-size: clamp(1.4rem, 2.6vw, 2rem); font-weight: 400; letter-spacing: -0.01em; }
|
|
19
|
+
.mk-calendar__views { display: inline-flex; padding: 4px; gap: 2px; border-radius: var(--mk-radius-full); background: var(--mk-surface-3); }
|
|
20
|
+
.mk-calendar__views button,
|
|
21
|
+
.mk-calendar__nav {
|
|
22
|
+
display: inline-grid;
|
|
23
|
+
place-items: center;
|
|
24
|
+
min-width: 44px;
|
|
25
|
+
height: 44px;
|
|
26
|
+
padding: 0 12px;
|
|
27
|
+
border: 0;
|
|
28
|
+
border-radius: var(--mk-radius-full);
|
|
29
|
+
background: transparent;
|
|
30
|
+
color: var(--mk-muted);
|
|
31
|
+
font: inherit;
|
|
32
|
+
cursor: pointer;
|
|
33
|
+
transition: background 0.2s, color 0.2s, transform 0.3s var(--mk-ease-nav-move);
|
|
34
|
+
}
|
|
35
|
+
.mk-calendar__views button[aria-pressed='true'] { background: var(--mk-surface-5); color: var(--mk-text); }
|
|
36
|
+
.mk-calendar__nav { background: var(--mk-surface-3); color: var(--mk-text); }
|
|
37
|
+
.mk-calendar__nav:active { transform: scale(0.92); }
|
|
38
|
+
:is(.mk-calendar__views button, .mk-calendar__nav):focus-visible { outline: 2px solid var(--mk-accent); outline-offset: 2px; }
|
|
39
|
+
|
|
40
|
+
[data-mk-calendar-grid] { position: relative; display: flex; flex-direction: column; gap: var(--mk-calendar-gap); }
|
|
41
|
+
.mk-calendar__head,
|
|
42
|
+
.mk-calendar__week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--mk-calendar-gap); }
|
|
43
|
+
.mk-calendar__body { display: flex; flex-direction: column; gap: var(--mk-calendar-gap); }
|
|
44
|
+
.mk-calendar__body--leaving { position: absolute; left: 0; right: 0; pointer-events: none; }
|
|
45
|
+
.mk-calendar__weekday {
|
|
46
|
+
padding: 8px 4px;
|
|
47
|
+
border-radius: var(--mk-radius-md);
|
|
48
|
+
background: var(--mk-surface-2);
|
|
49
|
+
text-align: center;
|
|
50
|
+
font-size: 0.95rem;
|
|
51
|
+
}
|
|
52
|
+
.mk-calendar__weekday-narrow { display: none; }
|
|
53
|
+
|
|
54
|
+
.mk-calendar__day {
|
|
55
|
+
position: relative;
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
gap: 4px;
|
|
59
|
+
min-width: 0;
|
|
60
|
+
min-height: var(--mk-calendar-day-height);
|
|
61
|
+
padding: 6px;
|
|
62
|
+
border-radius: var(--mk-calendar-radius);
|
|
63
|
+
background: var(--mk-surface-3);
|
|
64
|
+
transition: background 0.3s, box-shadow 0.3s;
|
|
65
|
+
container-type: inline-size;
|
|
66
|
+
}
|
|
67
|
+
.mk-calendar__body[data-view='week'] .mk-calendar__day { min-height: calc(var(--mk-calendar-day-height) * 3); }
|
|
68
|
+
.mk-calendar__day[data-outside] { background: var(--mk-surface-1); color: var(--mk-muted); }
|
|
69
|
+
.mk-calendar__day:hover { background: var(--mk-surface-4); }
|
|
70
|
+
.mk-calendar__day[aria-selected='true'] { box-shadow: inset 0 0 0 2px var(--mk-accent); }
|
|
71
|
+
.mk-calendar__number {
|
|
72
|
+
align-self: flex-end;
|
|
73
|
+
min-width: 2.2rem;
|
|
74
|
+
height: 2.2rem;
|
|
75
|
+
padding: 0 0.4rem;
|
|
76
|
+
border: 0;
|
|
77
|
+
border-radius: var(--mk-radius-full);
|
|
78
|
+
background: transparent;
|
|
79
|
+
color: inherit;
|
|
80
|
+
font: inherit;
|
|
81
|
+
font-size: 1.15rem;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
transition: background 0.3s, color 0.3s, border-radius 0.3s var(--mk-ease-nav-radius), transform 0.3s var(--mk-ease-nav-radius);
|
|
84
|
+
}
|
|
85
|
+
.mk-calendar__number:hover { background: var(--mk-surface-5); }
|
|
86
|
+
.mk-calendar__number:active { transform: scale(0.9); }
|
|
87
|
+
.mk-calendar__number:focus-visible { outline: 2px solid var(--mk-accent); outline-offset: 2px; }
|
|
88
|
+
.mk-calendar__day[data-today] .mk-calendar__number { background: var(--mk-accent); color: var(--mk-on-accent); }
|
|
89
|
+
|
|
90
|
+
.mk-calendar__events { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
|
|
91
|
+
.mk-calendar__event,
|
|
92
|
+
.mk-calendar__more {
|
|
93
|
+
--mk-calendar-event-color: var(--mk-accent);
|
|
94
|
+
display: flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
gap: 6px;
|
|
97
|
+
width: 100%;
|
|
98
|
+
min-width: 0;
|
|
99
|
+
padding: 5px 8px;
|
|
100
|
+
border: 0;
|
|
101
|
+
border-radius: 10px;
|
|
102
|
+
background: var(--mk-surface-4);
|
|
103
|
+
color: var(--mk-text);
|
|
104
|
+
font: inherit;
|
|
105
|
+
font-size: 0.85rem;
|
|
106
|
+
text-align: left;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
transition: background 0.2s, transform 0.3s var(--mk-ease-nav-move);
|
|
109
|
+
}
|
|
110
|
+
.mk-calendar__event[data-state='pending'] {
|
|
111
|
+
background: color-mix(in srgb, var(--mk-calendar-event-color) 30%, var(--mk-surface-3));
|
|
112
|
+
}
|
|
113
|
+
.mk-calendar__event:hover,
|
|
114
|
+
.mk-calendar__more:hover { transform: translateY(-1px); background: var(--mk-surface-5); }
|
|
115
|
+
.mk-calendar__event:focus-visible,
|
|
116
|
+
.mk-calendar__more:focus-visible { outline: 2px solid var(--mk-accent); outline-offset: 1px; }
|
|
117
|
+
.mk-calendar__status {
|
|
118
|
+
flex: none;
|
|
119
|
+
width: 0.8rem;
|
|
120
|
+
height: 0.8rem;
|
|
121
|
+
border: 2px solid currentColor;
|
|
122
|
+
border-radius: 50%;
|
|
123
|
+
}
|
|
124
|
+
.mk-calendar__event[data-state='done'] .mk-calendar__status { background: currentColor; box-shadow: inset 0 0 0 2px var(--mk-surface-4); }
|
|
125
|
+
.mk-calendar__event[data-state='cancelled'] .mk-calendar__event-title { text-decoration: line-through; opacity: 0.6; }
|
|
126
|
+
.mk-calendar__event-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
127
|
+
.mk-calendar__event-time { flex: none; font-variant-numeric: tabular-nums; opacity: 0.85; }
|
|
128
|
+
.mk-calendar__more { justify-content: center; background: transparent; color: var(--mk-muted); }
|
|
129
|
+
|
|
130
|
+
/* Narrow day cells: the month keeps the title (the time stays in the label); the week stacks the time under it. */
|
|
131
|
+
@container (max-width: 150px) {
|
|
132
|
+
.mk-calendar__body[data-view='month'] .mk-calendar__event-time { display: none; }
|
|
133
|
+
.mk-calendar__body[data-view='week'] .mk-calendar__event { flex-wrap: wrap; column-gap: 5px; row-gap: 1px; }
|
|
134
|
+
.mk-calendar__body[data-view='week'] .mk-calendar__event-title { flex: 1 1 0; }
|
|
135
|
+
.mk-calendar__body[data-view='week'] .mk-calendar__event-time { flex-basis: 100%; padding-left: calc(0.8rem + 5px); font-size: 0.72rem; }
|
|
136
|
+
}
|
|
137
|
+
@media (max-width: 680px) {
|
|
138
|
+
.mk-calendar,
|
|
139
|
+
mk-calendar { --mk-calendar-day-height: 64px; --mk-calendar-gap: 4px; --mk-calendar-radius: var(--mk-radius-sm); }
|
|
140
|
+
.mk-calendar__weekday-long { display: none; }
|
|
141
|
+
.mk-calendar__weekday-narrow { display: inline; }
|
|
142
|
+
.mk-calendar__number { align-self: center; font-size: 0.95rem; }
|
|
143
|
+
.mk-calendar__body[data-view='month'] .mk-calendar__events { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 3px; }
|
|
144
|
+
.mk-calendar__body[data-view='month'] :is(.mk-calendar__event, .mk-calendar__more) {
|
|
145
|
+
width: 7px;
|
|
146
|
+
height: 7px;
|
|
147
|
+
padding: 0;
|
|
148
|
+
border-radius: 50%;
|
|
149
|
+
background: var(--mk-calendar-event-color);
|
|
150
|
+
font-size: 0;
|
|
151
|
+
}
|
|
152
|
+
.mk-calendar__body[data-view='month'] .mk-calendar__status { display: none; }
|
|
153
|
+
.mk-calendar__body[data-view='week'] .mk-calendar__event-time { display: none; }
|
|
154
|
+
}
|
|
155
|
+
@media (prefers-reduced-motion: reduce) {
|
|
156
|
+
.mk-calendar *,
|
|
157
|
+
mk-calendar * { transition: none !important; }
|
|
158
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MkElement, defineElement, type OptionType } from '../../elements/base';
|
|
2
|
+
import { createCalendar, type CalendarEvent, type CalendarInstance } from './engine';
|
|
3
|
+
|
|
4
|
+
/** Light DOM: supply the header and the [data-mk-calendar-grid] shown in the README. */
|
|
5
|
+
export class MkCalendarElement extends MkElement<CalendarInstance> {
|
|
6
|
+
static options: Record<string, OptionType> = {
|
|
7
|
+
date: 'string', view: 'string', firstDay: 'number', locale: 'string', maxEvents: 'number', events: 'json', selected: 'string', today: 'string',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
protected create(options: Record<string, unknown>) {
|
|
11
|
+
return createCalendar(this, options);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
attributeChangedCallback(name: string, previous: string | null, next: string | null) {
|
|
15
|
+
if (previous === next || !this.isConnected || !this.instance) return;
|
|
16
|
+
if (name === 'events') {
|
|
17
|
+
this.instance.setEvents((this.options.events as CalendarEvent[] | undefined) ?? []);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
// Keep where the visitor is unless the changed attribute says otherwise.
|
|
21
|
+
const { date, view, selected } = this.instance;
|
|
22
|
+
this.instance.destroy();
|
|
23
|
+
this.instance = this.create({ date, view, selected, ...this.options });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const defineCalendar = () => defineElement('mk-calendar', MkCalendarElement);
|