@yewdiel21/motion-kit 0.0.0-stage → 0.9.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 +38 -0
- package/README.md +80 -2
- package/bin/motion-kit.mjs +242 -0
- package/css.d.ts +2 -0
- package/dist/auto/index.d.ts +63 -0
- package/dist/auto/index.js +207 -0
- package/dist/auto/index.js.map +1 -0
- package/dist/chunk-2BQGFOA7.js +177 -0
- package/dist/chunk-2BQGFOA7.js.map +1 -0
- package/dist/chunk-34XYOXHG.js +2374 -0
- package/dist/chunk-34XYOXHG.js.map +1 -0
- package/dist/chunk-6OJAP6ZL.js +832 -0
- package/dist/chunk-6OJAP6ZL.js.map +1 -0
- package/dist/chunk-ABNRDDO7.js +28 -0
- package/dist/chunk-ABNRDDO7.js.map +1 -0
- package/dist/chunk-FS2HJVVY.js +3320 -0
- package/dist/chunk-FS2HJVVY.js.map +1 -0
- package/dist/chunk-J27KH2A2.js +157 -0
- package/dist/chunk-J27KH2A2.js.map +1 -0
- package/dist/chunk-KLY5BRRI.js +18 -0
- package/dist/chunk-KLY5BRRI.js.map +1 -0
- package/dist/chunk-Q4LVFNLN.js +1617 -0
- package/dist/chunk-Q4LVFNLN.js.map +1 -0
- package/dist/chunk-RFDIZYFX.js +304 -0
- package/dist/chunk-RFDIZYFX.js.map +1 -0
- package/dist/chunk-TGV27ZWM.js +17 -0
- package/dist/chunk-TGV27ZWM.js.map +1 -0
- package/dist/confetti-BSX1CLLV.d.ts +41 -0
- package/dist/css/components/chat-background.css +87 -0
- package/dist/css/components/chat.css +237 -0
- package/dist/css/components/cursor.css +178 -0
- package/dist/css/components/dialog.css +259 -0
- package/dist/css/components/island.css +301 -0
- package/dist/css/components/menu.css +105 -0
- package/dist/css/components/nav.css +1054 -0
- package/dist/css/components/steps.css +50 -0
- package/dist/css/components/theme-picker.css +115 -0
- package/dist/css/components/toast.css +115 -0
- package/dist/css/controls.css +950 -0
- package/dist/css/effects.css +587 -0
- package/dist/css/fonts.css +3 -0
- package/dist/css/themes/black-green.css +126 -0
- package/dist/css/themes/black.css +126 -0
- package/dist/css/themes/blue.css +126 -0
- package/dist/css/themes/brown.css +126 -0
- package/dist/css/themes/cold-blue.css +126 -0
- package/dist/css/themes/funny.css +126 -0
- package/dist/css/themes/gray.css +126 -0
- package/dist/css/themes/green.css +126 -0
- package/dist/css/themes/modern-1.css +126 -0
- package/dist/css/themes/neogreen.css +126 -0
- package/dist/css/themes/new.css +126 -0
- package/dist/css/themes/new2.css +126 -0
- package/dist/css/themes/oled.css +126 -0
- package/dist/css/themes/orange.css +126 -0
- package/dist/css/themes/pastel-pink.css +126 -0
- package/dist/css/themes/pink.css +126 -0
- package/dist/css/themes/purple.css +126 -0
- package/dist/css/themes/red.css +126 -0
- package/dist/css/themes/super-blue.css +126 -0
- package/dist/css/themes.css +2431 -0
- package/dist/css/tokens.css +452 -0
- package/dist/elements/index.d.ts +183 -0
- package/dist/elements/index.js +472 -0
- package/dist/elements/index.js.map +1 -0
- package/dist/engine-CUr9QijM.d.ts +46 -0
- package/dist/gl/index.d.ts +61 -0
- package/dist/gl/index.js +18 -0
- package/dist/gl/index.js.map +1 -0
- package/dist/index.css +5296 -0
- package/dist/index.d.ts +440 -0
- package/dist/index.js +390 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.d.ts +476 -0
- package/dist/react/index.js +969 -0
- package/dist/react/index.js.map +1 -0
- package/dist/reduced-BM4Ls0g5.d.ts +566 -0
- package/dist/reveal-WFUWDrei.d.ts +416 -0
- package/dist/store-Bqy_obnD.d.ts +195 -0
- package/dist/theme/generate.d.ts +18 -0
- package/dist/theme/generate.js +64 -0
- package/dist/theme/generate.js.map +1 -0
- package/dist/theme/index.d.ts +17 -0
- package/dist/theme/index.js +32 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme-BFMoCzi6.d.ts +158 -0
- package/dist/types-BkS_raL8.d.ts +7 -0
- package/package.json +114 -3
- package/registry.json +469 -0
- package/skills/motion-kit/SKILL.md +189 -0
- package/skills/motion-kit/reference/components.md +86 -0
- package/skills/motion-kit/reference/design.md +92 -0
- package/skills/motion-kit/reference/recipes.md +172 -0
- package/src/auto/auto-init.ts +151 -0
- package/src/auto/index.ts +3 -0
- package/src/auto/parse-options.ts +68 -0
- package/src/components/chat/README.md +90 -0
- package/src/components/chat/chat.css +236 -0
- package/src/components/chat/element.ts +98 -0
- package/src/components/chat/engine.ts +295 -0
- package/src/components/chat/react.tsx +196 -0
- package/src/components/chat-background/README.md +50 -0
- package/src/components/chat-background/audio.ts +56 -0
- package/src/components/chat-background/chat-background.css +86 -0
- package/src/components/chat-background/element.ts +31 -0
- package/src/components/chat-background/engine.ts +108 -0
- package/src/components/chat-background/react.tsx +36 -0
- package/src/components/cursor/README.md +53 -0
- package/src/components/cursor/cursor.css +177 -0
- package/src/components/cursor/element.ts +23 -0
- package/src/components/cursor/engine.ts +254 -0
- package/src/components/cursor/react.tsx +26 -0
- package/src/components/dialog/README.md +106 -0
- package/src/components/dialog/dialog.css +258 -0
- package/src/components/dialog/element.ts +118 -0
- package/src/components/dialog/engine.ts +432 -0
- package/src/components/dialog/react.tsx +200 -0
- package/src/components/icon.tsx +10 -0
- package/src/components/icons.ts +24 -0
- package/src/components/island/README.md +91 -0
- package/src/components/island/element.ts +45 -0
- package/src/components/island/engine.ts +200 -0
- package/src/components/island/island.css +300 -0
- package/src/components/island/react.tsx +115 -0
- package/src/components/menu/README.md +67 -0
- package/src/components/menu/element.ts +55 -0
- package/src/components/menu/engine.ts +142 -0
- package/src/components/menu/menu.css +104 -0
- package/src/components/menu/react.tsx +82 -0
- package/src/components/nav/README.md +85 -0
- package/src/components/nav/element.ts +39 -0
- package/src/components/nav/engine.ts +164 -0
- package/src/components/nav/nav.css +1053 -0
- package/src/components/nav/react.tsx +90 -0
- package/src/components/steps/README.md +70 -0
- package/src/components/steps/element.ts +43 -0
- package/src/components/steps/engine.ts +185 -0
- package/src/components/steps/react.tsx +91 -0
- package/src/components/steps/steps.css +49 -0
- package/src/components/theme-picker/README.md +57 -0
- package/src/components/theme-picker/element.ts +20 -0
- package/src/components/theme-picker/engine.ts +91 -0
- package/src/components/theme-picker/react.tsx +31 -0
- package/src/components/theme-picker/theme-picker.css +114 -0
- package/src/components/toast/README.md +60 -0
- package/src/components/toast/element.ts +25 -0
- package/src/components/toast/engine.ts +483 -0
- package/src/components/toast/react.tsx +22 -0
- package/src/components/toast/store.ts +122 -0
- package/src/components/toast/toast.css +114 -0
- package/src/core/channels.ts +165 -0
- package/src/core/curves.ts +35 -0
- package/src/core/frame.ts +12 -0
- package/src/core/gsap.ts +65 -0
- package/src/core/loop.ts +44 -0
- package/src/core/math.ts +9 -0
- package/src/core/physics-spring.ts +59 -0
- package/src/core/pointer.ts +63 -0
- package/src/core/reduced.ts +21 -0
- package/src/core/scope.ts +70 -0
- package/src/core/scroll-track.ts +106 -0
- package/src/core/split.ts +68 -0
- package/src/core/spring.ts +22 -0
- package/src/core/styles.ts +31 -0
- package/src/core/timing.ts +204 -0
- package/src/core/types.ts +20 -0
- package/src/core/visible.ts +19 -0
- package/src/css/base.css +142 -0
- package/src/css/controls/README.md +122 -0
- package/src/css/controls/burger.css +67 -0
- package/src/css/controls/button.css +226 -0
- package/src/css/controls/checkbox.css +53 -0
- package/src/css/controls/chip.css +85 -0
- package/src/css/controls/field.css +124 -0
- package/src/css/controls/glass.css +220 -0
- package/src/css/controls/icon.css +26 -0
- package/src/css/controls/segmented.css +60 -0
- package/src/css/controls/switch.css +72 -0
- package/src/css/default-theme.css +123 -0
- package/src/css/effects/README.md +134 -0
- package/src/css/effects/anim.css +224 -0
- package/src/css/effects/fade.css +15 -0
- package/src/css/effects/float.css +64 -0
- package/src/css/effects/frost.css +62 -0
- package/src/css/effects/grain.css +58 -0
- package/src/css/effects/loading.css +60 -0
- package/src/css/effects/success.css +22 -0
- package/src/css/effects/text.css +67 -0
- package/src/css/fonts.css +3 -0
- package/src/css/states.css +51 -0
- package/src/css/themes/black-green.css +126 -0
- package/src/css/themes/black.css +126 -0
- package/src/css/themes/blue.css +126 -0
- package/src/css/themes/brown.css +126 -0
- package/src/css/themes/cold-blue.css +126 -0
- package/src/css/themes/funny.css +126 -0
- package/src/css/themes/gray.css +126 -0
- package/src/css/themes/green.css +126 -0
- package/src/css/themes/modern-1.css +126 -0
- package/src/css/themes/neogreen.css +126 -0
- package/src/css/themes/new.css +126 -0
- package/src/css/themes/new2.css +126 -0
- package/src/css/themes/oled.css +126 -0
- package/src/css/themes/orange.css +126 -0
- package/src/css/themes/pastel-pink.css +126 -0
- package/src/css/themes/pink.css +126 -0
- package/src/css/themes/purple.css +126 -0
- package/src/css/themes/red.css +126 -0
- package/src/css/themes/super-blue.css +126 -0
- package/src/css/tokens.css +182 -0
- package/src/elements/base.ts +76 -0
- package/src/elements/index.ts +48 -0
- package/src/gl/index.ts +15 -0
- package/src/gl/liquid-blend/README.md +23 -0
- package/src/gl/liquid-blend/create-liquid-blend.ts +7 -0
- package/src/gl/liquid-blend/shader.ts +9 -0
- package/src/gl/matcap/README.md +23 -0
- package/src/gl/matcap/create-matcap.ts +7 -0
- package/src/gl/matcap/shader.ts +16 -0
- package/src/gl/particle-hero/README.md +41 -0
- package/src/gl/particle-hero/create-particle-hero.ts +544 -0
- package/src/gl/particle-hero/particle-hero.css +19 -0
- package/src/gl/particle-hero/shaders.ts +84 -0
- package/src/gl/shader-blur/README.md +23 -0
- package/src/gl/shader-blur/create-shader-blur.ts +7 -0
- package/src/gl/shader-blur/shader.ts +11 -0
- package/src/gl/shader-grain/README.md +23 -0
- package/src/gl/shader-grain/create-shader-grain.ts +7 -0
- package/src/gl/shader-grain/shader.ts +6 -0
- package/src/gl/shared/create-shader-effect.ts +186 -0
- package/src/gl/shared/shader.css +3 -0
- package/src/gl/shared/shaders.ts +30 -0
- package/src/index.ts +177 -0
- package/src/motion/anchor.ts +45 -0
- package/src/motion/chat.ts +97 -0
- package/src/motion/confetti.ts +130 -0
- package/src/motion/count.ts +95 -0
- package/src/motion/details.ts +70 -0
- package/src/motion/drag-dismiss.ts +231 -0
- package/src/motion/effects.ts +81 -0
- package/src/motion/entrances.ts +27 -0
- package/src/motion/floating.ts +389 -0
- package/src/motion/flow.ts +115 -0
- package/src/motion/indicator.ts +44 -0
- package/src/motion/layout.ts +39 -0
- package/src/motion/liquid.ts +227 -0
- package/src/motion/morph.ts +540 -0
- package/src/motion/reveal.ts +112 -0
- package/src/motion/sheet.ts +65 -0
- package/src/motion/surface.ts +108 -0
- package/src/react/animated-number.tsx +30 -0
- package/src/react/flip-group.tsx +44 -0
- package/src/react/frost.tsx +33 -0
- package/src/react/index.ts +80 -0
- package/src/react/slot-text.tsx +44 -0
- package/src/react/theme-provider.tsx +42 -0
- package/src/react/use-card-dock.ts +9 -0
- package/src/react/use-cascade.ts +9 -0
- package/src/react/use-contrast.ts +9 -0
- package/src/react/use-counter.ts +8 -0
- package/src/react/use-curved-carousel.ts +10 -0
- package/src/react/use-depth-grid.ts +9 -0
- package/src/react/use-details.ts +7 -0
- package/src/react/use-dock-pill.ts +10 -0
- package/src/react/use-drag-ruler.ts +10 -0
- package/src/react/use-fill-text.ts +9 -0
- package/src/react/use-fit-text.ts +8 -0
- package/src/react/use-flow.ts +8 -0
- package/src/react/use-frame-zoom.ts +9 -0
- package/src/react/use-infinite-reel.ts +8 -0
- package/src/react/use-letters.ts +9 -0
- package/src/react/use-liquid-blend.ts +8 -0
- package/src/react/use-marquee.ts +9 -0
- package/src/react/use-mask-text.ts +9 -0
- package/src/react/use-matcap.ts +8 -0
- package/src/react/use-parallax.ts +9 -0
- package/src/react/use-particle-hero.ts +9 -0
- package/src/react/use-pile.ts +8 -0
- package/src/react/use-pop.ts +8 -0
- package/src/react/use-radial-menu.ts +10 -0
- package/src/react/use-recipe.ts +38 -0
- package/src/react/use-reflow.ts +9 -0
- package/src/react/use-repel-bento.ts +8 -0
- package/src/react/use-reveal.ts +8 -0
- package/src/react/use-rotator.ts +10 -0
- package/src/react/use-shader-blur.ts +8 -0
- package/src/react/use-shader-grain.ts +8 -0
- package/src/react/use-slot-text.ts +17 -0
- package/src/react/use-snap-strip.ts +9 -0
- package/src/react/use-sortable.ts +14 -0
- package/src/react/use-spring-cards.ts +8 -0
- package/src/react/use-stretch-footer.ts +20 -0
- package/src/react/use-tabs.ts +10 -0
- package/src/react/use-text-roll.ts +9 -0
- package/src/react/use-ticket-menu.ts +15 -0
- package/src/react/use-words.ts +8 -0
- package/src/recipes/card-dock/README.md +36 -0
- package/src/recipes/card-dock/card-dock.css +178 -0
- package/src/recipes/card-dock/create-card-dock.ts +97 -0
- package/src/recipes/cascade/README.md +33 -0
- package/src/recipes/cascade/create-cascade.ts +111 -0
- package/src/recipes/contrast/README.md +29 -0
- package/src/recipes/contrast/create-contrast.ts +68 -0
- package/src/recipes/counter/README.md +42 -0
- package/src/recipes/counter/create-counter.ts +84 -0
- package/src/recipes/curved-carousel/README.md +50 -0
- package/src/recipes/curved-carousel/carousel-math.ts +20 -0
- package/src/recipes/curved-carousel/create-curved-carousel.ts +257 -0
- package/src/recipes/curved-carousel/curved-carousel.css +50 -0
- package/src/recipes/depth-grid/README.md +30 -0
- package/src/recipes/depth-grid/create-depth-grid.ts +120 -0
- package/src/recipes/details/README.md +31 -0
- package/src/recipes/details/create-details.ts +27 -0
- package/src/recipes/dock-pill/README.md +23 -0
- package/src/recipes/dock-pill/create-dock-pill.ts +68 -0
- package/src/recipes/dock-pill/dock-pill.css +5 -0
- package/src/recipes/drag-ruler/README.md +21 -0
- package/src/recipes/drag-ruler/create-drag-ruler.ts +95 -0
- package/src/recipes/drag-ruler/drag-ruler.css +16 -0
- package/src/recipes/fill-text/README.md +27 -0
- package/src/recipes/fill-text/create-fill-text.ts +93 -0
- package/src/recipes/fit-text/README.md +37 -0
- package/src/recipes/fit-text/create-fit-text.ts +55 -0
- package/src/recipes/fit-text/fit-text.css +6 -0
- package/src/recipes/flow/README.md +46 -0
- package/src/recipes/flow/create-flow.ts +55 -0
- package/src/recipes/frame-zoom/README.md +29 -0
- package/src/recipes/frame-zoom/create-frame-zoom.ts +91 -0
- package/src/recipes/infinite-reel/README.md +23 -0
- package/src/recipes/infinite-reel/create-infinite-reel.ts +140 -0
- package/src/recipes/infinite-reel/infinite-reel.css +8 -0
- package/src/recipes/letters/README.md +30 -0
- package/src/recipes/letters/create-letters.ts +113 -0
- package/src/recipes/marquee/README.md +32 -0
- package/src/recipes/marquee/create-marquee.ts +74 -0
- package/src/recipes/marquee/marquee.css +41 -0
- package/src/recipes/mask-text/README.md +39 -0
- package/src/recipes/mask-text/create-mask-text.ts +134 -0
- package/src/recipes/parallax/README.md +31 -0
- package/src/recipes/parallax/create-parallax.ts +74 -0
- package/src/recipes/pile/README.md +48 -0
- package/src/recipes/pile/create-pile.ts +50 -0
- package/src/recipes/pile/pile-math.ts +27 -0
- package/src/recipes/pile/pile.css +63 -0
- package/src/recipes/pill/README.md +30 -0
- package/src/recipes/pill/pill.css +48 -0
- package/src/recipes/pop/README.md +36 -0
- package/src/recipes/pop/create-pop.ts +52 -0
- package/src/recipes/radial-menu/README.md +44 -0
- package/src/recipes/radial-menu/create-radial-menu.ts +96 -0
- package/src/recipes/radial-menu/radial-menu.css +45 -0
- package/src/recipes/reflow/README.md +47 -0
- package/src/recipes/reflow/create-reflow.ts +49 -0
- package/src/recipes/repel-bento/README.md +21 -0
- package/src/recipes/repel-bento/create-repel-bento.ts +65 -0
- package/src/recipes/repel-bento/repel-bento.css +3 -0
- package/src/recipes/reveal/README.md +36 -0
- package/src/recipes/reveal/create-reveal.ts +48 -0
- package/src/recipes/rotator/README.md +21 -0
- package/src/recipes/rotator/create-rotator.ts +66 -0
- package/src/recipes/rotator/rotator.css +3 -0
- package/src/recipes/slot-text/README.md +44 -0
- package/src/recipes/slot-text/create-slot-text.ts +244 -0
- package/src/recipes/slot-text/slot-text.css +42 -0
- package/src/recipes/snap-strip/README.md +31 -0
- package/src/recipes/snap-strip/create-snap-strip.ts +133 -0
- package/src/recipes/snap-strip/snap-strip.css +23 -0
- package/src/recipes/sortable/README.md +88 -0
- package/src/recipes/sortable/create-sortable.ts +863 -0
- package/src/recipes/sortable/sortable.css +40 -0
- package/src/recipes/spring-cards/README.md +48 -0
- package/src/recipes/spring-cards/create-spring-cards.ts +140 -0
- package/src/recipes/spring-cards/spring-cards.css +23 -0
- package/src/recipes/stretch-footer/README.md +44 -0
- package/src/recipes/stretch-footer/create-stretch-footer.ts +69 -0
- package/src/recipes/stretch-footer/stretch-footer.css +28 -0
- package/src/recipes/tabs/README.md +39 -0
- package/src/recipes/tabs/create-tabs.ts +91 -0
- package/src/recipes/tabs/tabs.css +19 -0
- package/src/recipes/text-roll/README.md +35 -0
- package/src/recipes/text-roll/create-text-roll.ts +137 -0
- package/src/recipes/text-roll/text-roll.css +21 -0
- package/src/recipes/ticket-menu/README.md +24 -0
- package/src/recipes/ticket-menu/create-ticket-menu.ts +6 -0
- package/src/recipes/words/README.md +43 -0
- package/src/recipes/words/create-words.ts +114 -0
- package/src/theme/css-format.ts +32 -0
- package/src/theme/generate.ts +72 -0
- package/src/theme/index.ts +15 -0
- package/src/theme/presets.ts +79 -0
- package/src/theme/theme.ts +119 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useRef } from 'react';
|
|
4
|
+
import { useIsomorphicLayoutEffect } from '../../react/use-recipe';
|
|
5
|
+
import { createCursor, type CursorOptions, type CursorVariant } from './engine';
|
|
6
|
+
|
|
7
|
+
export interface CursorProps {
|
|
8
|
+
/** 'chip' (Dousan, default) or 'dot' (Siena). */
|
|
9
|
+
variant?: CursorVariant;
|
|
10
|
+
/** dot: the word when nothing under the pointer gives one. */
|
|
11
|
+
text?: string;
|
|
12
|
+
arrows?: CursorOptions['arrows'];
|
|
13
|
+
/** CSS selector of the zone (dot: default the parent). */
|
|
14
|
+
zone?: string;
|
|
15
|
+
className?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Put <Cursor /> once in the layout (chip), or inside the zone (dot). */
|
|
19
|
+
export function Cursor({ variant = 'chip', text, arrows, zone, className }: CursorProps) {
|
|
20
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
21
|
+
useIsomorphicLayoutEffect(() => {
|
|
22
|
+
const cursor = createCursor(ref.current, { variant, text, arrows, zone: zone ? document.querySelector(zone) : undefined });
|
|
23
|
+
return () => cursor.destroy();
|
|
24
|
+
}, [variant, text, arrows, zone]);
|
|
25
|
+
return <div ref={ref} className={className} />;
|
|
26
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# dialog
|
|
2
|
+
|
|
3
|
+
El diálogo de Stepbro sobre `<dialog>` nativo (foco atrapado, Escape, capa superior). El botón que lo abre se convierte en el diálogo y al cerrar vuelve a él.
|
|
4
|
+
|
|
5
|
+
- **Abrir desde el botón (morph):** la superficie viaja recortada desde el rect del botón en 0.7 s con la curva signature y toma su color en 0.3 s; el contenido crece como grupo desde la caja del botón con blur 8 → 0. El botón se oculta en 80 ms mientras está "dentro".
|
|
6
|
+
- **Elementos compartidos:** `data-mk-shared="titulo"` en una pieza del botón y otra del diálogo: el texto vuela de una a otra (0.7 s al abrir, 0.5 s al cerrar).
|
|
7
|
+
- **Sin botón en pantalla:** escala .92 → 1 en 0.35 s (`power2.out`).
|
|
8
|
+
- **Cerrar:** el diálogo se cierra al instante (el foco vuelve y la página responde) mientras una copia inerte se pliega al botón: forma 0.5 s, contenido con blur → 32 px (`.37,.35,0,1`) y fundido (`.56,.27,0,1`), velo `power3.in`; el botón reaparece 0.3 s tras 0.2 s. Sin botón: escala .9 + blur 32.
|
|
9
|
+
- **Líquido** (`variant="liquid"`): dos blobs bajo filtro goo; posición con resorte 144/14 y patada de 2400 px/s, tamaño 0.3 s `cubic(.8,.3,.5,.8)`, radio 0.7 s, contenido `scale 2 → 1` y blur 8 → 0, color 0.4 s tras 0.15 s. Cierre con resorte 130/18.
|
|
10
|
+
- **Backdrop:** tinte 0.5 s con la curva signature (`linear()` de Stepbro).
|
|
11
|
+
- **Auto-resize:** si el contenido crece o se encoge, la altura se ajusta en 0.45 s (signature).
|
|
12
|
+
- **Arrastrar para cerrar:** sigue al puntero a la mitad y encoge (`1 − y/400`); pasados 100 px se cierra donde quedó, si no vuelve con `elastic.out(.5,.5)` 0.5 s. También con la rueda. Ignora controles, áreas con scroll y `[data-mk-no-drag]`.
|
|
13
|
+
- **Ventana flotante** (`float="clave"`, escritorio ≥ 680 px): el asa la levanta (la página sigue usable), se mueve con resorte 1100/38 e inercia, se queda dentro de la pantalla, se redimensiona por las esquinas (mín. 320 × 240) y recuerda su sitio. Un clic en el asa la devuelve.
|
|
14
|
+
- **Móvil (< 680 px):** pantalla completa, radio 0.
|
|
15
|
+
|
|
16
|
+
Origen: Stepbro ModalHost (`modal-origin`, `modal-close-origin`, `modal-fallback`, `modal-liquid`, `modal-auto-resize`, `modal-drag`, `modal-float` en el kit); motores portados de Kayro. Medidas observadas: 400 px de ancho y radio 40 en escritorio.
|
|
17
|
+
|
|
18
|
+
- **Sheet** (`variant="sheet"`, de Dousan Miao): la hoja sube desde abajo (`y 100% → 0`, 0.72 s `cubic-bezier(.16,1,.3,1)`) y lo marcado con `[data-mk-underlay]` se hunde a escala .98 y opacidad .4 con un resorte 300/30. Al cerrar, una copia inerte cae por debajo de la pantalla y el foco vuelve al instante. No sale del botón. Mientras está abierta, la página no hace scroll.
|
|
19
|
+
|
|
20
|
+
## HTML / Astro
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<button class="mk-button" data-mk-open="crear">Crear proyecto</button>
|
|
24
|
+
|
|
25
|
+
<mk-dialog id="crear" heading="Crear proyecto" description="Se guarda en tu espacio.">
|
|
26
|
+
<label class="mk-field"><span class="mk-field__label">Nombre</span><input /></label>
|
|
27
|
+
<div data-mk-part="footer">
|
|
28
|
+
<button class="mk-button mk-button--text" data-mk-close>Cancelar</button>
|
|
29
|
+
<button class="mk-button mk-button--primary">Crear</button>
|
|
30
|
+
</div>
|
|
31
|
+
</mk-dialog>
|
|
32
|
+
|
|
33
|
+
<script>
|
|
34
|
+
import { defineElements } from '@yewdiel21/motion-kit/elements';
|
|
35
|
+
defineElements(['mk-dialog']);
|
|
36
|
+
</script>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Sin `heading`, tus hijos van dentro tal cual si ya usan partes (`data-mk-part="header|body|footer"`), o dentro de un cuerpo si no. Sobre tu propio `<dialog class="mk-dialog">`: `createDialog(dialog, opciones)`.
|
|
40
|
+
|
|
41
|
+
## React
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
<Dialog.Root variant="liquid" onOpenChange={setOpen}>
|
|
45
|
+
<Dialog.Trigger className="mk-button">Crear</Dialog.Trigger>
|
|
46
|
+
<Dialog.Content>
|
|
47
|
+
<Dialog.Header>
|
|
48
|
+
<div><Dialog.Title>Crear proyecto</Dialog.Title></div>
|
|
49
|
+
<Dialog.Actions><Dialog.Close /></Dialog.Actions>
|
|
50
|
+
</Dialog.Header>
|
|
51
|
+
<Dialog.Body>…</Dialog.Body>
|
|
52
|
+
<Dialog.Footer>…</Dialog.Footer>
|
|
53
|
+
</Dialog.Content>
|
|
54
|
+
</Dialog.Root>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Las opciones van en `Dialog.Root` (`variant`, `placement`, `float`…). Controlado con `open` + `onOpenChange`, o libre con `defaultOpen`. `Dialog.Trigger` registra su botón como origen.
|
|
58
|
+
|
|
59
|
+
## Opciones
|
|
60
|
+
|
|
61
|
+
| Opción | Atributo | Por defecto | Qué hace |
|
|
62
|
+
|---|---|---|---|
|
|
63
|
+
| `variant` | `variant` | `'morph'` | `'liquid'` para la versión líquida; `'sheet'` para la hoja que sube desde abajo (Dousan) |
|
|
64
|
+
| `placement` | `placement` | `'center'` | `'anchor'` junto al botón, `'side'` panel lateral |
|
|
65
|
+
| `backdrop` | `no-backdrop` | `true` | Velo tintado |
|
|
66
|
+
| `closeOnBackdrop` | `persistent` | `true` | Clic fuera cierra |
|
|
67
|
+
| `drag` | `no-drag` | `true` | Arrastrar para cerrar |
|
|
68
|
+
| `float` | `float="clave"` | `false` | Ventana flotante (necesita un `[data-mk-part="handle"]`; con `heading` se crea) |
|
|
69
|
+
| `autoResize` | — | `true` | Ajuste suave de altura |
|
|
70
|
+
| `triggers` | (el `id`) | `true` | `[data-mk-open="<id>"]` lo abre |
|
|
71
|
+
| `modal` | — | `true` | Modal o no |
|
|
72
|
+
| `labels` | `close-label` | `{ close: 'Cerrar', float, dock }` | Textos accesibles |
|
|
73
|
+
| `size` | `size` | `md` (400 px) | `sm` 360, `lg` 640, `xl` 960 |
|
|
74
|
+
|
|
75
|
+
## Sheet
|
|
76
|
+
|
|
77
|
+
```html
|
|
78
|
+
<main data-mk-underlay>…la página…</main>
|
|
79
|
+
<button class="mk-button" data-mk-open="proyecto">Ver proyecto</button>
|
|
80
|
+
<mk-dialog id="proyecto" variant="sheet" heading="Private Space">…</mk-dialog>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
<Dialog.Root variant="sheet">
|
|
85
|
+
<Dialog.Trigger>Ver proyecto</Dialog.Trigger>
|
|
86
|
+
<Dialog.Content>…</Dialog.Content>
|
|
87
|
+
</Dialog.Root>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Ancho hasta `--mk-sheet-max-width` (720px), alto hasta `100dvh − 24px`, radio solo arriba; en el móvil ocupa todo el ancho. Se cierra con Escape, con el fondo, arrastrando hacia abajo o con `[data-mk-close]`. Con movimiento reducido aparece y desaparece sin animar y la página de detrás no cambia. Funciones sueltas: `sheetOpen`, `sheetClose`, `pushUnderlay`, `releaseUnderlay`.
|
|
91
|
+
|
|
92
|
+
Origen: dousanmiao.com, panel de proyecto a pantalla completa (`modal-project-fullscreen`).
|
|
93
|
+
|
|
94
|
+
## Controles y eventos
|
|
95
|
+
|
|
96
|
+
`open(origen?)`, `close()`, `toggle(origen?)`, `float()`, `dock()`, `isOpen`, `isFloating`, `destroy()`.
|
|
97
|
+
Eventos que burbujean desde el `<dialog>`: `mk:open` (`detail.origin`), `mk:close` (cancelable; `detail.inPlace` tras un arrastre), `mk:closed`.
|
|
98
|
+
Cualquier `[data-mk-part="close"]` o `[data-mk-close]` dentro lo cierra.
|
|
99
|
+
|
|
100
|
+
## Variables CSS
|
|
101
|
+
|
|
102
|
+
`--mk-dialog-bg` (surface-2), `--mk-dialog-radius` (40px), `--mk-dialog-width` (400px), `--mk-dialog-padding` (24px), `--mk-dialog-shadow`.
|
|
103
|
+
|
|
104
|
+
## Accesibilidad
|
|
105
|
+
|
|
106
|
+
`<dialog>` nativo: foco atrapado, Escape, fondo inerte. El título (`data-mk-part="title"`) nombra el diálogo y la descripción lo describe. El foco va al primer campo al abrir y vuelve al botón al cerrar. Con movimiento reducido abre y cierra sin viaje ni arrastre.
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/* dialog — Stepbro's modal surface: 400 px, radius 40, tonal surface; full screen under 680 px. */
|
|
2
|
+
.mk-dialog {
|
|
3
|
+
--mk-dialog-bg: var(--mk-surface-2);
|
|
4
|
+
--mk-dialog-radius: var(--mk-radius-dialog);
|
|
5
|
+
--mk-dialog-width: 400px;
|
|
6
|
+
--mk-dialog-padding: 24px;
|
|
7
|
+
--mk-dialog-shadow: 0 24px 64px -16px rgb(0 0 0 / 0.35);
|
|
8
|
+
width: min(var(--mk-dialog-width), calc(100vw - 32px));
|
|
9
|
+
max-width: none;
|
|
10
|
+
max-height: min(88dvh, calc(100dvh - 32px));
|
|
11
|
+
margin: auto;
|
|
12
|
+
padding: 0;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
border: 0;
|
|
15
|
+
border-radius: var(--mk-dialog-radius);
|
|
16
|
+
background: var(--mk-dialog-bg);
|
|
17
|
+
box-shadow: var(--mk-dialog-shadow);
|
|
18
|
+
color: var(--mk-text);
|
|
19
|
+
font-family: var(--mk-font);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.mk-dialog[open] {
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.mk-dialog--sm {
|
|
28
|
+
--mk-dialog-width: 360px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.mk-dialog--lg {
|
|
32
|
+
--mk-dialog-width: 640px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.mk-dialog--xl {
|
|
36
|
+
--mk-dialog-width: 960px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.mk-dialog::backdrop {
|
|
40
|
+
background: color-mix(in srgb, var(--mk-scrim, #000) 32%, transparent);
|
|
41
|
+
backdrop-filter: blur(4px);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.mk-dialog[data-mk-backdrop='none']::backdrop {
|
|
45
|
+
background: transparent;
|
|
46
|
+
backdrop-filter: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Parts */
|
|
50
|
+
.mk-dialog [data-mk-part='header'] {
|
|
51
|
+
display: flex;
|
|
52
|
+
flex: none;
|
|
53
|
+
align-items: flex-start;
|
|
54
|
+
justify-content: space-between;
|
|
55
|
+
gap: 16px;
|
|
56
|
+
padding: var(--mk-dialog-padding) var(--mk-dialog-padding) 12px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.mk-dialog [data-mk-part='header'] > :first-child {
|
|
60
|
+
min-width: 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.mk-dialog [data-mk-part='title'] {
|
|
64
|
+
margin: 0;
|
|
65
|
+
font-family: var(--md-sys-typescale-headline-small-font);
|
|
66
|
+
font-size: var(--md-sys-typescale-headline-small-size);
|
|
67
|
+
line-height: var(--md-sys-typescale-headline-small-line-height);
|
|
68
|
+
font-weight: var(--md-sys-typescale-headline-small-weight);
|
|
69
|
+
letter-spacing: -0.01em;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.mk-dialog [data-mk-part='description'] {
|
|
73
|
+
margin: 4px 0 0;
|
|
74
|
+
color: var(--mk-muted);
|
|
75
|
+
font-size: var(--md-sys-typescale-body-medium-size);
|
|
76
|
+
line-height: var(--md-sys-typescale-body-medium-line-height);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.mk-dialog [data-mk-part='actions'] {
|
|
80
|
+
display: flex;
|
|
81
|
+
flex: none;
|
|
82
|
+
gap: 4px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.mk-dialog [data-mk-part='body'] {
|
|
86
|
+
flex: 1 1 auto;
|
|
87
|
+
min-height: 0;
|
|
88
|
+
padding: 4px var(--mk-dialog-padding) var(--mk-dialog-padding);
|
|
89
|
+
overflow-y: auto;
|
|
90
|
+
overscroll-behavior: contain;
|
|
91
|
+
scrollbar-width: thin;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.mk-dialog [data-mk-part='footer'] {
|
|
95
|
+
display: flex;
|
|
96
|
+
flex: none;
|
|
97
|
+
flex-wrap: wrap;
|
|
98
|
+
align-items: center;
|
|
99
|
+
justify-content: flex-end;
|
|
100
|
+
gap: 8px;
|
|
101
|
+
padding: 12px var(--mk-dialog-padding) var(--mk-dialog-padding);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.mk-dialog :is([data-mk-part='close'], [data-mk-part='handle']) {
|
|
105
|
+
display: inline-grid;
|
|
106
|
+
flex: none;
|
|
107
|
+
place-items: center;
|
|
108
|
+
width: 40px;
|
|
109
|
+
height: 40px;
|
|
110
|
+
padding: 0;
|
|
111
|
+
border: 0;
|
|
112
|
+
border-radius: 50%;
|
|
113
|
+
background: transparent;
|
|
114
|
+
color: var(--mk-muted);
|
|
115
|
+
cursor: pointer;
|
|
116
|
+
transition:
|
|
117
|
+
background-color 0.2s ease,
|
|
118
|
+
color 0.2s ease;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.mk-dialog :is([data-mk-part='close'], [data-mk-part='handle']):hover {
|
|
122
|
+
background: color-mix(in srgb, currentColor 10%, transparent);
|
|
123
|
+
color: var(--mk-text);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.mk-dialog :is([data-mk-part='close'], [data-mk-part='handle']):focus-visible {
|
|
127
|
+
outline: 2px solid var(--mk-accent);
|
|
128
|
+
outline-offset: 2px;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* Container transform helpers (motion/morph.ts). */
|
|
132
|
+
.mk-morph-face {
|
|
133
|
+
position: absolute;
|
|
134
|
+
inset: 0;
|
|
135
|
+
z-index: 2147483647;
|
|
136
|
+
border-radius: inherit;
|
|
137
|
+
pointer-events: none;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* The opener hides as its surface starts (80 ms) and stays out of reach while inside it. */
|
|
141
|
+
[data-mk-morph-origin] {
|
|
142
|
+
opacity: 0 !important;
|
|
143
|
+
transition: opacity 80ms ease !important;
|
|
144
|
+
pointer-events: none;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
[data-mk-shared-hidden] {
|
|
148
|
+
opacity: 0 !important;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Placement */
|
|
152
|
+
.mk-dialog[data-mk-placement='anchor'] {
|
|
153
|
+
max-height: calc(100dvh - 32px);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.mk-dialog[data-mk-placement='side'] {
|
|
157
|
+
position: fixed;
|
|
158
|
+
inset: 8px 8px 8px auto;
|
|
159
|
+
width: min(440px, calc(100vw - 16px));
|
|
160
|
+
height: calc(100dvh - 16px);
|
|
161
|
+
max-height: none;
|
|
162
|
+
margin: 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Floating window (motion/floating.ts) */
|
|
166
|
+
.mk-dialog:popover-open {
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-direction: column;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.mk-dialog.is-floating {
|
|
172
|
+
z-index: 50;
|
|
173
|
+
box-shadow: rgb(0 0 0 / 0.24) 0 0 24px -6px;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.mk-float-corner {
|
|
177
|
+
position: absolute;
|
|
178
|
+
z-index: 3;
|
|
179
|
+
display: none;
|
|
180
|
+
width: 18px;
|
|
181
|
+
height: 18px;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.mk-dialog.is-floating .mk-float-corner {
|
|
185
|
+
display: block;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.mk-float-corner[data-mk-float-corner='tl'] {
|
|
189
|
+
top: 0;
|
|
190
|
+
left: 0;
|
|
191
|
+
cursor: nwse-resize;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.mk-float-corner[data-mk-float-corner='br'] {
|
|
195
|
+
right: 0;
|
|
196
|
+
bottom: 0;
|
|
197
|
+
cursor: nwse-resize;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.mk-float-corner[data-mk-float-corner='tr'] {
|
|
201
|
+
top: 0;
|
|
202
|
+
right: 0;
|
|
203
|
+
cursor: nesw-resize;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.mk-float-corner[data-mk-float-corner='bl'] {
|
|
207
|
+
bottom: 0;
|
|
208
|
+
left: 0;
|
|
209
|
+
cursor: nesw-resize;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* The custom element only wraps its <dialog>; before it is defined its content stays hidden. */
|
|
213
|
+
mk-dialog {
|
|
214
|
+
display: contents;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
mk-dialog:not(:defined) {
|
|
218
|
+
display: none;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* Phones: dialogs take the whole screen with square corners (Stepbro's responsive rules). */
|
|
222
|
+
@media (max-width: 679px) {
|
|
223
|
+
.mk-dialog:not([data-mk-placement='anchor']) {
|
|
224
|
+
width: 100vw;
|
|
225
|
+
height: 100dvh;
|
|
226
|
+
max-height: none;
|
|
227
|
+
margin: 0;
|
|
228
|
+
border-radius: 0;
|
|
229
|
+
padding: env(safe-area-inset-top) env(safe-area-inset-right) 0 env(safe-area-inset-left);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.mk-dialog [data-mk-part='handle'] {
|
|
233
|
+
display: none;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.mk-dialog [data-mk-part='footer'] {
|
|
237
|
+
padding-bottom: calc(var(--mk-dialog-padding) + env(safe-area-inset-bottom));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* Sheet (Dousan): pinned to the bottom, up to 720 px wide, rises from below. Also on phones. */
|
|
242
|
+
.mk-dialog[data-mk-variant='sheet'] {
|
|
243
|
+
--mk-dialog-width: var(--mk-sheet-max-width, 720px);
|
|
244
|
+
/* A modal <dialog> is inset: 0 — anchored only to the bottom, it takes its content's height. */
|
|
245
|
+
inset: auto 0 0;
|
|
246
|
+
width: min(var(--mk-dialog-width), 100vw);
|
|
247
|
+
height: auto;
|
|
248
|
+
max-height: calc(100dvh - 24px);
|
|
249
|
+
margin: 0 auto;
|
|
250
|
+
padding: 0 0 env(safe-area-inset-bottom);
|
|
251
|
+
border-radius: var(--mk-dialog-radius) var(--mk-dialog-radius) 0 0;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@media (prefers-reduced-motion: reduce) {
|
|
255
|
+
.mk-dialog :is([data-mk-part='close'], [data-mk-part='handle']) {
|
|
256
|
+
transition: none;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { MkElement, defineElement, type OptionType } from '../../elements/base';
|
|
2
|
+
import type { Instance } from '../../core/types';
|
|
3
|
+
import { iconSvg } from '../icons';
|
|
4
|
+
import { createDialog, type DialogInstance, type DialogPlacement, type DialogVariant } from './engine';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* <mk-dialog id="crear" heading="Crear proyecto" [description] [shared="id"] [variant="liquid"]
|
|
8
|
+
* [placement="anchor|side"] [size="sm|lg|xl"] [float="key"] [no-backdrop] [persistent] [no-drag]>…</mk-dialog>
|
|
9
|
+
* Any [data-mk-open="crear"] opens it from that button. On connect its children
|
|
10
|
+
* move into a <dialog class="mk-dialog"> (with `heading`, a header with title and
|
|
11
|
+
* close button and a body are made for them); on disconnect they move back.
|
|
12
|
+
*/
|
|
13
|
+
export class MkDialogElement extends MkElement<Instance> {
|
|
14
|
+
static options: Record<string, OptionType> = {
|
|
15
|
+
variant: 'string',
|
|
16
|
+
placement: 'string',
|
|
17
|
+
size: 'string',
|
|
18
|
+
heading: 'string',
|
|
19
|
+
description: 'string',
|
|
20
|
+
float: 'string',
|
|
21
|
+
noBackdrop: 'boolean',
|
|
22
|
+
persistent: 'boolean',
|
|
23
|
+
noDrag: 'boolean',
|
|
24
|
+
closeLabel: 'string',
|
|
25
|
+
shared: 'string',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
dialog: DialogInstance | null = null;
|
|
29
|
+
|
|
30
|
+
protected create(options: Record<string, unknown>): Instance {
|
|
31
|
+
const original = [...this.childNodes];
|
|
32
|
+
const dialog = document.createElement('dialog');
|
|
33
|
+
dialog.className = 'mk-dialog';
|
|
34
|
+
if (options.size && options.size !== 'md') dialog.classList.add(`mk-dialog--${options.size}`);
|
|
35
|
+
const hasParts = original.some((node) => node instanceof Element && node.matches('[data-mk-part]'));
|
|
36
|
+
const closeLabel = (options.closeLabel as string | undefined) ?? 'Cerrar';
|
|
37
|
+
if (options.heading) {
|
|
38
|
+
const header = document.createElement('header');
|
|
39
|
+
header.dataset.mkPart = 'header';
|
|
40
|
+
const text = document.createElement('div');
|
|
41
|
+
const title = document.createElement('h2');
|
|
42
|
+
title.dataset.mkPart = 'title';
|
|
43
|
+
title.textContent = options.heading as string;
|
|
44
|
+
if (options.shared) title.dataset.mkShared = options.shared as string;
|
|
45
|
+
text.append(title);
|
|
46
|
+
if (options.description) {
|
|
47
|
+
const description = document.createElement('p');
|
|
48
|
+
description.dataset.mkPart = 'description';
|
|
49
|
+
description.textContent = options.description as string;
|
|
50
|
+
text.append(description);
|
|
51
|
+
}
|
|
52
|
+
const actions = document.createElement('div');
|
|
53
|
+
actions.dataset.mkPart = 'actions';
|
|
54
|
+
if (options.float) {
|
|
55
|
+
const handle = document.createElement('button');
|
|
56
|
+
handle.type = 'button';
|
|
57
|
+
handle.dataset.mkPart = 'handle';
|
|
58
|
+
handle.innerHTML = iconSvg('expand', 18);
|
|
59
|
+
actions.append(handle);
|
|
60
|
+
}
|
|
61
|
+
const close = document.createElement('button');
|
|
62
|
+
close.type = 'button';
|
|
63
|
+
close.dataset.mkPart = 'close';
|
|
64
|
+
close.setAttribute('aria-label', closeLabel);
|
|
65
|
+
close.innerHTML = iconSvg('close');
|
|
66
|
+
actions.append(close);
|
|
67
|
+
header.append(text, actions);
|
|
68
|
+
const body = document.createElement('div');
|
|
69
|
+
body.dataset.mkPart = 'body';
|
|
70
|
+
// A footer stays out of the scrolling body.
|
|
71
|
+
const isFooter = (node: Node) => node instanceof Element && node.matches('[data-mk-part="footer"]');
|
|
72
|
+
body.append(...original.filter((node) => !isFooter(node)));
|
|
73
|
+
dialog.append(header, body, ...original.filter(isFooter));
|
|
74
|
+
} else if (hasParts) {
|
|
75
|
+
dialog.append(...original);
|
|
76
|
+
} else {
|
|
77
|
+
const body = document.createElement('div');
|
|
78
|
+
body.dataset.mkPart = 'body';
|
|
79
|
+
body.append(...original);
|
|
80
|
+
dialog.append(body);
|
|
81
|
+
}
|
|
82
|
+
this.append(dialog);
|
|
83
|
+
|
|
84
|
+
const engine = createDialog(dialog, {
|
|
85
|
+
variant: (options.variant as DialogVariant) ?? 'morph',
|
|
86
|
+
placement: (options.placement as DialogPlacement) ?? 'center',
|
|
87
|
+
backdrop: !options.noBackdrop,
|
|
88
|
+
closeOnBackdrop: !options.persistent,
|
|
89
|
+
drag: !options.noDrag,
|
|
90
|
+
float: (options.float as string) || false,
|
|
91
|
+
triggers: this.id || false,
|
|
92
|
+
labels: { close: closeLabel },
|
|
93
|
+
});
|
|
94
|
+
this.dialog = engine;
|
|
95
|
+
return {
|
|
96
|
+
destroy: () => {
|
|
97
|
+
engine.destroy();
|
|
98
|
+
this.append(...original);
|
|
99
|
+
dialog.remove();
|
|
100
|
+
this.dialog = null;
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
open(origin?: HTMLElement | null) {
|
|
106
|
+
this.dialog?.open(origin);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
close() {
|
|
110
|
+
this.dialog?.close();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
get isOpen() {
|
|
114
|
+
return this.dialog?.isOpen ?? false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export const defineDialog = () => defineElement('mk-dialog', MkDialogElement);
|