@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.
Files changed (391) hide show
  1. package/NOTICE +38 -0
  2. package/README.md +80 -2
  3. package/bin/motion-kit.mjs +242 -0
  4. package/css.d.ts +2 -0
  5. package/dist/auto/index.d.ts +63 -0
  6. package/dist/auto/index.js +207 -0
  7. package/dist/auto/index.js.map +1 -0
  8. package/dist/chunk-2BQGFOA7.js +177 -0
  9. package/dist/chunk-2BQGFOA7.js.map +1 -0
  10. package/dist/chunk-34XYOXHG.js +2374 -0
  11. package/dist/chunk-34XYOXHG.js.map +1 -0
  12. package/dist/chunk-6OJAP6ZL.js +832 -0
  13. package/dist/chunk-6OJAP6ZL.js.map +1 -0
  14. package/dist/chunk-ABNRDDO7.js +28 -0
  15. package/dist/chunk-ABNRDDO7.js.map +1 -0
  16. package/dist/chunk-FS2HJVVY.js +3320 -0
  17. package/dist/chunk-FS2HJVVY.js.map +1 -0
  18. package/dist/chunk-J27KH2A2.js +157 -0
  19. package/dist/chunk-J27KH2A2.js.map +1 -0
  20. package/dist/chunk-KLY5BRRI.js +18 -0
  21. package/dist/chunk-KLY5BRRI.js.map +1 -0
  22. package/dist/chunk-Q4LVFNLN.js +1617 -0
  23. package/dist/chunk-Q4LVFNLN.js.map +1 -0
  24. package/dist/chunk-RFDIZYFX.js +304 -0
  25. package/dist/chunk-RFDIZYFX.js.map +1 -0
  26. package/dist/chunk-TGV27ZWM.js +17 -0
  27. package/dist/chunk-TGV27ZWM.js.map +1 -0
  28. package/dist/confetti-BSX1CLLV.d.ts +41 -0
  29. package/dist/css/components/chat-background.css +87 -0
  30. package/dist/css/components/chat.css +237 -0
  31. package/dist/css/components/cursor.css +178 -0
  32. package/dist/css/components/dialog.css +259 -0
  33. package/dist/css/components/island.css +301 -0
  34. package/dist/css/components/menu.css +105 -0
  35. package/dist/css/components/nav.css +1054 -0
  36. package/dist/css/components/steps.css +50 -0
  37. package/dist/css/components/theme-picker.css +115 -0
  38. package/dist/css/components/toast.css +115 -0
  39. package/dist/css/controls.css +950 -0
  40. package/dist/css/effects.css +587 -0
  41. package/dist/css/fonts.css +3 -0
  42. package/dist/css/themes/black-green.css +126 -0
  43. package/dist/css/themes/black.css +126 -0
  44. package/dist/css/themes/blue.css +126 -0
  45. package/dist/css/themes/brown.css +126 -0
  46. package/dist/css/themes/cold-blue.css +126 -0
  47. package/dist/css/themes/funny.css +126 -0
  48. package/dist/css/themes/gray.css +126 -0
  49. package/dist/css/themes/green.css +126 -0
  50. package/dist/css/themes/modern-1.css +126 -0
  51. package/dist/css/themes/neogreen.css +126 -0
  52. package/dist/css/themes/new.css +126 -0
  53. package/dist/css/themes/new2.css +126 -0
  54. package/dist/css/themes/oled.css +126 -0
  55. package/dist/css/themes/orange.css +126 -0
  56. package/dist/css/themes/pastel-pink.css +126 -0
  57. package/dist/css/themes/pink.css +126 -0
  58. package/dist/css/themes/purple.css +126 -0
  59. package/dist/css/themes/red.css +126 -0
  60. package/dist/css/themes/super-blue.css +126 -0
  61. package/dist/css/themes.css +2431 -0
  62. package/dist/css/tokens.css +452 -0
  63. package/dist/elements/index.d.ts +183 -0
  64. package/dist/elements/index.js +472 -0
  65. package/dist/elements/index.js.map +1 -0
  66. package/dist/engine-CUr9QijM.d.ts +46 -0
  67. package/dist/gl/index.d.ts +61 -0
  68. package/dist/gl/index.js +18 -0
  69. package/dist/gl/index.js.map +1 -0
  70. package/dist/index.css +5296 -0
  71. package/dist/index.d.ts +440 -0
  72. package/dist/index.js +390 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/react/index.d.ts +476 -0
  75. package/dist/react/index.js +969 -0
  76. package/dist/react/index.js.map +1 -0
  77. package/dist/reduced-BM4Ls0g5.d.ts +566 -0
  78. package/dist/reveal-WFUWDrei.d.ts +416 -0
  79. package/dist/store-Bqy_obnD.d.ts +195 -0
  80. package/dist/theme/generate.d.ts +18 -0
  81. package/dist/theme/generate.js +64 -0
  82. package/dist/theme/generate.js.map +1 -0
  83. package/dist/theme/index.d.ts +17 -0
  84. package/dist/theme/index.js +32 -0
  85. package/dist/theme/index.js.map +1 -0
  86. package/dist/theme-BFMoCzi6.d.ts +158 -0
  87. package/dist/types-BkS_raL8.d.ts +7 -0
  88. package/package.json +114 -3
  89. package/registry.json +469 -0
  90. package/skills/motion-kit/SKILL.md +189 -0
  91. package/skills/motion-kit/reference/components.md +86 -0
  92. package/skills/motion-kit/reference/design.md +92 -0
  93. package/skills/motion-kit/reference/recipes.md +172 -0
  94. package/src/auto/auto-init.ts +151 -0
  95. package/src/auto/index.ts +3 -0
  96. package/src/auto/parse-options.ts +68 -0
  97. package/src/components/chat/README.md +90 -0
  98. package/src/components/chat/chat.css +236 -0
  99. package/src/components/chat/element.ts +98 -0
  100. package/src/components/chat/engine.ts +295 -0
  101. package/src/components/chat/react.tsx +196 -0
  102. package/src/components/chat-background/README.md +50 -0
  103. package/src/components/chat-background/audio.ts +56 -0
  104. package/src/components/chat-background/chat-background.css +86 -0
  105. package/src/components/chat-background/element.ts +31 -0
  106. package/src/components/chat-background/engine.ts +108 -0
  107. package/src/components/chat-background/react.tsx +36 -0
  108. package/src/components/cursor/README.md +53 -0
  109. package/src/components/cursor/cursor.css +177 -0
  110. package/src/components/cursor/element.ts +23 -0
  111. package/src/components/cursor/engine.ts +254 -0
  112. package/src/components/cursor/react.tsx +26 -0
  113. package/src/components/dialog/README.md +106 -0
  114. package/src/components/dialog/dialog.css +258 -0
  115. package/src/components/dialog/element.ts +118 -0
  116. package/src/components/dialog/engine.ts +432 -0
  117. package/src/components/dialog/react.tsx +200 -0
  118. package/src/components/icon.tsx +10 -0
  119. package/src/components/icons.ts +24 -0
  120. package/src/components/island/README.md +91 -0
  121. package/src/components/island/element.ts +45 -0
  122. package/src/components/island/engine.ts +200 -0
  123. package/src/components/island/island.css +300 -0
  124. package/src/components/island/react.tsx +115 -0
  125. package/src/components/menu/README.md +67 -0
  126. package/src/components/menu/element.ts +55 -0
  127. package/src/components/menu/engine.ts +142 -0
  128. package/src/components/menu/menu.css +104 -0
  129. package/src/components/menu/react.tsx +82 -0
  130. package/src/components/nav/README.md +85 -0
  131. package/src/components/nav/element.ts +39 -0
  132. package/src/components/nav/engine.ts +164 -0
  133. package/src/components/nav/nav.css +1053 -0
  134. package/src/components/nav/react.tsx +90 -0
  135. package/src/components/steps/README.md +70 -0
  136. package/src/components/steps/element.ts +43 -0
  137. package/src/components/steps/engine.ts +185 -0
  138. package/src/components/steps/react.tsx +91 -0
  139. package/src/components/steps/steps.css +49 -0
  140. package/src/components/theme-picker/README.md +57 -0
  141. package/src/components/theme-picker/element.ts +20 -0
  142. package/src/components/theme-picker/engine.ts +91 -0
  143. package/src/components/theme-picker/react.tsx +31 -0
  144. package/src/components/theme-picker/theme-picker.css +114 -0
  145. package/src/components/toast/README.md +60 -0
  146. package/src/components/toast/element.ts +25 -0
  147. package/src/components/toast/engine.ts +483 -0
  148. package/src/components/toast/react.tsx +22 -0
  149. package/src/components/toast/store.ts +122 -0
  150. package/src/components/toast/toast.css +114 -0
  151. package/src/core/channels.ts +165 -0
  152. package/src/core/curves.ts +35 -0
  153. package/src/core/frame.ts +12 -0
  154. package/src/core/gsap.ts +65 -0
  155. package/src/core/loop.ts +44 -0
  156. package/src/core/math.ts +9 -0
  157. package/src/core/physics-spring.ts +59 -0
  158. package/src/core/pointer.ts +63 -0
  159. package/src/core/reduced.ts +21 -0
  160. package/src/core/scope.ts +70 -0
  161. package/src/core/scroll-track.ts +106 -0
  162. package/src/core/split.ts +68 -0
  163. package/src/core/spring.ts +22 -0
  164. package/src/core/styles.ts +31 -0
  165. package/src/core/timing.ts +204 -0
  166. package/src/core/types.ts +20 -0
  167. package/src/core/visible.ts +19 -0
  168. package/src/css/base.css +142 -0
  169. package/src/css/controls/README.md +122 -0
  170. package/src/css/controls/burger.css +67 -0
  171. package/src/css/controls/button.css +226 -0
  172. package/src/css/controls/checkbox.css +53 -0
  173. package/src/css/controls/chip.css +85 -0
  174. package/src/css/controls/field.css +124 -0
  175. package/src/css/controls/glass.css +220 -0
  176. package/src/css/controls/icon.css +26 -0
  177. package/src/css/controls/segmented.css +60 -0
  178. package/src/css/controls/switch.css +72 -0
  179. package/src/css/default-theme.css +123 -0
  180. package/src/css/effects/README.md +134 -0
  181. package/src/css/effects/anim.css +224 -0
  182. package/src/css/effects/fade.css +15 -0
  183. package/src/css/effects/float.css +64 -0
  184. package/src/css/effects/frost.css +62 -0
  185. package/src/css/effects/grain.css +58 -0
  186. package/src/css/effects/loading.css +60 -0
  187. package/src/css/effects/success.css +22 -0
  188. package/src/css/effects/text.css +67 -0
  189. package/src/css/fonts.css +3 -0
  190. package/src/css/states.css +51 -0
  191. package/src/css/themes/black-green.css +126 -0
  192. package/src/css/themes/black.css +126 -0
  193. package/src/css/themes/blue.css +126 -0
  194. package/src/css/themes/brown.css +126 -0
  195. package/src/css/themes/cold-blue.css +126 -0
  196. package/src/css/themes/funny.css +126 -0
  197. package/src/css/themes/gray.css +126 -0
  198. package/src/css/themes/green.css +126 -0
  199. package/src/css/themes/modern-1.css +126 -0
  200. package/src/css/themes/neogreen.css +126 -0
  201. package/src/css/themes/new.css +126 -0
  202. package/src/css/themes/new2.css +126 -0
  203. package/src/css/themes/oled.css +126 -0
  204. package/src/css/themes/orange.css +126 -0
  205. package/src/css/themes/pastel-pink.css +126 -0
  206. package/src/css/themes/pink.css +126 -0
  207. package/src/css/themes/purple.css +126 -0
  208. package/src/css/themes/red.css +126 -0
  209. package/src/css/themes/super-blue.css +126 -0
  210. package/src/css/tokens.css +182 -0
  211. package/src/elements/base.ts +76 -0
  212. package/src/elements/index.ts +48 -0
  213. package/src/gl/index.ts +15 -0
  214. package/src/gl/liquid-blend/README.md +23 -0
  215. package/src/gl/liquid-blend/create-liquid-blend.ts +7 -0
  216. package/src/gl/liquid-blend/shader.ts +9 -0
  217. package/src/gl/matcap/README.md +23 -0
  218. package/src/gl/matcap/create-matcap.ts +7 -0
  219. package/src/gl/matcap/shader.ts +16 -0
  220. package/src/gl/particle-hero/README.md +41 -0
  221. package/src/gl/particle-hero/create-particle-hero.ts +544 -0
  222. package/src/gl/particle-hero/particle-hero.css +19 -0
  223. package/src/gl/particle-hero/shaders.ts +84 -0
  224. package/src/gl/shader-blur/README.md +23 -0
  225. package/src/gl/shader-blur/create-shader-blur.ts +7 -0
  226. package/src/gl/shader-blur/shader.ts +11 -0
  227. package/src/gl/shader-grain/README.md +23 -0
  228. package/src/gl/shader-grain/create-shader-grain.ts +7 -0
  229. package/src/gl/shader-grain/shader.ts +6 -0
  230. package/src/gl/shared/create-shader-effect.ts +186 -0
  231. package/src/gl/shared/shader.css +3 -0
  232. package/src/gl/shared/shaders.ts +30 -0
  233. package/src/index.ts +177 -0
  234. package/src/motion/anchor.ts +45 -0
  235. package/src/motion/chat.ts +97 -0
  236. package/src/motion/confetti.ts +130 -0
  237. package/src/motion/count.ts +95 -0
  238. package/src/motion/details.ts +70 -0
  239. package/src/motion/drag-dismiss.ts +231 -0
  240. package/src/motion/effects.ts +81 -0
  241. package/src/motion/entrances.ts +27 -0
  242. package/src/motion/floating.ts +389 -0
  243. package/src/motion/flow.ts +115 -0
  244. package/src/motion/indicator.ts +44 -0
  245. package/src/motion/layout.ts +39 -0
  246. package/src/motion/liquid.ts +227 -0
  247. package/src/motion/morph.ts +540 -0
  248. package/src/motion/reveal.ts +112 -0
  249. package/src/motion/sheet.ts +65 -0
  250. package/src/motion/surface.ts +108 -0
  251. package/src/react/animated-number.tsx +30 -0
  252. package/src/react/flip-group.tsx +44 -0
  253. package/src/react/frost.tsx +33 -0
  254. package/src/react/index.ts +80 -0
  255. package/src/react/slot-text.tsx +44 -0
  256. package/src/react/theme-provider.tsx +42 -0
  257. package/src/react/use-card-dock.ts +9 -0
  258. package/src/react/use-cascade.ts +9 -0
  259. package/src/react/use-contrast.ts +9 -0
  260. package/src/react/use-counter.ts +8 -0
  261. package/src/react/use-curved-carousel.ts +10 -0
  262. package/src/react/use-depth-grid.ts +9 -0
  263. package/src/react/use-details.ts +7 -0
  264. package/src/react/use-dock-pill.ts +10 -0
  265. package/src/react/use-drag-ruler.ts +10 -0
  266. package/src/react/use-fill-text.ts +9 -0
  267. package/src/react/use-fit-text.ts +8 -0
  268. package/src/react/use-flow.ts +8 -0
  269. package/src/react/use-frame-zoom.ts +9 -0
  270. package/src/react/use-infinite-reel.ts +8 -0
  271. package/src/react/use-letters.ts +9 -0
  272. package/src/react/use-liquid-blend.ts +8 -0
  273. package/src/react/use-marquee.ts +9 -0
  274. package/src/react/use-mask-text.ts +9 -0
  275. package/src/react/use-matcap.ts +8 -0
  276. package/src/react/use-parallax.ts +9 -0
  277. package/src/react/use-particle-hero.ts +9 -0
  278. package/src/react/use-pile.ts +8 -0
  279. package/src/react/use-pop.ts +8 -0
  280. package/src/react/use-radial-menu.ts +10 -0
  281. package/src/react/use-recipe.ts +38 -0
  282. package/src/react/use-reflow.ts +9 -0
  283. package/src/react/use-repel-bento.ts +8 -0
  284. package/src/react/use-reveal.ts +8 -0
  285. package/src/react/use-rotator.ts +10 -0
  286. package/src/react/use-shader-blur.ts +8 -0
  287. package/src/react/use-shader-grain.ts +8 -0
  288. package/src/react/use-slot-text.ts +17 -0
  289. package/src/react/use-snap-strip.ts +9 -0
  290. package/src/react/use-sortable.ts +14 -0
  291. package/src/react/use-spring-cards.ts +8 -0
  292. package/src/react/use-stretch-footer.ts +20 -0
  293. package/src/react/use-tabs.ts +10 -0
  294. package/src/react/use-text-roll.ts +9 -0
  295. package/src/react/use-ticket-menu.ts +15 -0
  296. package/src/react/use-words.ts +8 -0
  297. package/src/recipes/card-dock/README.md +36 -0
  298. package/src/recipes/card-dock/card-dock.css +178 -0
  299. package/src/recipes/card-dock/create-card-dock.ts +97 -0
  300. package/src/recipes/cascade/README.md +33 -0
  301. package/src/recipes/cascade/create-cascade.ts +111 -0
  302. package/src/recipes/contrast/README.md +29 -0
  303. package/src/recipes/contrast/create-contrast.ts +68 -0
  304. package/src/recipes/counter/README.md +42 -0
  305. package/src/recipes/counter/create-counter.ts +84 -0
  306. package/src/recipes/curved-carousel/README.md +50 -0
  307. package/src/recipes/curved-carousel/carousel-math.ts +20 -0
  308. package/src/recipes/curved-carousel/create-curved-carousel.ts +257 -0
  309. package/src/recipes/curved-carousel/curved-carousel.css +50 -0
  310. package/src/recipes/depth-grid/README.md +30 -0
  311. package/src/recipes/depth-grid/create-depth-grid.ts +120 -0
  312. package/src/recipes/details/README.md +31 -0
  313. package/src/recipes/details/create-details.ts +27 -0
  314. package/src/recipes/dock-pill/README.md +23 -0
  315. package/src/recipes/dock-pill/create-dock-pill.ts +68 -0
  316. package/src/recipes/dock-pill/dock-pill.css +5 -0
  317. package/src/recipes/drag-ruler/README.md +21 -0
  318. package/src/recipes/drag-ruler/create-drag-ruler.ts +95 -0
  319. package/src/recipes/drag-ruler/drag-ruler.css +16 -0
  320. package/src/recipes/fill-text/README.md +27 -0
  321. package/src/recipes/fill-text/create-fill-text.ts +93 -0
  322. package/src/recipes/fit-text/README.md +37 -0
  323. package/src/recipes/fit-text/create-fit-text.ts +55 -0
  324. package/src/recipes/fit-text/fit-text.css +6 -0
  325. package/src/recipes/flow/README.md +46 -0
  326. package/src/recipes/flow/create-flow.ts +55 -0
  327. package/src/recipes/frame-zoom/README.md +29 -0
  328. package/src/recipes/frame-zoom/create-frame-zoom.ts +91 -0
  329. package/src/recipes/infinite-reel/README.md +23 -0
  330. package/src/recipes/infinite-reel/create-infinite-reel.ts +140 -0
  331. package/src/recipes/infinite-reel/infinite-reel.css +8 -0
  332. package/src/recipes/letters/README.md +30 -0
  333. package/src/recipes/letters/create-letters.ts +113 -0
  334. package/src/recipes/marquee/README.md +32 -0
  335. package/src/recipes/marquee/create-marquee.ts +74 -0
  336. package/src/recipes/marquee/marquee.css +41 -0
  337. package/src/recipes/mask-text/README.md +39 -0
  338. package/src/recipes/mask-text/create-mask-text.ts +134 -0
  339. package/src/recipes/parallax/README.md +31 -0
  340. package/src/recipes/parallax/create-parallax.ts +74 -0
  341. package/src/recipes/pile/README.md +48 -0
  342. package/src/recipes/pile/create-pile.ts +50 -0
  343. package/src/recipes/pile/pile-math.ts +27 -0
  344. package/src/recipes/pile/pile.css +63 -0
  345. package/src/recipes/pill/README.md +30 -0
  346. package/src/recipes/pill/pill.css +48 -0
  347. package/src/recipes/pop/README.md +36 -0
  348. package/src/recipes/pop/create-pop.ts +52 -0
  349. package/src/recipes/radial-menu/README.md +44 -0
  350. package/src/recipes/radial-menu/create-radial-menu.ts +96 -0
  351. package/src/recipes/radial-menu/radial-menu.css +45 -0
  352. package/src/recipes/reflow/README.md +47 -0
  353. package/src/recipes/reflow/create-reflow.ts +49 -0
  354. package/src/recipes/repel-bento/README.md +21 -0
  355. package/src/recipes/repel-bento/create-repel-bento.ts +65 -0
  356. package/src/recipes/repel-bento/repel-bento.css +3 -0
  357. package/src/recipes/reveal/README.md +36 -0
  358. package/src/recipes/reveal/create-reveal.ts +48 -0
  359. package/src/recipes/rotator/README.md +21 -0
  360. package/src/recipes/rotator/create-rotator.ts +66 -0
  361. package/src/recipes/rotator/rotator.css +3 -0
  362. package/src/recipes/slot-text/README.md +44 -0
  363. package/src/recipes/slot-text/create-slot-text.ts +244 -0
  364. package/src/recipes/slot-text/slot-text.css +42 -0
  365. package/src/recipes/snap-strip/README.md +31 -0
  366. package/src/recipes/snap-strip/create-snap-strip.ts +133 -0
  367. package/src/recipes/snap-strip/snap-strip.css +23 -0
  368. package/src/recipes/sortable/README.md +88 -0
  369. package/src/recipes/sortable/create-sortable.ts +863 -0
  370. package/src/recipes/sortable/sortable.css +40 -0
  371. package/src/recipes/spring-cards/README.md +48 -0
  372. package/src/recipes/spring-cards/create-spring-cards.ts +140 -0
  373. package/src/recipes/spring-cards/spring-cards.css +23 -0
  374. package/src/recipes/stretch-footer/README.md +44 -0
  375. package/src/recipes/stretch-footer/create-stretch-footer.ts +69 -0
  376. package/src/recipes/stretch-footer/stretch-footer.css +28 -0
  377. package/src/recipes/tabs/README.md +39 -0
  378. package/src/recipes/tabs/create-tabs.ts +91 -0
  379. package/src/recipes/tabs/tabs.css +19 -0
  380. package/src/recipes/text-roll/README.md +35 -0
  381. package/src/recipes/text-roll/create-text-roll.ts +137 -0
  382. package/src/recipes/text-roll/text-roll.css +21 -0
  383. package/src/recipes/ticket-menu/README.md +24 -0
  384. package/src/recipes/ticket-menu/create-ticket-menu.ts +6 -0
  385. package/src/recipes/words/README.md +43 -0
  386. package/src/recipes/words/create-words.ts +114 -0
  387. package/src/theme/css-format.ts +32 -0
  388. package/src/theme/generate.ts +72 -0
  389. package/src/theme/index.ts +15 -0
  390. package/src/theme/presets.ts +79 -0
  391. package/src/theme/theme.ts +119 -0
