@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,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CustomEase,
|
|
2
3
|
EASE,
|
|
3
4
|
ELASTIC,
|
|
4
5
|
Flip,
|
|
@@ -16,20 +17,20 @@ import {
|
|
|
16
17
|
revealFrom,
|
|
17
18
|
splitGraphemes,
|
|
18
19
|
takeMovement
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-TFNRIZHU.js";
|
|
20
21
|
import {
|
|
21
22
|
clamp,
|
|
22
23
|
damp,
|
|
23
24
|
mapRange,
|
|
24
25
|
wrap
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-34EZ7DF4.js";
|
|
26
27
|
import {
|
|
27
28
|
TIMING,
|
|
28
29
|
createScope,
|
|
29
30
|
entrances,
|
|
30
31
|
reduced,
|
|
31
32
|
whileVisible
|
|
32
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-DOOMULVV.js";
|
|
33
34
|
import {
|
|
34
35
|
inert,
|
|
35
36
|
warnOnce
|
|
@@ -3271,6 +3272,1193 @@ function createDockPill(root, options = {}) {
|
|
|
3271
3272
|
}, destroy: () => scope.dispose() };
|
|
3272
3273
|
}
|
|
3273
3274
|
|
|
3275
|
+
// src/recipes/joined-cta/create-joined-cta.ts
|
|
3276
|
+
function createJoinedCta(root, options = {}) {
|
|
3277
|
+
if (!root) return inert({ expand() {
|
|
3278
|
+
}, collapse() {
|
|
3279
|
+
}, expanded: false });
|
|
3280
|
+
const scope = createScope();
|
|
3281
|
+
let expanded = false;
|
|
3282
|
+
let pointer2 = false;
|
|
3283
|
+
scope.attr(root, "style", root.getAttribute("style"));
|
|
3284
|
+
scope.attr(root, "data-mk-ready", "");
|
|
3285
|
+
if (Number.isFinite(options.duration)) root.style.setProperty("--mk-joined-duration", `${Math.max(0, options.duration)}s`);
|
|
3286
|
+
const set = (value) => {
|
|
3287
|
+
if (!scope.disposed) {
|
|
3288
|
+
expanded = value;
|
|
3289
|
+
scope.attr(root, "data-mk-expanded", value ? "" : null);
|
|
3290
|
+
}
|
|
3291
|
+
};
|
|
3292
|
+
scope.on(root, "pointerenter", () => {
|
|
3293
|
+
pointer2 = true;
|
|
3294
|
+
set(true);
|
|
3295
|
+
});
|
|
3296
|
+
scope.on(root, "pointerleave", () => {
|
|
3297
|
+
pointer2 = false;
|
|
3298
|
+
if (!root.contains(document.activeElement)) set(false);
|
|
3299
|
+
});
|
|
3300
|
+
scope.on(root, "focusin", () => set(true));
|
|
3301
|
+
scope.on(root, "focusout", (event) => {
|
|
3302
|
+
if (!pointer2 && !root.contains(event.relatedTarget)) set(false);
|
|
3303
|
+
});
|
|
3304
|
+
return { expand: () => set(true), collapse: () => set(false), get expanded() {
|
|
3305
|
+
return expanded;
|
|
3306
|
+
}, destroy: () => scope.dispose() };
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3309
|
+
// src/recipes/image-zoom/create-image-zoom.ts
|
|
3310
|
+
function createImageZoom(root, options = {}) {
|
|
3311
|
+
if (!root) return inert({ open() {
|
|
3312
|
+
}, active: false });
|
|
3313
|
+
const scope = createScope();
|
|
3314
|
+
let active = false;
|
|
3315
|
+
let pointer2 = false;
|
|
3316
|
+
scope.attr(root, "style", root.getAttribute("style"));
|
|
3317
|
+
scope.attr(root, "data-mk-ready", "");
|
|
3318
|
+
const setVariable = (name, value, suffix = "") => {
|
|
3319
|
+
if (Number.isFinite(value)) root.style.setProperty(name, `${Math.max(0, value)}${suffix}`);
|
|
3320
|
+
};
|
|
3321
|
+
setVariable("--mk-zoom-duration", options.duration, "s");
|
|
3322
|
+
setVariable("--mk-zoom-frame-scale", options.frameScale);
|
|
3323
|
+
setVariable("--mk-zoom-image-scale", options.imageScale);
|
|
3324
|
+
const set = (on) => {
|
|
3325
|
+
if (!scope.disposed) {
|
|
3326
|
+
active = on;
|
|
3327
|
+
scope.attr(root, "data-mk-active", on ? "" : null);
|
|
3328
|
+
}
|
|
3329
|
+
};
|
|
3330
|
+
scope.on(root, "pointerenter", () => {
|
|
3331
|
+
pointer2 = true;
|
|
3332
|
+
set(true);
|
|
3333
|
+
});
|
|
3334
|
+
scope.on(root, "pointerleave", () => {
|
|
3335
|
+
pointer2 = false;
|
|
3336
|
+
if (!root.contains(document.activeElement)) set(false);
|
|
3337
|
+
});
|
|
3338
|
+
scope.on(root, "focusin", () => set(true));
|
|
3339
|
+
scope.on(root, "focusout", (event) => {
|
|
3340
|
+
if (!pointer2 && !root.contains(event.relatedTarget)) set(false);
|
|
3341
|
+
});
|
|
3342
|
+
return { open: set, get active() {
|
|
3343
|
+
return active;
|
|
3344
|
+
}, destroy: () => scope.dispose() };
|
|
3345
|
+
}
|
|
3346
|
+
|
|
3347
|
+
// src/recipes/font-cycle/create-font-cycle.ts
|
|
3348
|
+
function applyFace(element, face2) {
|
|
3349
|
+
if (face2.family) element.style.fontFamily = face2.family;
|
|
3350
|
+
if (face2.weight !== void 0) element.style.fontWeight = String(face2.weight);
|
|
3351
|
+
if (face2.style) element.style.fontStyle = face2.style;
|
|
3352
|
+
const axes = Object.entries(face2.axes ?? {}).filter(([tag, value]) => /^[\w ]{4}$/.test(tag) && Number.isFinite(value));
|
|
3353
|
+
if (axes.length) element.style.fontVariationSettings = axes.map(([tag, value]) => `"${tag}" ${value}`).join(", ");
|
|
3354
|
+
}
|
|
3355
|
+
function createFontCycle(root, options = {}) {
|
|
3356
|
+
if (!root || typeof document === "undefined") return inert({ play() {
|
|
3357
|
+
}, reset() {
|
|
3358
|
+
}, active: false });
|
|
3359
|
+
registerMotion();
|
|
3360
|
+
const scope = createScope();
|
|
3361
|
+
const original = [...root.childNodes];
|
|
3362
|
+
const text = options.text ?? root.textContent ?? "";
|
|
3363
|
+
const faces = options.faces ?? [
|
|
3364
|
+
{ weight: 500, axes: { wght: 500, wdth: 75 } },
|
|
3365
|
+
{ family: root.dataset.mkFontAlternate, weight: 900, axes: { wght: 900, wdth: 125 } }
|
|
3366
|
+
];
|
|
3367
|
+
const duration = Math.max(0, options.duration ?? 0.6);
|
|
3368
|
+
const stagger = Math.max(0, options.stagger ?? 0.035);
|
|
3369
|
+
const tracks = [];
|
|
3370
|
+
let animation;
|
|
3371
|
+
let active = false;
|
|
3372
|
+
let hovered = false;
|
|
3373
|
+
let focused = false;
|
|
3374
|
+
const copy = document.createElement("span");
|
|
3375
|
+
copy.className = "mk-font-cycle__accessible";
|
|
3376
|
+
copy.textContent = text;
|
|
3377
|
+
const visual = document.createElement("span");
|
|
3378
|
+
visual.className = "mk-font-cycle__visual";
|
|
3379
|
+
visual.setAttribute("aria-hidden", "true");
|
|
3380
|
+
for (const [index, letter] of splitGraphemes(text, Number.MAX_SAFE_INTEGER).entries()) {
|
|
3381
|
+
const character = document.createElement("span");
|
|
3382
|
+
character.className = "mk-font-cycle__char";
|
|
3383
|
+
const track = document.createElement("span");
|
|
3384
|
+
track.className = "mk-font-cycle__track";
|
|
3385
|
+
for (let side = 0; side < 2; side++) {
|
|
3386
|
+
const face2 = document.createElement("span");
|
|
3387
|
+
face2.className = "mk-font-cycle__face";
|
|
3388
|
+
face2.textContent = letter === " " ? "\xA0" : letter;
|
|
3389
|
+
applyFace(face2, faces[(index + side) % 2]);
|
|
3390
|
+
const sizer = face2.cloneNode(true);
|
|
3391
|
+
sizer.className = "mk-font-cycle__sizer";
|
|
3392
|
+
character.append(sizer);
|
|
3393
|
+
track.append(face2);
|
|
3394
|
+
}
|
|
3395
|
+
character.append(track);
|
|
3396
|
+
visual.append(character);
|
|
3397
|
+
tracks.push(track);
|
|
3398
|
+
}
|
|
3399
|
+
root.replaceChildren(copy, visual);
|
|
3400
|
+
const overlaySrc = options.overlaySrc ?? root.dataset.mkFontOverlay;
|
|
3401
|
+
if (overlaySrc) {
|
|
3402
|
+
const overlay = document.createElement("img");
|
|
3403
|
+
overlay.className = "mk-font-cycle__overlay";
|
|
3404
|
+
overlay.alt = "";
|
|
3405
|
+
overlay.setAttribute("aria-hidden", "true");
|
|
3406
|
+
scope.attr(root, "data-mk-font-overlay-ready", null);
|
|
3407
|
+
const loaded = () => {
|
|
3408
|
+
if (!scope.disposed) scope.attr(root, "data-mk-font-overlay-ready", overlay.naturalWidth > 0 ? "" : null);
|
|
3409
|
+
};
|
|
3410
|
+
scope.on(overlay, "load", loaded);
|
|
3411
|
+
scope.on(overlay, "error", () => {
|
|
3412
|
+
if (!scope.disposed) scope.attr(root, "data-mk-font-overlay-ready", null);
|
|
3413
|
+
});
|
|
3414
|
+
overlay.src = overlaySrc;
|
|
3415
|
+
root.append(overlay);
|
|
3416
|
+
if (overlay.complete) loaded();
|
|
3417
|
+
}
|
|
3418
|
+
scope.add(() => root.replaceChildren(...original));
|
|
3419
|
+
scope.attr(root, "class", `${root.className} mk-font-cycle`.trim());
|
|
3420
|
+
scope.attr(root, "data-mk-ready", "");
|
|
3421
|
+
const setActive = (next) => {
|
|
3422
|
+
if (scope.disposed || next === active) return;
|
|
3423
|
+
active = next;
|
|
3424
|
+
scope.attr(root, "data-mk-active", next ? "" : null);
|
|
3425
|
+
animation?.kill();
|
|
3426
|
+
if (reduced() || duration === 0) gsap.set(tracks, { yPercent: next ? -50 : 0 });
|
|
3427
|
+
else animation = gsap.to(tracks, { yPercent: next ? -50 : 0, duration, stagger, ease: "power3.out", overwrite: true });
|
|
3428
|
+
};
|
|
3429
|
+
scope.on(root, "mouseenter", () => {
|
|
3430
|
+
hovered = true;
|
|
3431
|
+
setActive(true);
|
|
3432
|
+
});
|
|
3433
|
+
scope.on(root, "mouseleave", () => {
|
|
3434
|
+
hovered = false;
|
|
3435
|
+
setActive(focused);
|
|
3436
|
+
});
|
|
3437
|
+
scope.on(root, "focusin", () => {
|
|
3438
|
+
focused = true;
|
|
3439
|
+
setActive(true);
|
|
3440
|
+
});
|
|
3441
|
+
scope.on(root, "focusout", (event) => {
|
|
3442
|
+
if (event.relatedTarget instanceof Node && root.contains(event.relatedTarget)) return;
|
|
3443
|
+
focused = false;
|
|
3444
|
+
setActive(hovered);
|
|
3445
|
+
});
|
|
3446
|
+
scope.add(() => animation?.kill());
|
|
3447
|
+
return { play: () => setActive(true), reset: () => setActive(false), get active() {
|
|
3448
|
+
return active;
|
|
3449
|
+
}, destroy: () => scope.dispose() };
|
|
3450
|
+
}
|
|
3451
|
+
|
|
3452
|
+
// src/recipes/thumbnail-nav/create-thumbnail-nav.ts
|
|
3453
|
+
var panelSequence = 0;
|
|
3454
|
+
function createThumbnailNav(root, options = {}) {
|
|
3455
|
+
const items = root ? [...root.querySelectorAll("[data-mk-thumbnail-item]")] : [];
|
|
3456
|
+
if (!root || !items.length || typeof document === "undefined") return inert({ open() {
|
|
3457
|
+
}, close() {
|
|
3458
|
+
}, toggle() {
|
|
3459
|
+
}, select() {
|
|
3460
|
+
}, index: 0, expanded: false });
|
|
3461
|
+
registerMotion();
|
|
3462
|
+
const scope = createScope();
|
|
3463
|
+
const original = [...root.childNodes];
|
|
3464
|
+
const duration = Math.max(0, options.duration ?? 0.5);
|
|
3465
|
+
const disabled = (item) => item.matches(':disabled, [aria-disabled="true"]');
|
|
3466
|
+
const name = (item) => item.dataset.mkLabel ?? item.textContent?.trim() ?? "";
|
|
3467
|
+
let index = 0;
|
|
3468
|
+
let expanded = false;
|
|
3469
|
+
let animation;
|
|
3470
|
+
const button = document.createElement("button");
|
|
3471
|
+
button.type = "button";
|
|
3472
|
+
button.className = "mk-thumbnail-nav__toggle";
|
|
3473
|
+
button.setAttribute("aria-expanded", "false");
|
|
3474
|
+
const preview = document.createElement("span");
|
|
3475
|
+
preview.className = "mk-thumbnail-nav__preview";
|
|
3476
|
+
preview.setAttribute("aria-hidden", "true");
|
|
3477
|
+
const copy = document.createElement("span");
|
|
3478
|
+
copy.className = "mk-thumbnail-nav__copy";
|
|
3479
|
+
const kicker = document.createElement("span");
|
|
3480
|
+
kicker.className = "mk-thumbnail-nav__kicker";
|
|
3481
|
+
kicker.textContent = options.label ?? root.dataset.mkLabel ?? "Categor\xEDa";
|
|
3482
|
+
const label = document.createElement("span");
|
|
3483
|
+
label.className = "mk-thumbnail-nav__label";
|
|
3484
|
+
copy.append(kicker, label);
|
|
3485
|
+
const arrow = document.createElement("span");
|
|
3486
|
+
arrow.className = "mk-thumbnail-nav__chevron";
|
|
3487
|
+
arrow.setAttribute("aria-hidden", "true");
|
|
3488
|
+
arrow.textContent = "\u2304";
|
|
3489
|
+
button.append(preview, copy, arrow);
|
|
3490
|
+
const panel = document.createElement("div");
|
|
3491
|
+
panel.className = "mk-thumbnail-nav__panel";
|
|
3492
|
+
panel.id = `mk-thumbnail-panel-${++panelSequence}`;
|
|
3493
|
+
while (document.getElementById(panel.id)) panel.id = `mk-thumbnail-panel-${++panelSequence}`;
|
|
3494
|
+
panel.hidden = true;
|
|
3495
|
+
panel.inert = true;
|
|
3496
|
+
button.setAttribute("aria-controls", panel.id);
|
|
3497
|
+
panel.append(...original);
|
|
3498
|
+
root.replaceChildren(button, panel);
|
|
3499
|
+
scope.add(() => root.replaceChildren(...original));
|
|
3500
|
+
scope.attr(root, "class", `${root.className} mk-thumbnail-nav`.trim());
|
|
3501
|
+
scope.attr(root, "style", root.getAttribute("style"));
|
|
3502
|
+
root.style.setProperty("--mk-thumbnail-nav-duration", `${duration}s`);
|
|
3503
|
+
scope.attr(root, "data-mk-ready", "");
|
|
3504
|
+
const updatePreview = () => {
|
|
3505
|
+
label.textContent = name(items[index]);
|
|
3506
|
+
button.setAttribute("aria-label", `${kicker.textContent}: ${label.textContent}`);
|
|
3507
|
+
preview.replaceChildren();
|
|
3508
|
+
for (let offset = 0; offset < Math.min(3, items.length); offset++) {
|
|
3509
|
+
const item = items[wrap(index + offset, items.length)];
|
|
3510
|
+
const thumb = document.createElement("span");
|
|
3511
|
+
thumb.className = "mk-thumbnail-nav__thumb";
|
|
3512
|
+
thumb.style.setProperty("--mk-thumbnail-order", String(offset));
|
|
3513
|
+
const source = item.querySelector("img");
|
|
3514
|
+
if (source) {
|
|
3515
|
+
const image = source.cloneNode(false);
|
|
3516
|
+
image.removeAttribute("id");
|
|
3517
|
+
image.alt = "";
|
|
3518
|
+
thumb.append(image);
|
|
3519
|
+
} else thumb.textContent = name(item).slice(0, 1);
|
|
3520
|
+
preview.append(thumb);
|
|
3521
|
+
}
|
|
3522
|
+
};
|
|
3523
|
+
const focusItem = (candidate, direction = 1) => {
|
|
3524
|
+
for (let attempt = 0; attempt < items.length; attempt++) {
|
|
3525
|
+
const current = items[wrap(candidate, items.length)];
|
|
3526
|
+
if (!disabled(current)) {
|
|
3527
|
+
current.focus();
|
|
3528
|
+
return;
|
|
3529
|
+
}
|
|
3530
|
+
candidate += direction;
|
|
3531
|
+
}
|
|
3532
|
+
};
|
|
3533
|
+
const close = (restoreFocus = panel.contains(document.activeElement)) => {
|
|
3534
|
+
if (scope.disposed || !expanded) return;
|
|
3535
|
+
expanded = false;
|
|
3536
|
+
button.setAttribute("aria-expanded", "false");
|
|
3537
|
+
scope.attr(root, "data-mk-expanded", null);
|
|
3538
|
+
panel.inert = true;
|
|
3539
|
+
animation?.kill();
|
|
3540
|
+
if (restoreFocus) button.focus();
|
|
3541
|
+
if (reduced() || duration === 0) panel.hidden = true;
|
|
3542
|
+
else animation = gsap.to(panel, { autoAlpha: 0, y: 10, scale: 0.98, duration: duration * 0.6, ease: "power3.out", overwrite: true, onComplete: () => {
|
|
3543
|
+
panel.hidden = true;
|
|
3544
|
+
} });
|
|
3545
|
+
};
|
|
3546
|
+
const open = () => {
|
|
3547
|
+
if (scope.disposed || expanded) return;
|
|
3548
|
+
expanded = true;
|
|
3549
|
+
panel.hidden = false;
|
|
3550
|
+
panel.inert = false;
|
|
3551
|
+
button.setAttribute("aria-expanded", "true");
|
|
3552
|
+
scope.attr(root, "data-mk-expanded", "");
|
|
3553
|
+
animation?.kill();
|
|
3554
|
+
if (reduced() || duration === 0) gsap.set(panel, { autoAlpha: 1, y: 0, scale: 1 });
|
|
3555
|
+
else animation = gsap.fromTo(panel, { autoAlpha: 0, y: 12, scale: 0.96 }, { autoAlpha: 1, y: 0, scale: 1, duration, ease: "power3.out", overwrite: true });
|
|
3556
|
+
};
|
|
3557
|
+
const select = (next, notify = true) => {
|
|
3558
|
+
if (scope.disposed || !Number.isFinite(next)) return false;
|
|
3559
|
+
const candidate = wrap(Math.round(next), items.length);
|
|
3560
|
+
const item = items[candidate];
|
|
3561
|
+
if (disabled(item)) return false;
|
|
3562
|
+
if (notify && !root.dispatchEvent(new CustomEvent("mk:select", { bubbles: true, cancelable: true, detail: { index: candidate, item } }))) return false;
|
|
3563
|
+
index = candidate;
|
|
3564
|
+
items.forEach((entry, position) => scope.attr(entry, "aria-current", position === index ? "page" : null));
|
|
3565
|
+
updatePreview();
|
|
3566
|
+
if (notify) options.onSelect?.(index, item);
|
|
3567
|
+
return true;
|
|
3568
|
+
};
|
|
3569
|
+
scope.on(button, "click", () => {
|
|
3570
|
+
if (expanded) close();
|
|
3571
|
+
else open();
|
|
3572
|
+
});
|
|
3573
|
+
scope.on(root, "click", (event) => {
|
|
3574
|
+
const item = event.target.closest("[data-mk-thumbnail-item]");
|
|
3575
|
+
if (!item || !items.includes(item)) return;
|
|
3576
|
+
if (!select(items.indexOf(item))) {
|
|
3577
|
+
event.preventDefault();
|
|
3578
|
+
return;
|
|
3579
|
+
}
|
|
3580
|
+
close(true);
|
|
3581
|
+
});
|
|
3582
|
+
scope.on(root, "keydown", (event) => {
|
|
3583
|
+
if (event.key === "Escape" && expanded) {
|
|
3584
|
+
event.preventDefault();
|
|
3585
|
+
event.stopPropagation();
|
|
3586
|
+
close(true);
|
|
3587
|
+
return;
|
|
3588
|
+
}
|
|
3589
|
+
const current = items.indexOf(document.activeElement);
|
|
3590
|
+
const onTrigger = document.activeElement === button;
|
|
3591
|
+
const direction = event.key === "ArrowDown" || event.key === "ArrowRight" ? 1 : event.key === "ArrowUp" || event.key === "ArrowLeft" ? -1 : 0;
|
|
3592
|
+
if (!direction && event.key !== "Home" && event.key !== "End" || !onTrigger && current < 0) return;
|
|
3593
|
+
event.preventDefault();
|
|
3594
|
+
open();
|
|
3595
|
+
const candidate = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : onTrigger ? index : current + direction;
|
|
3596
|
+
focusItem(candidate, event.key === "End" ? -1 : direction || 1);
|
|
3597
|
+
});
|
|
3598
|
+
scope.on(root, "focusout", (event) => {
|
|
3599
|
+
if (event.relatedTarget instanceof Node && root.contains(event.relatedTarget)) return;
|
|
3600
|
+
scope.timeout(() => {
|
|
3601
|
+
if (!scope.disposed && !root.contains(document.activeElement)) close(false);
|
|
3602
|
+
}, 0);
|
|
3603
|
+
});
|
|
3604
|
+
scope.on(document, "pointerdown", (event) => {
|
|
3605
|
+
if (event.target instanceof Node && !root.contains(event.target)) close(false);
|
|
3606
|
+
});
|
|
3607
|
+
scope.add(() => animation?.kill());
|
|
3608
|
+
const initial = options.index ?? Math.max(0, items.findIndex((item) => item.getAttribute("aria-current") === "page"));
|
|
3609
|
+
const enabled = items.findIndex((item) => !disabled(item));
|
|
3610
|
+
if (!select(initial, false)) {
|
|
3611
|
+
if (enabled >= 0) select(enabled, false);
|
|
3612
|
+
else {
|
|
3613
|
+
updatePreview();
|
|
3614
|
+
button.disabled = true;
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
return { open, close: () => close(), toggle: () => {
|
|
3618
|
+
if (expanded) close();
|
|
3619
|
+
else open();
|
|
3620
|
+
}, select: (next) => {
|
|
3621
|
+
select(next);
|
|
3622
|
+
}, get index() {
|
|
3623
|
+
return index;
|
|
3624
|
+
}, get expanded() {
|
|
3625
|
+
return expanded;
|
|
3626
|
+
}, destroy: () => scope.dispose() };
|
|
3627
|
+
}
|
|
3628
|
+
|
|
3629
|
+
// src/recipes/action-button/create-action-button.ts
|
|
3630
|
+
function createActionButton(root, options = {}) {
|
|
3631
|
+
if (!root) return inert({ setPressed() {
|
|
3632
|
+
}, pressed: false });
|
|
3633
|
+
const scope = createScope();
|
|
3634
|
+
const variant = options.variant ?? root.getAttribute("data-mk-action-variant") ?? "primary";
|
|
3635
|
+
scope.attr(root, "data-mk-action-variant", variant);
|
|
3636
|
+
scope.attr(root, "data-mk-action-ready", "");
|
|
3637
|
+
const label = root.querySelector("[data-mk-action-label]");
|
|
3638
|
+
if (label && variant === "film") {
|
|
3639
|
+
const nodes = [...label.childNodes];
|
|
3640
|
+
const line = document.createElement("span");
|
|
3641
|
+
line.className = "mk-action-button__line";
|
|
3642
|
+
line.append(...nodes);
|
|
3643
|
+
const copy = document.createElement("span");
|
|
3644
|
+
copy.className = "mk-action-button__copy";
|
|
3645
|
+
copy.setAttribute("aria-hidden", "true");
|
|
3646
|
+
copy.textContent = line.textContent;
|
|
3647
|
+
label.append(line, copy);
|
|
3648
|
+
scope.add(() => {
|
|
3649
|
+
label.replaceChildren(...nodes);
|
|
3650
|
+
});
|
|
3651
|
+
}
|
|
3652
|
+
let pressed = options.pressed ?? root.getAttribute("aria-pressed") === "true";
|
|
3653
|
+
if (options.toggle || options.pressed !== void 0) scope.attr(root, "aria-pressed", String(pressed));
|
|
3654
|
+
const setPressed = (next) => {
|
|
3655
|
+
if (scope.disposed || next === pressed) return;
|
|
3656
|
+
pressed = next;
|
|
3657
|
+
scope.attr(root, "aria-pressed", String(pressed));
|
|
3658
|
+
options.onPressedChange?.(pressed);
|
|
3659
|
+
root.dispatchEvent(new CustomEvent("mk:action-change", { bubbles: true, detail: { pressed } }));
|
|
3660
|
+
};
|
|
3661
|
+
scope.on(root, "click", (event) => {
|
|
3662
|
+
if (event.defaultPrevented) return;
|
|
3663
|
+
if (root.hasAttribute("disabled") || root.getAttribute("aria-disabled") === "true") {
|
|
3664
|
+
event.preventDefault();
|
|
3665
|
+
return;
|
|
3666
|
+
}
|
|
3667
|
+
if (options.toggle) setPressed(!pressed);
|
|
3668
|
+
});
|
|
3669
|
+
return { setPressed, get pressed() {
|
|
3670
|
+
return pressed;
|
|
3671
|
+
}, destroy: () => scope.dispose() };
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
// src/recipes/film-hero/create-film-hero.ts
|
|
3675
|
+
function createFilmHero(root, options = {}) {
|
|
3676
|
+
if (!root) return inert({ replay() {
|
|
3677
|
+
}, refresh() {
|
|
3678
|
+
} });
|
|
3679
|
+
const scope = createScope();
|
|
3680
|
+
scope.attr(root, "data-mk-film-ready", "");
|
|
3681
|
+
scope.attr(root, "data-mk-film-edge", options.edge ?? "organic");
|
|
3682
|
+
scope.attr(root, "style", root.getAttribute("style"));
|
|
3683
|
+
const still = reduced();
|
|
3684
|
+
const lines = [...root.querySelectorAll("[data-mk-film-line]")];
|
|
3685
|
+
const rules = [...root.querySelectorAll("[data-mk-film-rule]")];
|
|
3686
|
+
[...lines, ...rules].forEach((element) => scope.attr(element, "style", element.getAttribute("style")));
|
|
3687
|
+
let timeline = null;
|
|
3688
|
+
const context = gsap.context(() => {
|
|
3689
|
+
}, root);
|
|
3690
|
+
const replay = () => {
|
|
3691
|
+
if (scope.disposed || !entrances()) return;
|
|
3692
|
+
registerMotion();
|
|
3693
|
+
context.add(() => {
|
|
3694
|
+
timeline?.kill();
|
|
3695
|
+
timeline = gsap.timeline();
|
|
3696
|
+
if (lines.length) timeline.fromTo(lines, { yPercent: 120 }, { yPercent: 0, duration: options.duration ?? 0.7, stagger: options.stagger ?? 0.08, ease: "power3.out" }, 0);
|
|
3697
|
+
if (rules.length) timeline.fromTo(rules, { scaleX: 0, transformOrigin: "left center" }, { scaleX: 1, duration: 0.9, stagger: 0.06, ease: "power3.out" }, 0.08);
|
|
3698
|
+
});
|
|
3699
|
+
};
|
|
3700
|
+
replay();
|
|
3701
|
+
const scroller = options.scroller ?? root.closest("[data-mk-scroll-root]") ?? window;
|
|
3702
|
+
let frame = 0;
|
|
3703
|
+
const refresh = () => {
|
|
3704
|
+
if (scope.disposed || still) return;
|
|
3705
|
+
const rect = root.getBoundingClientRect();
|
|
3706
|
+
const view = scroller instanceof HTMLElement ? scroller.getBoundingClientRect() : { top: 0, height: window.innerHeight };
|
|
3707
|
+
const progress = Math.max(0, Math.min(1, (view.top - rect.top) / Math.max(1, rect.height)));
|
|
3708
|
+
root.style.setProperty("--mk-film-shift", `${(progress * rect.height * (options.parallax ?? 0.12)).toFixed(2)}px`);
|
|
3709
|
+
root.style.setProperty("--mk-film-scale", String((options.scale ?? 1.08) - progress * Math.max(0, (options.scale ?? 1.08) - 1)));
|
|
3710
|
+
};
|
|
3711
|
+
if (!still) {
|
|
3712
|
+
const schedule = () => {
|
|
3713
|
+
if (frame) return;
|
|
3714
|
+
frame = requestAnimationFrame(() => {
|
|
3715
|
+
frame = 0;
|
|
3716
|
+
refresh();
|
|
3717
|
+
});
|
|
3718
|
+
};
|
|
3719
|
+
scope.on(scroller, "scroll", schedule, { passive: true });
|
|
3720
|
+
scope.on(window, "resize", schedule, { passive: true });
|
|
3721
|
+
if (typeof ResizeObserver === "function") scope.observe(new ResizeObserver(schedule)).observe(root);
|
|
3722
|
+
scope.add(() => cancelAnimationFrame(frame));
|
|
3723
|
+
refresh();
|
|
3724
|
+
}
|
|
3725
|
+
scope.add(() => {
|
|
3726
|
+
timeline?.kill();
|
|
3727
|
+
context.revert();
|
|
3728
|
+
});
|
|
3729
|
+
return { replay, refresh, destroy: () => scope.dispose() };
|
|
3730
|
+
}
|
|
3731
|
+
|
|
3732
|
+
// src/recipes/editorial-reveal/create-editorial-reveal.ts
|
|
3733
|
+
var nextScope = 0;
|
|
3734
|
+
function createEditorialReveal(root, options = {}) {
|
|
3735
|
+
if (!root) return inert({ play() {
|
|
3736
|
+
}, reset() {
|
|
3737
|
+
} });
|
|
3738
|
+
registerMotion();
|
|
3739
|
+
const scope = createScope();
|
|
3740
|
+
const context = gsap.context(() => {
|
|
3741
|
+
}, root);
|
|
3742
|
+
const trigger = options.trigger ?? "scroll";
|
|
3743
|
+
const duration = options.duration ?? 1.2;
|
|
3744
|
+
const stagger = options.stagger ?? 0.03;
|
|
3745
|
+
const hoverDuration = options.hoverDuration ?? 0.5;
|
|
3746
|
+
const ease = options.ease ?? "mk-editorial-reference";
|
|
3747
|
+
CustomEase.create("mk-editorial-reference", "M0,0 C0.6,0 0,1 1,1");
|
|
3748
|
+
const preserve = (el) => ["style", "data-mk-ready", "aria-label"].forEach((name) => scope.attr(el, name, el.getAttribute(name)));
|
|
3749
|
+
preserve(root);
|
|
3750
|
+
root.querySelectorAll("[data-mk-editorial-title],[data-mk-editorial-group],[data-mk-cascade],[data-mk-editorial-image],[data-mk-parallax-target],[data-mk-editorial-header],[data-mk-editorial-card-image],[data-mk-editorial-button-content]").forEach(preserve);
|
|
3751
|
+
const titles = [...root.querySelectorAll("[data-mk-editorial-title]")].map((el) => createMaskText(el, { by: "lines", trigger, once: true, y: options.y ?? 110, duration, stagger, ease, delay: 0 }));
|
|
3752
|
+
const groups = [...root.querySelectorAll("[data-mk-editorial-group]")].map((el) => createCascade(el, { trigger, duration, step: stagger, once: true }));
|
|
3753
|
+
const images = options.parallax === false ? [] : [...root.querySelectorAll("[data-mk-editorial-image]")].map((el) => createParallax(el, { amount: 0.25 }));
|
|
3754
|
+
const header = root.querySelector("[data-mk-editorial-header]");
|
|
3755
|
+
const sections = [...root.querySelectorAll("[data-mk-tone]")];
|
|
3756
|
+
const scopeId = String(++nextScope);
|
|
3757
|
+
sections.forEach((el) => scope.attr(el, "data-mk-editorial-scope", scopeId));
|
|
3758
|
+
const contrast = header ? createContrast(header, { sections: `[data-mk-editorial-scope="${scopeId}"]` }) : null;
|
|
3759
|
+
scope.add(() => {
|
|
3760
|
+
titles.forEach((instance) => instance.destroy());
|
|
3761
|
+
groups.forEach((instance) => instance.destroy());
|
|
3762
|
+
images.forEach((instance) => instance.destroy());
|
|
3763
|
+
contrast?.destroy();
|
|
3764
|
+
context.revert();
|
|
3765
|
+
});
|
|
3766
|
+
root.querySelectorAll("[data-mk-editorial-button]").forEach((button) => {
|
|
3767
|
+
const content = button.querySelector("[data-mk-editorial-button-content]");
|
|
3768
|
+
if (!content) return;
|
|
3769
|
+
let pointerInside = false;
|
|
3770
|
+
const render = () => {
|
|
3771
|
+
const active = pointerInside || button.contains(root.ownerDocument.activeElement);
|
|
3772
|
+
context.add(() => gsap.to(content, { x: active && !reduced() ? `${options.buttonShift ?? 2.25}em` : "0em", duration: reduced() ? 0 : hoverDuration, ease, overwrite: true }));
|
|
3773
|
+
};
|
|
3774
|
+
scope.on(button, "pointerenter", () => {
|
|
3775
|
+
pointerInside = true;
|
|
3776
|
+
render();
|
|
3777
|
+
});
|
|
3778
|
+
scope.on(button, "pointerleave", () => {
|
|
3779
|
+
pointerInside = false;
|
|
3780
|
+
render();
|
|
3781
|
+
});
|
|
3782
|
+
scope.on(button, "focusin", render);
|
|
3783
|
+
scope.on(button, "focusout", () => {
|
|
3784
|
+
scope.timeout(render, 0);
|
|
3785
|
+
});
|
|
3786
|
+
});
|
|
3787
|
+
const cursor = root.querySelector("[data-mk-editorial-cursor]");
|
|
3788
|
+
if (cursor) {
|
|
3789
|
+
preserve(cursor);
|
|
3790
|
+
scope.attr(cursor, "aria-hidden", "true");
|
|
3791
|
+
scope.attr(cursor, "hidden", "");
|
|
3792
|
+
}
|
|
3793
|
+
root.querySelectorAll("[data-mk-editorial-card]").forEach((card) => {
|
|
3794
|
+
const image = card.querySelector("[data-mk-editorial-card-image]");
|
|
3795
|
+
let pointerInside = false;
|
|
3796
|
+
const render = () => {
|
|
3797
|
+
const active = pointerInside || card.contains(root.ownerDocument.activeElement);
|
|
3798
|
+
scope.attr(card, "data-mk-editorial-active", active ? "" : null);
|
|
3799
|
+
if (image) context.add(() => gsap.to(image, { scale: active && !reduced() ? options.imageScale ?? 1.04 : 1, duration: reduced() ? 0 : hoverDuration, ease, overwrite: true }));
|
|
3800
|
+
};
|
|
3801
|
+
scope.on(card, "pointerenter", (event) => {
|
|
3802
|
+
pointerInside = true;
|
|
3803
|
+
render();
|
|
3804
|
+
if (cursor && !reduced() && event.pointerType !== "touch") scope.attr(cursor, "hidden", null);
|
|
3805
|
+
});
|
|
3806
|
+
scope.on(card, "pointerleave", () => {
|
|
3807
|
+
pointerInside = false;
|
|
3808
|
+
render();
|
|
3809
|
+
if (cursor) scope.attr(cursor, "hidden", "");
|
|
3810
|
+
});
|
|
3811
|
+
scope.on(card, "pointermove", (event) => {
|
|
3812
|
+
if (!cursor || reduced() || event.pointerType === "touch") return;
|
|
3813
|
+
const rect = root.getBoundingClientRect();
|
|
3814
|
+
cursor.style.transform = `translate(${event.clientX - rect.left + 16}px, ${event.clientY - rect.top + 16}px)`;
|
|
3815
|
+
});
|
|
3816
|
+
scope.on(card, "focusin", render);
|
|
3817
|
+
scope.on(card, "focusout", () => {
|
|
3818
|
+
scope.timeout(render, 0);
|
|
3819
|
+
});
|
|
3820
|
+
});
|
|
3821
|
+
scope.attr(root, "data-mk-ready", "");
|
|
3822
|
+
return {
|
|
3823
|
+
play() {
|
|
3824
|
+
if (!scope.disposed) {
|
|
3825
|
+
titles.forEach((instance) => instance.play());
|
|
3826
|
+
groups.forEach((instance) => instance.play());
|
|
3827
|
+
}
|
|
3828
|
+
},
|
|
3829
|
+
reset() {
|
|
3830
|
+
if (!scope.disposed) {
|
|
3831
|
+
titles.forEach((instance) => instance.hide());
|
|
3832
|
+
groups.forEach((instance) => instance.reset());
|
|
3833
|
+
}
|
|
3834
|
+
},
|
|
3835
|
+
destroy() {
|
|
3836
|
+
scope.dispose();
|
|
3837
|
+
}
|
|
3838
|
+
};
|
|
3839
|
+
}
|
|
3840
|
+
|
|
3841
|
+
// src/recipes/weight-hover/create-weight-hover.ts
|
|
3842
|
+
var FAR = -1e5;
|
|
3843
|
+
function createWeightHover(root, options = {}) {
|
|
3844
|
+
if (!root) return inert({ pointAt() {
|
|
3845
|
+
} });
|
|
3846
|
+
const scope = createScope();
|
|
3847
|
+
scope.attr(root, "data-mk-ready", "");
|
|
3848
|
+
if (reduced()) return { pointAt() {
|
|
3849
|
+
}, destroy: () => scope.dispose() };
|
|
3850
|
+
const num = (value, fallback) => Number.isFinite(value) ? value : fallback;
|
|
3851
|
+
const rest = num(options.rest, 900);
|
|
3852
|
+
const near = num(options.near, 200);
|
|
3853
|
+
const radius = Math.max(1, num(options.radius, 400));
|
|
3854
|
+
const lerp = Math.min(1, Math.max(0.01, num(options.lerp, 0.1)));
|
|
3855
|
+
const axis = /^[A-Za-z]{4}$/.test(options.axis ?? "") ? options.axis : "wght";
|
|
3856
|
+
const setting = (value) => `"${axis}" ${value.toFixed(1)}`;
|
|
3857
|
+
const original = [...root.childNodes];
|
|
3858
|
+
const copy = document.createElement("span");
|
|
3859
|
+
copy.className = "mk-sr-only";
|
|
3860
|
+
const spoken = root.cloneNode(true);
|
|
3861
|
+
spoken.querySelectorAll("br").forEach((br) => br.replaceWith(" "));
|
|
3862
|
+
copy.textContent = spoken.textContent?.replace(/\s+/g, " ").trim() ?? "";
|
|
3863
|
+
const visual = document.createElement("span");
|
|
3864
|
+
visual.className = "mk-weight-hover__visual";
|
|
3865
|
+
visual.setAttribute("aria-hidden", "true");
|
|
3866
|
+
visual.append(...original.map((node) => node.cloneNode(true)));
|
|
3867
|
+
const letters2 = [];
|
|
3868
|
+
const walker = document.createTreeWalker(visual, NodeFilter.SHOW_TEXT);
|
|
3869
|
+
const texts = [];
|
|
3870
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) texts.push(node);
|
|
3871
|
+
for (const text of texts) {
|
|
3872
|
+
const fragment = document.createDocumentFragment();
|
|
3873
|
+
for (const char of text.data) {
|
|
3874
|
+
if (/\s/.test(char)) {
|
|
3875
|
+
fragment.append(char);
|
|
3876
|
+
continue;
|
|
3877
|
+
}
|
|
3878
|
+
const span = document.createElement("span");
|
|
3879
|
+
span.dataset.mkWeightChar = "";
|
|
3880
|
+
span.textContent = char;
|
|
3881
|
+
span.style.fontVariationSettings = setting(rest);
|
|
3882
|
+
fragment.append(span);
|
|
3883
|
+
letters2.push({ span, value: rest, x: 0, y: 0 });
|
|
3884
|
+
}
|
|
3885
|
+
text.replaceWith(fragment);
|
|
3886
|
+
}
|
|
3887
|
+
root.replaceChildren(copy, visual);
|
|
3888
|
+
scope.add(() => root.replaceChildren(...original));
|
|
3889
|
+
const measure = () => {
|
|
3890
|
+
const box = root.getBoundingClientRect();
|
|
3891
|
+
for (const letter of letters2) {
|
|
3892
|
+
const r = letter.span.getBoundingClientRect();
|
|
3893
|
+
letter.x = r.left + r.width / 2 - box.left;
|
|
3894
|
+
letter.y = r.top + r.height / 2 - box.top;
|
|
3895
|
+
}
|
|
3896
|
+
};
|
|
3897
|
+
measure();
|
|
3898
|
+
if (typeof ResizeObserver === "function") scope.observe(new ResizeObserver(measure)).observe(root);
|
|
3899
|
+
document.fonts?.ready.then(() => {
|
|
3900
|
+
if (!scope.disposed) measure();
|
|
3901
|
+
});
|
|
3902
|
+
const pointer2 = { x: FAR, y: FAR };
|
|
3903
|
+
let frame = 0;
|
|
3904
|
+
const tick = () => {
|
|
3905
|
+
frame = 0;
|
|
3906
|
+
if (scope.disposed) return;
|
|
3907
|
+
const box = root.getBoundingClientRect();
|
|
3908
|
+
let moving = false;
|
|
3909
|
+
for (const letter of letters2) {
|
|
3910
|
+
const distance = Math.hypot(pointer2.x - (box.left + letter.x), pointer2.y - (box.top + letter.y));
|
|
3911
|
+
const d = Math.max(0, 1 - distance / radius);
|
|
3912
|
+
const target = rest + (near - rest) * d * d * (3 - 2 * d);
|
|
3913
|
+
letter.value += (target - letter.value) * lerp;
|
|
3914
|
+
if (Math.abs(target - letter.value) > 0.5) moving = true;
|
|
3915
|
+
else letter.value = target;
|
|
3916
|
+
letter.span.style.fontVariationSettings = setting(letter.value);
|
|
3917
|
+
}
|
|
3918
|
+
if (moving) frame = requestAnimationFrame(tick);
|
|
3919
|
+
};
|
|
3920
|
+
const wake = () => {
|
|
3921
|
+
if (!frame && !scope.disposed) frame = requestAnimationFrame(tick);
|
|
3922
|
+
};
|
|
3923
|
+
scope.add(() => cancelAnimationFrame(frame));
|
|
3924
|
+
scope.on(window, "pointermove", (event) => {
|
|
3925
|
+
const e = event;
|
|
3926
|
+
if (!options.anyPointer && e.pointerType && e.pointerType !== "mouse") return;
|
|
3927
|
+
pointer2.x = e.clientX;
|
|
3928
|
+
pointer2.y = e.clientY;
|
|
3929
|
+
wake();
|
|
3930
|
+
}, { passive: true });
|
|
3931
|
+
scope.on(document, "pointerleave", () => {
|
|
3932
|
+
pointer2.x = pointer2.y = FAR;
|
|
3933
|
+
wake();
|
|
3934
|
+
});
|
|
3935
|
+
return {
|
|
3936
|
+
pointAt(point) {
|
|
3937
|
+
if (scope.disposed) return;
|
|
3938
|
+
pointer2.x = point ? point.x : FAR;
|
|
3939
|
+
pointer2.y = point ? point.y : FAR;
|
|
3940
|
+
wake();
|
|
3941
|
+
},
|
|
3942
|
+
destroy: () => scope.dispose()
|
|
3943
|
+
};
|
|
3944
|
+
}
|
|
3945
|
+
|
|
3946
|
+
// src/recipes/sticker/create-sticker.ts
|
|
3947
|
+
var easeOutCubic = (t) => 1 - (1 - t) ** 3;
|
|
3948
|
+
var clamp2 = (v, min, max) => Math.min(max, Math.max(min, v));
|
|
3949
|
+
function clipHalfPlane(poly, m, n) {
|
|
3950
|
+
const side = (p) => (p.x - m.x) * n.x + (p.y - m.y) * n.y;
|
|
3951
|
+
const out = [];
|
|
3952
|
+
for (let i = 0; i < poly.length; i++) {
|
|
3953
|
+
const a = poly[i];
|
|
3954
|
+
const b = poly[(i + 1) % poly.length];
|
|
3955
|
+
const sa = side(a);
|
|
3956
|
+
const sb = side(b);
|
|
3957
|
+
if (sa >= 0) out.push(a);
|
|
3958
|
+
if (sa >= 0 !== sb >= 0) {
|
|
3959
|
+
const t = sa / (sa - sb);
|
|
3960
|
+
out.push({ x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t });
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
return out;
|
|
3964
|
+
}
|
|
3965
|
+
var area = (poly) => {
|
|
3966
|
+
let sum = 0;
|
|
3967
|
+
for (let i = 0; i < poly.length; i++) {
|
|
3968
|
+
const a = poly[i];
|
|
3969
|
+
const b = poly[(i + 1) % poly.length];
|
|
3970
|
+
sum += a.x * b.y - b.x * a.y;
|
|
3971
|
+
}
|
|
3972
|
+
return Math.abs(sum) / 2;
|
|
3973
|
+
};
|
|
3974
|
+
var polygon = (poly) => poly.length < 3 ? "polygon(0 0, 0 0, 0 0)" : `polygon(${poly.map((p) => `${p.x.toFixed(2)}px ${p.y.toFixed(2)}px`).join(", ")})`;
|
|
3975
|
+
function createSticker(root, options = {}) {
|
|
3976
|
+
if (!root) return inert({ state: "idle" });
|
|
3977
|
+
const scope = createScope();
|
|
3978
|
+
const still = reduced();
|
|
3979
|
+
const detachAt = clamp2(Number.isFinite(options.detachAt) ? options.detachAt : 0.3, 0.05, 1);
|
|
3980
|
+
const returnDelay = Math.max(0, Number.isFinite(options.returnDelay) ? options.returnDelay : 2500);
|
|
3981
|
+
let state = "idle";
|
|
3982
|
+
const frames = /* @__PURE__ */ new Set();
|
|
3983
|
+
const raf = (fn) => {
|
|
3984
|
+
const id = requestAnimationFrame((time) => {
|
|
3985
|
+
frames.delete(id);
|
|
3986
|
+
fn(time);
|
|
3987
|
+
});
|
|
3988
|
+
frames.add(id);
|
|
3989
|
+
};
|
|
3990
|
+
scope.add(() => {
|
|
3991
|
+
frames.forEach(cancelAnimationFrame);
|
|
3992
|
+
frames.clear();
|
|
3993
|
+
});
|
|
3994
|
+
scope.attr(root, "data-mk-ready", "");
|
|
3995
|
+
scope.attr(root, "style", root.getAttribute("style"));
|
|
3996
|
+
if (options.holo !== false) scope.attr(root, "data-mk-holo", "");
|
|
3997
|
+
const original = [...root.childNodes];
|
|
3998
|
+
const peelBox = document.createElement("div");
|
|
3999
|
+
peelBox.className = "mk-sticker__peel";
|
|
4000
|
+
const top = document.createElement("div");
|
|
4001
|
+
top.className = "mk-sticker__top";
|
|
4002
|
+
top.append(...original);
|
|
4003
|
+
peelBox.append(top);
|
|
4004
|
+
root.append(peelBox);
|
|
4005
|
+
scope.add(() => root.replaceChildren(...original));
|
|
4006
|
+
let back = null;
|
|
4007
|
+
if (options.holo !== false) {
|
|
4008
|
+
const holo = { x: 0.5, y: 0.5 };
|
|
4009
|
+
let mouse = null;
|
|
4010
|
+
let visible = typeof IntersectionObserver !== "function";
|
|
4011
|
+
const hoverless = typeof matchMedia === "function" && matchMedia("(hover: none)").matches;
|
|
4012
|
+
root.style.setProperty("--mk-sticker-x", "0.5");
|
|
4013
|
+
root.style.setProperty("--mk-sticker-y", "0.5");
|
|
4014
|
+
if (!still) {
|
|
4015
|
+
scope.on(window, "pointermove", (event) => {
|
|
4016
|
+
const e = event;
|
|
4017
|
+
if (e.pointerType === "mouse") mouse = { x: e.clientX, y: e.clientY };
|
|
4018
|
+
}, { passive: true });
|
|
4019
|
+
scope.on(document, "pointerleave", () => {
|
|
4020
|
+
mouse = null;
|
|
4021
|
+
});
|
|
4022
|
+
if (typeof IntersectionObserver === "function") {
|
|
4023
|
+
scope.observe(new IntersectionObserver(([entry]) => {
|
|
4024
|
+
const was = visible;
|
|
4025
|
+
visible = entry.isIntersecting;
|
|
4026
|
+
if (visible && !was) raf(loop);
|
|
4027
|
+
})).observe(root);
|
|
4028
|
+
}
|
|
4029
|
+
const loop = (time) => {
|
|
4030
|
+
if (scope.disposed || !visible) return;
|
|
4031
|
+
const box = top.getBoundingClientRect();
|
|
4032
|
+
let x;
|
|
4033
|
+
let y;
|
|
4034
|
+
if (mouse && !hoverless && box.width && box.height) {
|
|
4035
|
+
x = clamp2((mouse.x - box.left) / box.width, -0.5, 1.5);
|
|
4036
|
+
y = clamp2((mouse.y - box.top) / box.height, -0.5, 1.5);
|
|
4037
|
+
} else {
|
|
4038
|
+
x = 0.5 + Math.sin(time / 1600 + box.left / 200) * 0.6;
|
|
4039
|
+
y = 0.5 + Math.cos(time / 2100 + box.top / 200) * 0.6;
|
|
4040
|
+
}
|
|
4041
|
+
holo.x += (x - holo.x) * 0.08;
|
|
4042
|
+
holo.y += (y - holo.y) * 0.08;
|
|
4043
|
+
root.style.setProperty("--mk-sticker-x", holo.x.toFixed(4));
|
|
4044
|
+
root.style.setProperty("--mk-sticker-y", holo.y.toFixed(4));
|
|
4045
|
+
raf(loop);
|
|
4046
|
+
};
|
|
4047
|
+
if (visible) raf(loop);
|
|
4048
|
+
}
|
|
4049
|
+
}
|
|
4050
|
+
if (options.peel === false) return { get state() {
|
|
4051
|
+
return state;
|
|
4052
|
+
}, destroy: () => scope.dispose() };
|
|
4053
|
+
let w = 0;
|
|
4054
|
+
let h = 0;
|
|
4055
|
+
let corner = { x: 0, y: 0 };
|
|
4056
|
+
let current = { x: 0, y: 0 };
|
|
4057
|
+
let grabbed = { x: 0, y: 0 };
|
|
4058
|
+
let lifted = 0;
|
|
4059
|
+
let anchor = { x: 0, y: 0 };
|
|
4060
|
+
let reach = 0;
|
|
4061
|
+
let outward = { x: 1, y: 0 };
|
|
4062
|
+
let detachDistance = 80;
|
|
4063
|
+
let pose = { angle: 0, scale: 1, prop: 1 };
|
|
4064
|
+
let frozen = null;
|
|
4065
|
+
const readPose = () => {
|
|
4066
|
+
const style = getComputedStyle(root);
|
|
4067
|
+
const prop = parseFloat(style.scale) || 1;
|
|
4068
|
+
const matrix = /^matrix\(([^)]+)\)$/.exec(style.transform || "");
|
|
4069
|
+
if (matrix) {
|
|
4070
|
+
const [a, b] = matrix[1].split(",").map(Number);
|
|
4071
|
+
return { angle: Math.atan2(b, a), scale: Math.hypot(a, b) || 1, prop, transform: style.transform };
|
|
4072
|
+
}
|
|
4073
|
+
const angle = (parseFloat(style.getPropertyValue("--mk-sticker-rot")) || 0) * (Math.PI / 180);
|
|
4074
|
+
return { angle, scale: 1, prop, transform: `rotate(${angle}rad)` };
|
|
4075
|
+
};
|
|
4076
|
+
const freeze = () => {
|
|
4077
|
+
const now = readPose();
|
|
4078
|
+
pose = now;
|
|
4079
|
+
if (!frozen) frozen = { transform: root.style.transform, transition: root.style.transition };
|
|
4080
|
+
root.style.transition = "none";
|
|
4081
|
+
root.style.transform = now.transform;
|
|
4082
|
+
};
|
|
4083
|
+
const unfreeze = () => {
|
|
4084
|
+
if (!frozen) return;
|
|
4085
|
+
root.style.transform = frozen.transform;
|
|
4086
|
+
root.style.transition = frozen.transition;
|
|
4087
|
+
frozen = null;
|
|
4088
|
+
};
|
|
4089
|
+
scope.add(unfreeze);
|
|
4090
|
+
const toLocal = (clientX, clientY) => {
|
|
4091
|
+
const box = peelBox.getBoundingClientRect();
|
|
4092
|
+
const a = -pose.angle;
|
|
4093
|
+
const s = pose.scale * pose.prop;
|
|
4094
|
+
const dx = (clientX - (box.left + box.width / 2)) / s;
|
|
4095
|
+
const dy = (clientY - (box.top + box.height / 2)) / s;
|
|
4096
|
+
return { x: dx * Math.cos(a) - dy * Math.sin(a) + w / 2, y: dx * Math.sin(a) + dy * Math.cos(a) + h / 2 };
|
|
4097
|
+
};
|
|
4098
|
+
const CORNERS = () => [{ x: 0, y: 0 }, { x: w, y: 0 }, { x: w, y: h }, { x: 0, y: h }];
|
|
4099
|
+
const nearBorder = (p) => Math.min(p.x, w - p.x, p.y, h - p.y) < Math.min(w, h) * 0.35;
|
|
4100
|
+
const closestCorner = (p) => CORNERS().reduce((a, b) => Math.hypot(b.x - p.x, b.y - p.y) < Math.hypot(a.x - p.x, a.y - p.y) ? b : a);
|
|
4101
|
+
const cornerAgainst = (d) => CORNERS().reduce((a, b) => (b.x - w / 2) * -d.x + (b.y - h / 2) * -d.y > (a.x - w / 2) * -d.x + (a.y - h / 2) * -d.y + 1e-6 ? b : a);
|
|
4102
|
+
let choosing = false;
|
|
4103
|
+
const useCorner = (c) => {
|
|
4104
|
+
choosing = false;
|
|
4105
|
+
corner = c;
|
|
4106
|
+
anchor = { x: w - c.x, y: h - c.y };
|
|
4107
|
+
reach = Math.hypot(c.x - anchor.x, c.y - anchor.y);
|
|
4108
|
+
const ox = c.x - w / 2;
|
|
4109
|
+
const oy = c.y - h / 2;
|
|
4110
|
+
outward = { x: ox / (Math.hypot(ox, oy) || 1), y: oy / (Math.hypot(ox, oy) || 1) };
|
|
4111
|
+
current = { ...c };
|
|
4112
|
+
};
|
|
4113
|
+
const ensureBack = () => {
|
|
4114
|
+
if (back) return back;
|
|
4115
|
+
back = document.createElement("div");
|
|
4116
|
+
back.className = "mk-sticker__back";
|
|
4117
|
+
back.setAttribute("aria-hidden", "true");
|
|
4118
|
+
const face2 = document.createElement("div");
|
|
4119
|
+
face2.className = "mk-sticker__back-face";
|
|
4120
|
+
const copy = top.cloneNode(true);
|
|
4121
|
+
copy.querySelectorAll("[id]").forEach((el) => el.removeAttribute("id"));
|
|
4122
|
+
face2.append(...copy.childNodes);
|
|
4123
|
+
back.append(face2);
|
|
4124
|
+
peelBox.append(back);
|
|
4125
|
+
return back;
|
|
4126
|
+
};
|
|
4127
|
+
const flat = () => {
|
|
4128
|
+
top.style.clipPath = "";
|
|
4129
|
+
if (back) back.style.visibility = "hidden";
|
|
4130
|
+
root.removeAttribute("data-mk-peeling");
|
|
4131
|
+
lifted = 0;
|
|
4132
|
+
unfreeze();
|
|
4133
|
+
};
|
|
4134
|
+
scope.add(() => {
|
|
4135
|
+
top.style.clipPath = "";
|
|
4136
|
+
back?.remove();
|
|
4137
|
+
back = null;
|
|
4138
|
+
});
|
|
4139
|
+
const fold = (p) => {
|
|
4140
|
+
current = p;
|
|
4141
|
+
const dx = p.x - corner.x;
|
|
4142
|
+
const dy = p.y - corner.y;
|
|
4143
|
+
const length = Math.hypot(dx, dy);
|
|
4144
|
+
if (length < 0.5) {
|
|
4145
|
+
top.style.clipPath = "";
|
|
4146
|
+
if (back) back.style.visibility = "hidden";
|
|
4147
|
+
lifted = 0;
|
|
4148
|
+
return;
|
|
4149
|
+
}
|
|
4150
|
+
const n = { x: dx / length, y: dy / length };
|
|
4151
|
+
const m = { x: (corner.x + p.x) / 2, y: (corner.y + p.y) / 2 };
|
|
4152
|
+
const rect = [{ x: 0, y: 0 }, { x: w, y: 0 }, { x: w, y: h }, { x: 0, y: h }];
|
|
4153
|
+
const stuck = clipHalfPlane(rect, m, n);
|
|
4154
|
+
const flap = clipHalfPlane(rect, m, { x: -n.x, y: -n.y });
|
|
4155
|
+
lifted = area(flap) / (w * h || 1);
|
|
4156
|
+
top.style.clipPath = polygon(stuck);
|
|
4157
|
+
const b = ensureBack();
|
|
4158
|
+
const d = m.x * n.x + m.y * n.y;
|
|
4159
|
+
b.style.transform = `matrix(${1 - 2 * n.x * n.x}, ${-2 * n.x * n.y}, ${-2 * n.x * n.y}, ${1 - 2 * n.y * n.y}, ${2 * d * n.x}, ${2 * d * n.y})`;
|
|
4160
|
+
b.firstElementChild.style.clipPath = polygon(flap);
|
|
4161
|
+
b.style.setProperty("--mk-sticker-fold", `${Math.atan2(-n.x, n.y) * 180 / Math.PI}deg`);
|
|
4162
|
+
b.style.visibility = flap.length >= 3 ? "visible" : "hidden";
|
|
4163
|
+
};
|
|
4164
|
+
const NUDGE = 8;
|
|
4165
|
+
const pull = (at) => {
|
|
4166
|
+
const dx = at.x - grabbed.x;
|
|
4167
|
+
const dy = at.y - grabbed.y;
|
|
4168
|
+
const depth = Math.hypot(dx, dy);
|
|
4169
|
+
const perp = { x: -outward.y, y: outward.x };
|
|
4170
|
+
const side = clamp2(dx * perp.x + dy * perp.y, -depth * 0.7, depth * 0.7) * 0.6;
|
|
4171
|
+
let p = {
|
|
4172
|
+
x: corner.x - outward.x * (NUDGE + depth) + perp.x * side,
|
|
4173
|
+
y: corner.y - outward.y * (NUDGE + depth) + perp.y * side
|
|
4174
|
+
};
|
|
4175
|
+
const ax = p.x - anchor.x;
|
|
4176
|
+
const ay = p.y - anchor.y;
|
|
4177
|
+
const length = Math.hypot(ax, ay);
|
|
4178
|
+
if (length > reach) p = { x: anchor.x + ax * reach / length, y: anchor.y + ay * reach / length };
|
|
4179
|
+
return p;
|
|
4180
|
+
};
|
|
4181
|
+
let generation = 0;
|
|
4182
|
+
const settle = (from, duration, done) => {
|
|
4183
|
+
const start = performance.now();
|
|
4184
|
+
const mine = generation;
|
|
4185
|
+
const step = () => {
|
|
4186
|
+
if (scope.disposed || mine !== generation) return;
|
|
4187
|
+
const t = Math.min(1, (performance.now() - start) / duration);
|
|
4188
|
+
const e = easeOutCubic(t);
|
|
4189
|
+
fold({ x: from.x + (corner.x - from.x) * e, y: from.y + (corner.y - from.y) * e });
|
|
4190
|
+
if (t < 1) raf(step);
|
|
4191
|
+
else {
|
|
4192
|
+
flat();
|
|
4193
|
+
done?.();
|
|
4194
|
+
}
|
|
4195
|
+
};
|
|
4196
|
+
raf(step);
|
|
4197
|
+
};
|
|
4198
|
+
const velocity = { x: 0, y: 0 };
|
|
4199
|
+
let last = { x: 0, y: 0, t: 0 };
|
|
4200
|
+
const track = (e) => {
|
|
4201
|
+
const now = performance.now();
|
|
4202
|
+
const frames60 = Math.max(1, (now - last.t) / 16);
|
|
4203
|
+
velocity.x = velocity.x * 0.5 + (e.clientX - last.x) / frames60 * 0.5;
|
|
4204
|
+
velocity.y = velocity.y * 0.5 + (e.clientY - last.y) / frames60 * 0.5;
|
|
4205
|
+
last = { x: e.clientX, y: e.clientY, t: now };
|
|
4206
|
+
};
|
|
4207
|
+
let home = null;
|
|
4208
|
+
const carry = { x: 0, y: 0, tx: 0, ty: 0, offX: 0, offY: 0, lift: 0, tilt: 0, base: 0, from: 1, to: 1.08 };
|
|
4209
|
+
const carryScale = () => carry.from + (carry.to - carry.from) * carry.lift;
|
|
4210
|
+
const paint = () => {
|
|
4211
|
+
root.style.left = `${carry.x}px`;
|
|
4212
|
+
root.style.top = `${carry.y}px`;
|
|
4213
|
+
root.style.transform = `rotate(${carry.base + carry.tilt}deg) scale(${carryScale()})`;
|
|
4214
|
+
root.style.filter = `drop-shadow(0 ${8 + 14 * carry.lift}px ${14 + 12 * carry.lift}px rgb(0 0 0 / ${0.16 + 0.14 * carry.lift}))`;
|
|
4215
|
+
};
|
|
4216
|
+
const follow = () => {
|
|
4217
|
+
if (state !== "carried" || scope.disposed) return;
|
|
4218
|
+
carry.x += (carry.tx - carry.x) * 0.22;
|
|
4219
|
+
carry.y += (carry.ty - carry.y) * 0.22;
|
|
4220
|
+
carry.lift += (1 - carry.lift) * 0.15;
|
|
4221
|
+
carry.tilt += (clamp2(velocity.x * 1.2, -16, 16) - carry.tilt) * 0.15;
|
|
4222
|
+
paint();
|
|
4223
|
+
raf(follow);
|
|
4224
|
+
};
|
|
4225
|
+
const detach = (e) => {
|
|
4226
|
+
state = "carried";
|
|
4227
|
+
root.removeAttribute("data-mk-peeling");
|
|
4228
|
+
root.setAttribute("data-mk-carried", "");
|
|
4229
|
+
settle({ ...current }, 160);
|
|
4230
|
+
const box = root.getBoundingClientRect();
|
|
4231
|
+
unfreeze();
|
|
4232
|
+
carry.base = pose.angle * (180 / Math.PI);
|
|
4233
|
+
carry.from = pose.scale;
|
|
4234
|
+
carry.to = Math.max(1, pose.scale) + 0.08;
|
|
4235
|
+
home = { parent: root.parentNode, next: root.nextSibling, style: root.getAttribute("style") };
|
|
4236
|
+
const width = root.offsetWidth;
|
|
4237
|
+
const height = root.offsetHeight;
|
|
4238
|
+
document.body.append(root);
|
|
4239
|
+
Object.assign(root.style, { position: "fixed", right: "auto", bottom: "auto", margin: "0", translate: "none", scale: String(pose.prop), zIndex: "999", animation: "none", transition: "none" });
|
|
4240
|
+
carry.x = box.left + box.width / 2 - width / 2;
|
|
4241
|
+
carry.y = box.top + box.height / 2 - height / 2;
|
|
4242
|
+
carry.offX = e.clientX - carry.x;
|
|
4243
|
+
carry.offY = e.clientY - carry.y;
|
|
4244
|
+
carry.tx = carry.x;
|
|
4245
|
+
carry.ty = carry.y;
|
|
4246
|
+
carry.lift = 0;
|
|
4247
|
+
carry.tilt = 0;
|
|
4248
|
+
paint();
|
|
4249
|
+
options.onPeel?.();
|
|
4250
|
+
raf(follow);
|
|
4251
|
+
};
|
|
4252
|
+
const goHome = () => {
|
|
4253
|
+
if (!home) return;
|
|
4254
|
+
const { parent, next, style } = home;
|
|
4255
|
+
home = null;
|
|
4256
|
+
parent.insertBefore(root, next && next.parentNode === parent ? next : null);
|
|
4257
|
+
if (style === null) root.removeAttribute("style");
|
|
4258
|
+
else root.setAttribute("style", style);
|
|
4259
|
+
root.style.animationDelay = "0s";
|
|
4260
|
+
root.removeAttribute("data-mk-carried");
|
|
4261
|
+
root.removeAttribute("data-mk-away");
|
|
4262
|
+
state = "idle";
|
|
4263
|
+
options.onReturn?.();
|
|
4264
|
+
};
|
|
4265
|
+
scope.add(goHome);
|
|
4266
|
+
const away = () => {
|
|
4267
|
+
state = "away";
|
|
4268
|
+
root.setAttribute("data-mk-away", "");
|
|
4269
|
+
scope.timeout(goHome, returnDelay);
|
|
4270
|
+
};
|
|
4271
|
+
const fall = () => {
|
|
4272
|
+
state = "falling";
|
|
4273
|
+
root.style.pointerEvents = "none";
|
|
4274
|
+
if (still) {
|
|
4275
|
+
away();
|
|
4276
|
+
return;
|
|
4277
|
+
}
|
|
4278
|
+
let x = 0;
|
|
4279
|
+
let y = 0;
|
|
4280
|
+
let angle = carry.base + carry.tilt;
|
|
4281
|
+
let vx = clamp2(velocity.x * 40, -900, 900);
|
|
4282
|
+
let vy = clamp2(velocity.y * 40, -500, 600) - 120;
|
|
4283
|
+
const spin = vx * 0.35 + (Math.random() - 0.5) * 120;
|
|
4284
|
+
const startY = carry.y;
|
|
4285
|
+
let then = performance.now();
|
|
4286
|
+
const step = () => {
|
|
4287
|
+
if (scope.disposed || state !== "falling") return;
|
|
4288
|
+
const time = performance.now();
|
|
4289
|
+
const dt = Math.min(0.05, Math.max(0, time - then) / 1e3);
|
|
4290
|
+
then = time;
|
|
4291
|
+
vy += 1600 * dt;
|
|
4292
|
+
x += vx * dt;
|
|
4293
|
+
y += vy * dt;
|
|
4294
|
+
vx *= 1 - 0.6 * dt;
|
|
4295
|
+
angle += spin * dt;
|
|
4296
|
+
root.style.transform = `translate(${x}px, ${y}px) rotate(${angle}deg) scale(${carryScale()})`;
|
|
4297
|
+
if (startY + y < innerHeight + 40) raf(step);
|
|
4298
|
+
else away();
|
|
4299
|
+
};
|
|
4300
|
+
raf(step);
|
|
4301
|
+
};
|
|
4302
|
+
let pointerId = null;
|
|
4303
|
+
scope.on(root, "pointerdown", (event) => {
|
|
4304
|
+
const e = event;
|
|
4305
|
+
if (state !== "idle" || e.button !== 0) return;
|
|
4306
|
+
e.preventDefault();
|
|
4307
|
+
generation++;
|
|
4308
|
+
freeze();
|
|
4309
|
+
state = "peeling";
|
|
4310
|
+
root.setAttribute("data-mk-peeling", "");
|
|
4311
|
+
pointerId = e.pointerId;
|
|
4312
|
+
root.setPointerCapture?.(e.pointerId);
|
|
4313
|
+
w = top.offsetWidth;
|
|
4314
|
+
h = top.offsetHeight;
|
|
4315
|
+
peelBox.style.width = `${w}px`;
|
|
4316
|
+
peelBox.style.height = `${h}px`;
|
|
4317
|
+
const at = toLocal(e.clientX, e.clientY);
|
|
4318
|
+
grabbed = at;
|
|
4319
|
+
detachDistance = Number.isFinite(options.detachDistance) ? Math.max(1, options.detachDistance) : Math.max(80, Math.max(w, h) / 2);
|
|
4320
|
+
last = { x: e.clientX, y: e.clientY, t: performance.now() };
|
|
4321
|
+
velocity.x = velocity.y = 0;
|
|
4322
|
+
if (nearBorder(at)) {
|
|
4323
|
+
useCorner(closestCorner(at));
|
|
4324
|
+
fold(pull(at));
|
|
4325
|
+
} else {
|
|
4326
|
+
choosing = true;
|
|
4327
|
+
corner = current = { ...at };
|
|
4328
|
+
}
|
|
4329
|
+
});
|
|
4330
|
+
scope.on(root, "pointermove", (event) => {
|
|
4331
|
+
const e = event;
|
|
4332
|
+
if (state !== "peeling" || e.pointerId !== pointerId) return;
|
|
4333
|
+
track(e);
|
|
4334
|
+
const at = toLocal(e.clientX, e.clientY);
|
|
4335
|
+
if (choosing) {
|
|
4336
|
+
const dx = at.x - grabbed.x;
|
|
4337
|
+
const dy = at.y - grabbed.y;
|
|
4338
|
+
const moved = Math.hypot(dx, dy);
|
|
4339
|
+
if (moved < 4) return;
|
|
4340
|
+
useCorner(cornerAgainst({ x: dx / moved, y: dy / moved }));
|
|
4341
|
+
}
|
|
4342
|
+
fold(pull(at));
|
|
4343
|
+
if (lifted > detachAt || Math.hypot(at.x - grabbed.x, at.y - grabbed.y) > detachDistance) detach(e);
|
|
4344
|
+
});
|
|
4345
|
+
scope.on(document, "pointermove", (event) => {
|
|
4346
|
+
const e = event;
|
|
4347
|
+
if (state !== "carried" || e.pointerId !== pointerId) return;
|
|
4348
|
+
track(e);
|
|
4349
|
+
carry.tx = e.clientX - carry.offX;
|
|
4350
|
+
carry.ty = e.clientY - carry.offY;
|
|
4351
|
+
});
|
|
4352
|
+
const release = (event) => {
|
|
4353
|
+
const e = event;
|
|
4354
|
+
if (e.pointerId !== pointerId) return;
|
|
4355
|
+
if (state === "peeling") {
|
|
4356
|
+
state = "idle";
|
|
4357
|
+
settle({ ...current }, 380);
|
|
4358
|
+
} else if (state === "carried") fall();
|
|
4359
|
+
};
|
|
4360
|
+
scope.on(document, "pointerup", release);
|
|
4361
|
+
scope.on(document, "pointercancel", release);
|
|
4362
|
+
scope.add(() => {
|
|
4363
|
+
peelBox.style.width = "";
|
|
4364
|
+
peelBox.style.height = "";
|
|
4365
|
+
});
|
|
4366
|
+
return {
|
|
4367
|
+
get state() {
|
|
4368
|
+
return state;
|
|
4369
|
+
},
|
|
4370
|
+
destroy: () => scope.dispose()
|
|
4371
|
+
};
|
|
4372
|
+
}
|
|
4373
|
+
|
|
4374
|
+
// src/recipes/scroll-dock/create-scroll-dock.ts
|
|
4375
|
+
function createScrollDock(root, options = {}) {
|
|
4376
|
+
if (!root) return inert({ visible: false, update() {
|
|
4377
|
+
} });
|
|
4378
|
+
const scope = createScope();
|
|
4379
|
+
const threshold = Number.isFinite(options.threshold) ? Math.max(0, options.threshold) : 0.6;
|
|
4380
|
+
const hideOffset = Number.isFinite(options.hideOffset) ? options.hideOffset : 40;
|
|
4381
|
+
const scroller = typeof options.scroller === "string" ? root.closest(options.scroller) ?? document.querySelector(options.scroller) : options.scroller ?? null;
|
|
4382
|
+
const hideTarget = () => typeof options.hideWhen === "string" ? document.querySelector(options.hideWhen) : options.hideWhen ?? null;
|
|
4383
|
+
let visible = false;
|
|
4384
|
+
let queued = false;
|
|
4385
|
+
scope.attr(root, "data-mk-ready", "");
|
|
4386
|
+
const update = () => {
|
|
4387
|
+
queued = false;
|
|
4388
|
+
if (scope.disposed) return;
|
|
4389
|
+
const offset = scroller ? scroller.scrollTop : window.scrollY;
|
|
4390
|
+
const viewport = scroller ? scroller.clientHeight : window.innerHeight;
|
|
4391
|
+
const bottom = scroller ? scroller.getBoundingClientRect().bottom : window.innerHeight;
|
|
4392
|
+
const end = hideTarget();
|
|
4393
|
+
const reachedEnd = end ? end.getBoundingClientRect().top < bottom - hideOffset : false;
|
|
4394
|
+
const next = offset > viewport * threshold && !reachedEnd;
|
|
4395
|
+
if (next === visible) return;
|
|
4396
|
+
visible = next;
|
|
4397
|
+
scope.attr(root, "data-mk-visible", next ? "" : null);
|
|
4398
|
+
options.onChange?.(next);
|
|
4399
|
+
root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { visible: next } }));
|
|
4400
|
+
};
|
|
4401
|
+
const queue = () => {
|
|
4402
|
+
if (queued) return;
|
|
4403
|
+
queued = true;
|
|
4404
|
+
requestAnimationFrame(update);
|
|
4405
|
+
};
|
|
4406
|
+
scope.on(scroller ?? window, "scroll", queue, { passive: true });
|
|
4407
|
+
scope.on(window, "resize", queue, { passive: true });
|
|
4408
|
+
update();
|
|
4409
|
+
return {
|
|
4410
|
+
get visible() {
|
|
4411
|
+
return visible;
|
|
4412
|
+
},
|
|
4413
|
+
update,
|
|
4414
|
+
destroy: () => scope.dispose()
|
|
4415
|
+
};
|
|
4416
|
+
}
|
|
4417
|
+
|
|
4418
|
+
// src/recipes/local-clock/create-local-clock.ts
|
|
4419
|
+
function createLocalClock(root, options = {}) {
|
|
4420
|
+
if (!root) return inert({ text: "" });
|
|
4421
|
+
const scope = createScope();
|
|
4422
|
+
const original = [...root.childNodes];
|
|
4423
|
+
scope.add(() => root.replaceChildren(...original));
|
|
4424
|
+
scope.attr(root, "data-mk-ready", "");
|
|
4425
|
+
let formatter;
|
|
4426
|
+
try {
|
|
4427
|
+
formatter = new Intl.DateTimeFormat(options.locale ?? "es", options.format ?? {
|
|
4428
|
+
hour: "2-digit",
|
|
4429
|
+
minute: "2-digit",
|
|
4430
|
+
...options.seconds ? { second: "2-digit" } : {},
|
|
4431
|
+
hour12: options.hour12 ?? false,
|
|
4432
|
+
timeZone: options.timeZone
|
|
4433
|
+
});
|
|
4434
|
+
} catch {
|
|
4435
|
+
formatter = new Intl.DateTimeFormat(void 0, { hour: "2-digit", minute: "2-digit", hour12: options.hour12 ?? false });
|
|
4436
|
+
}
|
|
4437
|
+
let text = "";
|
|
4438
|
+
const isTime = root instanceof HTMLTimeElement;
|
|
4439
|
+
const render = () => {
|
|
4440
|
+
const now = /* @__PURE__ */ new Date();
|
|
4441
|
+
text = formatter.format(now);
|
|
4442
|
+
if (root.textContent !== text) root.textContent = text;
|
|
4443
|
+
if (isTime) scope.attr(root, "datetime", now.toISOString());
|
|
4444
|
+
};
|
|
4445
|
+
const step = options.seconds || options.format?.second ? 1e3 : 6e4;
|
|
4446
|
+
const schedule = () => {
|
|
4447
|
+
const wait = step - Date.now() % step + 20;
|
|
4448
|
+
scope.timeout(() => {
|
|
4449
|
+
if (!scope.disposed) {
|
|
4450
|
+
render();
|
|
4451
|
+
schedule();
|
|
4452
|
+
}
|
|
4453
|
+
}, wait);
|
|
4454
|
+
};
|
|
4455
|
+
render();
|
|
4456
|
+
schedule();
|
|
4457
|
+
return { get text() {
|
|
4458
|
+
return text;
|
|
4459
|
+
}, destroy: () => scope.dispose() };
|
|
4460
|
+
}
|
|
4461
|
+
|
|
3274
4462
|
export {
|
|
3275
4463
|
trackScroll,
|
|
3276
4464
|
toggleDetails,
|
|
@@ -3315,6 +4503,17 @@ export {
|
|
|
3315
4503
|
createRepelBento,
|
|
3316
4504
|
createRotator,
|
|
3317
4505
|
createDragRuler,
|
|
3318
|
-
createDockPill
|
|
4506
|
+
createDockPill,
|
|
4507
|
+
createJoinedCta,
|
|
4508
|
+
createImageZoom,
|
|
4509
|
+
createFontCycle,
|
|
4510
|
+
createThumbnailNav,
|
|
4511
|
+
createActionButton,
|
|
4512
|
+
createFilmHero,
|
|
4513
|
+
createEditorialReveal,
|
|
4514
|
+
createWeightHover,
|
|
4515
|
+
createSticker,
|
|
4516
|
+
createScrollDock,
|
|
4517
|
+
createLocalClock
|
|
3319
4518
|
};
|
|
3320
|
-
//# sourceMappingURL=chunk-
|
|
4519
|
+
//# sourceMappingURL=chunk-XAKC2QY7.js.map
|