@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,1617 @@
1
+ import {
2
+ EASE,
3
+ Flip,
4
+ bezier,
5
+ channels,
6
+ clearStyles,
7
+ easeInCubic,
8
+ easeOut,
9
+ easeOutCubic,
10
+ eased,
11
+ flowIn,
12
+ flowInPalette,
13
+ flowOut,
14
+ gsap,
15
+ motionSpring,
16
+ nextFrame,
17
+ registerMotion,
18
+ revealCounter,
19
+ revealFrom,
20
+ splitGraphemes,
21
+ splitWords,
22
+ spring,
23
+ springEase
24
+ } from "./chunk-34XYOXHG.js";
25
+ import {
26
+ THEMES,
27
+ THEME_EVENT,
28
+ getTheme,
29
+ setTheme
30
+ } from "./chunk-J27KH2A2.js";
31
+ import {
32
+ TIMING,
33
+ createScope,
34
+ entrances,
35
+ reduced,
36
+ subscribe
37
+ } from "./chunk-RFDIZYFX.js";
38
+ import {
39
+ inert,
40
+ warnOnce
41
+ } from "./chunk-TGV27ZWM.js";
42
+
43
+ // src/motion/chat.ts
44
+ var isUser = (bubble) => bubble.dataset.mkRole === "user" || bubble.classList.contains("user");
45
+ function enterMessages(bubbles, { textSelector = "[data-mk-text], .message-text" } = {}) {
46
+ if (!bubbles.length || reduced()) return null;
47
+ registerMotion();
48
+ const reverts = [];
49
+ const cleanup = () => {
50
+ for (const revert of reverts.splice(0)) revert();
51
+ };
52
+ const timeline = gsap.timeline({ onComplete: cleanup, onInterrupt: cleanup });
53
+ bubbles.forEach((bubble, index) => {
54
+ gsap.set(bubble, { transformOrigin: isUser(bubble) ? "100% 50%" : "0% 50%" });
55
+ timeline.fromTo(
56
+ bubble,
57
+ { scale: 0.5, autoAlpha: 0, filter: "blur(24px)" },
58
+ { scale: 1, autoAlpha: 1, filter: "blur(0px)", duration: TIMING.bubble, ease: EASE.signature, clearProps: "transform,opacity,visibility,filter" },
59
+ index * TIMING.bubbleStagger
60
+ );
61
+ const text = bubble.querySelector(textSelector);
62
+ if (!text) return;
63
+ const before = text.offsetHeight;
64
+ const split = splitWords(text);
65
+ const lineHeight = parseFloat(getComputedStyle(text).lineHeight) || 0;
66
+ let targets = split.parts;
67
+ if (!split.parts.length || text.offsetHeight - before > lineHeight / 2) {
68
+ split.revert();
69
+ targets = [text];
70
+ } else reverts.push(() => split.revert());
71
+ timeline.fromTo(
72
+ targets,
73
+ { y: 16, autoAlpha: 0, filter: "blur(6px)" },
74
+ {
75
+ y: 0,
76
+ autoAlpha: 1,
77
+ filter: "blur(0px)",
78
+ duration: TIMING.word,
79
+ ease: "back.out(1)",
80
+ stagger: TIMING.wordStagger,
81
+ clearProps: "transform,opacity,visibility,filter"
82
+ },
83
+ index * TIMING.bubbleStagger
84
+ );
85
+ });
86
+ return timeline;
87
+ }
88
+ function fitComposer(field, min = 64) {
89
+ const from = field.offsetHeight;
90
+ field.style.height = "auto";
91
+ const to = Math.max(min, field.scrollHeight);
92
+ field.style.height = `${from}px`;
93
+ if (from === to || reduced()) {
94
+ field.style.height = `${to}px`;
95
+ return null;
96
+ }
97
+ registerMotion();
98
+ return gsap.to(field, { height: to, duration: TIMING.composer, ease: "power2.out", overwrite: "auto" });
99
+ }
100
+ function scrollToLatest(scroller) {
101
+ const top = scroller.scrollHeight - scroller.clientHeight;
102
+ if (reduced()) {
103
+ scroller.scrollTop = top;
104
+ return null;
105
+ }
106
+ registerMotion();
107
+ const state = { top: scroller.scrollTop };
108
+ return gsap.to(state, {
109
+ top,
110
+ duration: TIMING.chatScroll,
111
+ ease: EASE.chatScroll,
112
+ overwrite: "auto",
113
+ onUpdate: () => {
114
+ scroller.scrollTop = state.top;
115
+ }
116
+ });
117
+ }
118
+
119
+ // src/components/theme-picker/engine.ts
120
+ function createThemePicker(root, options = {}) {
121
+ if (!root) {
122
+ warnOnce("theme-picker: missing root");
123
+ return inert({ select() {
124
+ } });
125
+ }
126
+ registerMotion();
127
+ const scope = createScope();
128
+ const ctx = gsap.context(() => {
129
+ });
130
+ const generated = [];
131
+ let swatches = [...root.querySelectorAll("[data-mk-swatch]")];
132
+ if (!swatches.length) {
133
+ const byId = new Map(THEMES.map((theme) => [theme.id, theme]));
134
+ const ids = options.themes ?? THEMES.filter((theme) => options.showHidden || !theme.hidden).map((theme) => theme.id);
135
+ for (const id of ids) {
136
+ const theme = byId.get(id);
137
+ if (!theme) {
138
+ warnOnce(`theme-picker: unknown theme "${id}"`);
139
+ continue;
140
+ }
141
+ const button = document.createElement("button");
142
+ button.type = "button";
143
+ button.className = "mk-swatch";
144
+ button.dataset.mkSwatch = theme.id;
145
+ button.title = theme.name;
146
+ button.setAttribute("aria-label", theme.name);
147
+ button.style.setProperty("--mk-swatch", theme.seed);
148
+ root.append(button);
149
+ generated.push(button);
150
+ }
151
+ swatches = generated;
152
+ }
153
+ scope.attr(root, "role", "group");
154
+ if (!root.hasAttribute("aria-label")) scope.attr(root, "aria-label", options.labels?.group ?? "Tema");
155
+ const sync = () => {
156
+ const current = getTheme().id;
157
+ for (const swatch of swatches) scope.attr(swatch, "aria-pressed", String(swatch.dataset.mkSwatch === current));
158
+ };
159
+ const select = (id) => {
160
+ setTheme(id);
161
+ options.onChange?.(id);
162
+ };
163
+ scope.on(root, "click", (event) => {
164
+ const swatch = event.target?.closest("[data-mk-swatch]");
165
+ if (swatch && root.contains(swatch) && swatch.dataset.mkSwatch) select(swatch.dataset.mkSwatch);
166
+ });
167
+ scope.on(document, THEME_EVENT, sync);
168
+ sync();
169
+ if (entrances()) ctx.add(() => flowInPalette(swatches));
170
+ root.dataset.mkReady = "";
171
+ return {
172
+ select,
173
+ destroy() {
174
+ scope.dispose();
175
+ ctx.revert();
176
+ for (const button of generated.splice(0)) button.remove();
177
+ delete root.dataset.mkReady;
178
+ }
179
+ };
180
+ }
181
+
182
+ // src/components/toast/store.ts
183
+ var TOAST_LIMIT = 5;
184
+ var items = [];
185
+ var nextId = 1;
186
+ var listeners = /* @__PURE__ */ new Set();
187
+ var emit = () => {
188
+ for (const listener of listeners) listener();
189
+ };
190
+ var getToasts = () => items;
191
+ function subscribeToasts(listener) {
192
+ listeners.add(listener);
193
+ return () => {
194
+ listeners.delete(listener);
195
+ };
196
+ }
197
+ function show(message, { origin = null, duration = 4e3, tone = "success", action, icon = true } = {}) {
198
+ const id = nextId++;
199
+ const live = items.filter((item) => !item.closing);
200
+ const extra = new Set(live.slice(0, Math.max(0, live.length - TOAST_LIMIT + 1)).map((item) => item.id));
201
+ items = [
202
+ ...items.map((item) => extra.has(item.id) ? { ...item, closing: true } : item),
203
+ { id, message, origin, duration, tone, action: action ?? null, icon, closing: false }
204
+ ];
205
+ emit();
206
+ return id;
207
+ }
208
+ function dismissToast(id) {
209
+ const item = items.find((entry) => entry.id === id);
210
+ if (!item || item.closing) return;
211
+ items = items.map((entry) => entry.id === id ? { ...entry, closing: true } : entry);
212
+ emit();
213
+ }
214
+ function removeToast(id) {
215
+ toastTimers.clear(id);
216
+ items = items.filter((entry) => entry.id !== id);
217
+ emit();
218
+ }
219
+ function clearToasts() {
220
+ for (const item of items) toastTimers.clear(item.id);
221
+ items = [];
222
+ emit();
223
+ }
224
+ var toast = Object.assign(show, { dismiss: dismissToast, clear: clearToasts });
225
+ var running = /* @__PURE__ */ new Map();
226
+ var toastTimers = {
227
+ start(id, duration) {
228
+ if (duration <= 0 || running.has(id)) return;
229
+ running.set(id, { handle: setTimeout(() => dismissToast(id), duration), remaining: duration, started: Date.now() });
230
+ },
231
+ pause(id) {
232
+ const timer = running.get(id);
233
+ if (!timer?.handle) return;
234
+ clearTimeout(timer.handle);
235
+ timer.remaining = Math.max(0, timer.remaining - (Date.now() - timer.started));
236
+ timer.handle = null;
237
+ },
238
+ resume(id) {
239
+ const timer = running.get(id);
240
+ if (!timer || timer.handle) return;
241
+ if (timer.remaining <= 0) {
242
+ dismissToast(id);
243
+ return;
244
+ }
245
+ timer.started = Date.now();
246
+ timer.handle = setTimeout(() => dismissToast(id), timer.remaining);
247
+ },
248
+ clear(id) {
249
+ const timer = running.get(id);
250
+ if (timer?.handle) clearTimeout(timer.handle);
251
+ running.delete(id);
252
+ }
253
+ };
254
+
255
+ // src/components/icons.ts
256
+ var ICON_PATHS = {
257
+ close: "M6 6l12 12M18 6L6 18",
258
+ expand: "M14 4h6v6M10 20H4v-6M20 4l-7 7M4 20l7-7",
259
+ shrink: "M4 14h6v6M20 10h-6V4M10 14l-7 7M14 10l7-7",
260
+ check: "M5 12.5l4.5 4.5L19 7.5",
261
+ alert: "M12 8v5M12 16.5v.01M10.3 3.9L2.6 17.3a2 2 0 001.7 3h15.4a2 2 0 001.7-3L13.7 3.9a2 2 0 00-3.4 0z",
262
+ info: "M12 11v6M12 7.5v.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z",
263
+ send: "M12 19V5M5.5 11.5L12 5l6.5 6.5",
264
+ mic: "M12 3a3 3 0 00-3 3v6a3 3 0 006 0V6a3 3 0 00-3-3zM5.5 11a6.5 6.5 0 0013 0M12 17.5V21",
265
+ sparkle: "M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9z",
266
+ grip: "M9 6h.01M15 6h.01M9 12h.01M15 12h.01M9 18h.01M15 18h.01"
267
+ };
268
+ function iconSvg(name, size = 20) {
269
+ return `<svg aria-hidden="true" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="${ICON_PATHS[name]}"/></svg>`;
270
+ }
271
+
272
+ // src/components/toast/engine.ts
273
+ var STACK = { peek: 16, scaleStep: 0.05, minScale: 0.7, maxVisible: 3, gap: 8, baseZ: 1e3 };
274
+ var DISTANCE = { enter: 12, enterBlur: 6, exit: 24, exitBlur: 4, fade: 120 };
275
+ var GESTURE = { swipe: 48, wheel: 80, expandDrag: 24, resistance: 0.15, wheelEndMs: 140 };
276
+ var TONE_ICONS = { success: "check", error: "alert", info: "info", neutral: null };
277
+ function layout(count, expanded, heights) {
278
+ let offset = 0;
279
+ return Array.from({ length: count }, (_, index) => {
280
+ if (expanded) {
281
+ const slot = { y: offset, scale: 1, opacity: 1, visible: true, zIndex: STACK.baseZ - index };
282
+ offset += (heights[index] ?? 0) + STACK.gap;
283
+ return slot;
284
+ }
285
+ const visible = index < STACK.maxVisible;
286
+ return {
287
+ y: index * STACK.peek,
288
+ scale: Math.max(STACK.minScale, 1 - index * STACK.scaleStep),
289
+ opacity: visible ? 1 : 0,
290
+ visible,
291
+ zIndex: STACK.baseZ - index
292
+ };
293
+ });
294
+ }
295
+ function revealLetters(element) {
296
+ const text = element.textContent ?? "";
297
+ const T = TIMING.toast;
298
+ if (!text || text.length > 64 || reduced()) return;
299
+ const letters = splitGraphemes(text, 64);
300
+ const original = element.innerHTML;
301
+ const width = element.getBoundingClientRect().width;
302
+ const fragment = document.createDocumentFragment();
303
+ const chars = [];
304
+ let word = null;
305
+ for (const letter of letters) {
306
+ if (!letter.trim()) {
307
+ word = null;
308
+ fragment.append(document.createTextNode(letter));
309
+ continue;
310
+ }
311
+ if (!word) {
312
+ word = document.createElement("span");
313
+ word.style.display = "inline-block";
314
+ word.style.whiteSpace = "nowrap";
315
+ fragment.append(word);
316
+ }
317
+ const char = document.createElement("span");
318
+ char.textContent = letter;
319
+ char.style.display = "inline-block";
320
+ word.append(char);
321
+ chars.push(char);
322
+ }
323
+ if (width) element.style.width = `${width}px`;
324
+ element.textContent = "";
325
+ element.append(fragment);
326
+ gsap.fromTo(
327
+ chars,
328
+ { opacity: 0, yPercent: 40, filter: "blur(4px)" },
329
+ {
330
+ opacity: 1,
331
+ yPercent: 0,
332
+ filter: "blur(0px)",
333
+ duration: T.chars,
334
+ ease: easeOutCubic,
335
+ delay: (index) => T.charsDelay + index * T.charsStagger,
336
+ onComplete: () => {
337
+ element.innerHTML = original;
338
+ element.style.width = "";
339
+ }
340
+ }
341
+ );
342
+ }
343
+ function morphFrom(card, shell, body, origin) {
344
+ const T = TIMING.toast;
345
+ const box = shell.getBoundingClientRect();
346
+ const start = origin.getBoundingClientRect();
347
+ const look = getComputedStyle(origin);
348
+ const own = getComputedStyle(shell);
349
+ const endRadius = parseFloat(own.borderTopLeftRadius) || 20;
350
+ const startRadius = Math.min(parseFloat(look.borderTopLeftRadius) || 0, start.height / 2);
351
+ card.style.width = `${box.width}px`;
352
+ card.style.height = `${box.height}px`;
353
+ body.style.width = `${body.getBoundingClientRect().width}px`;
354
+ const towardX = start.left + start.width / 2 < innerWidth / 2 ? 1 : -1;
355
+ const towardY = start.top + start.height / 2 < innerHeight / 2 ? 1 : -1;
356
+ const offset = { x: start.left - box.left, y: start.top - box.top };
357
+ Object.assign(shell.style, {
358
+ position: "absolute",
359
+ top: "0px",
360
+ left: "0px",
361
+ width: `${start.width}px`,
362
+ height: `${start.height}px`,
363
+ borderRadius: `${startRadius}px`,
364
+ background: look.backgroundColor,
365
+ transform: `translate(${offset.x}px, ${offset.y}px)`,
366
+ transition: "none"
367
+ });
368
+ Object.assign(body.style, { transform: "scale(2)", transformOrigin: "center center", filter: "blur(8px)", opacity: "0" });
369
+ origin.style.transition = "opacity 160ms ease";
370
+ origin.style.opacity = "0";
371
+ void shell.offsetWidth;
372
+ shell.style.transition = `background ${T.morphColor}s ease-out ${T.morphColorDelay}s, box-shadow ${T.morphShadow}s ease-out ${T.morphShadowDelay}s`;
373
+ shell.style.background = "";
374
+ body.style.transition = `opacity ${T.morphColor}s ease-out ${T.morphColorDelay}s`;
375
+ body.style.opacity = "1";
376
+ const motion = channels(
377
+ { x: offset.x, y: offset.y, width: start.width, height: start.height, radius: startRadius, scale: 2, blur: 8 },
378
+ (name, value) => {
379
+ if (name === "x") offset.x = value;
380
+ else if (name === "y") offset.y = value;
381
+ else if (name === "width") shell.style.width = `${value}px`;
382
+ else if (name === "height") shell.style.height = `${value}px`;
383
+ else if (name === "radius") shell.style.borderRadius = `${value}px`;
384
+ else if (name === "scale") body.style.transform = `scale(${value})`;
385
+ else if (name === "blur") body.style.filter = `blur(${value}px)`;
386
+ if (name === "x" || name === "y") shell.style.transform = `translate(${offset.x}px, ${offset.y}px)`;
387
+ }
388
+ );
389
+ void motion.animate(
390
+ { x: 0, y: 0, width: box.width, height: box.height, radius: endRadius, scale: 1, blur: 0 },
391
+ {
392
+ x: spring(144, 14, { velocity: 2400, direction: towardX }),
393
+ y: spring(144, 14, { velocity: 2400, direction: towardY }),
394
+ width: eased(T.morphSize, bezier(0.8, 0.3, 0.5, 0.8)),
395
+ height: eased(T.morphSize, bezier(0.8, 0.3, 0.5, 0.8)),
396
+ radius: eased(T.morphRadius, easeOut),
397
+ scale: eased(T.morphContent, easeOut),
398
+ blur: eased(T.morphContent, easeOut)
399
+ }
400
+ );
401
+ let settled = false;
402
+ const settle = () => {
403
+ if (settled) return;
404
+ settled = true;
405
+ clearTimeout(timer);
406
+ motion.stop();
407
+ for (const name of ["position", "top", "left", "width", "height", "border-radius", "background", "transform", "transition"]) shell.style.removeProperty(name);
408
+ card.style.removeProperty("width");
409
+ card.style.removeProperty("height");
410
+ for (const name of ["transform", "transform-origin", "filter", "opacity", "width", "transition"]) body.style.removeProperty(name);
411
+ origin.style.transition = "opacity 300ms ease";
412
+ origin.style.opacity = "";
413
+ setTimeout(() => {
414
+ origin.style.transition = "";
415
+ }, 320);
416
+ };
417
+ const timer = setTimeout(settle, T.safetyMs);
418
+ return settle;
419
+ }
420
+ function buildCard(item, dismissLabel) {
421
+ const card = document.createElement("div");
422
+ card.className = "mk-toast";
423
+ card.dataset.mkToast = String(item.id);
424
+ card.dataset.mkTone = item.tone;
425
+ const shell = document.createElement("div");
426
+ shell.className = "mk-toast__shell";
427
+ const body = document.createElement("div");
428
+ body.className = "mk-toast__body";
429
+ const icon = item.icon ? TONE_ICONS[item.tone] : null;
430
+ if (icon) {
431
+ const holder = document.createElement("span");
432
+ holder.className = "mk-toast__icon";
433
+ holder.innerHTML = iconSvg(icon, 18);
434
+ body.append(holder);
435
+ }
436
+ const message = document.createElement("span");
437
+ message.className = "mk-toast__message";
438
+ message.textContent = item.message;
439
+ body.append(message);
440
+ if (item.action) {
441
+ const action = document.createElement("button");
442
+ action.type = "button";
443
+ action.className = "mk-toast__action";
444
+ action.dataset.mkToastAction = "";
445
+ action.textContent = item.action.label;
446
+ body.append(action);
447
+ }
448
+ const dismiss = document.createElement("button");
449
+ dismiss.type = "button";
450
+ dismiss.className = "mk-toast__dismiss";
451
+ dismiss.dataset.mkToastDismiss = "";
452
+ dismiss.setAttribute("aria-label", dismissLabel);
453
+ dismiss.innerHTML = iconSvg("close", 14);
454
+ body.append(dismiss);
455
+ shell.append(body);
456
+ card.append(shell);
457
+ return { card, shell, body, message };
458
+ }
459
+ function createToaster(host, options = {}) {
460
+ if (!host) {
461
+ warnOnce("toaster: missing host");
462
+ return inert();
463
+ }
464
+ registerMotion();
465
+ const dismissLabel = options.labels?.dismiss ?? "Cerrar";
466
+ const scope = createScope();
467
+ const cards = /* @__PURE__ */ new Map();
468
+ const entered = /* @__PURE__ */ new Set();
469
+ const leaving = /* @__PURE__ */ new Set();
470
+ const dragging = /* @__PURE__ */ new Set();
471
+ const settles = /* @__PURE__ */ new Map();
472
+ let expanded = false;
473
+ let collapse;
474
+ const popover = typeof host.showPopover === "function";
475
+ scope.attr(host, "role", "status");
476
+ scope.attr(host, "aria-live", "polite");
477
+ if (popover) scope.attr(host, "popover", "manual");
478
+ const live = () => getToasts().filter((item) => !item.closing).reverse().map((item) => ({ item, entry: cards.get(item.id) })).filter((pair) => pair.entry !== void 0);
479
+ const slotsFor = () => {
480
+ const entries = live();
481
+ return { entries, slots: layout(entries.length, expanded, entries.map(({ entry }) => entry.card.offsetHeight)) };
482
+ };
483
+ const relayout = (duration = TIMING.toast.relayout, ease = easeOutCubic, stagger = 0) => {
484
+ const { entries, slots } = slotsFor();
485
+ entries.forEach(({ item, entry }, index) => {
486
+ const slot = slots[index];
487
+ if (!slot) return;
488
+ entry.card.style.zIndex = String(slot.zIndex);
489
+ entry.card.style.pointerEvents = slot.visible ? "auto" : "none";
490
+ entry.card.setAttribute("aria-hidden", slot.visible ? "false" : "true");
491
+ if (dragging.has(item.id) || !entered.has(item.id)) return;
492
+ gsap.to(entry.card, {
493
+ xPercent: -50,
494
+ y: slot.y,
495
+ scale: slot.scale,
496
+ opacity: slot.opacity,
497
+ duration: reduced() ? 0 : duration,
498
+ ease,
499
+ delay: stagger * index,
500
+ overwrite: "auto"
501
+ });
502
+ });
503
+ };
504
+ const restingY = (id) => {
505
+ const { entries, slots } = slotsFor();
506
+ return slots[entries.findIndex(({ item }) => item.id === id)]?.y ?? 0;
507
+ };
508
+ const openDeck = () => {
509
+ clearTimeout(collapse);
510
+ if (expanded) return;
511
+ expanded = true;
512
+ for (const { item } of live()) toastTimers.pause(item.id);
513
+ relayout(TIMING.toast.expand, springEase(0.55), TIMING.toast.expandStagger);
514
+ };
515
+ const closeDeck = () => {
516
+ clearTimeout(collapse);
517
+ collapse = setTimeout(() => {
518
+ if (!expanded) return;
519
+ expanded = false;
520
+ for (const { item } of live()) toastTimers.resume(item.id);
521
+ relayout(TIMING.toast.expand, springEase(0.55), TIMING.toast.expandStagger);
522
+ }, TIMING.toast.collapseDelayMs);
523
+ };
524
+ const showLayer = (visible) => {
525
+ if (!popover) return;
526
+ try {
527
+ if (host.matches(":popover-open")) host.hidePopover();
528
+ if (visible) host.showPopover();
529
+ } catch {
530
+ }
531
+ };
532
+ const attachGestures = (item, card) => {
533
+ let start = null;
534
+ let wheel = null;
535
+ const move = (offset) => gsap.set(card, { y: restingY(item.id) + offset, opacity: Math.max(0, 1 + Math.min(0, offset) / DISTANCE.fade) });
536
+ const cancel = () => {
537
+ dragging.delete(item.id);
538
+ gsap.to(card, { y: restingY(item.id), opacity: 1, duration: 0.25, ease: easeOutCubic });
539
+ if (!expanded) toastTimers.resume(item.id);
540
+ };
541
+ card.addEventListener("mouseenter", openDeck);
542
+ card.addEventListener("mouseleave", closeDeck);
543
+ card.addEventListener("pointerdown", (event) => {
544
+ if (event.button !== 0 || event.target.closest('button, a, input, textarea, select, [role="button"]')) return;
545
+ start = { y: event.clientY, type: event.pointerType };
546
+ card.setPointerCapture?.(event.pointerId);
547
+ dragging.add(item.id);
548
+ gsap.killTweensOf(card);
549
+ toastTimers.pause(item.id);
550
+ });
551
+ card.addEventListener("pointermove", (event) => {
552
+ if (!start) return;
553
+ const dy = event.clientY - start.y;
554
+ move(dy < 0 ? dy : start.type === "touch" ? dy * GESTURE.resistance : 0);
555
+ });
556
+ const up = (event) => {
557
+ if (!start) return;
558
+ const dy = event.clientY - start.y;
559
+ const type = start.type;
560
+ start = null;
561
+ if (dy < -GESTURE.swipe) {
562
+ dragging.delete(item.id);
563
+ dismissToast(item.id);
564
+ } else if (type === "touch" && dy > GESTURE.expandDrag) {
565
+ cancel();
566
+ if (expanded) closeDeck();
567
+ else openDeck();
568
+ } else cancel();
569
+ };
570
+ card.addEventListener("pointerup", up);
571
+ card.addEventListener("pointercancel", up);
572
+ card.addEventListener(
573
+ "wheel",
574
+ (event) => {
575
+ const delta = event.deltaMode === 1 ? event.deltaY * 16 : event.deltaMode === 2 ? event.deltaY * innerHeight : event.deltaY;
576
+ if (!wheel) {
577
+ wheel = { offset: 0, end: void 0 };
578
+ dragging.add(item.id);
579
+ toastTimers.pause(item.id);
580
+ }
581
+ wheel.offset = Math.min(0, wheel.offset - delta);
582
+ move(wheel.offset);
583
+ clearTimeout(wheel.end);
584
+ wheel.end = setTimeout(() => {
585
+ const offset = wheel?.offset ?? 0;
586
+ wheel = null;
587
+ if (offset < -GESTURE.wheel) {
588
+ dragging.delete(item.id);
589
+ dismissToast(item.id);
590
+ } else cancel();
591
+ }, GESTURE.wheelEndMs);
592
+ },
593
+ { passive: true }
594
+ );
595
+ card.addEventListener("click", (event) => {
596
+ const target = event.target;
597
+ if (target.closest("[data-mk-toast-dismiss]")) dismissToast(item.id);
598
+ else if (target.closest("[data-mk-toast-action]")) {
599
+ item.action?.onClick();
600
+ dismissToast(item.id);
601
+ }
602
+ });
603
+ };
604
+ const finishCard = (id) => {
605
+ settles.get(id)?.();
606
+ settles.delete(id);
607
+ const entry = cards.get(id);
608
+ if (entry) {
609
+ gsap.killTweensOf(entry.card);
610
+ entry.card.remove();
611
+ }
612
+ cards.delete(id);
613
+ entered.delete(id);
614
+ leaving.delete(id);
615
+ dragging.delete(id);
616
+ };
617
+ const render = () => {
618
+ const list = getToasts();
619
+ const ids = new Set(list.map((item) => item.id));
620
+ for (const id of [...cards.keys()]) if (!ids.has(id)) finishCard(id);
621
+ for (const item of list) {
622
+ if (!cards.has(item.id) && !item.closing) {
623
+ const entry = buildCard(item, dismissLabel);
624
+ cards.set(item.id, entry);
625
+ host.append(entry.card);
626
+ gsap.set(entry.card, { xPercent: -50 });
627
+ attachGestures(item, entry.card);
628
+ }
629
+ }
630
+ showLayer(list.some((item) => !item.closing) || leaving.size > 0);
631
+ for (const item of list) {
632
+ const entry = cards.get(item.id);
633
+ if (!entry) continue;
634
+ if (!entered.has(item.id) && !item.closing) {
635
+ entered.add(item.id);
636
+ toastTimers.start(item.id, item.duration);
637
+ relayout();
638
+ gsap.killTweensOf(entry.card);
639
+ gsap.set(entry.card, { xPercent: -50, y: restingY(item.id), scale: 1, opacity: 1 });
640
+ if (expanded) toastTimers.pause(item.id);
641
+ revealLetters(entry.message);
642
+ if (reduced()) continue;
643
+ if (item.origin?.isConnected) settles.set(item.id, morphFrom(entry.card, entry.shell, entry.body, item.origin));
644
+ else {
645
+ const y = restingY(item.id);
646
+ gsap.fromTo(
647
+ entry.card,
648
+ { y: y - DISTANCE.enter, opacity: 0, filter: `blur(${DISTANCE.enterBlur}px)` },
649
+ { y, opacity: 1, filter: "blur(0px)", duration: TIMING.toast.enter, ease: springEase(0.58, -3.5), clearProps: "filter" }
650
+ );
651
+ }
652
+ }
653
+ if (item.closing && !leaving.has(item.id)) {
654
+ leaving.add(item.id);
655
+ toastTimers.clear(item.id);
656
+ entry.card.style.zIndex = String(STACK.baseZ + 1);
657
+ const done = () => {
658
+ finishCard(item.id);
659
+ removeToast(item.id);
660
+ };
661
+ if (reduced()) done();
662
+ else {
663
+ gsap.to(entry.card, {
664
+ y: Number(gsap.getProperty(entry.card, "y")) - DISTANCE.exit,
665
+ opacity: 0,
666
+ filter: `blur(${DISTANCE.exitBlur}px)`,
667
+ duration: TIMING.toast.exit,
668
+ ease: easeInCubic,
669
+ overwrite: "auto",
670
+ onComplete: done
671
+ });
672
+ }
673
+ relayout();
674
+ }
675
+ }
676
+ };
677
+ scope.add(subscribeToasts(render));
678
+ render();
679
+ host.dataset.mkReady = "";
680
+ return {
681
+ destroy() {
682
+ clearTimeout(collapse);
683
+ for (const id of [...cards.keys()]) finishCard(id);
684
+ showLayer(false);
685
+ scope.dispose();
686
+ delete host.dataset.mkReady;
687
+ }
688
+ };
689
+ }
690
+
691
+ // src/components/chat-background/engine.ts
692
+ var VARS = ["--mk-chat-orbit-1", "--mk-chat-orbit-2", "--mk-chat-blob-opacity", "--mk-chat-scale"];
693
+ var instances = /* @__PURE__ */ new WeakMap();
694
+ var chatBackgroundOf = (el) => el ? instances.get(el) ?? null : null;
695
+ function createChatBackground(root, options = {}) {
696
+ if (!root) {
697
+ warnOnce("chat-background: missing root");
698
+ return inert({ setEnergy() {
699
+ }, setScale() {
700
+ }, busy() {
701
+ }, energy: 0, scale: 1 });
702
+ }
703
+ registerMotion();
704
+ const scope = createScope();
705
+ const state = { energy: options.energy ?? 0, scale: options.scale ?? 1 };
706
+ let noise = root.querySelector(":scope > .mk-chat-background__noise");
707
+ if (!noise) {
708
+ noise = document.createElement("div");
709
+ noise.className = "mk-chat-background__noise";
710
+ noise.setAttribute("aria-hidden", "true");
711
+ root.append(noise);
712
+ const created = noise;
713
+ scope.add(() => created.remove());
714
+ }
715
+ scope.attr(root, "aria-hidden", "true");
716
+ const paint = () => {
717
+ const e = Math.max(0, state.energy);
718
+ root.style.setProperty("--mk-chat-orbit-1", `${Math.max(1, 10 - 3.5 * e).toFixed(3)}s`);
719
+ root.style.setProperty("--mk-chat-orbit-2", `${Math.max(1, 15 - 4.5 * e).toFixed(3)}s`);
720
+ root.style.setProperty("--mk-chat-blob-opacity", (0.5 + 0.15 * e).toFixed(3));
721
+ root.style.setProperty("--mk-chat-scale", ((1 + 0.1 * e) * state.scale).toFixed(3));
722
+ };
723
+ scope.add(() => {
724
+ gsap.killTweensOf(state);
725
+ for (const name of VARS) root.style.removeProperty(name);
726
+ if (root.getAttribute("style") === "") root.removeAttribute("style");
727
+ });
728
+ paint();
729
+ const instance = {
730
+ setEnergy(energy) {
731
+ state.energy = Number.isFinite(energy) ? energy : 0;
732
+ paint();
733
+ },
734
+ setScale(scale) {
735
+ state.scale = Number.isFinite(scale) ? scale : 1;
736
+ paint();
737
+ },
738
+ busy(on) {
739
+ const to = on ? { energy: 1.6, scale: 1.8 } : { energy: 0, scale: 1 };
740
+ gsap.killTweensOf(state);
741
+ if (reduced()) {
742
+ Object.assign(state, to);
743
+ paint();
744
+ return;
745
+ }
746
+ gsap.to(state, {
747
+ ...to,
748
+ duration: on ? TIMING.onboarding.busy : TIMING.onboarding.idle,
749
+ ease: on ? "power2.out" : "power2.inOut",
750
+ onUpdate: paint
751
+ });
752
+ },
753
+ get energy() {
754
+ return state.energy;
755
+ },
756
+ get scale() {
757
+ return state.scale;
758
+ },
759
+ destroy() {
760
+ instances.delete(root);
761
+ scope.dispose();
762
+ delete root.dataset.mkReady;
763
+ }
764
+ };
765
+ instances.set(root, instance);
766
+ root.dataset.mkReady = "";
767
+ return instance;
768
+ }
769
+
770
+ // src/components/chat/engine.ts
771
+ var MESSAGE = "[data-mk-message]";
772
+ var PENDING_ID = "mk-chat-pending";
773
+ var part = (root, name) => root.querySelector(`[data-mk-part="${name}"]`);
774
+ var capturePending = (placeholder) => {
775
+ registerMotion();
776
+ return placeholder ? Flip.getState(placeholder) : null;
777
+ };
778
+ function morphPendingToReply(state, reply, scroller) {
779
+ registerMotion();
780
+ if (!state || reduced()) {
781
+ if (!reduced()) enterMessages([reply]);
782
+ return null;
783
+ }
784
+ const text = reply.querySelector("[data-mk-text], .message-text");
785
+ if (text) text.style.width = `${text.getBoundingClientRect().width}px`;
786
+ reply.setAttribute("data-flip-id", PENDING_ID);
787
+ const words = text && !text.querySelector("table, pre") ? splitWords(text) : null;
788
+ if (words?.parts.length) {
789
+ gsap.fromTo(
790
+ words.parts,
791
+ { y: 16, autoAlpha: 0, filter: "blur(6px)" },
792
+ {
793
+ y: 0,
794
+ autoAlpha: 1,
795
+ filter: "blur(0px)",
796
+ duration: TIMING.word,
797
+ ease: "back.out(1)",
798
+ stagger: TIMING.wordStagger,
799
+ clearProps: "transform,opacity,visibility,filter",
800
+ onComplete: () => words.revert()
801
+ }
802
+ );
803
+ }
804
+ return Flip.from(state, {
805
+ targets: reply,
806
+ duration: TIMING.bubble,
807
+ scale: false,
808
+ ease: EASE.signature,
809
+ onUpdate: () => {
810
+ if (scroller) scroller.scrollTop = scroller.scrollHeight;
811
+ },
812
+ onComplete: () => {
813
+ reply.removeAttribute("data-flip-id");
814
+ if (text) text.style.width = "";
815
+ }
816
+ });
817
+ }
818
+ function chatMessage(role, text) {
819
+ const message = document.createElement("div");
820
+ message.dataset.mkMessage = "";
821
+ message.dataset.mkRole = role;
822
+ const body = document.createElement("span");
823
+ body.dataset.mkText = "";
824
+ body.textContent = text;
825
+ message.append(body);
826
+ return message;
827
+ }
828
+ function createChat(root, options = {}) {
829
+ const messages = root ? part(root, "messages") : null;
830
+ if (!root || !messages) {
831
+ warnOnce('chat: needs a [data-mk-part="messages"] container');
832
+ return inert({
833
+ add: () => document.createElement("div"),
834
+ pending() {
835
+ },
836
+ reply: () => document.createElement("div"),
837
+ confirm() {
838
+ },
839
+ setRecording() {
840
+ },
841
+ scrollToLatest() {
842
+ },
843
+ adopt() {
844
+ },
845
+ messages: null
846
+ });
847
+ }
848
+ registerMotion();
849
+ const { clearOnSend = true } = options;
850
+ const thinking = options.labels?.thinking ?? "Pensando...";
851
+ const scope = createScope();
852
+ const composer = part(root, "composer");
853
+ const input = composer?.querySelector('[data-mk-part="input"], textarea') ?? null;
854
+ const mic = part(root, "mic");
855
+ const seen = /* @__PURE__ */ new WeakSet();
856
+ let placeholder = null;
857
+ let pendingTimer;
858
+ let waiting = false;
859
+ scope.attr(messages, "role", "log");
860
+ scope.attr(messages, "aria-live", "polite");
861
+ const existing = [...messages.querySelectorAll(MESSAGE)];
862
+ if (options.animateExisting) enterMessages(existing);
863
+ for (const message of existing) seen.add(message);
864
+ const observer = scope.observe(
865
+ new MutationObserver((records) => {
866
+ const fresh = [];
867
+ for (const record of records) {
868
+ for (const node of record.addedNodes) {
869
+ if (!(node instanceof HTMLElement) || !node.matches(MESSAGE) || seen.has(node)) continue;
870
+ seen.add(node);
871
+ fresh.push(node);
872
+ }
873
+ }
874
+ if (!fresh.length) return;
875
+ enterMessages(fresh);
876
+ scrollToLatest(messages);
877
+ })
878
+ );
879
+ observer.observe(messages, { childList: true });
880
+ const clearPending = () => {
881
+ clearTimeout(pendingTimer);
882
+ pendingTimer = void 0;
883
+ waiting = false;
884
+ };
885
+ const add = (role, text) => {
886
+ const message = chatMessage(role, text);
887
+ messages.append(message);
888
+ return message;
889
+ };
890
+ const pending = () => {
891
+ clearPending();
892
+ waiting = true;
893
+ pendingTimer = setTimeout(() => {
894
+ pendingTimer = void 0;
895
+ if (!waiting || placeholder) return;
896
+ placeholder = document.createElement("div");
897
+ placeholder.dataset.mkMessage = "";
898
+ placeholder.dataset.mkRole = "assistant";
899
+ placeholder.dataset.mkPending = "";
900
+ placeholder.setAttribute("data-flip-id", PENDING_ID);
901
+ placeholder.innerHTML = `<span class="mk-chat__thinking">${iconSvg("sparkle", 18)}<span></span></span>`;
902
+ placeholder.querySelector("span span").textContent = thinking;
903
+ seen.add(placeholder);
904
+ messages.append(placeholder);
905
+ enterMessages([placeholder]);
906
+ scrollToLatest(messages);
907
+ }, TIMING.chat.pendingDelayMs);
908
+ };
909
+ const reply = (content) => {
910
+ const message = typeof content === "string" ? chatMessage("assistant", content) : content;
911
+ clearPending();
912
+ seen.add(message);
913
+ const was = placeholder;
914
+ placeholder = null;
915
+ if (was?.isConnected) {
916
+ const state = capturePending(was);
917
+ was.replaceWith(message);
918
+ morphPendingToReply(state, message, messages);
919
+ } else {
920
+ if (!message.isConnected) messages.append(message);
921
+ enterMessages([message]);
922
+ scrollToLatest(messages);
923
+ }
924
+ return message;
925
+ };
926
+ const confirm = (bar) => {
927
+ if (reduced()) return;
928
+ flowIn(bar);
929
+ const words = splitWords(bar);
930
+ if (!words.parts.length) return;
931
+ gsap.fromTo(
932
+ words.parts,
933
+ { y: 16, autoAlpha: 0, filter: "blur(6px)" },
934
+ {
935
+ y: 0,
936
+ autoAlpha: 1,
937
+ filter: "blur(0px)",
938
+ duration: TIMING.word,
939
+ ease: "back.out(1)",
940
+ stagger: TIMING.chat.confirmWordStagger,
941
+ clearProps: "transform,opacity,visibility,filter",
942
+ onComplete: () => words.revert()
943
+ }
944
+ );
945
+ };
946
+ const send = () => {
947
+ if (!input) return;
948
+ const text = input.value.trim();
949
+ if (!text) return;
950
+ const allowed = root.dispatchEvent(new CustomEvent("mk:send", { bubbles: true, cancelable: true, detail: { text } }));
951
+ if (!allowed) return;
952
+ options.onSend?.(text);
953
+ if (clearOnSend) {
954
+ input.value = "";
955
+ fitComposer(input);
956
+ }
957
+ };
958
+ if (input) {
959
+ scope.on(input, "input", () => fitComposer(input));
960
+ scope.on(input, "keydown", (event) => {
961
+ const key = event;
962
+ if (key.key !== "Enter" || key.shiftKey || key.isComposing) return;
963
+ event.preventDefault();
964
+ send();
965
+ });
966
+ }
967
+ if (composer) {
968
+ scope.on(composer, "submit", (event) => {
969
+ event.preventDefault();
970
+ send();
971
+ });
972
+ const sendButton = part(root, "send");
973
+ if (sendButton && !composer.matches("form")) scope.on(sendButton, "click", send);
974
+ }
975
+ scope.add(() => {
976
+ clearPending();
977
+ placeholder?.remove();
978
+ placeholder = null;
979
+ });
980
+ if (input) fitComposer(input);
981
+ root.dataset.mkReady = "";
982
+ return {
983
+ add,
984
+ pending,
985
+ reply,
986
+ confirm,
987
+ setRecording(on) {
988
+ if (mic) scope.attr(mic, "data-mk-recording", on ? "" : null);
989
+ },
990
+ scrollToLatest: () => scrollToLatest(messages),
991
+ adopt: (message) => seen.add(message),
992
+ messages,
993
+ destroy() {
994
+ scope.dispose();
995
+ if (input) input.style.removeProperty("height");
996
+ delete root.dataset.mkReady;
997
+ }
998
+ };
999
+ }
1000
+
1001
+ // src/components/nav/engine.ts
1002
+ var NAV_STYLES = ["clasica", "bonita", "dock", "guapa", "tasks", "melon", "tunnel"];
1003
+ var ITEM = ".mk-nav__buttons .mk-nav__button";
1004
+ var isStyle = (value) => NAV_STYLES.includes(value);
1005
+ var valueOf = (item) => item.dataset.mkValue ?? item.getAttribute("href") ?? void 0;
1006
+ var read = (key) => {
1007
+ try {
1008
+ return localStorage.getItem(key);
1009
+ } catch {
1010
+ return null;
1011
+ }
1012
+ };
1013
+ var write = (key, value) => {
1014
+ try {
1015
+ localStorage.setItem(key, value);
1016
+ } catch {
1017
+ }
1018
+ };
1019
+ function revealShell(nav) {
1020
+ if (!entrances()) return null;
1021
+ const shell = nav.closest(".mk-shell") ?? nav.parentElement;
1022
+ if (!shell) return null;
1023
+ const origin = nav.querySelector(".mk-nav__button--first") ?? nav.querySelector(ITEM) ?? nav;
1024
+ return revealFrom(shell, { origin });
1025
+ }
1026
+ function createNav(root, options = {}) {
1027
+ if (!root) {
1028
+ warnOnce("nav: missing root");
1029
+ return inert({ select() {
1030
+ }, setStyle() {
1031
+ }, setAccent() {
1032
+ }, index: -1, style: "bonita", items: [] });
1033
+ }
1034
+ const scope = createScope();
1035
+ const items2 = () => [...root.querySelectorAll(ITEM)];
1036
+ const fromClass = NAV_STYLES.find((name) => root.classList.contains(`mk-nav--${name}`));
1037
+ const saved = options.storageKey ? read(options.storageKey) : null;
1038
+ let style = options.style ?? (isStyle(saved) ? saved : void 0) ?? fromClass ?? "bonita";
1039
+ const paint = (accent2) => {
1040
+ const classes = new Set(root.classList);
1041
+ for (const name of NAV_STYLES) classes.delete(`mk-nav--${name}`);
1042
+ classes.add("mk-nav");
1043
+ classes.add(`mk-nav--${style}`);
1044
+ if (accent2) classes.add("mk-nav--accent");
1045
+ else classes.delete("mk-nav--accent");
1046
+ scope.attr(root, "class", [...classes].join(" "));
1047
+ };
1048
+ let accent = options.accent ?? root.classList.contains("mk-nav--accent");
1049
+ paint(accent);
1050
+ if (root.localName !== "nav") scope.attr(root, "role", "navigation");
1051
+ if (!root.hasAttribute("aria-label") && !root.hasAttribute("aria-labelledby")) scope.attr(root, "aria-label", options.labels?.nav ?? "Principal");
1052
+ const mark = (current) => {
1053
+ for (const item of items2()) scope.attr(item, "aria-current", item === current ? "page" : null);
1054
+ };
1055
+ const find = (target) => {
1056
+ const list = items2();
1057
+ return typeof target === "number" ? list[target] : list.find((item) => valueOf(item) === target);
1058
+ };
1059
+ scope.on(root, "click", (event) => {
1060
+ const item = event.target?.closest(ITEM);
1061
+ if (!item || !root.contains(item)) return;
1062
+ const index = items2().indexOf(item);
1063
+ const value = valueOf(item);
1064
+ const detail = { index, value, item, originalEvent: event };
1065
+ if (!root.dispatchEvent(new CustomEvent("mk:navigate", { bubbles: true, cancelable: true, detail }))) {
1066
+ event.preventDefault();
1067
+ return;
1068
+ }
1069
+ mark(item);
1070
+ options.onSelect?.(index, value, item);
1071
+ });
1072
+ let reveal = null;
1073
+ if (options.reveal) reveal = revealShell(root);
1074
+ root.dataset.mkReady = "";
1075
+ return {
1076
+ select(target) {
1077
+ const item = find(target);
1078
+ if (!item) warnOnce(`nav: no item ${JSON.stringify(target)}`);
1079
+ else mark(item);
1080
+ },
1081
+ setStyle(next) {
1082
+ if (!isStyle(next)) {
1083
+ warnOnce(`nav: unknown style "${String(next)}" (use ${NAV_STYLES.join(", ")})`);
1084
+ return;
1085
+ }
1086
+ style = next;
1087
+ paint(accent);
1088
+ if (options.storageKey) write(options.storageKey, next);
1089
+ },
1090
+ setAccent(on) {
1091
+ accent = on;
1092
+ paint(accent);
1093
+ },
1094
+ get index() {
1095
+ return items2().findIndex((item) => item.getAttribute("aria-current") === "page");
1096
+ },
1097
+ get style() {
1098
+ return style;
1099
+ },
1100
+ get items() {
1101
+ return items2();
1102
+ },
1103
+ destroy() {
1104
+ reveal?.cancel();
1105
+ reveal = null;
1106
+ scope.dispose();
1107
+ delete root.dataset.mkReady;
1108
+ }
1109
+ };
1110
+ }
1111
+
1112
+ // src/components/steps/engine.ts
1113
+ var STEP = "[data-mk-step]";
1114
+ var ITEM_STYLES = ["transform", "translate", "rotate", "scale", "filter", "opacity", "visibility"];
1115
+ function createSteps(root, options = {}) {
1116
+ const steps = root ? [...root.querySelectorAll(STEP)].filter((step) => {
1117
+ const outer = step.parentElement?.closest(STEP);
1118
+ return !outer || !root.contains(outer);
1119
+ }) : [];
1120
+ if (!root || !steps.length) {
1121
+ warnOnce("steps: needs [data-mk-step] children");
1122
+ return inert({ next: async () => {
1123
+ }, prev: async () => {
1124
+ }, goTo: async () => {
1125
+ }, busy() {
1126
+ }, index: -1, count: 0, steps: [] });
1127
+ }
1128
+ registerMotion();
1129
+ const scope = createScope();
1130
+ const { duration = TIMING.onboarding.step, animateFirst = true, target = "[data-mk-flow-item]" } = options;
1131
+ const clamp = (value) => Math.min(steps.length - 1, Math.max(0, Math.round(value)));
1132
+ const marked = steps.findIndex((step) => step.hasAttribute("data-mk-current"));
1133
+ let index = clamp(options.index ?? (marked >= 0 ? marked : 0));
1134
+ let wanted = index;
1135
+ let running2 = null;
1136
+ let stopCounter = () => {
1137
+ };
1138
+ const itemsOf = (step) => {
1139
+ const marked2 = [...step.querySelectorAll(target)];
1140
+ return marked2.length ? marked2 : [...step.children];
1141
+ };
1142
+ const show2 = (current) => {
1143
+ steps.forEach((step, i) => {
1144
+ scope.attr(step, "hidden", i === current ? null : "");
1145
+ scope.attr(step, "data-mk-current", i === current ? "" : null);
1146
+ });
1147
+ };
1148
+ const counter = () => {
1149
+ const el = root.querySelector("[data-mk-counter]");
1150
+ if (!el) return;
1151
+ stopCounter();
1152
+ stopCounter = revealCounter(el, index + 1, { duration: TIMING.onboarding.counter });
1153
+ };
1154
+ const focusTitle = (step) => {
1155
+ const title = step.querySelector("[data-mk-step-title]") ?? step.querySelector("h1, h2, h3, h4, h5, h6");
1156
+ if (!title) return;
1157
+ if (!title.hasAttribute("tabindex") && title.tabIndex < 0) scope.attr(title, "tabindex", "-1");
1158
+ title.focus({ preventScroll: true });
1159
+ };
1160
+ const change = async () => {
1161
+ try {
1162
+ while (wanted !== index && !scope.disposed) {
1163
+ const previous = index;
1164
+ const next = wanted;
1165
+ const out = reduced() ? null : flowOut(itemsOf(steps[previous]), { duration });
1166
+ if (out) await out;
1167
+ if (scope.disposed) return;
1168
+ index = next;
1169
+ show2(index);
1170
+ const step = steps[index];
1171
+ await nextFrame();
1172
+ if (scope.disposed) return;
1173
+ const items2 = itemsOf(step);
1174
+ clearStyles(items2, ["visibility"]);
1175
+ flowIn(items2, { duration, autoAlpha: false });
1176
+ counter();
1177
+ focusTitle(step);
1178
+ root.dispatchEvent(new CustomEvent("mk:step", { bubbles: true, detail: { index, previous, step } }));
1179
+ options.onChange?.(index, previous);
1180
+ }
1181
+ } finally {
1182
+ running2 = null;
1183
+ }
1184
+ };
1185
+ const goTo = (to) => {
1186
+ wanted = clamp(to);
1187
+ if (wanted === index && !running2) return Promise.resolve();
1188
+ running2 ??= change();
1189
+ return running2;
1190
+ };
1191
+ show2(index);
1192
+ scope.add(() => {
1193
+ stopCounter();
1194
+ for (const step of steps) {
1195
+ const items2 = itemsOf(step);
1196
+ gsap.killTweensOf(items2);
1197
+ clearStyles(items2, ITEM_STYLES);
1198
+ }
1199
+ });
1200
+ scope.on(root, "click", (event) => {
1201
+ const trigger = event.target?.closest("[data-mk-step-next], [data-mk-step-prev], [data-mk-step-goto]");
1202
+ if (!trigger || !root.contains(trigger)) return;
1203
+ if (trigger.hasAttribute("data-mk-step-next")) void goTo(wanted + 1);
1204
+ else if (trigger.hasAttribute("data-mk-step-prev")) void goTo(wanted - 1);
1205
+ else void goTo(Number(trigger.dataset.mkStepGoto) - 1);
1206
+ });
1207
+ const counterEl = root.querySelector("[data-mk-counter]");
1208
+ if (counterEl) {
1209
+ const text = counterEl.textContent;
1210
+ counterEl.textContent = String(index + 1);
1211
+ scope.add(() => {
1212
+ counterEl.textContent = text;
1213
+ });
1214
+ }
1215
+ if (animateFirst && entrances()) flowIn(itemsOf(steps[index]), { duration });
1216
+ root.dataset.mkReady = "";
1217
+ return {
1218
+ next: () => goTo(wanted + 1),
1219
+ prev: () => goTo(wanted - 1),
1220
+ goTo,
1221
+ busy(on) {
1222
+ scope.attr(root, "aria-busy", on ? "true" : null);
1223
+ const background = root.querySelector(".mk-chat-background, mk-chat-background");
1224
+ chatBackgroundOf(background)?.busy(on);
1225
+ },
1226
+ get index() {
1227
+ return index;
1228
+ },
1229
+ get count() {
1230
+ return steps.length;
1231
+ },
1232
+ get steps() {
1233
+ return steps;
1234
+ },
1235
+ destroy() {
1236
+ scope.dispose();
1237
+ delete root.dataset.mkReady;
1238
+ }
1239
+ };
1240
+ }
1241
+
1242
+ // src/components/cursor/engine.ts
1243
+ var svg = (extra = "") => `<svg aria-hidden="true" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"${extra}><path d="${ICON_PATHS.send}"/></svg>`;
1244
+ function backgroundTone(el) {
1245
+ if (!el) return "light";
1246
+ if (el.closest("img, video, picture, canvas")) return "dark";
1247
+ for (let node = el; node; node = node.parentElement) {
1248
+ const match = getComputedStyle(node).backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
1249
+ if (!match) continue;
1250
+ const alpha = match[4] === void 0 ? 1 : parseFloat(match[4]);
1251
+ if (alpha <= 0.1) continue;
1252
+ const luminance = (Number(match[1]) * 299 + Number(match[2]) * 587 + Number(match[3]) * 114) / 1e3;
1253
+ return luminance > TIMING.cursor.light ? "light" : "dark";
1254
+ }
1255
+ return "light";
1256
+ }
1257
+ function createCursor(host, options = {}) {
1258
+ const variant = options.variant ?? "chip";
1259
+ const idle = inert({ visible: false, label: "", position: { x: 0, y: 0 }, tone: "light", update() {
1260
+ } });
1261
+ if (!host) {
1262
+ warnOnce("cursor: missing element");
1263
+ return idle;
1264
+ }
1265
+ const coarse = typeof matchMedia === "function" && matchMedia("(pointer: coarse)").matches;
1266
+ if (coarse || reduced()) return idle;
1267
+ registerMotion();
1268
+ const scope = createScope();
1269
+ const t = TIMING.cursor;
1270
+ const zone = options.zone ?? (variant === "dot" ? host.parentElement ?? document.body : document.documentElement);
1271
+ scope.attr(host, "class", [host.getAttribute("class"), "mk-cursor", `mk-cursor--${variant}`].filter(Boolean).join(" "));
1272
+ scope.attr(host, "aria-hidden", "true");
1273
+ const pointer = { x: -100, y: -100, placed: false };
1274
+ const position = { x: -100, y: -100 };
1275
+ const velocity = { x: 0, y: 0 };
1276
+ let visible = false;
1277
+ let label = "";
1278
+ let tone = "light";
1279
+ const made = [];
1280
+ let chip = null;
1281
+ let chipLabel = null;
1282
+ let chipIcon = null;
1283
+ let word = null;
1284
+ const size = { width: 0, height: 0 };
1285
+ if (variant === "chip") {
1286
+ chip = document.createElement("span");
1287
+ chip.className = "mk-cursor__chip mk-glass";
1288
+ chip.innerHTML = '<span class="mk-glass__shadow" aria-hidden="true"></span><span class="mk-cursor__icon mk-icon"></span><span class="mk-cursor__label"></span>';
1289
+ chipIcon = chip.querySelector(".mk-cursor__icon");
1290
+ chipLabel = chip.querySelector(".mk-cursor__label");
1291
+ host.append(chip);
1292
+ made.push(chip);
1293
+ gsap.set(chip, { autoAlpha: 0, scale: 0.8 });
1294
+ } else {
1295
+ const arrows = options.arrows ?? "y";
1296
+ scope.attr(host, "data-mk-arrows", arrows);
1297
+ scope.attr(zone, "data-mk-cursor-zone", "");
1298
+ const dot = document.createElement("span");
1299
+ dot.className = "mk-cursor__dot";
1300
+ dot.innerHTML = arrows === "none" ? '<span class="mk-cursor__circle"></span><span class="mk-cursor__text"><span class="mk-cursor__word"></span></span>' : `<span class="mk-cursor__circle"></span><span class="mk-cursor__arrow mk-cursor__arrow--start">${svg()}</span><span class="mk-cursor__text"><span class="mk-cursor__word"></span></span><span class="mk-cursor__arrow mk-cursor__arrow--end">${svg()}</span>`;
1301
+ word = dot.querySelector(".mk-cursor__word");
1302
+ if (word) word.textContent = options.text ?? "";
1303
+ host.append(dot);
1304
+ made.push(dot);
1305
+ scope.attr(host, "data-mk-hidden", "");
1306
+ }
1307
+ const appear = motionSpring(...TIMING.springs.cursorAppear);
1308
+ const showChip = (next) => {
1309
+ if (!chip || !chipLabel || !chipIcon) return;
1310
+ const text = next?.dataset.mkCursor ?? "";
1311
+ if (text) {
1312
+ label = text;
1313
+ chipLabel.textContent = text;
1314
+ chipIcon.textContent = next?.dataset.mkCursorIcon ?? "";
1315
+ chip.classList.toggle("mk-cursor__chip--circle", next?.dataset.mkCursorShape === "circle");
1316
+ const box = chip.getBoundingClientRect();
1317
+ size.width = box.width;
1318
+ size.height = box.height;
1319
+ }
1320
+ if (Boolean(text) === visible) return;
1321
+ visible = Boolean(text);
1322
+ if (!visible) label = "";
1323
+ gsap.to(chip, {
1324
+ autoAlpha: visible ? 1 : 0,
1325
+ scale: visible ? 1 : 0.8,
1326
+ duration: appear.duration,
1327
+ ease: appear.ease,
1328
+ overwrite: "auto"
1329
+ });
1330
+ };
1331
+ let inZone = false;
1332
+ let overHide = false;
1333
+ const syncDot = () => scope.attr(host, "data-mk-hidden", inZone && !overHide ? null : "");
1334
+ const wordFor = (target) => {
1335
+ if (!word) return;
1336
+ const source = target?.closest("[data-mk-cursor]");
1337
+ word.textContent = source && zone.contains(source) ? source.dataset.mkCursor ?? "" : options.text ?? "";
1338
+ };
1339
+ const place = (event) => {
1340
+ if (event.pointerType === "touch") return;
1341
+ pointer.x = event.clientX;
1342
+ pointer.y = event.clientY;
1343
+ if (!pointer.placed) {
1344
+ pointer.placed = true;
1345
+ if (variant === "dot") {
1346
+ position.x = pointer.x;
1347
+ position.y = pointer.y;
1348
+ }
1349
+ }
1350
+ };
1351
+ scope.on(window, "pointermove", (event) => place(event), { passive: true });
1352
+ const overTarget = variant === "chip" ? document : zone;
1353
+ scope.on(overTarget, "pointerover", (event) => {
1354
+ const target = event.target;
1355
+ if (variant === "chip") {
1356
+ const source = target?.closest("[data-mk-cursor]") ?? null;
1357
+ showChip(source && zone.contains(source) ? source : null);
1358
+ return;
1359
+ }
1360
+ overHide = Boolean(target?.closest("[data-mk-cursor-hide]"));
1361
+ wordFor(target);
1362
+ syncDot();
1363
+ });
1364
+ if (variant === "dot") {
1365
+ scope.on(zone, "pointerenter", (event) => {
1366
+ place(event);
1367
+ inZone = true;
1368
+ visible = true;
1369
+ syncDot();
1370
+ });
1371
+ scope.on(zone, "pointerleave", () => {
1372
+ inZone = false;
1373
+ visible = false;
1374
+ scope.attr(host, "data-mk-pressed", null);
1375
+ syncDot();
1376
+ });
1377
+ scope.on(zone, "pointerdown", () => scope.attr(host, "data-mk-pressed", ""));
1378
+ scope.on(window, "pointerup", () => scope.attr(host, "data-mk-pressed", null));
1379
+ }
1380
+ const [stiffness, damping] = TIMING.springs.cursorFollow;
1381
+ const update = (dt = 1) => {
1382
+ if (variant === "chip") {
1383
+ const halfW = size.width / 2 + t.gutter;
1384
+ const halfH = size.height / 2 + t.gutter;
1385
+ const tx = size.width ? Math.min(Math.max(pointer.x, halfW), innerWidth - halfW) : pointer.x;
1386
+ const ty = size.height ? Math.min(Math.max(pointer.y, halfH), innerHeight - halfH) : pointer.y;
1387
+ const steps = Math.max(1, Math.ceil(dt * 4));
1388
+ const h = dt / 60 / steps;
1389
+ for (let i = 0; i < steps; i++) {
1390
+ velocity.x += (stiffness * (tx - position.x) - damping * velocity.x) * h;
1391
+ velocity.y += (stiffness * (ty - position.y) - damping * velocity.y) * h;
1392
+ position.x += velocity.x * h;
1393
+ position.y += velocity.y * h;
1394
+ }
1395
+ if (visible && typeof document.elementFromPoint === "function") {
1396
+ tone = backgroundTone(document.elementFromPoint(pointer.x, pointer.y));
1397
+ if (chip && chip.dataset.mkTone !== tone) chip.dataset.mkTone = tone;
1398
+ }
1399
+ } else {
1400
+ const step = 1 - Math.pow(1 - t.dotLerp, dt);
1401
+ position.x += (pointer.x - position.x) * step;
1402
+ position.y += (pointer.y - position.y) * step;
1403
+ }
1404
+ host.style.transform = `translate3d(${position.x.toFixed(2)}px, ${position.y.toFixed(2)}px, 0) translate(-50%, -50%)`;
1405
+ };
1406
+ scope.add(subscribe(update));
1407
+ update(0);
1408
+ host.dataset.mkReady = "";
1409
+ return {
1410
+ get visible() {
1411
+ return visible;
1412
+ },
1413
+ get label() {
1414
+ return label;
1415
+ },
1416
+ get position() {
1417
+ return { ...position };
1418
+ },
1419
+ get tone() {
1420
+ return tone;
1421
+ },
1422
+ update,
1423
+ destroy() {
1424
+ if (chip) gsap.killTweensOf(chip);
1425
+ scope.dispose();
1426
+ for (const node of made.splice(0)) node.remove();
1427
+ host.style.removeProperty("transform");
1428
+ if (host.getAttribute("style") === "") host.removeAttribute("style");
1429
+ delete host.dataset.mkReady;
1430
+ }
1431
+ };
1432
+ }
1433
+
1434
+ // src/components/island/engine.ts
1435
+ var sequence = 0;
1436
+ var FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
1437
+ function createIsland(root, options = {}) {
1438
+ const shell = root?.querySelector(".mk-island__shell") ?? null;
1439
+ const panels = root ? [...root.querySelectorAll("[data-mk-island-panel]")] : [];
1440
+ if (!root || !shell || !panels.length) {
1441
+ warnOnce("island: needs .mk-island__shell and at least one [data-mk-island-panel]");
1442
+ return inert({ open() {
1443
+ }, close() {
1444
+ }, toggle() {
1445
+ }, ready() {
1446
+ }, active: null });
1447
+ }
1448
+ const t = TIMING.island;
1449
+ const { entrance = true, closeOnScroll = true, closeOnNavigate = true, focusOnOpen = true, onChange } = options;
1450
+ registerMotion();
1451
+ const scope = createScope();
1452
+ const toggles = [...root.querySelectorAll("[data-mk-island-toggle]")];
1453
+ const cta = root.querySelector(".mk-island__cta");
1454
+ const backdrops = [...root.querySelectorAll("[data-mk-island-close]")];
1455
+ let active = null;
1456
+ let trigger = null;
1457
+ let scrollStart = 0;
1458
+ let armed = false;
1459
+ let focusTimer;
1460
+ let entered = false;
1461
+ let entry = null;
1462
+ const flag = (el, name, on) => {
1463
+ if (el) scope.attr(el, name, on ? "" : null);
1464
+ };
1465
+ const sync = () => {
1466
+ for (const panel of panels) {
1467
+ const on = panel.dataset.mkIslandPanel === active;
1468
+ if (active) flag(panel, "hidden", !on);
1469
+ scope.attr(panel, "aria-hidden", String(!on));
1470
+ flag(panel, "inert", !on);
1471
+ }
1472
+ for (const button of toggles) scope.attr(button, "aria-expanded", String(button.dataset.mkIslandToggle === active));
1473
+ flag(cta, "inert", Boolean(active));
1474
+ for (const backdrop of backdrops) {
1475
+ flag(backdrop, "inert", !active);
1476
+ scope.attr(backdrop, "aria-hidden", String(!active));
1477
+ }
1478
+ flag(root, "data-mk-open", Boolean(active));
1479
+ scope.attr(root, "data-mk-active", active);
1480
+ };
1481
+ const stagger = (opening) => {
1482
+ root.querySelectorAll("[data-mk-island-item]").forEach((item, index) => {
1483
+ scope.attr(item, "style", item.getAttribute("style"));
1484
+ item.style.setProperty("--mk-island-delay", opening ? `${Number((t.delay + index * t.step).toFixed(3))}s` : "0s");
1485
+ });
1486
+ };
1487
+ const close = (returnFocus = true) => {
1488
+ if (scope.disposed || !active) return;
1489
+ clearTimeout(focusTimer);
1490
+ active = null;
1491
+ stagger(false);
1492
+ sync();
1493
+ onChange?.(null);
1494
+ if (returnFocus && trigger?.isConnected) trigger.focus({ preventScroll: true });
1495
+ };
1496
+ const open = (name = panels[0].dataset.mkIslandPanel, source) => {
1497
+ if (scope.disposed) return;
1498
+ const panel = panels.find((el) => el.dataset.mkIslandPanel === name);
1499
+ if (!panel) return;
1500
+ const wasClosed = !active;
1501
+ clearTimeout(focusTimer);
1502
+ active = name;
1503
+ trigger = source ?? toggles.find((el) => el.dataset.mkIslandToggle === name) ?? trigger;
1504
+ if (wasClosed) {
1505
+ scrollStart = window.scrollY;
1506
+ armed = false;
1507
+ stagger(true);
1508
+ }
1509
+ sync();
1510
+ onChange?.(name);
1511
+ if (focusOnOpen)
1512
+ focusTimer = setTimeout(
1513
+ () => {
1514
+ if (active !== name) return;
1515
+ const first = [...panel.querySelectorAll(FOCUSABLE)].find((el) => !el.closest("[hidden], [inert]"));
1516
+ (first ?? panel).focus({ preventScroll: true });
1517
+ },
1518
+ reduced() ? 0 : t.focus
1519
+ );
1520
+ };
1521
+ const toggle = (name = panels[0].dataset.mkIslandPanel, source) => active === name ? close(false) : open(name, source);
1522
+ for (const panel of panels) {
1523
+ if (!panel.id) scope.attr(panel, "id", `mk-island-panel-${++sequence}`);
1524
+ if (!panel.hasAttribute("tabindex")) scope.attr(panel, "tabindex", "-1");
1525
+ if (!panel.hasAttribute("role")) scope.attr(panel, "role", "region");
1526
+ }
1527
+ for (const button of toggles) {
1528
+ const panel = panels.find((el) => el.dataset.mkIslandPanel === button.dataset.mkIslandToggle);
1529
+ if (panel) scope.attr(button, "aria-controls", panel.id);
1530
+ scope.on(button, "click", () => toggle(button.dataset.mkIslandToggle, button));
1531
+ }
1532
+ for (const backdrop of backdrops) scope.on(backdrop, "click", () => close(true));
1533
+ scope.on(document, "keydown", (event) => {
1534
+ if (active && event.key === "Escape") {
1535
+ event.preventDefault();
1536
+ close(true);
1537
+ }
1538
+ });
1539
+ if (closeOnNavigate)
1540
+ scope.on(root, "click", (event) => {
1541
+ const link = event.target?.closest?.("a[href]");
1542
+ if (active && link?.closest("[data-mk-island-panel]")) close(false);
1543
+ });
1544
+ if (closeOnScroll) {
1545
+ const arm = () => {
1546
+ if (active) armed = true;
1547
+ };
1548
+ scope.on(window, "wheel", arm, { passive: true });
1549
+ scope.on(window, "touchmove", arm, { passive: true });
1550
+ scope.on(
1551
+ window,
1552
+ "scroll",
1553
+ () => {
1554
+ if (active && armed && Math.abs(window.scrollY - scrollStart) > 1) close(false);
1555
+ },
1556
+ { passive: true }
1557
+ );
1558
+ }
1559
+ scope.add(() => clearTimeout(focusTimer));
1560
+ const moving = entrance !== false && entrances();
1561
+ if (moving) gsap.set(shell, { yPercent: t.offset });
1562
+ const ready = () => {
1563
+ if (scope.disposed || entered || !moving) return;
1564
+ entered = true;
1565
+ entry = gsap.to(shell, { yPercent: 0, duration: t.entrance });
1566
+ };
1567
+ scope.add(() => {
1568
+ entry?.kill();
1569
+ if (moving) gsap.set(shell, { clearProps: "transform,translate" });
1570
+ if (shell.getAttribute("style") === "") shell.removeAttribute("style");
1571
+ });
1572
+ sync();
1573
+ if (entrance === true) ready();
1574
+ scope.attr(root, "data-mk-ready", "");
1575
+ return {
1576
+ open: (name) => open(name),
1577
+ close,
1578
+ toggle: (name) => toggle(name),
1579
+ ready,
1580
+ get active() {
1581
+ return active;
1582
+ },
1583
+ destroy: () => scope.dispose()
1584
+ };
1585
+ }
1586
+
1587
+ export {
1588
+ enterMessages,
1589
+ fitComposer,
1590
+ scrollToLatest,
1591
+ createThemePicker,
1592
+ ICON_PATHS,
1593
+ iconSvg,
1594
+ TOAST_LIMIT,
1595
+ getToasts,
1596
+ subscribeToasts,
1597
+ dismissToast,
1598
+ removeToast,
1599
+ clearToasts,
1600
+ toast,
1601
+ toastTimers,
1602
+ createToaster,
1603
+ chatBackgroundOf,
1604
+ createChatBackground,
1605
+ PENDING_ID,
1606
+ capturePending,
1607
+ morphPendingToReply,
1608
+ chatMessage,
1609
+ createChat,
1610
+ NAV_STYLES,
1611
+ revealShell,
1612
+ createNav,
1613
+ createSteps,
1614
+ createCursor,
1615
+ createIsland
1616
+ };
1617
+ //# sourceMappingURL=chunk-Q4LVFNLN.js.map