@@ -0,0 +1,2374 @@
1
+ import {
2
+ TIMING,
3
+ createScope,
4
+ reduced
5
+ } from "./chunk-RFDIZYFX.js";
6
+ import {
7
+ inert,
8
+ warnOnce
9
+ } from "./chunk-TGV27ZWM.js";
10
+
11
+ // src/core/curves.ts
12
+ var PATHS = {
13
+ /** The signature: a strong deceleration that is not a plain ease-out. */
14
+ signature: "M0,0 C0.308,0.19 0.107,0.633 0.288,0.866 0.382,0.987 0.656,1 1,1",
15
+ /** Lists and steps entering (`flowSoft`, also `numberSoft`). */
16
+ flow: "M0,0 C0.25,0.1 0.25,1 1,1",
17
+ /** A conversation scrolling to its newest message. */
18
+ chatScroll: "M0,0 C0.308,0.19 0.318,0.567 0.5,0.8 0.593,0.921 0.656,1 1,1"
19
+ };
20
+ function springPath(ratio, velocity = 0, steps = 72) {
21
+ const damping = Math.min(Math.max(ratio, 0.05), 0.999);
22
+ const stiffness = 5.6;
23
+ const frequency = stiffness / damping * Math.sqrt(1 - damping * damping);
24
+ const phase = (velocity - stiffness) / frequency;
25
+ const at = (time) => 1 + Math.exp(-stiffness * time) * (-Math.cos(frequency * time) + phase * Math.sin(frequency * time));
26
+ let path = "M0,0";
27
+ for (let step = 1; step <= steps; step += 1) {
28
+ const time = step / steps;
29
+ path += ` L${time.toFixed(4)},${(step === steps ? 1 : at(time)).toFixed(4)}`;
30
+ }
31
+ return path;
32
+ }
33
+ var SIGNATURE_LINEAR = "linear(0 0%, .017 2.5%, .037 5%, .061 7.5%, .091 10%, .13 12.5%, .184 15%, .275 17.5%, .562 20%, .733 22.5%, .803 25%, .848 27.5%, .88 30%, .902 32.5%, .942 40%, .97 50%, .985 60%, .993 70%, .998 80%, 1 90%, 1 100%)";
34
+
35
+ // src/core/gsap.ts
36
+ import { gsap } from "gsap";
37
+ import { ScrollTrigger } from "gsap/ScrollTrigger";
38
+ import { SplitText } from "gsap/SplitText";
39
+ import { CustomEase } from "gsap/CustomEase";
40
+ import { Flip } from "gsap/Flip";
41
+ var ELASTIC = "elastic.out(1, 0.45)";
42
+ var EASE = {
43
+ signature: "mk-signature",
44
+ flow: "mk-flow",
45
+ /** A closing surface's fade (`.56,.27,0,1`). Kept from v0.1; same curve as `fadeAway`. */
46
+ close: "mk-close",
47
+ fadeAway: "mk-fade-away",
48
+ /** A closing surface's blur (`.37,.35,0,1`). */
49
+ blurAway: "mk-blur-away",
50
+ chatScroll: "mk-chat-scroll",
51
+ /** Items travelling to a new place in a list (spring ratio .52). */
52
+ layoutReflow: "mk-layout-reflow",
53
+ /** A dragged item landing in its slot (spring ratio .62). */
54
+ sortableLand: "mk-sortable-land",
55
+ slot: "mk-slot",
56
+ slotResize: "mk-slot-resize",
57
+ liquidSize: "mk-liquid-size",
58
+ swatch: "mk-swatch",
59
+ swatchLight: "mk-swatch-light",
60
+ sheet: "mk-sheet",
61
+ inOut: "mk-in-out"
62
+ };
63
+ var CURVES = {
64
+ signature: PATHS.signature,
65
+ flow: PATHS.flow,
66
+ close: ".56,.27,0,1",
67
+ fadeAway: ".56,.27,0,1",
68
+ blurAway: ".37,.35,0,1",
69
+ chatScroll: PATHS.chatScroll,
70
+ layoutReflow: springPath(0.52),
71
+ sortableLand: springPath(0.62),
72
+ slot: ".34,1.56,.64,1",
73
+ slotResize: ".2,0,0,1",
74
+ liquidSize: ".8,.3,.5,.8",
75
+ swatch: ".38,.49,0,1.5",
76
+ swatchLight: ".11,1,0,1",
77
+ sheet: ".16,1,.3,1",
78
+ inOut: ".42,0,.58,1"
79
+ };
80
+ var registered = false;
81
+ function registerMotion() {
82
+ if (typeof window === "undefined") return;
83
+ document.documentElement.classList.add("mk-ready");
84
+ if (registered) return;
85
+ registered = true;
86
+ gsap.registerPlugin(ScrollTrigger, SplitText, CustomEase, Flip);
87
+ for (const key of Object.keys(EASE)) CustomEase.create(EASE[key], CURVES[key]);
88
+ }
89
+
90
+ // src/core/channels.ts
91
+ import { gsap as gsap2 } from "gsap";
92
+ var easeOut = (t) => 1 - (1 - t) * (1 - t);
93
+ var easeOutCubic = (t) => 1 - (1 - t) ** 3;
94
+ var easeInCubic = (t) => t * t * t;
95
+ function bezier(x1, y1, x2, y2) {
96
+ const at = (t, a, b) => {
97
+ const u = 1 - t;
98
+ return 3 * u * u * t * a + 3 * u * t * t * b + t * t * t;
99
+ };
100
+ return (progress) => {
101
+ if (progress <= 0 || progress >= 1) return Math.min(1, Math.max(0, progress));
102
+ let low = 0;
103
+ let high = 1;
104
+ let t = progress;
105
+ for (let step = 0; step < 24; step += 1) {
106
+ const x = at(t, x1, x2);
107
+ if (Math.abs(x - progress) < 1e-5) break;
108
+ if (x < progress) low = t;
109
+ else high = t;
110
+ t = (low + high) / 2;
111
+ }
112
+ return at(t, y1, y2);
113
+ };
114
+ }
115
+ var spring = (stiffness, damping, extra = {}) => ({
116
+ type: "spring",
117
+ stiffness,
118
+ damping,
119
+ ...extra
120
+ });
121
+ var eased = (duration, ease) => ({ type: "ease", duration, ease });
122
+ var createChannelState = (value) => ({
123
+ current: value,
124
+ origin: value,
125
+ target: value,
126
+ velocity: 0,
127
+ elapsed: 0,
128
+ active: false,
129
+ config: null
130
+ });
131
+ function stepChannel(channel, seconds) {
132
+ const config = channel.config;
133
+ if (!channel.active || !config) return;
134
+ if (config.type === "spring") {
135
+ const time = Math.min(0.064, Math.max(0, seconds));
136
+ const steps = Math.max(1, Math.ceil(time / (1 / 60) - 1e-9));
137
+ const step = time / steps;
138
+ for (let index = 0; index < steps; index += 1) {
139
+ const force = -config.stiffness * (channel.current - channel.target) - config.damping * channel.velocity;
140
+ channel.velocity += force / (config.mass ?? 1) * step;
141
+ channel.current += channel.velocity * step;
142
+ }
143
+ if (Math.abs(channel.velocity) <= 0.01 && Math.abs(channel.target - channel.current) <= 0.01) {
144
+ channel.current = channel.target;
145
+ channel.velocity = 0;
146
+ channel.active = false;
147
+ }
148
+ } else {
149
+ channel.elapsed += Math.max(0, seconds);
150
+ const progress = Math.min(1, channel.elapsed / config.duration);
151
+ channel.current = progress >= 1 ? channel.target : channel.origin + (channel.target - channel.origin) * config.ease(progress);
152
+ if (progress >= 1) channel.active = false;
153
+ }
154
+ }
155
+ function channels(start, onChange) {
156
+ const names = Object.keys(start);
157
+ const state = Object.fromEntries(names.map((name) => [name, createChannelState(start[name])]));
158
+ let last = 0;
159
+ let resolveDone = null;
160
+ const tick = () => {
161
+ const now = performance.now();
162
+ const elapsed = Math.max(0, (now - last) / 1e3);
163
+ last = now;
164
+ let running2 = false;
165
+ for (const name of names) {
166
+ const channel = state[name];
167
+ if (!channel.active) continue;
168
+ stepChannel(channel, elapsed);
169
+ onChange(name, channel.current);
170
+ running2 ||= channel.active;
171
+ }
172
+ if (!running2) {
173
+ gsap2.ticker.remove(tick);
174
+ resolveDone?.();
175
+ resolveDone = null;
176
+ }
177
+ };
178
+ return {
179
+ state,
180
+ /** Start moving; resolves when every channel has settled (or `stop()` is called). */
181
+ animate(targets, configs) {
182
+ for (const name of Object.keys(targets)) {
183
+ const channel = state[name];
184
+ const config = configs[name];
185
+ if (!channel || !config) continue;
186
+ channel.config = config;
187
+ channel.origin = channel.current;
188
+ channel.target = targets[name];
189
+ channel.elapsed = 0;
190
+ if (config.type === "spring" && config.velocity) {
191
+ const sign = config.direction !== void 0 ? Math.sign(config.direction) : Math.sign(channel.target - channel.current);
192
+ channel.velocity = Math.abs(config.velocity) * sign;
193
+ }
194
+ channel.active = channel.target !== channel.current || channel.velocity !== 0;
195
+ }
196
+ last = performance.now();
197
+ gsap2.ticker.remove(tick);
198
+ gsap2.ticker.add(tick);
199
+ resolveDone?.();
200
+ return new Promise((resolve) => {
201
+ resolveDone = resolve;
202
+ });
203
+ },
204
+ stop() {
205
+ gsap2.ticker.remove(tick);
206
+ for (const name of names) state[name].active = false;
207
+ resolveDone?.();
208
+ resolveDone = null;
209
+ }
210
+ };
211
+ }
212
+ function springEase(ratio, velocity = 0) {
213
+ const damping = Math.min(Math.max(ratio, 0.05), 0.999);
214
+ const stiffness = 5.6;
215
+ const frequency = stiffness / damping * Math.sqrt(1 - damping * damping);
216
+ const phase = (velocity - stiffness) / frequency;
217
+ return (progress) => progress >= 1 ? 1 : 1 + Math.exp(-stiffness * progress) * (-Math.cos(frequency * progress) + phase * Math.sin(frequency * progress));
218
+ }
219
+
220
+ // src/core/split.ts
221
+ function splitWords(el, { exclude = ["table", "pre"], className = "mk-split-word" } = {}) {
222
+ const parts = [];
223
+ const replaced = [];
224
+ const skip = exclude.join(",");
225
+ const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
226
+ const texts = [];
227
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
228
+ const parent = node.parentElement;
229
+ if (skip && parent?.closest(skip) && el.contains(parent.closest(skip))) continue;
230
+ if (node.data.trim()) texts.push(node);
231
+ }
232
+ for (const text of texts) {
233
+ const pieces = text.data.split(/(\s+)/);
234
+ const nodes = [];
235
+ for (const piece of pieces) {
236
+ if (!piece) continue;
237
+ if (/^\s+$/.test(piece)) {
238
+ nodes.push(document.createTextNode(piece));
239
+ continue;
240
+ }
241
+ const span = document.createElement("span");
242
+ span.className = className;
243
+ span.style.display = "inline-block";
244
+ span.textContent = piece;
245
+ parts.push(span);
246
+ nodes.push(span);
247
+ }
248
+ text.replaceWith(...nodes);
249
+ replaced.push([text, nodes]);
250
+ }
251
+ let reverted = false;
252
+ return {
253
+ parts,
254
+ revert() {
255
+ if (reverted) return;
256
+ reverted = true;
257
+ for (const [text, nodes] of replaced.reverse()) {
258
+ nodes[0]?.parentNode?.insertBefore(text, nodes[0]);
259
+ for (const node of nodes) node.parentNode?.removeChild(node);
260
+ }
261
+ el.normalize();
262
+ }
263
+ };
264
+ }
265
+ function splitGraphemes(text, limit = 64) {
266
+ const Ctor = Intl.Segmenter;
267
+ const all = Ctor ? Array.from(new Ctor(void 0, { granularity: "grapheme" }).segment(text), (part2) => part2.segment) : Array.from(text);
268
+ return all.slice(0, limit);
269
+ }
270
+
271
+ // src/core/frame.ts
272
+ function requestFrame(fn) {
273
+ if (typeof requestAnimationFrame === "function") {
274
+ const id2 = requestAnimationFrame(fn);
275
+ return () => cancelAnimationFrame(id2);
276
+ }
277
+ const id = setTimeout(() => fn(Date.now()), 16);
278
+ return () => clearTimeout(id);
279
+ }
280
+ var nextFrame = () => new Promise((resolve) => requestFrame(() => resolve()));
281
+
282
+ // src/core/styles.ts
283
+ function clearStyles(targets, properties) {
284
+ for (const element of targets) {
285
+ const style = element.style;
286
+ if (!style) continue;
287
+ for (const property of properties) style.removeProperty(property);
288
+ if (element.getAttribute("style") === "") element.removeAttribute("style");
289
+ delete element._gsap;
290
+ }
291
+ }
292
+ var MORPH_STYLES = [
293
+ "transform",
294
+ "translate",
295
+ "rotate",
296
+ "scale",
297
+ "transform-origin",
298
+ "clip-path",
299
+ "opacity",
300
+ "visibility",
301
+ "filter",
302
+ "will-change"
303
+ ];
304
+
305
+ // src/core/physics-spring.ts
306
+ var REST = 1e-3;
307
+ var STEP = 1 / 240;
308
+ var LIMIT = 10;
309
+ function position(stiffness, damping, mass) {
310
+ const w0 = Math.sqrt(stiffness / mass);
311
+ const zeta = damping / (2 * Math.sqrt(stiffness * mass));
312
+ if (zeta < 1) {
313
+ const wd = w0 * Math.sqrt(1 - zeta * zeta);
314
+ return (t) => 1 - Math.exp(-zeta * w0 * t) * (Math.cos(wd * t) + zeta * w0 / wd * Math.sin(wd * t));
315
+ }
316
+ if (zeta === 1) return (t) => 1 - Math.exp(-w0 * t) * (1 + w0 * t);
317
+ const root = Math.sqrt(zeta * zeta - 1);
318
+ const r1 = -w0 * (zeta - root);
319
+ const r2 = -w0 * (zeta + root);
320
+ return (t) => 1 - (r2 * Math.exp(r1 * t) - r1 * Math.exp(r2 * t)) / (r2 - r1);
321
+ }
322
+ var springs = /* @__PURE__ */ new Map();
323
+ function motionSpring(stiffness, damping, mass = 1) {
324
+ const key = `${stiffness}/${damping}/${mass}`;
325
+ const known = springs.get(key);
326
+ if (known) return known;
327
+ const x = position(Math.max(stiffness, 1e-6), Math.max(damping, 0), Math.max(mass, 1e-6));
328
+ let settled = 0;
329
+ for (let i = 0; i * STEP <= LIMIT; i++) if (Math.abs(x(i * STEP) - 1) > REST) settled = (i + 1) * STEP;
330
+ const duration = Math.round(Math.min(settled, LIMIT) * 1e3) / 1e3;
331
+ const spring2 = {
332
+ ease: (progress) => progress <= 0 ? 0 : progress >= 1 ? 1 : x(progress * duration),
333
+ duration
334
+ };
335
+ springs.set(key, spring2);
336
+ return spring2;
337
+ }
338
+ var springDuration = (stiffness, damping, mass = 1) => motionSpring(stiffness, damping, mass).duration;
339
+ function springLinear(stiffness, damping, mass = 1, points = 40) {
340
+ const { ease } = motionSpring(stiffness, damping, mass);
341
+ return `linear(${Array.from({ length: points + 1 }, (_, i) => Number(ease(i / points).toFixed(4))).join(", ")})`;
342
+ }
343
+
344
+ // src/motion/flow.ts
345
+ var CLEAR = "transform,filter,opacity,visibility";
346
+ function list(targets, target, reverse) {
347
+ let items;
348
+ if (target && targets instanceof Element) items = [...targets.querySelectorAll(target)];
349
+ else items = gsap.utils.toArray(targets);
350
+ return reverse ? items.reverse() : items;
351
+ }
352
+ function flowIn(targets, options = {}) {
353
+ registerMotion();
354
+ const {
355
+ y = 20,
356
+ blur = 16,
357
+ duration = TIMING.flow,
358
+ stagger = TIMING.flowStagger,
359
+ delay = 0,
360
+ style = 1,
361
+ startScale = 0.9,
362
+ reverse = false,
363
+ target,
364
+ ease = EASE.flow,
365
+ autoAlpha = true
366
+ } = options;
367
+ const items = list(targets, target, reverse);
368
+ if (!items.length) return null;
369
+ if (reduced()) {
370
+ clearStyles(items, ["transform", "translate", "rotate", "scale", "filter", "opacity", "visibility"]);
371
+ return null;
372
+ }
373
+ const from = style === 2 ? { scale: startScale } : { y: -y };
374
+ const to = style === 2 ? { scale: 1 } : { y: 0 };
375
+ const alpha = autoAlpha ? "autoAlpha" : "opacity";
376
+ return gsap.fromTo(
377
+ items,
378
+ { ...from, [alpha]: 0, filter: `blur(${blur}px)` },
379
+ { ...to, [alpha]: 1, filter: "blur(0px)", duration, stagger, delay, ease, clearProps: CLEAR }
380
+ );
381
+ }
382
+ function flowOut(targets, options = {}) {
383
+ registerMotion();
384
+ const { y = 20, blur = 16, duration = TIMING.flow, stagger = TIMING.flowStagger, delay = 0, reverse = false, target } = options;
385
+ const items = list(targets, target, reverse);
386
+ if (!items.length) return null;
387
+ if (reduced()) {
388
+ gsap.set(items, { autoAlpha: 0 });
389
+ return null;
390
+ }
391
+ return gsap.to(items, { y, autoAlpha: 0, filter: `blur(${blur}px)`, duration, stagger, delay, ease: EASE.flow });
392
+ }
393
+ async function stepChange(container, mutate, { duration = TIMING.stepChange } = {}) {
394
+ const before = [...container.children];
395
+ const out = flowOut(before, { duration });
396
+ if (out) await out;
397
+ await mutate();
398
+ await nextFrame();
399
+ flowIn([...container.children], { duration });
400
+ }
401
+
402
+ // src/motion/entrances.ts
403
+ var flowInMenu = (targets) => flowIn(targets, { style: 2, startScale: 0.9, blur: 4, reverse: true, autoAlpha: false, ...TIMING.menu });
404
+ var flowInPalette = (targets) => flowIn(targets, { style: 2, startScale: 0.5, blur: 4, autoAlpha: false, ...TIMING.palette });
405
+ var flowInForm = (targets) => flowIn(targets, { style: 2, startScale: 0.9, blur: 8, ...TIMING.form });
406
+ var flowInLanding = (targets) => flowIn(targets, { style: 2, startScale: 0.85, blur: 24, ...TIMING.landing });
407
+ var flowInContent = (root) => flowIn(root, { style: 2, target: "[data-flow], .markdown-content > *", ...TIMING.content });
408
+
409
+ // src/core/pointer.ts
410
+ import { gsap as gsap3 } from "gsap";
411
+ var pointer = { x: 0, y: 0, active: false };
412
+ var mx = 0;
413
+ var my = 0;
414
+ var lastX = null;
415
+ var lastY = null;
416
+ var users = 0;
417
+ function onMove(e) {
418
+ if (lastX !== null && lastY !== null) {
419
+ mx += e.clientX - lastX;
420
+ my += e.clientY - lastY;
421
+ }
422
+ lastX = pointer.x = e.clientX;
423
+ lastY = pointer.y = e.clientY;
424
+ pointer.active = true;
425
+ }
426
+ function onOut(e) {
427
+ if (e.relatedTarget) return;
428
+ pointer.active = false;
429
+ lastX = lastY = null;
430
+ }
431
+ function bindPointer() {
432
+ if (users++ === 0) {
433
+ addEventListener("pointermove", onMove, { passive: true });
434
+ document.addEventListener("pointerout", onOut);
435
+ }
436
+ let released = false;
437
+ return () => {
438
+ if (released) return;
439
+ released = true;
440
+ if (--users > 0) return;
441
+ removeEventListener("pointermove", onMove);
442
+ document.removeEventListener("pointerout", onOut);
443
+ pointer.active = false;
444
+ lastX = lastY = null;
445
+ mx = my = 0;
446
+ };
447
+ }
448
+ var frameMovement = { mx: 0, my: 0 };
449
+ var movementFrame = -1;
450
+ function takeMovement() {
451
+ const frame = gsap3.ticker.frame;
452
+ if (frame !== movementFrame) {
453
+ movementFrame = frame;
454
+ frameMovement = { mx, my };
455
+ mx = my = 0;
456
+ }
457
+ return frameMovement;
458
+ }
459
+
460
+ // src/motion/reveal.ts
461
+ var TRANSPARENT = /^(transparent|rgba\(0, 0, 0, 0\))$/;
462
+ function backgroundOf(el) {
463
+ for (let node = el; node; node = node.parentElement) {
464
+ const color = getComputedStyle(node).backgroundColor;
465
+ if (color && !TRANSPARENT.test(color)) return color;
466
+ }
467
+ return "var(--mk-bg, #fff)";
468
+ }
469
+ function revealFrom(target, options = {}) {
470
+ if (reduced() || !target.isConnected) return null;
471
+ registerMotion();
472
+ const { speed = "normal", delay = 0, overshoot = 2 } = options;
473
+ const style = getComputedStyle(target);
474
+ const fill = options.fill ?? backgroundOf(target);
475
+ const position2 = target.style.position;
476
+ if (style.position === "static") target.style.position = "relative";
477
+ const box = target.getBoundingClientRect();
478
+ const width = target.clientWidth;
479
+ const height = target.clientHeight;
480
+ let point = null;
481
+ const origin = options.origin;
482
+ if (origin instanceof Element) {
483
+ if (origin.isConnected) {
484
+ const rect = origin.getBoundingClientRect();
485
+ point = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
486
+ }
487
+ } else if (origin) point = origin;
488
+ else if (origin === void 0 && pointer.active) point = { x: pointer.x, y: pointer.y };
489
+ const x = point ? point.x - box.left - target.clientLeft : width / 2;
490
+ const y = point ? point.y - box.top - target.clientTop : height / 2;
491
+ const radius = Math.max(Math.hypot(x, y), Math.hypot(width - x, y), Math.hypot(x, height - y), Math.hypot(width - x, height - y)) * overshoot;
492
+ const veil = document.createElement("div");
493
+ veil.setAttribute("aria-hidden", "true");
494
+ veil.dataset.mkVeil = "";
495
+ Object.assign(veil.style, {
496
+ position: "absolute",
497
+ top: `${target.scrollTop}px`,
498
+ left: `${target.scrollLeft}px`,
499
+ width: `${width}px`,
500
+ height: `${height}px`,
501
+ borderRadius: style.borderRadius,
502
+ pointerEvents: "none",
503
+ zIndex: "1000"
504
+ });
505
+ const progress = { value: 0 };
506
+ const paint = () => {
507
+ veil.style.background = `radial-gradient(${radius}px at ${x}px ${y}px, transparent 0%, ${fill} ${progress.value}%)`;
508
+ };
509
+ paint();
510
+ target.append(veil);
511
+ let done = false;
512
+ let resolve;
513
+ const finished = new Promise((r) => resolve = r);
514
+ const cleanup = () => {
515
+ if (done) return;
516
+ done = true;
517
+ veil.remove();
518
+ target.style.position = position2;
519
+ resolve();
520
+ };
521
+ const [duration, fade] = TIMING.reveal[speed];
522
+ const timeline = gsap.timeline({ delay, onComplete: cleanup, onInterrupt: cleanup }).to(progress, { value: 100, duration, ease: "power2.out", onUpdate: paint }, 0).to(veil, { opacity: 0, duration: fade, ease: "power1.out" }, Math.max(0, duration * Math.min(1, 1 / overshoot) - 0.1));
523
+ return {
524
+ timeline,
525
+ finished,
526
+ cancel() {
527
+ timeline.kill();
528
+ cleanup();
529
+ }
530
+ };
531
+ }
532
+
533
+ // src/motion/count.ts
534
+ var shown = /* @__PURE__ */ new WeakMap();
535
+ var tweens = /* @__PURE__ */ new WeakMap();
536
+ var frames = /* @__PURE__ */ new WeakMap();
537
+ var defaultFormat = (value) => String(Math.round(value));
538
+ function current(el) {
539
+ const known = shown.get(el);
540
+ if (known !== void 0) return known;
541
+ const parsed = Number((el.textContent ?? "").replace(/[^\d.-]/g, ""));
542
+ return Number.isFinite(parsed) ? parsed : 0;
543
+ }
544
+ function tweenNumber(from, to, onUpdate, { duration = TIMING.number } = {}) {
545
+ registerMotion();
546
+ if (from === to || reduced()) {
547
+ onUpdate(to);
548
+ return null;
549
+ }
550
+ const state = { value: from };
551
+ return gsap.to(state, { value: to, duration, ease: EASE.flow, onUpdate: () => onUpdate(state.value), onComplete: () => onUpdate(to) });
552
+ }
553
+ function countTo(el, to, { from, duration = TIMING.number, format = defaultFormat } = {}) {
554
+ registerMotion();
555
+ tweens.get(el)?.kill();
556
+ const start = from ?? current(el);
557
+ const write = (value) => {
558
+ shown.set(el, value);
559
+ el.textContent = format(value);
560
+ };
561
+ if (start === to || reduced()) {
562
+ write(to);
563
+ return null;
564
+ }
565
+ const state = { value: start };
566
+ const tween = gsap.to(state, {
567
+ value: to,
568
+ duration,
569
+ ease: EASE.flow,
570
+ onUpdate: () => write(state.value),
571
+ onComplete: () => {
572
+ write(to);
573
+ tweens.delete(el);
574
+ }
575
+ });
576
+ tweens.set(el, tween);
577
+ return tween;
578
+ }
579
+ function revealCounter(el, to, { from, duration = TIMING.revealCounter, format = defaultFormat } = {}) {
580
+ frames.get(el)?.();
581
+ const start = from ?? current(el);
582
+ const write = (value) => {
583
+ shown.set(el, value);
584
+ el.textContent = format(value);
585
+ };
586
+ if (start === to || reduced()) {
587
+ write(to);
588
+ return () => {
589
+ };
590
+ }
591
+ let began = null;
592
+ let cancel = () => {
593
+ };
594
+ const step = (time) => {
595
+ began ??= time;
596
+ const progress = Math.min(1, (time - began) / (duration * 1e3));
597
+ write(start + (to - start) * (1 - (1 - progress) ** 3));
598
+ if (progress < 1) cancel = requestFrame(step);
599
+ else frames.delete(el);
600
+ };
601
+ cancel = requestFrame(step);
602
+ const stop2 = () => cancel();
603
+ frames.set(el, stop2);
604
+ return stop2;
605
+ }
606
+
607
+ // src/motion/anchor.ts
608
+ var EDGE = 16;
609
+ var GAP = 8;
610
+ var PHONE = 680;
611
+ var PLACED = ["top", "left", "right", "bottom", "margin", "margin-top", "margin-right", "margin-bottom", "margin-left"];
612
+ function anchorSurface(surface, origin, viewport) {
613
+ const view = viewport ?? { width: innerWidth, height: innerHeight };
614
+ if (!origin || view.width < PHONE) {
615
+ for (const side of PLACED) surface.style.removeProperty(side);
616
+ return;
617
+ }
618
+ const box = surface.getBoundingClientRect();
619
+ const clampLeft = (value) => Math.max(EDGE, Math.min(value, view.width - box.width - EDGE));
620
+ const below = origin.bottom + GAP;
621
+ const above = origin.top - GAP - box.height;
622
+ const lowest = Math.max(EDGE, view.height - box.height - EDGE);
623
+ const besideRight = origin.right + GAP;
624
+ const besideLeft = origin.left - GAP - box.width;
625
+ let top;
626
+ let left;
627
+ if (below <= lowest) [top, left] = [below, clampLeft(origin.left)];
628
+ else if (above >= EDGE) [top, left] = [above, clampLeft(origin.left)];
629
+ else if (besideRight + box.width <= view.width - EDGE) [top, left] = [Math.min(Math.max(EDGE, origin.top), lowest), besideRight];
630
+ else if (besideLeft >= EDGE) [top, left] = [Math.min(Math.max(EDGE, origin.top), lowest), besideLeft];
631
+ else [top, left] = [lowest, clampLeft(origin.left)];
632
+ Object.assign(surface.style, { margin: "0", top: `${Math.round(top)}px`, left: `${Math.round(left)}px`, right: "auto", bottom: "auto" });
633
+ }
634
+ function clearAnchor(surface) {
635
+ for (const side of PLACED) surface.style.removeProperty(side);
636
+ }
637
+
638
+ // src/motion/drag-dismiss.ts
639
+ var START = 6;
640
+ var FOLLOW = 0.5;
641
+ var DISMISS = 100;
642
+ var SHRINK = 400;
643
+ var WHEEL_SPEED = 1.5;
644
+ var WHEEL_MIN = 16;
645
+ var WHEEL_IDLE = 90;
646
+ var WHEEL_COOLDOWN = 250;
647
+ var CONTROLS = [
648
+ "a[href]",
649
+ "button",
650
+ "input",
651
+ "select",
652
+ "textarea",
653
+ "label",
654
+ "summary",
655
+ '[contenteditable="true"]',
656
+ '[role="button"]',
657
+ '[role="slider"]',
658
+ '[role="combobox"]',
659
+ '[role="option"]',
660
+ '[role="checkbox"]',
661
+ '[role="menuitem"]'
662
+ ].join(",");
663
+ function scrollerOf(target, surface) {
664
+ let element = target instanceof Element ? target : null;
665
+ while (element) {
666
+ if (element.scrollHeight > element.clientHeight + 1) {
667
+ const overflow = getComputedStyle(element).overflowY;
668
+ if (overflow === "auto" || overflow === "scroll") return element;
669
+ }
670
+ if (element === surface) break;
671
+ element = element.parentElement;
672
+ }
673
+ return null;
674
+ }
675
+ var draggableFrom = (target, surface) => target instanceof Element && !target.closest("[data-mk-no-drag], [popover]") && !target.closest(CONTROLS) && !(surface.querySelector("[data-mk-drag-handle]") && !target.closest("[data-mk-drag-handle]"));
676
+ function attachDragDismiss(surface, { canDrag = () => true, onDismiss }) {
677
+ registerMotion();
678
+ let pointer2 = null;
679
+ let startX = 0;
680
+ let startY = 0;
681
+ let mode = null;
682
+ let pulled = 0;
683
+ let base = { x: 0, y: 0, scale: 1 };
684
+ let target = null;
685
+ const noSelect = (event) => event.preventDefault();
686
+ const begin = () => {
687
+ mode = "drag";
688
+ gsap.killTweensOf(surface, "x,y,scale");
689
+ base = {
690
+ x: Number(gsap.getProperty(surface, "x")) || 0,
691
+ y: Number(gsap.getProperty(surface, "y")) || 0,
692
+ scale: Number(gsap.getProperty(surface, "scaleX")) || 1
693
+ };
694
+ window.getSelection?.()?.removeAllRanges();
695
+ document.body.style.userSelect = "none";
696
+ document.addEventListener("selectstart", noSelect);
697
+ };
698
+ const follow = (dx, dy) => {
699
+ pulled = dy * FOLLOW;
700
+ gsap.set(surface, { x: base.x + dx * FOLLOW, y: base.y + pulled, scale: Math.max(0.1, base.scale * (1 - pulled / SHRINK)) });
701
+ };
702
+ const restore = () => gsap.to(surface, { x: 0, y: 0, scale: 1, duration: TIMING.drag.restore, ease: "elastic.out(0.5,0.5)" });
703
+ const release = () => {
704
+ document.removeEventListener("selectstart", noSelect);
705
+ document.body.style.userSelect = "";
706
+ const dismiss = pulled > DISMISS;
707
+ mode = null;
708
+ pulled = 0;
709
+ if (dismiss) onDismiss();
710
+ else restore();
711
+ };
712
+ const onPointerDown = (event) => {
713
+ if (event.button !== 0 || pointer2 !== null || reduced() || !canDrag()) return;
714
+ if (!draggableFrom(event.target, surface)) return;
715
+ pointer2 = event.pointerId;
716
+ target = event.target;
717
+ startX = event.clientX;
718
+ startY = event.clientY;
719
+ mode = null;
720
+ pulled = 0;
721
+ };
722
+ const onPointerMove = (event) => {
723
+ if (event.pointerId !== pointer2 || mode === "scroll") return;
724
+ const dx = event.clientX - startX;
725
+ const dy = event.clientY - startY;
726
+ if (mode === null) {
727
+ if (Math.abs(dx) < START && Math.abs(dy) < START) return;
728
+ if (event.pointerType !== "mouse") {
729
+ const scroller = scrollerOf(target, surface);
730
+ if (scroller && Math.abs(dx) < Math.abs(dy) && !(dy > 0 && scroller.scrollTop <= 0)) {
731
+ mode = "scroll";
732
+ return;
733
+ }
734
+ }
735
+ begin();
736
+ }
737
+ if (event.cancelable) event.preventDefault();
738
+ follow(dx, dy);
739
+ };
740
+ const onPointerUp = (event) => {
741
+ if (event.pointerId !== pointer2) return;
742
+ pointer2 = null;
743
+ target = null;
744
+ if (mode !== "drag") {
745
+ mode = null;
746
+ return;
747
+ }
748
+ const swallow = (click) => {
749
+ click.stopPropagation();
750
+ click.preventDefault();
751
+ };
752
+ window.addEventListener("click", swallow, { capture: true, once: true });
753
+ setTimeout(() => window.removeEventListener("click", swallow, { capture: true }), 50);
754
+ release();
755
+ };
756
+ let wheeling = false;
757
+ let wheelPull = 0;
758
+ let wheelSpeed = 0;
759
+ let lastWheel = 0;
760
+ let idle;
761
+ let quietUntil = 0;
762
+ const deltaOf = (event) => event.deltaMode === 1 ? event.deltaY * 16 : event.deltaMode === 2 ? event.deltaY * innerHeight : event.deltaY;
763
+ function endWheel(dismiss, at) {
764
+ window.removeEventListener("wheel", onWheelCapture, { capture: true });
765
+ clearTimeout(idle);
766
+ wheeling = false;
767
+ quietUntil = at + WHEEL_COOLDOWN;
768
+ pulled = 0;
769
+ wheelPull = 0;
770
+ wheelSpeed = 0;
771
+ lastWheel = 0;
772
+ document.body.style.userSelect = "";
773
+ if (dismiss) onDismiss();
774
+ else restore();
775
+ }
776
+ function stepWheel(event) {
777
+ const amount = -deltaOf(event);
778
+ const elapsed = lastWheel ? Math.max(1, event.timeStamp - lastWheel) : 16;
779
+ lastWheel = event.timeStamp;
780
+ wheelSpeed = wheelSpeed * 0.4 + amount / elapsed * 0.6;
781
+ wheelPull = Math.max(0, wheelPull + amount);
782
+ follow(0, wheelPull);
783
+ if (wheelSpeed > WHEEL_SPEED && pulled > WHEEL_MIN || pulled > DISMISS) {
784
+ endWheel(true, event.timeStamp);
785
+ return;
786
+ }
787
+ clearTimeout(idle);
788
+ idle = setTimeout(() => wheeling && endWheel(false, performance.now()), WHEEL_IDLE);
789
+ }
790
+ function onWheelCapture(event) {
791
+ if (!wheeling) return;
792
+ event.preventDefault();
793
+ event.stopPropagation();
794
+ stepWheel(event);
795
+ }
796
+ const onWheel = (event) => {
797
+ if (wheeling || reduced() || !canDrag()) return;
798
+ const up = deltaOf(event) < 0;
799
+ const scroller = scrollerOf(event.target, surface);
800
+ const canScroll = scroller ? up ? scroller.scrollTop > 0 : scroller.scrollTop + scroller.clientHeight < scroller.scrollHeight - 1 : false;
801
+ if (canScroll || !up || event.timeStamp < quietUntil) return;
802
+ if (event.target instanceof Element && event.target.closest("[data-mk-no-drag], [popover]")) return;
803
+ event.preventDefault();
804
+ wheeling = true;
805
+ wheelPull = 0;
806
+ wheelSpeed = 0;
807
+ lastWheel = 0;
808
+ begin();
809
+ mode = null;
810
+ window.addEventListener("wheel", onWheelCapture, { passive: false, capture: true });
811
+ stepWheel(event);
812
+ };
813
+ surface.addEventListener("pointerdown", onPointerDown);
814
+ window.addEventListener("pointermove", onPointerMove, { passive: false });
815
+ window.addEventListener("pointerup", onPointerUp);
816
+ window.addEventListener("pointercancel", onPointerUp);
817
+ surface.addEventListener("wheel", onWheel, { passive: false });
818
+ return () => {
819
+ surface.removeEventListener("pointerdown", onPointerDown);
820
+ window.removeEventListener("pointermove", onPointerMove);
821
+ window.removeEventListener("pointerup", onPointerUp);
822
+ window.removeEventListener("pointercancel", onPointerUp);
823
+ surface.removeEventListener("wheel", onWheel);
824
+ window.removeEventListener("wheel", onWheelCapture, { capture: true });
825
+ clearTimeout(idle);
826
+ document.removeEventListener("selectstart", noSelect);
827
+ document.body.style.userSelect = "";
828
+ };
829
+ }
830
+
831
+ // src/motion/floating.ts
832
+ var MIN_WIDTH = 320;
833
+ var MIN_HEIGHT = 240;
834
+ var MARGIN = 8;
835
+ var DESKTOP = 680;
836
+ var LIFT = 4;
837
+ var SPRING = { stiffness: 1100, damping: 38 };
838
+ var MASS_AREA = 24e3;
839
+ var MAX_MASS = 1.5;
840
+ var REST_SPEED = 24;
841
+ var FLING_SPEED = 350;
842
+ var POINTER_SMOOTHING = 0.05;
843
+ var SHRINK_FULL = 0.85;
844
+ var FLOAT_SHADOW = "rgba(0, 0, 0, 0.24) 0px 0px 24px -6px";
845
+ var floatingAvailable = () => typeof innerWidth === "number" && innerWidth >= DESKTOP;
846
+ function clampRect(rect, viewport = { width: innerWidth, height: innerHeight }) {
847
+ const maxWidth = Math.max(MIN_WIDTH, viewport.width - MARGIN * 2);
848
+ const maxHeight = Math.max(MIN_HEIGHT, viewport.height - MARGIN * 2);
849
+ const width = Math.min(maxWidth, Math.max(MIN_WIDTH, rect.width));
850
+ const height = Math.min(maxHeight, Math.max(MIN_HEIGHT, rect.height));
851
+ return {
852
+ top: Math.min(Math.max(MARGIN, viewport.height - height - MARGIN), Math.max(MARGIN, rect.top)),
853
+ left: Math.min(Math.max(MARGIN, viewport.width - width - MARGIN), Math.max(MARGIN, rect.left)),
854
+ width,
855
+ height
856
+ };
857
+ }
858
+ var rectOf = (element) => {
859
+ const box = element.getBoundingClientRect();
860
+ return { top: box.top, left: box.left, width: box.width, height: box.height };
861
+ };
862
+ var place = (element, rect) => Object.assign(element.style, {
863
+ position: "fixed",
864
+ inset: "auto",
865
+ margin: "0",
866
+ top: `${rect.top}px`,
867
+ left: `${rect.left}px`,
868
+ width: `${rect.width}px`,
869
+ height: `${rect.height}px`,
870
+ maxWidth: "none",
871
+ maxHeight: "none"
872
+ });
873
+ var storageKey = (key) => `mk-float.${key}`;
874
+ function savedFloat(key) {
875
+ try {
876
+ const value = JSON.parse(localStorage.getItem(storageKey(key)) ?? "null");
877
+ return value && ["top", "left", "width", "height"].every((name) => Number.isFinite(value[name])) ? clampRect(value) : null;
878
+ } catch {
879
+ return null;
880
+ }
881
+ }
882
+ function saveFloat(key, rect) {
883
+ try {
884
+ localStorage.setItem(
885
+ storageKey(key),
886
+ JSON.stringify({ top: Math.round(rect.top), left: Math.round(rect.left), width: Math.round(rect.width), height: Math.round(rect.height) })
887
+ );
888
+ } catch {
889
+ }
890
+ }
891
+ function forgetFloat(key) {
892
+ try {
893
+ localStorage.removeItem(storageKey(key));
894
+ } catch {
895
+ }
896
+ }
897
+ function liftWindow(surface, rect) {
898
+ registerMotion();
899
+ place(surface, clampRect(rect));
900
+ surface.classList.add("is-floating");
901
+ if (!reduced()) {
902
+ gsap.fromTo(
903
+ surface,
904
+ { boxShadow: "rgba(0, 0, 0, 0) 0px 0px 0px 0px" },
905
+ { boxShadow: FLOAT_SHADOW, duration: TIMING.float.shadow, ease: EASE.signature, clearProps: "boxShadow" }
906
+ );
907
+ }
908
+ }
909
+ var PLACED2 = [
910
+ "position",
911
+ "inset",
912
+ "right",
913
+ "bottom",
914
+ "margin",
915
+ "margin-top",
916
+ "margin-right",
917
+ "margin-bottom",
918
+ "margin-left",
919
+ "top",
920
+ "left",
921
+ "width",
922
+ "height",
923
+ "max-width",
924
+ "max-height"
925
+ ];
926
+ function unplaceWindow(surface) {
927
+ surface.classList.remove("is-floating");
928
+ for (const name of PLACED2) surface.style.removeProperty(name);
929
+ }
930
+ function dockWindow(surface, from) {
931
+ registerMotion();
932
+ unplaceWindow(surface);
933
+ if (reduced()) return;
934
+ const to = rectOf(surface);
935
+ gsap.from(surface, { x: from.left - to.left, y: from.top - to.top, duration: TIMING.float.shadow, ease: EASE.signature, clearProps: "transform" });
936
+ }
937
+ function attachFloating(surface, { key, handle, corners = [], isFloating, float, dock }) {
938
+ const cleanups = [];
939
+ const listen = (element, listener) => {
940
+ element.addEventListener("pointerdown", listener);
941
+ cleanups.push(() => element.removeEventListener("pointerdown", listener));
942
+ };
943
+ let active = null;
944
+ let release = null;
945
+ const capture = (element, down, { onMove: onMove2, onUp }) => {
946
+ release?.();
947
+ active = down.pointerId;
948
+ try {
949
+ element.setPointerCapture?.(down.pointerId);
950
+ } catch {
951
+ }
952
+ const move = (event) => {
953
+ if (event.pointerId === active) onMove2(event);
954
+ };
955
+ const up = (event) => {
956
+ if (event.pointerId !== active) return;
957
+ stop2();
958
+ onUp();
959
+ };
960
+ const stop2 = () => {
961
+ active = null;
962
+ release = null;
963
+ window.removeEventListener("pointermove", move);
964
+ window.removeEventListener("pointerup", up);
965
+ window.removeEventListener("pointercancel", up);
966
+ };
967
+ release = stop2;
968
+ window.addEventListener("pointermove", move);
969
+ window.addEventListener("pointerup", up);
970
+ window.addEventListener("pointercancel", up);
971
+ };
972
+ cleanups.push(() => release?.());
973
+ let body = null;
974
+ const settle = () => {
975
+ if (!body) return;
976
+ gsap.ticker.remove(tick);
977
+ body = null;
978
+ };
979
+ function tick() {
980
+ if (!body) return;
981
+ const now = performance.now();
982
+ const elapsed = Math.min((now - body.time) / 1e3, 1 / 30);
983
+ if (elapsed <= 0) return;
984
+ body.time = now;
985
+ if (body.gliding) {
986
+ const decay = Math.exp(-elapsed / TIMING.float.glideDecay);
987
+ body.vx *= decay;
988
+ body.vy *= decay;
989
+ } else {
990
+ body.vx += ((body.targetX - body.x) * SPRING.stiffness - body.vx * SPRING.damping) * elapsed / body.mass;
991
+ body.vy += ((body.targetY - body.y) * SPRING.stiffness - body.vy * SPRING.damping) * elapsed / body.mass;
992
+ }
993
+ body.x += body.vx * elapsed;
994
+ body.y += body.vy * elapsed;
995
+ const smoothing = 1 - Math.exp(-elapsed / TIMING.float.sizeSmoothing);
996
+ body.w += (body.targetW - body.w) * smoothing;
997
+ body.h += (body.targetH - body.h) * smoothing;
998
+ if (Math.abs(body.targetW - body.w) < 0.5) body.w = body.targetW;
999
+ if (Math.abs(body.targetH - body.h) < 0.5) body.h = body.targetH;
1000
+ const rect = clampRect({ top: body.y, left: body.x, width: body.w, height: body.h });
1001
+ if (rect.left !== body.x) {
1002
+ body.x = rect.left;
1003
+ body.vx = 0;
1004
+ }
1005
+ if (rect.top !== body.y) {
1006
+ body.y = rect.top;
1007
+ body.vy = 0;
1008
+ }
1009
+ place(surface, rect);
1010
+ const resting = Math.hypot(body.vx, body.vy) < REST_SPEED && body.w === body.targetW && body.h === body.targetH;
1011
+ if (body.gliding && resting) {
1012
+ saveFloat(key, rect);
1013
+ settle();
1014
+ }
1015
+ }
1016
+ listen(handle, (down) => {
1017
+ if (down.button !== 0 || active !== null || !floatingAvailable()) return;
1018
+ down.preventDefault();
1019
+ settle();
1020
+ let moved = false;
1021
+ capture(handle, down, {
1022
+ onMove(event) {
1023
+ const dx = event.clientX - down.clientX;
1024
+ const dy = event.clientY - down.clientY;
1025
+ if (!moved) {
1026
+ if (Math.abs(dx) < LIFT && Math.abs(dy) < LIFT) return;
1027
+ moved = true;
1028
+ if (!isFloating()) float();
1029
+ const rect = rectOf(surface);
1030
+ const fullWidth = innerWidth - MARGIN * 2;
1031
+ const fullHeight = innerHeight - MARGIN * 2;
1032
+ const width = rect.width >= fullWidth - 2 ? Math.max(MIN_WIDTH, Math.round(fullWidth * SHRINK_FULL)) : rect.width;
1033
+ const height = rect.height >= fullHeight - 2 ? Math.max(MIN_HEIGHT, Math.round(fullHeight * SHRINK_FULL)) : rect.height;
1034
+ const grip = rect.width > 0 ? (down.clientX - rect.left) / rect.width : 0;
1035
+ const left = rect.left + (rect.width - width) * grip;
1036
+ const now2 = performance.now();
1037
+ body = {
1038
+ x: left,
1039
+ y: rect.top,
1040
+ vx: 0,
1041
+ vy: 0,
1042
+ w: rect.width,
1043
+ h: rect.height,
1044
+ targetX: left,
1045
+ targetY: rect.top,
1046
+ targetW: width,
1047
+ targetH: height,
1048
+ mass: Math.min(MAX_MASS, Math.max(1, Math.sqrt(rect.width * rect.height / MASS_AREA))),
1049
+ time: now2,
1050
+ gliding: false,
1051
+ fromX: left,
1052
+ fromY: rect.top,
1053
+ pointerVx: 0,
1054
+ pointerVy: 0,
1055
+ pointerX: event.clientX,
1056
+ pointerY: event.clientY,
1057
+ pointerTime: now2
1058
+ };
1059
+ gsap.ticker.add(tick);
1060
+ }
1061
+ if (!body) return;
1062
+ body.targetX = body.fromX + dx;
1063
+ body.targetY = body.fromY + dy;
1064
+ const now = performance.now();
1065
+ const seconds = Math.max(1, now - body.pointerTime) / 1e3;
1066
+ const smoothing = 1 - Math.exp(-seconds / POINTER_SMOOTHING);
1067
+ body.pointerVx += ((event.clientX - body.pointerX) / seconds - body.pointerVx) * smoothing;
1068
+ body.pointerVy += ((event.clientY - body.pointerY) / seconds - body.pointerVy) * smoothing;
1069
+ body.pointerX = event.clientX;
1070
+ body.pointerY = event.clientY;
1071
+ body.pointerTime = now;
1072
+ },
1073
+ onUp() {
1074
+ if (!moved) {
1075
+ if (isFloating()) dock();
1076
+ else float();
1077
+ return;
1078
+ }
1079
+ if (!body) return;
1080
+ const speed = performance.now() - body.pointerTime > 80 ? 0 : Math.hypot(body.pointerVx, body.pointerVy);
1081
+ if (speed >= FLING_SPEED) {
1082
+ body.vx = body.pointerVx;
1083
+ body.vy = body.pointerVy;
1084
+ } else {
1085
+ body.vx = 0;
1086
+ body.vy = 0;
1087
+ body.targetX = body.x;
1088
+ body.targetY = body.y;
1089
+ }
1090
+ body.gliding = true;
1091
+ }
1092
+ });
1093
+ });
1094
+ for (const corner of corners) {
1095
+ listen(corner, (down) => {
1096
+ if (down.button !== 0 || active !== null || !floatingAvailable()) return;
1097
+ down.preventDefault();
1098
+ settle();
1099
+ const side = corner.dataset.mkFloatCorner ?? "br";
1100
+ const fromLeft = side.endsWith("l");
1101
+ const fromTop = side.startsWith("t");
1102
+ let start = null;
1103
+ capture(corner, down, {
1104
+ onMove(event) {
1105
+ const dx = event.clientX - down.clientX;
1106
+ const dy = event.clientY - down.clientY;
1107
+ if (!start) {
1108
+ if (Math.abs(dx) < LIFT && Math.abs(dy) < LIFT) return;
1109
+ if (!isFloating()) float();
1110
+ start = rectOf(surface);
1111
+ }
1112
+ const width = Math.min(innerWidth - MARGIN * 2, Math.max(MIN_WIDTH, fromLeft ? start.width - dx : start.width + dx));
1113
+ const height = Math.min(innerHeight - MARGIN * 2, Math.max(MIN_HEIGHT, fromTop ? start.height - dy : start.height + dy));
1114
+ place(
1115
+ surface,
1116
+ clampRect({
1117
+ top: fromTop ? start.top + start.height - height : start.top,
1118
+ left: fromLeft ? start.left + start.width - width : start.left,
1119
+ width,
1120
+ height
1121
+ })
1122
+ );
1123
+ },
1124
+ onUp() {
1125
+ if (start) saveFloat(key, rectOf(surface));
1126
+ }
1127
+ });
1128
+ });
1129
+ }
1130
+ return () => {
1131
+ if (body?.gliding) saveFloat(key, rectOf(surface));
1132
+ settle();
1133
+ for (const cleanup of cleanups) cleanup();
1134
+ };
1135
+ }
1136
+
1137
+ // src/motion/surface.ts
1138
+ var transparentColor = (color) => !color || color === "transparent" || /,\s*0\)$/.test(color) || /\/\s*0\)$/.test(color);
1139
+ function openModal(dialog, modal = true) {
1140
+ if (dialog.hasAttribute("open")) return;
1141
+ if (modal && typeof dialog.showModal === "function") dialog.showModal();
1142
+ else if (typeof dialog.show === "function") dialog.show();
1143
+ else dialog.setAttribute("open", "");
1144
+ }
1145
+ function closeModal(dialog) {
1146
+ if (typeof dialog.close === "function") dialog.close();
1147
+ else dialog.removeAttribute("open");
1148
+ }
1149
+ function fadeBackdrop(dialog, direction) {
1150
+ if (typeof dialog.animate !== "function" || reduced()) return Promise.resolve();
1151
+ try {
1152
+ const animation = dialog.animate(direction === "in" ? [{ opacity: 0 }, { opacity: 1 }] : [{ opacity: 1 }, { opacity: 0 }], {
1153
+ duration: (direction === "in" ? TIMING.dialog.backdrop : TIMING.dialog.close) * 1e3,
1154
+ easing: direction === "in" ? SIGNATURE_LINEAR : "linear",
1155
+ fill: direction === "out" ? "forwards" : "none",
1156
+ pseudoElement: "::backdrop"
1157
+ });
1158
+ return animation.finished.then(
1159
+ () => void 0,
1160
+ () => void 0
1161
+ );
1162
+ } catch {
1163
+ return Promise.resolve();
1164
+ }
1165
+ }
1166
+ function backdropVeil(surface) {
1167
+ const backdrop = getComputedStyle(surface, "::backdrop");
1168
+ const veil = document.createElement("div");
1169
+ veil.setAttribute("aria-hidden", "true");
1170
+ veil.dataset.mkVeil = "";
1171
+ Object.assign(veil.style, {
1172
+ position: "fixed",
1173
+ inset: "0",
1174
+ zIndex: "2147483645",
1175
+ background: backdrop.background || backdrop.backgroundColor,
1176
+ backdropFilter: backdrop.backdropFilter,
1177
+ pointerEvents: "none"
1178
+ });
1179
+ return veil;
1180
+ }
1181
+ function ghostOf(surface) {
1182
+ const rect = surface.getBoundingClientRect();
1183
+ if (rect.width === 0 || rect.height === 0) return null;
1184
+ const style = getComputedStyle(surface);
1185
+ const ghost = document.createElement("div");
1186
+ ghost.className = surface.className;
1187
+ ghost.innerHTML = surface.innerHTML;
1188
+ ghost.setAttribute("aria-hidden", "true");
1189
+ ghost.inert = true;
1190
+ ghost.dataset.mkGhost = "";
1191
+ const strip = ["id", "for", "name", "aria-labelledby", "aria-describedby", "aria-label", "role"];
1192
+ for (const element of ghost.querySelectorAll(strip.map((name) => `[${name}]`).join(","))) {
1193
+ for (const name of strip) element.removeAttribute(name);
1194
+ }
1195
+ for (const label of ghost.querySelectorAll("label")) {
1196
+ const span = document.createElement("span");
1197
+ span.className = label.className;
1198
+ span.append(...label.childNodes);
1199
+ label.replaceWith(span);
1200
+ }
1201
+ Object.assign(ghost.style, {
1202
+ position: "fixed",
1203
+ inset: "auto",
1204
+ left: `${rect.left}px`,
1205
+ top: `${rect.top}px`,
1206
+ width: `${rect.width}px`,
1207
+ height: `${rect.height}px`,
1208
+ margin: "0",
1209
+ display: style.display === "none" ? "flex" : style.display,
1210
+ flexDirection: style.flexDirection,
1211
+ zIndex: "2147483646",
1212
+ pointerEvents: "none"
1213
+ });
1214
+ return ghost;
1215
+ }
1216
+
1217
+ // src/motion/liquid.ts
1218
+ var GOO = "mk-liquid-goo";
1219
+ function ensureGoo() {
1220
+ if (document.getElementById(GOO)) return;
1221
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
1222
+ svg.setAttribute("aria-hidden", "true");
1223
+ svg.setAttribute("width", "0");
1224
+ svg.setAttribute("height", "0");
1225
+ svg.style.position = "absolute";
1226
+ svg.innerHTML = `<defs><filter id="${GOO}" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur in="SourceGraphic" stdDeviation="20"/><feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9"/></filter></defs>`;
1227
+ document.body.append(svg);
1228
+ }
1229
+ function gooLayer(surface) {
1230
+ ensureGoo();
1231
+ const box = surface.getBoundingClientRect();
1232
+ const layer = document.createElement("div");
1233
+ layer.className = "mk-morph-face mk-liquid";
1234
+ layer.setAttribute("aria-hidden", "true");
1235
+ Object.assign(layer.style, {
1236
+ position: "absolute",
1237
+ left: `${-box.left - surface.clientLeft}px`,
1238
+ top: `${-box.top - surface.clientTop}px`,
1239
+ width: `${innerWidth}px`,
1240
+ height: `${innerHeight}px`,
1241
+ zIndex: "-1",
1242
+ pointerEvents: "none",
1243
+ filter: `url(#${GOO})`,
1244
+ borderRadius: "0",
1245
+ background: "none"
1246
+ });
1247
+ const blob = (from, radius, color) => {
1248
+ const element = document.createElement("div");
1249
+ Object.assign(element.style, {
1250
+ position: "absolute",
1251
+ top: `${from.top}px`,
1252
+ left: `${from.left}px`,
1253
+ width: `${from.width}px`,
1254
+ height: `${from.height}px`,
1255
+ borderRadius: `${radius}px`,
1256
+ background: color
1257
+ });
1258
+ layer.append(element);
1259
+ return element;
1260
+ };
1261
+ surface.append(layer);
1262
+ return { layer, blob };
1263
+ }
1264
+ function hideFrame(surface) {
1265
+ const saved = surface.getAttribute("style");
1266
+ Object.assign(surface.style, {
1267
+ transition: "none",
1268
+ background: "transparent",
1269
+ boxShadow: "none",
1270
+ borderColor: "transparent",
1271
+ overflow: "visible"
1272
+ });
1273
+ return () => {
1274
+ if (saved === null) surface.removeAttribute("style");
1275
+ else surface.setAttribute("style", saved);
1276
+ };
1277
+ }
1278
+ var radiusOf = (element, box) => Math.min(parseFloat(getComputedStyle(element).borderTopLeftRadius) || 0, box.width / 2, box.height / 2);
1279
+ function centerParts(surface, parts) {
1280
+ const box = surface.getBoundingClientRect();
1281
+ const centerX = box.left + box.width / 2;
1282
+ const centerY = box.top + box.height / 2;
1283
+ for (const part2 of parts) {
1284
+ const own = part2.getBoundingClientRect();
1285
+ gsap.set(part2, { transformOrigin: `${centerX - own.left}px ${centerY - own.top}px` });
1286
+ }
1287
+ return { centerX, centerY };
1288
+ }
1289
+ function liquidOpen(surface, origin, parts) {
1290
+ const box = surface.getBoundingClientRect();
1291
+ const start = origin.getBoundingClientRect();
1292
+ const surfaceColor = getComputedStyle(surface).backgroundColor;
1293
+ const originLook = getComputedStyle(origin).backgroundColor;
1294
+ const originColor = transparentColor(originLook) ? surfaceColor : originLook;
1295
+ const endRadius = radiusOf(surface, box);
1296
+ const startRadius = radiusOf(origin, start);
1297
+ const { centerX, centerY } = centerParts(surface, parts);
1298
+ const restore = hideFrame(surface);
1299
+ const { layer, blob } = gooLayer(surface);
1300
+ const originBlob = blob(start, startRadius, originColor);
1301
+ const shape = blob(start, startRadius, originColor);
1302
+ const towardX = start.left + start.width / 2 < innerWidth / 2 ? 1 : -1;
1303
+ const towardY = start.top + start.height / 2 < innerHeight / 2 ? 1 : -1;
1304
+ if (parts.length) gsap.set(parts, { opacity: 0 });
1305
+ const current2 = { top: start.top, left: start.left, width: start.width, height: start.height, scale: 2, blur: 8 };
1306
+ const paint = () => {
1307
+ if (!parts.length) return;
1308
+ gsap.set(parts, {
1309
+ x: current2.left + current2.width / 2 - centerX,
1310
+ y: current2.top + current2.height / 2 - centerY,
1311
+ scale: current2.scale,
1312
+ filter: `blur(${current2.blur}px)`
1313
+ });
1314
+ };
1315
+ const motion = channels({ ...current2, radius: startRadius }, (name, value) => {
1316
+ if (name === "radius") shape.style.borderRadius = `${value}px`;
1317
+ else {
1318
+ current2[name] = value;
1319
+ if (name === "top" || name === "left" || name === "width" || name === "height") shape.style[name] = `${value}px`;
1320
+ paint();
1321
+ }
1322
+ });
1323
+ const L = TIMING.liquid;
1324
+ void motion.animate(
1325
+ { top: box.top, left: box.left, width: box.width, height: box.height, radius: endRadius, scale: 1, blur: 0 },
1326
+ {
1327
+ top: spring(144, 14, { velocity: 2400, direction: towardY }),
1328
+ left: spring(144, 14, { velocity: 2400, direction: towardX }),
1329
+ width: eased(L.size, bezier(0.8, 0.3, 0.5, 0.8)),
1330
+ height: eased(L.size, bezier(0.8, 0.3, 0.5, 0.8)),
1331
+ radius: eased(L.radius, easeOut),
1332
+ scale: eased(L.content, easeOut),
1333
+ blur: eased(L.content, easeOut)
1334
+ }
1335
+ );
1336
+ gsap.to(shape, { background: surfaceColor, duration: L.color, delay: L.colorDelay, ease: "power2.out" });
1337
+ if (parts.length) gsap.to(parts, { opacity: 1, duration: L.color, delay: L.colorDelay, ease: "power2.out" });
1338
+ gsap.to(originBlob, { opacity: 0, duration: L.ghost, delay: L.ghostDelay, ease: "power2.out" });
1339
+ let done = false;
1340
+ const finish = () => {
1341
+ if (done) return;
1342
+ done = true;
1343
+ motion.stop();
1344
+ clearTimeout(timer);
1345
+ layer.remove();
1346
+ restore();
1347
+ if (parts.length) gsap.set(parts, { clearProps: "opacity,transform,transformOrigin,filter" });
1348
+ };
1349
+ const timer = setTimeout(finish, L.safetyMs);
1350
+ return finish;
1351
+ }
1352
+ function liquidClose(surface, origin, parts, onComplete) {
1353
+ const box = surface.getBoundingClientRect();
1354
+ const end = origin.getBoundingClientRect();
1355
+ const surfaceColor = getComputedStyle(surface).backgroundColor;
1356
+ const originLook = getComputedStyle(origin).backgroundColor;
1357
+ const originColor = transparentColor(originLook) ? surfaceColor : originLook;
1358
+ const startRadius = radiusOf(surface, box);
1359
+ const endRadius = radiusOf(origin, end);
1360
+ const { centerX, centerY } = centerParts(surface, parts);
1361
+ hideFrame(surface);
1362
+ const { blob } = gooLayer(surface);
1363
+ const originBlob = blob(end, endRadius, originColor);
1364
+ originBlob.style.opacity = "0";
1365
+ const shape = blob(box, startRadius, surfaceColor);
1366
+ const current2 = { top: box.top, left: box.left, width: box.width, height: box.height, scale: 1, blur: 0 };
1367
+ const motion = channels({ ...current2, radius: startRadius, opacity: 1 }, (name, value) => {
1368
+ if (name === "radius") shape.style.borderRadius = `${value}px`;
1369
+ else if (name === "opacity") {
1370
+ if (parts.length) gsap.set(parts, { opacity: value });
1371
+ } else {
1372
+ current2[name] = value;
1373
+ if (name === "top" || name === "left" || name === "width" || name === "height") shape.style[name] = `${value}px`;
1374
+ if (parts.length) {
1375
+ gsap.set(parts, {
1376
+ x: current2.left + current2.width / 2 - centerX,
1377
+ y: current2.top + current2.height / 2 - centerY,
1378
+ scale: current2.scale,
1379
+ filter: `blur(${current2.blur}px)`
1380
+ });
1381
+ }
1382
+ }
1383
+ });
1384
+ const L = TIMING.liquid;
1385
+ void motion.animate(
1386
+ { top: end.top, left: end.left, width: end.width, height: end.height, radius: endRadius, scale: 2, blur: 8, opacity: 0 },
1387
+ {
1388
+ top: spring(130, 18),
1389
+ left: spring(130, 18),
1390
+ width: eased(L.closeSize, easeOut),
1391
+ height: eased(L.closeSize, easeOut),
1392
+ // It rounds into the opener's shape early, long before it arrives.
1393
+ radius: eased(L.closeSize, easeOut),
1394
+ scale: eased(L.closeContent, easeOut),
1395
+ blur: eased(L.closeContent, easeOut),
1396
+ opacity: spring(137, 20)
1397
+ }
1398
+ );
1399
+ gsap.to(originBlob, { opacity: 1, duration: L.originRestore, delay: 0.15, ease: "power2.in" });
1400
+ gsap.to(shape, { background: originColor, duration: L.originRestore, ease: "power2.out" });
1401
+ gsap.to(surface, { opacity: 0, duration: TIMING.dialog.close, ease: "power3.in" });
1402
+ setTimeout(() => {
1403
+ motion.stop();
1404
+ onComplete();
1405
+ }, L.safetyMs);
1406
+ }
1407
+
1408
+ // src/motion/morph.ts
1409
+ var FACE = "mk-morph-face";
1410
+ var HIDDEN_ORIGIN = "data-mk-morph-origin";
1411
+ var SHARED = "data-mk-shared";
1412
+ var SHARED_HIDDEN = "data-mk-shared-hidden";
1413
+ var clamp = (value, min, max) => Math.min(Math.max(value, min), Math.max(min, max));
1414
+ var radiusOf2 = (value, size) => {
1415
+ const parsed = Number.parseFloat(value) || 0;
1416
+ return value.trim().endsWith("%") ? parsed / 100 * size : parsed;
1417
+ };
1418
+ function shapeOf(surface, origin) {
1419
+ if (!origin?.isConnected) return null;
1420
+ const start = origin.getBoundingClientRect();
1421
+ const box = surface.getBoundingClientRect();
1422
+ if (start.width < 4 || start.height < 4 || !box.width || !box.height) return null;
1423
+ if (start.bottom < 0 || start.top > innerHeight || start.right < 0 || start.left > innerWidth) return null;
1424
+ const width = Math.min(start.width, box.width);
1425
+ const height = Math.min(start.height, box.height);
1426
+ const left = clamp(start.left - box.left, 0, box.width - width);
1427
+ const top = clamp(start.top - box.top, 0, box.height - height);
1428
+ const corner = Math.min(radiusOf2(getComputedStyle(origin).borderTopLeftRadius, start.height), width / 2, height / 2);
1429
+ const radius = radiusOf2(getComputedStyle(surface).borderTopLeftRadius, box.height);
1430
+ return {
1431
+ x: start.left + (start.width - width) / 2 - (box.left + left),
1432
+ y: start.top + (start.height - height) / 2 - (box.top + top),
1433
+ from: `inset(${top}px ${box.width - left - width}px ${box.height - top - height}px ${left}px round ${corner}px)`,
1434
+ to: `inset(0px 0px 0px 0px round ${radius}px)`,
1435
+ left,
1436
+ top,
1437
+ width,
1438
+ height
1439
+ };
1440
+ }
1441
+ var LOOK = [
1442
+ "display",
1443
+ "alignItems",
1444
+ "justifyContent",
1445
+ "gap",
1446
+ "padding",
1447
+ "borderRadius",
1448
+ "borderWidth",
1449
+ "borderStyle",
1450
+ "borderColor",
1451
+ "backgroundColor",
1452
+ "color",
1453
+ "fontFamily",
1454
+ "fontSize",
1455
+ "fontWeight",
1456
+ "lineHeight",
1457
+ "letterSpacing",
1458
+ "whiteSpace"
1459
+ ];
1460
+ function faceOf(surface, origin, shape, withCopy) {
1461
+ const look = getComputedStyle(origin);
1462
+ const face = document.createElement("div");
1463
+ face.className = FACE;
1464
+ face.setAttribute("aria-hidden", "true");
1465
+ face.inert = true;
1466
+ if (!transparentColor(look.backgroundColor)) face.style.background = look.backgroundColor;
1467
+ surface.append(face);
1468
+ if (!withCopy) return { face, copy: null };
1469
+ const copy = document.createElement("span");
1470
+ copy.innerHTML = origin.innerHTML;
1471
+ for (const element of copy.querySelectorAll("[id], [name], [for]")) for (const name of ["id", "name", "for"]) element.removeAttribute(name);
1472
+ for (const property of LOOK) copy.style[property] = look[property];
1473
+ Object.assign(copy.style, {
1474
+ position: "absolute",
1475
+ left: `${shape.left}px`,
1476
+ top: `${shape.top}px`,
1477
+ width: `${shape.width}px`,
1478
+ height: `${shape.height}px`,
1479
+ boxSizing: "border-box",
1480
+ margin: "0",
1481
+ overflow: "hidden"
1482
+ });
1483
+ face.append(copy);
1484
+ return { face, copy };
1485
+ }
1486
+ var running = /* @__PURE__ */ new WeakMap();
1487
+ var isMorphing = (surface) => running.has(surface);
1488
+ function stop(surface) {
1489
+ running.get(surface)?.kill();
1490
+ running.delete(surface);
1491
+ gsap.killTweensOf(surface);
1492
+ for (const face of surface.querySelectorAll(`:scope > .${FACE}`)) face.remove();
1493
+ clearStyles([surface], MORPH_STYLES);
1494
+ }
1495
+ function stopMorph(surface) {
1496
+ stop(surface);
1497
+ const parts = [...surface.querySelectorAll(":scope > *")].filter((element) => !element.classList.contains("mk-liquid"));
1498
+ gsap.killTweensOf(parts);
1499
+ clearStyles(parts, MORPH_STYLES);
1500
+ }
1501
+ var compact = (element) => {
1502
+ const box = element.getBoundingClientRect();
1503
+ return box.width <= 360 && box.height <= 72;
1504
+ };
1505
+ function showOrigin(origin, { fade = false } = {}) {
1506
+ if (!origin?.hasAttribute(HIDDEN_ORIGIN)) return;
1507
+ if (!fade || reduced()) {
1508
+ origin.removeAttribute(HIDDEN_ORIGIN);
1509
+ return;
1510
+ }
1511
+ const previous = origin.style.transition;
1512
+ const { originShow, originShowDelay } = TIMING.dialog;
1513
+ origin.style.transition = `opacity ${originShow}s cubic-bezier(0.215, 0.61, 0.355, 1) ${originShowDelay}s`;
1514
+ origin.removeAttribute(HIDDEN_ORIGIN);
1515
+ setTimeout(() => {
1516
+ origin.style.transition = previous;
1517
+ }, (originShow + originShowDelay) * 1e3 + 50);
1518
+ }
1519
+ function groupOf(surface, parts, shape) {
1520
+ const box = surface.getBoundingClientRect();
1521
+ for (const part2 of parts) {
1522
+ const own = part2.getBoundingClientRect();
1523
+ gsap.set(part2, { transformOrigin: `${box.left - own.left}px ${box.top - own.top}px` });
1524
+ }
1525
+ return {
1526
+ x: shape.left,
1527
+ y: shape.top,
1528
+ scaleX: box.width ? shape.width / box.width : 1,
1529
+ scaleY: box.height ? shape.height / box.height : 1
1530
+ };
1531
+ }
1532
+ var escape = (value) => typeof CSS !== "undefined" && CSS.escape ? CSS.escape(value) : value.replace(/"/g, '\\"');
1533
+ function sharedPairs(origin, surface) {
1534
+ return [origin, ...origin.querySelectorAll(`[${SHARED}]`)].filter((source) => source.hasAttribute(SHARED)).map((source) => ({
1535
+ source,
1536
+ target: surface.querySelector(`[${SHARED}="${escape(source.getAttribute(SHARED) ?? "")}"]`)
1537
+ })).filter((pair) => pair.target !== null);
1538
+ }
1539
+ function textBox(element) {
1540
+ const box = element.getBoundingClientRect();
1541
+ const style = getComputedStyle(element);
1542
+ const px = (value) => parseFloat(value) || 0;
1543
+ const left = box.left + px(style.borderLeftWidth) + px(style.paddingLeft);
1544
+ const top = box.top + px(style.borderTopWidth) + px(style.paddingTop);
1545
+ const bottom = box.bottom - px(style.borderBottomWidth) - px(style.paddingBottom);
1546
+ return { left, top, height: Math.max(0, bottom - top), style };
1547
+ }
1548
+ var textOf = (element) => element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement ? element.value || element.placeholder : element.firstChild?.textContent ?? element.textContent ?? "";
1549
+ function flyText(from, to, text, duration) {
1550
+ return new Promise((resolve) => {
1551
+ const start = textBox(from);
1552
+ const end = textBox(to);
1553
+ const fromSize = parseFloat(start.style.fontSize) || 16;
1554
+ const toSize = parseFloat(end.style.fontSize) || fromSize;
1555
+ const scale = toSize / fromSize;
1556
+ const ghost = document.createElement("div");
1557
+ ghost.setAttribute("aria-hidden", "true");
1558
+ ghost.setAttribute("popover", "manual");
1559
+ ghost.textContent = text;
1560
+ Object.assign(ghost.style, {
1561
+ position: "fixed",
1562
+ inset: "auto",
1563
+ left: `${start.left}px`,
1564
+ top: `${start.top}px`,
1565
+ margin: "0",
1566
+ padding: "0",
1567
+ border: "0",
1568
+ background: "transparent",
1569
+ overflow: "visible",
1570
+ whiteSpace: "nowrap",
1571
+ pointerEvents: "none",
1572
+ fontFamily: start.style.fontFamily,
1573
+ fontSize: start.style.fontSize,
1574
+ fontWeight: start.style.fontWeight,
1575
+ lineHeight: `${start.height || fromSize * 1.2}px`,
1576
+ letterSpacing: start.style.letterSpacing,
1577
+ color: start.style.color,
1578
+ transformOrigin: "0 0"
1579
+ });
1580
+ document.body.append(ghost);
1581
+ if (typeof ghost.showPopover === "function") ghost.showPopover();
1582
+ const height = (start.height || fromSize * 1.2) * scale;
1583
+ gsap.to(ghost, {
1584
+ x: end.left - start.left,
1585
+ y: end.top + end.height / 2 - height / 2 - start.top,
1586
+ scale,
1587
+ color: end.style.color,
1588
+ duration,
1589
+ ease: EASE.signature,
1590
+ onComplete: () => {
1591
+ ghost.remove();
1592
+ resolve();
1593
+ }
1594
+ });
1595
+ });
1596
+ }
1597
+ function releaseShared(origin) {
1598
+ if (!origin) return;
1599
+ for (const element of [origin, ...origin.querySelectorAll(`[${SHARED_HIDDEN}]`)]) element.removeAttribute(SHARED_HIDDEN);
1600
+ }
1601
+ function shareInto(origin, surface, duration = TIMING.dialog.open) {
1602
+ for (const { source, target } of sharedPairs(origin, surface)) {
1603
+ const text = textOf(source);
1604
+ source.setAttribute(SHARED_HIDDEN, "");
1605
+ gsap.set(target, { opacity: 0 });
1606
+ void flyText(source, target, text, duration).then(() => gsap.set(target, { clearProps: "opacity" }));
1607
+ }
1608
+ }
1609
+ function shareBack(surface, origin, duration = TIMING.dialog.close) {
1610
+ for (const { source, target } of sharedPairs(origin, surface)) {
1611
+ gsap.set(target, { opacity: 0 });
1612
+ void flyText(target, source, textOf(source), duration).then(() => source.removeAttribute(SHARED_HIDDEN));
1613
+ }
1614
+ }
1615
+ var partsOf = (surface, content) => [...surface.querySelectorAll(content ?? ":scope > *")].filter(
1616
+ (element) => !element.classList.contains(FACE) && !element.classList.contains("mk-liquid")
1617
+ );
1618
+ function morphOpen(surface, origin, options = {}) {
1619
+ registerMotion();
1620
+ const { duration = TIMING.dialog.open, hideOrigin = false, content, stagger = 0, liquid = false } = options;
1621
+ stop(surface);
1622
+ if (reduced()) return null;
1623
+ const parts = partsOf(surface, content);
1624
+ if (liquid && !stagger && origin && shapeOf(surface, origin)) {
1625
+ if (hideOrigin && compact(origin)) origin.setAttribute(HIDDEN_ORIGIN, "");
1626
+ const settle = liquidOpen(surface, origin, parts);
1627
+ const window2 = gsap.timeline({
1628
+ onComplete: () => {
1629
+ settle();
1630
+ running.delete(surface);
1631
+ },
1632
+ onInterrupt: settle
1633
+ });
1634
+ window2.to({}, { duration: TIMING.liquid.safetyMs / 1e3 });
1635
+ running.set(surface, window2);
1636
+ return window2;
1637
+ }
1638
+ const enter = stagger ? { opacity: 1, y: 0, duration: TIMING.dialog.list, ease: "power2.out", stagger, clearProps: "opacity,transform" } : { opacity: 1, filter: "blur(0px)", duration, ease: EASE.signature, clearProps: "opacity,filter" };
1639
+ const enterFrom = stagger ? { opacity: 0, y: -6 } : { opacity: 0, filter: "blur(8px)" };
1640
+ const shape = shapeOf(surface, origin);
1641
+ if (!shape || !origin) {
1642
+ const rise = gsap.timeline({
1643
+ onComplete: () => {
1644
+ running.delete(surface);
1645
+ }
1646
+ }).fromTo(
1647
+ surface,
1648
+ { opacity: 0, scale: 0.92 },
1649
+ { opacity: 1, scale: 1, duration: TIMING.dialog.fallback, ease: "power2.out", clearProps: "opacity,transform" }
1650
+ );
1651
+ if (parts.length) rise.fromTo(parts, enterFrom, { ...enter, duration: Math.min(enter.duration, TIMING.dialog.fallback) }, 0);
1652
+ running.set(surface, rise);
1653
+ return rise;
1654
+ }
1655
+ const list2 = Boolean(stagger);
1656
+ if (!list2) shareInto(origin, surface, duration);
1657
+ const { face, copy } = faceOf(surface, origin, shape, list2);
1658
+ const group = list2 ? null : groupOf(surface, parts, shape);
1659
+ if (hideOrigin && compact(origin)) origin.setAttribute(HIDDEN_ORIGIN, "");
1660
+ const finish = () => {
1661
+ face.remove();
1662
+ running.delete(surface);
1663
+ gsap.set(surface, { clearProps: "transform,clipPath,willChange" });
1664
+ if (parts.length) gsap.set(parts, { clearProps: "opacity,transform,transformOrigin,filter" });
1665
+ };
1666
+ const timeline = gsap.timeline({ onComplete: finish, onInterrupt: finish }).fromTo(
1667
+ surface,
1668
+ { x: shape.x, y: shape.y, clipPath: shape.from, willChange: "transform,clip-path" },
1669
+ { x: 0, y: 0, clipPath: shape.to, duration, ease: EASE.signature },
1670
+ 0
1671
+ ).to(face, { opacity: 0, duration: TIMING.dialog.surfaceColor, ease: EASE.signature }, 0);
1672
+ if (copy) timeline.to(copy, { opacity: 0, duration: 0.25, ease: "power2.out" }, 0.05);
1673
+ if (parts.length) {
1674
+ if (group) {
1675
+ timeline.fromTo(
1676
+ parts,
1677
+ { ...group, opacity: 0, filter: "blur(8px)" },
1678
+ { x: 0, y: 0, scaleX: 1, scaleY: 1, opacity: 1, filter: "blur(0px)", duration, ease: EASE.signature },
1679
+ 0
1680
+ );
1681
+ } else timeline.fromTo(parts, enterFrom, enter, duration * 0.2);
1682
+ }
1683
+ running.set(surface, timeline);
1684
+ return timeline;
1685
+ }
1686
+ function morphClose(surface, origin, onComplete, options = {}) {
1687
+ registerMotion();
1688
+ const { duration = TIMING.dialog.close, content, liquid = false } = options;
1689
+ stop(surface);
1690
+ if (reduced()) {
1691
+ onComplete();
1692
+ return null;
1693
+ }
1694
+ const parts = partsOf(surface, content);
1695
+ const shape = shapeOf(surface, origin);
1696
+ if (!shape || !origin) {
1697
+ const fade = gsap.timeline({
1698
+ onComplete: () => {
1699
+ running.delete(surface);
1700
+ onComplete();
1701
+ gsap.set(surface, { clearProps: "opacity,transform" });
1702
+ if (parts.length) gsap.set(parts, { clearProps: "filter" });
1703
+ }
1704
+ }).to(surface, { scale: 0.9, duration, ease: EASE.signature }, 0).to(surface, { opacity: 0, duration, ease: EASE.fadeAway }, 0);
1705
+ if (parts.length) fade.to(parts, { filter: "blur(32px)", duration, ease: EASE.blurAway }, 0);
1706
+ running.set(surface, fade);
1707
+ return fade;
1708
+ }
1709
+ const list2 = content !== void 0;
1710
+ if (liquid && !list2) {
1711
+ liquidClose(surface, origin, parts, onComplete);
1712
+ return null;
1713
+ }
1714
+ const { face, copy } = faceOf(surface, origin, shape, list2);
1715
+ gsap.set(copy ? [face, copy] : face, { opacity: 0 });
1716
+ if (!list2) {
1717
+ shareBack(surface, origin, duration);
1718
+ const group = groupOf(surface, parts, shape);
1719
+ const signature = gsap.parseEase(EASE.signature);
1720
+ const toward = (progress) => signature(progress * (duration / TIMING.dialog.contentReturn));
1721
+ const timeline2 = gsap.timeline({
1722
+ onComplete: () => {
1723
+ running.delete(surface);
1724
+ onComplete();
1725
+ face.remove();
1726
+ gsap.set(surface, { clearProps: "transform,clipPath,opacity,willChange" });
1727
+ if (parts.length) gsap.set(parts, { clearProps: "opacity,transform,transformOrigin,filter,borderRadius" });
1728
+ },
1729
+ onInterrupt: () => {
1730
+ face.remove();
1731
+ if (parts.length) gsap.set(parts, { clearProps: "opacity,transform,transformOrigin,filter,borderRadius" });
1732
+ }
1733
+ }).fromTo(
1734
+ surface,
1735
+ { clipPath: shape.to, willChange: "transform,clip-path" },
1736
+ { x: shape.x, y: shape.y, clipPath: shape.from, duration, ease: EASE.signature },
1737
+ 0
1738
+ ).to(face, { opacity: 1, duration, ease: EASE.signature }, 0).to(surface, { opacity: 0, duration, ease: "power3.in" }, 0);
1739
+ if (parts.length) {
1740
+ timeline2.to(parts, { ...group, duration, ease: toward }, 0).to(parts, { opacity: 0, borderRadius: "400px", duration, ease: EASE.fadeAway }, 0).to(parts, { filter: "blur(32px)", duration, ease: EASE.blurAway }, 0);
1741
+ }
1742
+ running.set(surface, timeline2);
1743
+ return timeline2;
1744
+ }
1745
+ const timeline = gsap.timeline({
1746
+ onComplete: () => {
1747
+ running.delete(surface);
1748
+ onComplete();
1749
+ face.remove();
1750
+ gsap.set(surface, { clearProps: "transform,clipPath,willChange" });
1751
+ if (parts.length) gsap.set(parts, { clearProps: "opacity,transform,filter" });
1752
+ },
1753
+ onInterrupt: () => {
1754
+ face.remove();
1755
+ if (parts.length) gsap.set(parts, { clearProps: "opacity,transform,filter" });
1756
+ }
1757
+ }).fromTo(
1758
+ surface,
1759
+ { clipPath: shape.to, willChange: "transform,clip-path" },
1760
+ { x: shape.x, y: shape.y, clipPath: shape.from, duration, ease: EASE.signature },
1761
+ 0
1762
+ ).to(face, { opacity: 1, duration: duration * 0.5, ease: "power1.in" }, duration * 0.3);
1763
+ if (parts.length) timeline.to(parts, { opacity: 0, filter: "blur(32px)", duration: duration * 0.7, ease: "power2.in" }, 0);
1764
+ if (copy) timeline.to(copy, { opacity: 1, duration: duration * 0.3, ease: "power1.in" }, duration * 0.65);
1765
+ running.set(surface, timeline);
1766
+ return timeline;
1767
+ }
1768
+ function morphCloseWithGhost(surface, origin, { inPlace = false, liquid = false } = {}) {
1769
+ registerMotion();
1770
+ const dragged = inPlace ? {
1771
+ x: Number(gsap.getProperty(surface, "x")) || 0,
1772
+ y: Number(gsap.getProperty(surface, "y")) || 0,
1773
+ scale: Number(gsap.getProperty(surface, "scaleX")) || 1
1774
+ } : null;
1775
+ if (dragged) gsap.set(surface, { clearProps: "transform" });
1776
+ const ghost = reduced() ? null : ghostOf(surface);
1777
+ if (!ghost) {
1778
+ showOrigin(origin);
1779
+ releaseShared(origin);
1780
+ return;
1781
+ }
1782
+ const veil = backdropVeil(surface);
1783
+ document.body.append(veil, ghost);
1784
+ showOrigin(origin, { fade: true });
1785
+ gsap.to(veil, { opacity: 0, duration: TIMING.dialog.close, ease: "power3.in" });
1786
+ if (dragged) gsap.set(ghost, { ...dragged, transformOrigin: getComputedStyle(surface).transformOrigin });
1787
+ morphClose(
1788
+ ghost,
1789
+ dragged ? null : origin,
1790
+ () => {
1791
+ showOrigin(origin);
1792
+ releaseShared(origin);
1793
+ ghost.remove();
1794
+ veil.remove();
1795
+ },
1796
+ { liquid }
1797
+ );
1798
+ }
1799
+
1800
+ // src/motion/sheet.ts
1801
+ var UNDERLAY_STYLES = ["transform", "translate", "rotate", "scale", "transform-origin", "opacity"];
1802
+ function sheetOpen(surface) {
1803
+ if (reduced()) return null;
1804
+ registerMotion();
1805
+ return gsap.fromTo(surface, { yPercent: 100 }, { yPercent: 0, duration: TIMING.sheet.open, ease: EASE.sheet, clearProps: "transform" });
1806
+ }
1807
+ function sheetClose(surface, { inPlace = false } = {}) {
1808
+ registerMotion();
1809
+ const dragged = inPlace ? Number(gsap.getProperty(surface, "y")) || 0 : 0;
1810
+ gsap.killTweensOf(surface);
1811
+ clearStyles([surface], ["transform", "translate", "rotate", "scale"]);
1812
+ const ghost = reduced() ? null : ghostOf(surface);
1813
+ if (!ghost) return null;
1814
+ const veil = backdropVeil(surface);
1815
+ document.body.append(veil, ghost);
1816
+ gsap.to(veil, { opacity: 0, duration: TIMING.sheet.close, ease: "power3.in", onComplete: () => veil.remove() });
1817
+ return gsap.fromTo(
1818
+ ghost,
1819
+ { y: dragged, yPercent: 0 },
1820
+ { yPercent: 100, duration: TIMING.sheet.close, ease: EASE.sheet, onComplete: () => ghost.remove() }
1821
+ );
1822
+ }
1823
+ function pushUnderlay(elements) {
1824
+ if (!elements.length || reduced()) return;
1825
+ registerMotion();
1826
+ const { ease, duration } = motionSpring(...TIMING.springs.underlay);
1827
+ gsap.to(elements, {
1828
+ scale: TIMING.sheet.underlayScale,
1829
+ opacity: TIMING.sheet.underlayOpacity,
1830
+ transformOrigin: "50% 0",
1831
+ duration,
1832
+ ease,
1833
+ overwrite: "auto"
1834
+ });
1835
+ }
1836
+ function releaseUnderlay(elements, animated = true) {
1837
+ if (!elements.length) return;
1838
+ const restore = () => clearStyles(elements, UNDERLAY_STYLES);
1839
+ if (!animated || reduced()) {
1840
+ gsap.killTweensOf(elements);
1841
+ restore();
1842
+ return;
1843
+ }
1844
+ const { ease, duration } = motionSpring(...TIMING.springs.underlay);
1845
+ gsap.to(elements, { scale: 1, opacity: 1, duration, ease, overwrite: "auto", onComplete: restore });
1846
+ }
1847
+
1848
+ // src/components/dialog/engine.ts
1849
+ var DEFAULT_LABELS = { close: "Cerrar", float: "Ventana flotante", dock: "Volver a su sitio" };
1850
+ var FIELDS = '[autofocus], input:not([type="hidden"]):not(:disabled), textarea:not(:disabled), select:not(:disabled)';
1851
+ var CORNERS = ["tl", "tr", "bl", "br"];
1852
+ var uid = 0;
1853
+ var part = (dialog, name) => dialog.querySelector(`[data-mk-part="${name}"]`);
1854
+ function createDialog(dialog, options = {}) {
1855
+ if (!dialog) {
1856
+ warnOnce("dialog: missing <dialog> element");
1857
+ return inert({ open() {
1858
+ }, close() {
1859
+ }, toggle() {
1860
+ }, float() {
1861
+ }, dock() {
1862
+ }, isOpen: false, isFloating: false, element: null });
1863
+ }
1864
+ registerMotion();
1865
+ const {
1866
+ variant = "morph",
1867
+ placement = "center",
1868
+ backdrop = true,
1869
+ closeOnBackdrop = true,
1870
+ drag = true,
1871
+ float: floatKey = false,
1872
+ autoResize = true,
1873
+ triggers = true,
1874
+ modal = true
1875
+ } = options;
1876
+ const labels = { ...DEFAULT_LABELS, ...options.labels };
1877
+ const liquid = variant === "liquid";
1878
+ const sheet = variant === "sheet";
1879
+ const scope = createScope();
1880
+ let session = [];
1881
+ let opener = null;
1882
+ let isOpen = false;
1883
+ let closing = false;
1884
+ let floating = false;
1885
+ let ownCloses = 0;
1886
+ const closeNatively = () => {
1887
+ if (!dialog.hasAttribute("open")) return;
1888
+ ownCloses += 1;
1889
+ closeModal(dialog);
1890
+ };
1891
+ let destroyed = false;
1892
+ let tearingDown = false;
1893
+ if (placement !== "center") scope.attr(dialog, "data-mk-placement", placement);
1894
+ if (!backdrop) scope.attr(dialog, "data-mk-backdrop", "none");
1895
+ scope.attr(dialog, "data-mk-variant", variant);
1896
+ const title = part(dialog, "title");
1897
+ if (title && !dialog.hasAttribute("aria-label") && !dialog.hasAttribute("aria-labelledby")) {
1898
+ if (!title.id) scope.attr(title, "id", `mk-dialog-title-${++uid}`);
1899
+ scope.attr(dialog, "aria-labelledby", title.id);
1900
+ }
1901
+ const description = part(dialog, "description");
1902
+ if (description && !dialog.hasAttribute("aria-describedby")) {
1903
+ if (!description.id) scope.attr(description, "id", `mk-dialog-description-${++uid}`);
1904
+ scope.attr(dialog, "aria-describedby", description.id);
1905
+ }
1906
+ const closeButton = part(dialog, "close");
1907
+ if (closeButton && !closeButton.hasAttribute("aria-label") && !closeButton.textContent?.trim()) {
1908
+ scope.attr(closeButton, "aria-label", labels.close);
1909
+ }
1910
+ const handle = floatKey ? part(dialog, "handle") : null;
1911
+ if (handle) {
1912
+ scope.attr(handle, "data-mk-no-drag", "");
1913
+ scope.attr(handle, "aria-pressed", "false");
1914
+ scope.attr(handle, "aria-label", labels.float);
1915
+ }
1916
+ const corners = [];
1917
+ if (floatKey) {
1918
+ for (const corner of CORNERS) {
1919
+ const element = document.createElement("span");
1920
+ element.className = "mk-float-corner";
1921
+ element.dataset.mkFloatCorner = corner;
1922
+ element.dataset.mkNoDrag = "";
1923
+ element.setAttribute("aria-hidden", "true");
1924
+ dialog.append(element);
1925
+ corners.push(element);
1926
+ }
1927
+ scope.add(() => corners.forEach((corner) => corner.remove()));
1928
+ }
1929
+ const emit = (type, cancelable = false, detail = {}) => dialog.dispatchEvent(new CustomEvent(type, { bubbles: true, cancelable, detail: { dialog, ...detail } }));
1930
+ const endSession = () => {
1931
+ for (const cleanup of session.splice(0).reverse()) cleanup();
1932
+ };
1933
+ const settleFloating = () => {
1934
+ if (!floating) return;
1935
+ floating = false;
1936
+ if (typeof dialog.hidePopover === "function" && dialog.hasAttribute("popover")) {
1937
+ try {
1938
+ dialog.hidePopover();
1939
+ } catch {
1940
+ }
1941
+ }
1942
+ dialog.removeAttribute("popover");
1943
+ unplaceWindow(dialog);
1944
+ if (handle) {
1945
+ handle.setAttribute("aria-pressed", "false");
1946
+ handle.setAttribute("aria-label", labels.float);
1947
+ }
1948
+ };
1949
+ const closedQuietly = () => {
1950
+ stopMorph(dialog);
1951
+ endSession();
1952
+ isOpen = false;
1953
+ closing = false;
1954
+ showOrigin(opener);
1955
+ releaseShared(opener);
1956
+ emit("mk:closed");
1957
+ options.onClose?.();
1958
+ };
1959
+ const lift = () => {
1960
+ if (!floatKey || floating || !isOpen || !floatingAvailable()) return;
1961
+ const box = dialog.getBoundingClientRect();
1962
+ const rect = savedFloat(floatKey) ?? { top: box.top, left: box.left, width: box.width, height: box.height };
1963
+ const focused = document.activeElement;
1964
+ const backdropStyle = getComputedStyle(dialog, "::backdrop");
1965
+ const veil = document.createElement("div");
1966
+ veil.setAttribute("aria-hidden", "true");
1967
+ Object.assign(veil.style, {
1968
+ position: "fixed",
1969
+ inset: "0",
1970
+ background: backdropStyle.background || backdropStyle.backgroundColor,
1971
+ backdropFilter: backdropStyle.backdropFilter,
1972
+ pointerEvents: "none"
1973
+ });
1974
+ closeNatively();
1975
+ document.body.append(veil);
1976
+ dialog.setAttribute("popover", "manual");
1977
+ if (typeof dialog.showPopover === "function") dialog.showPopover();
1978
+ else openModal(dialog, false);
1979
+ liftWindow(dialog, rect);
1980
+ gsap.to(veil, { opacity: 0, duration: reduced() ? 0 : TIMING.float.shadow, ease: EASE.signature, onComplete: () => veil.remove() });
1981
+ floating = true;
1982
+ if (handle) {
1983
+ handle.setAttribute("aria-pressed", "true");
1984
+ handle.setAttribute("aria-label", labels.dock);
1985
+ }
1986
+ showOrigin(opener, { fade: true });
1987
+ if (focused instanceof HTMLElement && dialog.contains(focused)) focused.focus();
1988
+ };
1989
+ const dock = () => {
1990
+ if (!floatKey || !floating) return;
1991
+ const box = dialog.getBoundingClientRect();
1992
+ const focused = document.activeElement;
1993
+ floating = false;
1994
+ if (typeof dialog.hidePopover === "function") dialog.hidePopover();
1995
+ dialog.removeAttribute("popover");
1996
+ closeNatively();
1997
+ openModal(dialog, modal);
1998
+ dockWindow(dialog, { top: box.top, left: box.left, width: box.width, height: box.height });
1999
+ if (backdrop) void fadeBackdrop(dialog, "in");
2000
+ forgetFloat(floatKey);
2001
+ if (handle) {
2002
+ handle.setAttribute("aria-pressed", "false");
2003
+ handle.setAttribute("aria-label", labels.float);
2004
+ }
2005
+ if (focused instanceof HTMLElement && dialog.contains(focused)) focused.focus();
2006
+ };
2007
+ const startSession = () => {
2008
+ if (sheet) {
2009
+ const behind = [...document.querySelectorAll("[data-mk-underlay]")];
2010
+ pushUnderlay(behind);
2011
+ const root = document.documentElement;
2012
+ const overflow = root.style.overflow;
2013
+ root.style.overflow = "hidden";
2014
+ session.push(() => {
2015
+ root.style.overflow = overflow;
2016
+ if (root.getAttribute("style") === "") root.removeAttribute("style");
2017
+ releaseUnderlay(behind, !tearingDown);
2018
+ });
2019
+ }
2020
+ if (autoResize && typeof ResizeObserver === "function") {
2021
+ let last = dialog.offsetHeight;
2022
+ let resizing = null;
2023
+ const observer = new ResizeObserver(() => {
2024
+ if (resizing?.isActive()) return;
2025
+ const next = dialog.offsetHeight;
2026
+ const previous = last;
2027
+ last = next;
2028
+ if (floating || Math.abs(next - previous) < 2 || !previous || isMorphing(dialog) || reduced()) return;
2029
+ resizing = gsap.fromTo(
2030
+ dialog,
2031
+ { height: previous },
2032
+ {
2033
+ height: next,
2034
+ duration: TIMING.dialog.autoResize,
2035
+ ease: EASE.signature,
2036
+ clearProps: "height",
2037
+ onComplete: () => {
2038
+ last = dialog.offsetHeight;
2039
+ }
2040
+ }
2041
+ );
2042
+ });
2043
+ observer.observe(dialog);
2044
+ session.push(() => {
2045
+ observer.disconnect();
2046
+ resizing?.kill();
2047
+ clearStyles([dialog], ["height"]);
2048
+ });
2049
+ }
2050
+ if (drag) {
2051
+ session.push(
2052
+ attachDragDismiss(dialog, {
2053
+ canDrag: () => !isMorphing(dialog) && !floating && !closing && isOpen,
2054
+ onDismiss: () => close(true)
2055
+ })
2056
+ );
2057
+ }
2058
+ if (placement === "anchor") {
2059
+ const onResize = () => {
2060
+ if (isOpen && !floating) anchorSurface(dialog, opener?.isConnected ? opener.getBoundingClientRect() : null);
2061
+ };
2062
+ addEventListener("resize", onResize);
2063
+ session.push(() => {
2064
+ removeEventListener("resize", onResize);
2065
+ clearAnchor(dialog);
2066
+ });
2067
+ }
2068
+ if (floatKey && handle) {
2069
+ session.push(attachFloating(dialog, { key: floatKey, handle, corners, isFloating: () => floating, float: lift, dock }));
2070
+ const onResize = () => {
2071
+ if (floating && !floatingAvailable()) dock();
2072
+ };
2073
+ addEventListener("resize", onResize);
2074
+ session.push(() => removeEventListener("resize", onResize));
2075
+ }
2076
+ };
2077
+ const open = (origin) => {
2078
+ if (destroyed || isOpen) return;
2079
+ const active = document.activeElement;
2080
+ opener = origin !== void 0 ? origin : active instanceof HTMLElement && active !== document.body && !dialog.contains(active) ? active : null;
2081
+ closing = false;
2082
+ isOpen = true;
2083
+ openModal(dialog, modal);
2084
+ if (placement === "anchor") anchorSurface(dialog, opener?.getBoundingClientRect());
2085
+ if (backdrop && modal) void fadeBackdrop(dialog, "in");
2086
+ if (sheet) sheetOpen(dialog);
2087
+ else morphOpen(dialog, opener, { hideOrigin: true, liquid, content: options.animateContent === false ? ":scope > :not(*)" : void 0 });
2088
+ startSession();
2089
+ dialog.querySelector(FIELDS)?.focus({ preventScroll: true });
2090
+ emit("mk:open", false, { origin: opener });
2091
+ options.onOpen?.();
2092
+ };
2093
+ const close = (inPlace = false) => {
2094
+ if (destroyed || !isOpen || closing) return;
2095
+ if (!emit("mk:close", true, { inPlace })) return;
2096
+ closing = true;
2097
+ if (sheet) sheetClose(dialog, { inPlace });
2098
+ else morphCloseWithGhost(dialog, opener, { inPlace, liquid });
2099
+ endSession();
2100
+ if (floating) settleFloating();
2101
+ if (dialog.hasAttribute("open")) closeModal(dialog);
2102
+ isOpen = false;
2103
+ closing = false;
2104
+ if (opener?.isConnected) opener.focus();
2105
+ emit("mk:closed");
2106
+ options.onClose?.();
2107
+ };
2108
+ scope.on(dialog, "cancel", (event) => {
2109
+ event.preventDefault();
2110
+ close();
2111
+ });
2112
+ scope.on(dialog, "close", () => {
2113
+ if (ownCloses > 0) {
2114
+ ownCloses -= 1;
2115
+ return;
2116
+ }
2117
+ if (!isOpen || closing) return;
2118
+ closedQuietly();
2119
+ });
2120
+ scope.on(dialog, "keydown", (event) => {
2121
+ if (event.key === "Escape" && floating) {
2122
+ event.preventDefault();
2123
+ close();
2124
+ }
2125
+ });
2126
+ scope.on(dialog, "click", (event) => {
2127
+ const target = event.target;
2128
+ if (target?.closest('[data-mk-part="close"], [data-mk-close]') && dialog.contains(target)) {
2129
+ close();
2130
+ return;
2131
+ }
2132
+ if (target !== dialog || !closeOnBackdrop || floating) return;
2133
+ const mouse = event;
2134
+ const box = dialog.getBoundingClientRect();
2135
+ if (mouse.clientX < box.left || mouse.clientX > box.right || mouse.clientY < box.top || mouse.clientY > box.bottom) close();
2136
+ });
2137
+ const triggerId = triggers === true ? dialog.id : triggers || "";
2138
+ if (triggerId) {
2139
+ const selector = `[data-mk-open="${typeof CSS !== "undefined" && CSS.escape ? CSS.escape(triggerId) : triggerId}"]`;
2140
+ scope.on(document, "click", (event) => {
2141
+ const trigger = event.target?.closest(selector);
2142
+ if (!trigger || dialog.contains(trigger)) return;
2143
+ event.preventDefault();
2144
+ if (isOpen) close();
2145
+ else open(trigger);
2146
+ });
2147
+ }
2148
+ dialog.dataset.mkReady = "";
2149
+ return {
2150
+ open,
2151
+ close: () => close(),
2152
+ toggle: (origin) => isOpen ? close() : open(origin),
2153
+ float: lift,
2154
+ dock,
2155
+ get isOpen() {
2156
+ return isOpen;
2157
+ },
2158
+ get isFloating() {
2159
+ return floating;
2160
+ },
2161
+ element: dialog,
2162
+ destroy() {
2163
+ if (destroyed) return;
2164
+ tearingDown = true;
2165
+ if (isOpen) {
2166
+ settleFloating();
2167
+ closing = true;
2168
+ if (dialog.hasAttribute("open")) closeModal(dialog);
2169
+ closedQuietly();
2170
+ }
2171
+ destroyed = true;
2172
+ endSession();
2173
+ gsap.killTweensOf(dialog);
2174
+ clearStyles([dialog], [...MORPH_STYLES, "height"]);
2175
+ scope.dispose();
2176
+ delete dialog.dataset.mkReady;
2177
+ }
2178
+ };
2179
+ }
2180
+
2181
+ // src/components/menu/engine.ts
2182
+ var ITEM = "[data-mk-item]";
2183
+ function createMenu(dialog, options = {}) {
2184
+ if (!dialog) {
2185
+ warnOnce("menu: missing <dialog> element");
2186
+ return inert({
2187
+ open() {
2188
+ },
2189
+ close() {
2190
+ },
2191
+ toggle() {
2192
+ },
2193
+ float() {
2194
+ },
2195
+ dock() {
2196
+ },
2197
+ isOpen: false,
2198
+ isFloating: false,
2199
+ element: null,
2200
+ items: []
2201
+ });
2202
+ }
2203
+ const { closeOnSelect = true } = options;
2204
+ const scope = createScope();
2205
+ let ticketAnimation;
2206
+ if (options.ticket) {
2207
+ scope.attr(dialog, "data-mk-ticket", "");
2208
+ scope.attr(dialog, "style", dialog.getAttribute("style"));
2209
+ for (const item of dialog.querySelectorAll(ITEM)) scope.attr(item, "style", item.getAttribute("style"));
2210
+ scope.add(() => ticketAnimation?.kill());
2211
+ }
2212
+ const items = () => [...dialog.querySelectorAll(ITEM)].filter((item) => !item.hasAttribute("disabled") && item.getAttribute("aria-disabled") !== "true");
2213
+ scope.attr(dialog, "role", "menu");
2214
+ const markItems = () => {
2215
+ for (const item of dialog.querySelectorAll(ITEM)) {
2216
+ scope.attr(item, "role", "menuitem");
2217
+ scope.attr(item, "tabindex", "-1");
2218
+ }
2219
+ };
2220
+ markItems();
2221
+ const surface = createDialog(dialog, {
2222
+ ...options,
2223
+ placement: "anchor",
2224
+ backdrop: false,
2225
+ drag: false,
2226
+ autoResize: false,
2227
+ animateContent: false,
2228
+ onOpen: () => {
2229
+ markItems();
2230
+ const list2 = items();
2231
+ if (options.ticket && !reduced()) {
2232
+ ticketAnimation?.kill();
2233
+ ticketAnimation = gsap.timeline().fromTo(dialog, { clipPath: "inset(0 0 100% 0)" }, { clipPath: "inset(0 0 0% 0)", duration: TIMING.ticketMenu.open, ease: "expo.out" }).fromTo(list2, { yPercent: TIMING.ticketMenu.from }, { yPercent: 0, duration: TIMING.ticketMenu.content, stagger: TIMING.ticketMenu.stagger, ease: "expo.out" }, 0);
2234
+ } else flowInMenu(list2);
2235
+ list2[0]?.focus({ preventScroll: true });
2236
+ options.onOpen?.();
2237
+ }
2238
+ });
2239
+ const select = (item) => {
2240
+ const value = item.dataset.mkValue ?? item.textContent?.trim() ?? "";
2241
+ dialog.dispatchEvent(new CustomEvent("mk:select", { bubbles: true, detail: { value, item } }));
2242
+ options.onSelect?.(value, item);
2243
+ if (closeOnSelect) surface.close();
2244
+ };
2245
+ scope.on(dialog, "click", (event) => {
2246
+ const item = event.target?.closest(ITEM);
2247
+ if (item && dialog.contains(item) && items().includes(item)) select(item);
2248
+ });
2249
+ scope.on(dialog, "keydown", (event) => {
2250
+ const key = event.key;
2251
+ const list2 = items();
2252
+ if (!list2.length) return;
2253
+ const at = list2.indexOf(document.activeElement);
2254
+ const moves = {
2255
+ ArrowDown: at < 0 ? 0 : (at + 1) % list2.length,
2256
+ ArrowUp: at < 0 ? list2.length - 1 : (at - 1 + list2.length) % list2.length,
2257
+ Home: 0,
2258
+ End: list2.length - 1
2259
+ };
2260
+ if (key in moves) {
2261
+ event.preventDefault();
2262
+ list2[moves[key]]?.focus();
2263
+ return;
2264
+ }
2265
+ const target = event.target;
2266
+ if ((key === "Enter" || key === " ") && list2.includes(target) && !target.matches("button, a[href]")) {
2267
+ event.preventDefault();
2268
+ select(target);
2269
+ }
2270
+ });
2271
+ return {
2272
+ open: surface.open,
2273
+ close: surface.close,
2274
+ toggle: surface.toggle,
2275
+ float: surface.float,
2276
+ dock: surface.dock,
2277
+ get isOpen() {
2278
+ return surface.isOpen;
2279
+ },
2280
+ get isFloating() {
2281
+ return surface.isFloating;
2282
+ },
2283
+ get items() {
2284
+ return items();
2285
+ },
2286
+ element: dialog,
2287
+ destroy() {
2288
+ surface.destroy();
2289
+ scope.dispose();
2290
+ }
2291
+ };
2292
+ }
2293
+
2294
+ export {
2295
+ PATHS,
2296
+ springPath,
2297
+ SIGNATURE_LINEAR,
2298
+ gsap,
2299
+ ScrollTrigger,
2300
+ SplitText,
2301
+ CustomEase,
2302
+ Flip,
2303
+ ELASTIC,
2304
+ EASE,
2305
+ registerMotion,
2306
+ easeOut,
2307
+ easeOutCubic,
2308
+ easeInCubic,
2309
+ bezier,
2310
+ spring,
2311
+ eased,
2312
+ createChannelState,
2313
+ stepChannel,
2314
+ channels,
2315
+ springEase,
2316
+ splitWords,
2317
+ splitGraphemes,
2318
+ requestFrame,
2319
+ nextFrame,
2320
+ clearStyles,
2321
+ MORPH_STYLES,
2322
+ motionSpring,
2323
+ springDuration,
2324
+ springLinear,
2325
+ flowIn,
2326
+ flowOut,
2327
+ stepChange,
2328
+ flowInMenu,
2329
+ flowInPalette,
2330
+ flowInForm,
2331
+ flowInLanding,
2332
+ flowInContent,
2333
+ pointer,
2334
+ bindPointer,
2335
+ takeMovement,
2336
+ revealFrom,
2337
+ tweenNumber,
2338
+ countTo,
2339
+ revealCounter,
2340
+ anchorSurface,
2341
+ clearAnchor,
2342
+ attachDragDismiss,
2343
+ floatingAvailable,
2344
+ clampRect,
2345
+ savedFloat,
2346
+ forgetFloat,
2347
+ liftWindow,
2348
+ dockWindow,
2349
+ attachFloating,
2350
+ transparentColor,
2351
+ openModal,
2352
+ closeModal,
2353
+ fadeBackdrop,
2354
+ backdropVeil,
2355
+ ghostOf,
2356
+ liquidOpen,
2357
+ liquidClose,
2358
+ isMorphing,
2359
+ stopMorph,
2360
+ showOrigin,
2361
+ releaseShared,
2362
+ shareInto,
2363
+ shareBack,
2364
+ morphOpen,
2365
+ morphClose,
2366
+ morphCloseWithGhost,
2367
+ sheetOpen,
2368
+ sheetClose,
2369
+ pushUnderlay,
2370
+ releaseUnderlay,
2371
+ createDialog,
2372
+ createMenu
2373
+ };
2374
+ //# sourceMappingURL=chunk-34XYOXHG.js.map