@yewdiel21/motion-kit 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (399) hide show
  1. package/NOTICE +3 -35
  2. package/README.md +93 -81
  3. package/dist/auto/index.d.ts +22 -3
  4. package/dist/auto/index.js +43 -5
  5. package/dist/auto/index.js.map +1 -1
  6. package/dist/{chunk-KLY5BRRI.js → chunk-34EZ7DF4.js} +1 -1
  7. package/dist/chunk-34EZ7DF4.js.map +1 -0
  8. package/dist/{chunk-RFDIZYFX.js → chunk-DOOMULVV.js} +20 -20
  9. package/dist/chunk-DOOMULVV.js.map +1 -0
  10. package/dist/{chunk-ABNRDDO7.js → chunk-I3DXF2KQ.js} +2 -2
  11. package/dist/{chunk-Q4LVFNLN.js → chunk-IKQ5FODN.js} +4 -4
  12. package/dist/chunk-IKQ5FODN.js.map +1 -0
  13. package/dist/{chunk-2BQGFOA7.js → chunk-J6OCFNGU.js} +2 -2
  14. package/dist/chunk-J6OCFNGU.js.map +1 -0
  15. package/dist/{chunk-6OJAP6ZL.js → chunk-QFBOHPWZ.js} +3 -3
  16. package/dist/chunk-QFBOHPWZ.js.map +1 -0
  17. package/dist/{chunk-J27KH2A2.js → chunk-RVSKEBIC.js} +1 -1
  18. package/dist/chunk-RVSKEBIC.js.map +1 -0
  19. package/dist/{chunk-34XYOXHG.js → chunk-TFNRIZHU.js} +1615 -12
  20. package/dist/chunk-TFNRIZHU.js.map +1 -0
  21. package/dist/{chunk-FS2HJVVY.js → chunk-XAKC2QY7.js} +1204 -5
  22. package/dist/chunk-XAKC2QY7.js.map +1 -0
  23. package/dist/css/components/calendar.css +159 -0
  24. package/dist/css/components/chat-background.css +2 -2
  25. package/dist/css/components/chat.css +1 -1
  26. package/dist/css/components/cursor.css +3 -3
  27. package/dist/css/components/dialog.css +3 -3
  28. package/dist/css/components/hover-card.css +14 -0
  29. package/dist/css/components/input-otp.css +10 -0
  30. package/dist/css/components/island.css +1 -1
  31. package/dist/css/components/menu.css +1 -1
  32. package/dist/css/components/nav.css +1 -5
  33. package/dist/css/components/pagination.css +11 -0
  34. package/dist/css/components/quantity.css +16 -0
  35. package/dist/css/components/slot-picker.css +126 -0
  36. package/dist/css/components/steps.css +2 -2
  37. package/dist/css/components/studio-dock.css +35 -0
  38. package/dist/css/components/theme-picker.css +1 -1
  39. package/dist/css/components/toast.css +1 -1
  40. package/dist/css/components/trailer.css +37 -0
  41. package/dist/css/controls.css +78 -13
  42. package/dist/css/effects.css +8 -8
  43. package/dist/css/fonts.css +1 -1
  44. package/dist/css/themes/black-green.css +1 -1
  45. package/dist/css/themes/black.css +1 -1
  46. package/dist/css/themes/blue.css +1 -1
  47. package/dist/css/themes/brown.css +1 -1
  48. package/dist/css/themes/cold-blue.css +1 -1
  49. package/dist/css/themes/funny.css +1 -1
  50. package/dist/css/themes/gray.css +1 -1
  51. package/dist/css/themes/green.css +1 -1
  52. package/dist/css/themes/modern-1.css +1 -1
  53. package/dist/css/themes/neogreen.css +1 -1
  54. package/dist/css/themes/new.css +1 -1
  55. package/dist/css/themes/new2.css +1 -1
  56. package/dist/css/themes/oled.css +1 -1
  57. package/dist/css/themes/orange.css +1 -1
  58. package/dist/css/themes/pastel-pink.css +1 -1
  59. package/dist/css/themes/pink.css +1 -1
  60. package/dist/css/themes/purple.css +1 -1
  61. package/dist/css/themes/red.css +1 -1
  62. package/dist/css/themes/super-blue.css +1 -1
  63. package/dist/css/themes.css +19 -19
  64. package/dist/css/tokens.css +9 -9
  65. package/dist/elements/index.d.ts +75 -7
  66. package/dist/elements/index.js +172 -6
  67. package/dist/elements/index.js.map +1 -1
  68. package/dist/{engine-CUr9QijM.d.ts → engine-GDGwQnJE.d.ts} +2 -2
  69. package/dist/gl/index.js +3 -3
  70. package/dist/index.css +1076 -63
  71. package/dist/index.d.ts +17 -17
  72. package/dist/index.js +49 -7
  73. package/dist/index.js.map +1 -1
  74. package/dist/react/index.d.ts +139 -40
  75. package/dist/react/index.js +355 -8
  76. package/dist/react/index.js.map +1 -1
  77. package/dist/{reduced-BM4Ls0g5.d.ts → reduced-BmBzKH94.d.ts} +215 -18
  78. package/dist/{reveal-WFUWDrei.d.ts → reveal-jsX-uwUz.d.ts} +233 -24
  79. package/dist/{store-Bqy_obnD.d.ts → store-DYb3tTsZ.d.ts} +5 -5
  80. package/dist/theme/generate.d.ts +1 -1
  81. package/dist/theme/generate.js +2 -2
  82. package/dist/theme/generate.js.map +1 -1
  83. package/dist/theme/index.d.ts +2 -2
  84. package/dist/theme/index.js +2 -2
  85. package/dist/{theme-BFMoCzi6.d.ts → theme-Bjf9qIIy.d.ts} +1 -1
  86. package/package.json +2 -2
  87. package/registry.json +230 -156
  88. package/skills/motion-kit/SKILL.md +209 -189
  89. package/skills/motion-kit/reference/components.md +5 -5
  90. package/skills/motion-kit/reference/design.md +14 -14
  91. package/skills/motion-kit/reference/recipes.md +48 -49
  92. package/src/auto/auto-init.ts +38 -0
  93. package/src/components/calendar/README.md +82 -0
  94. package/src/components/calendar/calendar.css +158 -0
  95. package/src/components/calendar/element.ts +27 -0
  96. package/src/components/calendar/engine.ts +412 -0
  97. package/src/components/calendar/react.tsx +69 -0
  98. package/src/components/chat/README.md +1 -3
  99. package/src/components/chat/chat.css +1 -1
  100. package/src/components/chat/engine.ts +1 -1
  101. package/src/components/chat/react.tsx +1 -1
  102. package/src/components/chat-background/README.md +1 -3
  103. package/src/components/chat-background/audio.ts +1 -1
  104. package/src/components/chat-background/chat-background.css +2 -2
  105. package/src/components/chat-background/engine.ts +1 -1
  106. package/src/components/chat-background/react.tsx +1 -1
  107. package/src/components/cursor/README.md +3 -5
  108. package/src/components/cursor/cursor.css +3 -3
  109. package/src/components/cursor/element.ts +2 -2
  110. package/src/components/cursor/engine.ts +5 -5
  111. package/src/components/cursor/react.tsx +1 -1
  112. package/src/components/dialog/README.md +4 -8
  113. package/src/components/dialog/dialog.css +3 -3
  114. package/src/components/dialog/engine.ts +2 -2
  115. package/src/components/dialog/react.tsx +1 -1
  116. package/src/components/hover-card/README.md +16 -0
  117. package/src/components/hover-card/element.ts +8 -0
  118. package/src/components/hover-card/engine.ts +69 -0
  119. package/src/components/hover-card/hover-card.css +13 -0
  120. package/src/components/hover-card/react.tsx +19 -0
  121. package/src/components/input-otp/README.md +18 -0
  122. package/src/components/input-otp/element.ts +14 -0
  123. package/src/components/input-otp/engine.ts +106 -0
  124. package/src/components/input-otp/input-otp.css +9 -0
  125. package/src/components/input-otp/react.tsx +21 -0
  126. package/src/components/island/README.md +7 -7
  127. package/src/components/island/engine.ts +3 -3
  128. package/src/components/island/island.css +1 -1
  129. package/src/components/island/react.tsx +3 -3
  130. package/src/components/menu/README.md +2 -4
  131. package/src/components/menu/engine.ts +1 -1
  132. package/src/components/menu/menu.css +1 -1
  133. package/src/components/menu/react.tsx +1 -1
  134. package/src/components/nav/README.md +12 -14
  135. package/src/components/nav/engine.ts +5 -5
  136. package/src/components/nav/nav.css +1 -5
  137. package/src/components/nav/react.tsx +3 -3
  138. package/src/components/pagination/README.md +17 -0
  139. package/src/components/pagination/element.ts +14 -0
  140. package/src/components/pagination/engine.ts +102 -0
  141. package/src/components/pagination/pagination.css +10 -0
  142. package/src/components/pagination/react.tsx +22 -0
  143. package/src/components/quantity/README.md +20 -0
  144. package/src/components/quantity/element.ts +14 -0
  145. package/src/components/quantity/engine.ts +85 -0
  146. package/src/components/quantity/quantity.css +15 -0
  147. package/src/components/quantity/react.tsx +21 -0
  148. package/src/components/slot-picker/README.md +68 -0
  149. package/src/components/slot-picker/element.ts +27 -0
  150. package/src/components/slot-picker/engine.ts +412 -0
  151. package/src/components/slot-picker/react.tsx +76 -0
  152. package/src/components/slot-picker/slot-picker.css +125 -0
  153. package/src/components/steps/README.md +1 -3
  154. package/src/components/steps/engine.ts +3 -3
  155. package/src/components/steps/react.tsx +2 -2
  156. package/src/components/steps/steps.css +2 -2
  157. package/src/components/studio-dock/README.md +44 -0
  158. package/src/components/studio-dock/element.ts +11 -0
  159. package/src/components/studio-dock/engine.ts +212 -0
  160. package/src/components/studio-dock/react.tsx +23 -0
  161. package/src/components/studio-dock/studio-dock.css +34 -0
  162. package/src/components/theme-picker/README.md +3 -5
  163. package/src/components/theme-picker/engine.ts +2 -2
  164. package/src/components/theme-picker/react.tsx +1 -1
  165. package/src/components/theme-picker/theme-picker.css +1 -1
  166. package/src/components/toast/README.md +1 -3
  167. package/src/components/toast/engine.ts +2 -2
  168. package/src/components/toast/react.tsx +1 -1
  169. package/src/components/toast/store.ts +1 -2
  170. package/src/components/toast/toast.css +1 -1
  171. package/src/components/trailer/README.md +28 -0
  172. package/src/components/trailer/element.ts +13 -0
  173. package/src/components/trailer/engine.ts +189 -0
  174. package/src/components/trailer/react.tsx +16 -0
  175. package/src/components/trailer/trailer.css +36 -0
  176. package/src/core/channels.ts +3 -3
  177. package/src/core/curves.ts +3 -3
  178. package/src/core/dates.ts +98 -0
  179. package/src/core/gsap.ts +2 -2
  180. package/src/core/loop.ts +1 -1
  181. package/src/core/math.ts +1 -1
  182. package/src/core/physics-spring.ts +2 -2
  183. package/src/core/scroll-track.ts +2 -4
  184. package/src/core/spring.ts +1 -1
  185. package/src/core/timing.ts +21 -22
  186. package/src/css/controls/README.md +24 -20
  187. package/src/css/controls/burger.css +1 -1
  188. package/src/css/controls/button.css +4 -4
  189. package/src/css/controls/checkbox.css +1 -1
  190. package/src/css/controls/chip.css +1 -1
  191. package/src/css/controls/field.css +2 -2
  192. package/src/css/controls/glass.css +4 -4
  193. package/src/css/controls/status.css +63 -0
  194. package/src/css/default-theme.css +1 -1
  195. package/src/css/effects/README.md +19 -21
  196. package/src/css/effects/anim.css +1 -1
  197. package/src/css/effects/fade.css +1 -1
  198. package/src/css/effects/float.css +1 -1
  199. package/src/css/effects/frost.css +1 -1
  200. package/src/css/effects/grain.css +1 -1
  201. package/src/css/effects/loading.css +1 -1
  202. package/src/css/effects/success.css +1 -1
  203. package/src/css/effects/text.css +1 -1
  204. package/src/css/fonts.css +1 -1
  205. package/src/css/states.css +1 -1
  206. package/src/css/themes/black-green.css +1 -1
  207. package/src/css/themes/black.css +1 -1
  208. package/src/css/themes/blue.css +1 -1
  209. package/src/css/themes/brown.css +1 -1
  210. package/src/css/themes/cold-blue.css +1 -1
  211. package/src/css/themes/funny.css +1 -1
  212. package/src/css/themes/gray.css +1 -1
  213. package/src/css/themes/green.css +1 -1
  214. package/src/css/themes/modern-1.css +1 -1
  215. package/src/css/themes/neogreen.css +1 -1
  216. package/src/css/themes/new.css +1 -1
  217. package/src/css/themes/new2.css +1 -1
  218. package/src/css/themes/oled.css +1 -1
  219. package/src/css/themes/orange.css +1 -1
  220. package/src/css/themes/pastel-pink.css +1 -1
  221. package/src/css/themes/pink.css +1 -1
  222. package/src/css/themes/purple.css +1 -1
  223. package/src/css/themes/red.css +1 -1
  224. package/src/css/themes/super-blue.css +1 -1
  225. package/src/css/tokens.css +8 -8
  226. package/src/elements/index.ts +24 -0
  227. package/src/gl/liquid-blend/README.md +3 -3
  228. package/src/gl/matcap/README.md +3 -3
  229. package/src/gl/particle-hero/README.md +1 -1
  230. package/src/gl/particle-hero/create-particle-hero.ts +3 -5
  231. package/src/gl/particle-hero/shaders.ts +1 -1
  232. package/src/gl/shader-blur/README.md +3 -3
  233. package/src/gl/shader-grain/README.md +3 -3
  234. package/src/index.ts +25 -0
  235. package/src/motion/chat.ts +2 -2
  236. package/src/motion/confetti.ts +1 -1
  237. package/src/motion/count.ts +1 -1
  238. package/src/motion/details.ts +1 -1
  239. package/src/motion/drag-dismiss.ts +1 -1
  240. package/src/motion/effects.ts +1 -1
  241. package/src/motion/entrances.ts +1 -1
  242. package/src/motion/floating.ts +1 -1
  243. package/src/motion/flow.ts +2 -2
  244. package/src/motion/indicator.ts +1 -1
  245. package/src/motion/layout.ts +1 -1
  246. package/src/motion/liquid.ts +1 -1
  247. package/src/motion/morph.ts +2 -2
  248. package/src/motion/reveal.ts +1 -1
  249. package/src/motion/sheet.ts +1 -1
  250. package/src/motion/surface.ts +1 -1
  251. package/src/react/animated-number.tsx +2 -2
  252. package/src/react/flip-group.tsx +1 -1
  253. package/src/react/frost.tsx +1 -1
  254. package/src/react/index.ts +21 -0
  255. package/src/react/slot-text.tsx +1 -1
  256. package/src/react/use-action-button.ts +6 -0
  257. package/src/react/use-card-dock.ts +1 -1
  258. package/src/react/use-cascade.ts +1 -1
  259. package/src/react/use-contrast.ts +1 -1
  260. package/src/react/use-depth-grid.ts +1 -1
  261. package/src/react/use-editorial-reveal.ts +7 -0
  262. package/src/react/use-fill-text.ts +1 -1
  263. package/src/react/use-film-hero.ts +6 -0
  264. package/src/react/use-font-cycle.ts +7 -0
  265. package/src/react/use-frame-zoom.ts +1 -1
  266. package/src/react/use-image-zoom.ts +5 -0
  267. package/src/react/use-joined-cta.ts +5 -0
  268. package/src/react/use-letters.ts +1 -1
  269. package/src/react/use-local-clock.ts +5 -0
  270. package/src/react/use-marquee.ts +1 -1
  271. package/src/react/use-mask-text.ts +1 -1
  272. package/src/react/use-parallax.ts +1 -1
  273. package/src/react/use-particle-hero.ts +1 -1
  274. package/src/react/use-scroll-dock.ts +5 -0
  275. package/src/react/use-snap-strip.ts +1 -1
  276. package/src/react/use-sticker.ts +5 -0
  277. package/src/react/use-studio-dock.ts +8 -0
  278. package/src/react/use-text-roll.ts +1 -1
  279. package/src/react/use-thumbnail-nav.ts +7 -0
  280. package/src/react/use-trailer.ts +6 -0
  281. package/src/react/use-weight-hover.ts +5 -0
  282. package/src/recipes/action-button/README.md +31 -0
  283. package/src/recipes/action-button/action-button.css +113 -0
  284. package/src/recipes/action-button/create-action-button.ts +56 -0
  285. package/src/recipes/card-dock/README.md +1 -1
  286. package/src/recipes/card-dock/card-dock.css +1 -1
  287. package/src/recipes/card-dock/create-card-dock.ts +2 -2
  288. package/src/recipes/cascade/README.md +1 -3
  289. package/src/recipes/cascade/create-cascade.ts +3 -3
  290. package/src/recipes/contrast/README.md +0 -2
  291. package/src/recipes/contrast/create-contrast.ts +1 -1
  292. package/src/recipes/counter/README.md +0 -2
  293. package/src/recipes/counter/create-counter.ts +1 -1
  294. package/src/recipes/curved-carousel/README.md +0 -2
  295. package/src/recipes/curved-carousel/create-curved-carousel.ts +2 -2
  296. package/src/recipes/curved-carousel/curved-carousel.css +1 -1
  297. package/src/recipes/depth-grid/README.md +0 -2
  298. package/src/recipes/depth-grid/create-depth-grid.ts +3 -4
  299. package/src/recipes/details/README.md +0 -2
  300. package/src/recipes/details/create-details.ts +1 -1
  301. package/src/recipes/dock-pill/README.md +3 -3
  302. package/src/recipes/drag-ruler/README.md +3 -3
  303. package/src/recipes/editorial-reveal/README.md +35 -0
  304. package/src/recipes/editorial-reveal/create-editorial-reveal.ts +91 -0
  305. package/src/recipes/editorial-reveal/editorial-reveal.css +17 -0
  306. package/src/recipes/fill-text/README.md +1 -1
  307. package/src/recipes/fill-text/create-fill-text.ts +1 -1
  308. package/src/recipes/film-hero/README.md +23 -0
  309. package/src/recipes/film-hero/create-film-hero.ts +65 -0
  310. package/src/recipes/film-hero/film-hero.css +29 -0
  311. package/src/recipes/fit-text/README.md +0 -2
  312. package/src/recipes/flow/README.md +0 -2
  313. package/src/recipes/flow/create-flow.ts +1 -1
  314. package/src/recipes/font-cycle/README.md +11 -0
  315. package/src/recipes/font-cycle/create-font-cycle.ts +126 -0
  316. package/src/recipes/font-cycle/font-cycle.css +36 -0
  317. package/src/recipes/frame-zoom/README.md +1 -3
  318. package/src/recipes/frame-zoom/create-frame-zoom.ts +2 -2
  319. package/src/recipes/image-zoom/README.md +16 -0
  320. package/src/recipes/image-zoom/create-image-zoom.ts +27 -0
  321. package/src/recipes/image-zoom/image-zoom.css +7 -0
  322. package/src/recipes/infinite-reel/README.md +3 -3
  323. package/src/recipes/joined-cta/README.md +13 -0
  324. package/src/recipes/joined-cta/create-joined-cta.ts +22 -0
  325. package/src/recipes/joined-cta/joined-cta.css +17 -0
  326. package/src/recipes/letters/README.md +2 -4
  327. package/src/recipes/letters/create-letters.ts +3 -3
  328. package/src/recipes/local-clock/README.md +31 -0
  329. package/src/recipes/local-clock/create-local-clock.ts +61 -0
  330. package/src/recipes/marquee/README.md +0 -2
  331. package/src/recipes/marquee/create-marquee.ts +3 -3
  332. package/src/recipes/marquee/marquee.css +1 -1
  333. package/src/recipes/mask-text/README.md +3 -5
  334. package/src/recipes/mask-text/create-mask-text.ts +4 -4
  335. package/src/recipes/parallax/README.md +1 -3
  336. package/src/recipes/parallax/create-parallax.ts +1 -1
  337. package/src/recipes/pile/README.md +0 -2
  338. package/src/recipes/pile/create-pile.ts +1 -1
  339. package/src/recipes/pile/pile-math.ts +1 -1
  340. package/src/recipes/pile/pile.css +1 -1
  341. package/src/recipes/pill/README.md +0 -2
  342. package/src/recipes/pill/pill.css +2 -2
  343. package/src/recipes/pop/README.md +0 -2
  344. package/src/recipes/pop/create-pop.ts +1 -1
  345. package/src/recipes/radial-menu/README.md +0 -2
  346. package/src/recipes/radial-menu/create-radial-menu.ts +1 -1
  347. package/src/recipes/radial-menu/radial-menu.css +1 -1
  348. package/src/recipes/reflow/README.md +3 -5
  349. package/src/recipes/reflow/create-reflow.ts +1 -1
  350. package/src/recipes/repel-bento/README.md +3 -3
  351. package/src/recipes/reveal/README.md +0 -2
  352. package/src/recipes/reveal/create-reveal.ts +1 -1
  353. package/src/recipes/rotator/README.md +3 -3
  354. package/src/recipes/scroll-dock/README.md +46 -0
  355. package/src/recipes/scroll-dock/create-scroll-dock.ts +72 -0
  356. package/src/recipes/scroll-dock/scroll-dock.css +70 -0
  357. package/src/recipes/slot-text/README.md +0 -2
  358. package/src/recipes/slot-text/create-slot-text.ts +1 -1
  359. package/src/recipes/snap-strip/README.md +1 -1
  360. package/src/recipes/snap-strip/create-snap-strip.ts +5 -6
  361. package/src/recipes/snap-strip/snap-strip.css +1 -1
  362. package/src/recipes/sortable/README.md +3 -5
  363. package/src/recipes/sortable/create-sortable.ts +4 -4
  364. package/src/recipes/sortable/sortable.css +1 -1
  365. package/src/recipes/spring-cards/README.md +0 -2
  366. package/src/recipes/spring-cards/create-spring-cards.ts +1 -1
  367. package/src/recipes/spring-cards/spring-cards.css +1 -1
  368. package/src/recipes/sticker/README.md +59 -0
  369. package/src/recipes/sticker/create-sticker.ts +490 -0
  370. package/src/recipes/sticker/sticker.css +112 -0
  371. package/src/recipes/stretch-footer/README.md +0 -2
  372. package/src/recipes/stretch-footer/create-stretch-footer.ts +1 -1
  373. package/src/recipes/stretch-footer/stretch-footer.css +1 -1
  374. package/src/recipes/tabs/README.md +0 -2
  375. package/src/recipes/tabs/create-tabs.ts +1 -1
  376. package/src/recipes/text-roll/README.md +1 -3
  377. package/src/recipes/text-roll/create-text-roll.ts +3 -3
  378. package/src/recipes/text-roll/text-roll.css +1 -1
  379. package/src/recipes/thumbnail-nav/README.md +16 -0
  380. package/src/recipes/thumbnail-nav/create-thumbnail-nav.ts +165 -0
  381. package/src/recipes/thumbnail-nav/thumbnail-nav.css +108 -0
  382. package/src/recipes/ticket-menu/README.md +3 -3
  383. package/src/recipes/weight-hover/README.md +37 -0
  384. package/src/recipes/weight-hover/create-weight-hover.ts +136 -0
  385. package/src/recipes/weight-hover/weight-hover.css +7 -0
  386. package/src/recipes/words/README.md +0 -2
  387. package/src/recipes/words/create-words.ts +1 -1
  388. package/src/theme/generate.ts +1 -1
  389. package/src/theme/presets.ts +2 -2
  390. package/src/theme/theme.ts +1 -2
  391. package/dist/chunk-2BQGFOA7.js.map +0 -1
  392. package/dist/chunk-34XYOXHG.js.map +0 -1
  393. package/dist/chunk-6OJAP6ZL.js.map +0 -1
  394. package/dist/chunk-FS2HJVVY.js.map +0 -1
  395. package/dist/chunk-J27KH2A2.js.map +0 -1
  396. package/dist/chunk-KLY5BRRI.js.map +0 -1
  397. package/dist/chunk-Q4LVFNLN.js.map +0 -1
  398. package/dist/chunk-RFDIZYFX.js.map +0 -1
  399. /package/dist/{chunk-ABNRDDO7.js.map → chunk-I3DXF2KQ.js.map} +0 -0
@@ -2,7 +2,7 @@ import {
2
2
  TIMING,
3
3
  createScope,
4
4
  reduced
5
- } from "./chunk-RFDIZYFX.js";
5
+ } from "./chunk-DOOMULVV.js";
6
6
  import {
7
7
  inert,
8
8
  warnOnce
@@ -22,11 +22,11 @@ function springPath(ratio, velocity = 0, steps = 72) {
22
22
  const stiffness = 5.6;
23
23
  const frequency = stiffness / damping * Math.sqrt(1 - damping * damping);
24
24
  const phase = (velocity - stiffness) / frequency;
25
- const at = (time) => 1 + Math.exp(-stiffness * time) * (-Math.cos(frequency * time) + phase * Math.sin(frequency * time));
25
+ const at = (time2) => 1 + Math.exp(-stiffness * time2) * (-Math.cos(frequency * time2) + phase * Math.sin(frequency * time2));
26
26
  let path = "M0,0";
27
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)}`;
28
+ const time2 = step / steps;
29
+ path += ` L${time2.toFixed(4)},${(step === steps ? 1 : at(time2)).toFixed(4)}`;
30
30
  }
31
31
  return path;
32
32
  }
@@ -132,9 +132,9 @@ function stepChannel(channel, seconds) {
132
132
  const config = channel.config;
133
133
  if (!channel.active || !config) return;
134
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;
135
+ const time2 = Math.min(0.064, Math.max(0, seconds));
136
+ const steps = Math.max(1, Math.ceil(time2 / (1 / 60) - 1e-9));
137
+ const step = time2 / steps;
138
138
  for (let index = 0; index < steps; index += 1) {
139
139
  const force = -config.stiffness * (channel.current - channel.target) - config.damping * channel.velocity;
140
140
  channel.velocity += force / (config.mass ?? 1) * step;
@@ -591,9 +591,9 @@ function revealCounter(el, to, { from, duration = TIMING.revealCounter, format =
591
591
  let began = null;
592
592
  let cancel = () => {
593
593
  };
594
- const step = (time) => {
595
- began ??= time;
596
- const progress = Math.min(1, (time - began) / (duration * 1e3));
594
+ const step = (time2) => {
595
+ began ??= time2;
596
+ const progress = Math.min(1, (time2 - began) / (duration * 1e3));
597
597
  write(start + (to - start) * (1 - (1 - progress) ** 3));
598
598
  if (progress < 1) cancel = requestFrame(step);
599
599
  else frames.delete(el);
@@ -2291,6 +2291,1599 @@ function createMenu(dialog, options = {}) {
2291
2291
  };
2292
2292
  }
2293
2293
 
2294
+ // src/components/quantity/engine.ts
2295
+ function createQuantity(root, options = {}) {
2296
+ const input = root?.querySelector("[data-mk-quantity-input]");
2297
+ if (!root || !input) return inert({ setValue() {
2298
+ }, value: 0 });
2299
+ const scope = createScope();
2300
+ const min = Number.isFinite(options.min) ? options.min : 1;
2301
+ const max = Number.isFinite(options.max) ? Math.max(min, options.max) : Math.max(min, 999);
2302
+ const step = Number.isFinite(options.step) && options.step > 0 ? options.step : 1;
2303
+ const steps = Math.floor((max - min) / step + 1e-9);
2304
+ const upper = Math.min(max, Number((min + steps * step).toFixed(10)));
2305
+ const normalize = (n) => Math.max(min, Math.min(upper, Number((min + Math.round((n - min) / step) * step).toFixed(10))));
2306
+ const original = input.value;
2307
+ const disabled = options.disabled ?? input.disabled;
2308
+ const decrease = root.querySelector("[data-mk-quantity-decrease]");
2309
+ const increase = root.querySelector("[data-mk-quantity-increase]");
2310
+ scope.attr(input, "min", String(min));
2311
+ scope.attr(input, "max", String(max));
2312
+ scope.attr(input, "step", String(step));
2313
+ scope.attr(input, "disabled", disabled ? "" : null);
2314
+ scope.attr(root, "data-mk-ready", "");
2315
+ const initial = input.value.trim() ? Number(input.value) : NaN;
2316
+ let value = normalize(Number.isFinite(options.value) ? options.value : Number.isFinite(initial) ? initial : min);
2317
+ let pendingReset = null;
2318
+ const typed = () => input.value.trim() && Number.isFinite(input.valueAsNumber) ? input.valueAsNumber : NaN;
2319
+ const render = (syncInput = true) => {
2320
+ if (pendingReset) {
2321
+ if (pendingReset.eventPhase !== 0) return;
2322
+ if (!pendingReset.defaultPrevented) value = normalize(Number.isFinite(typed()) ? typed() : min);
2323
+ pendingReset = null;
2324
+ }
2325
+ if (syncInput) input.value = String(value);
2326
+ if (decrease) scope.attr(decrease, "disabled", disabled || value <= min ? "" : null);
2327
+ if (increase) scope.attr(increase, "disabled", disabled || value >= upper ? "" : null);
2328
+ };
2329
+ const commit = (next, notify, syncInput) => {
2330
+ if (scope.disposed || !Number.isFinite(next)) return;
2331
+ if (pendingReset?.eventPhase === 0) pendingReset = null;
2332
+ const previous = value;
2333
+ value = normalize(next);
2334
+ render(syncInput);
2335
+ if (notify && value !== previous) {
2336
+ options.onChange?.(value);
2337
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { value, previous } }));
2338
+ }
2339
+ };
2340
+ const setValue = (next, notify = true) => commit(next, notify, true);
2341
+ if (decrease) scope.on(decrease, "click", () => {
2342
+ if (!decrease.disabled) setValue(value - step);
2343
+ });
2344
+ if (increase) scope.on(increase, "click", () => {
2345
+ if (!increase.disabled) setValue(value + step);
2346
+ });
2347
+ scope.on(input, "input", () => {
2348
+ const n = typed();
2349
+ if (Number.isFinite(n) && normalize(n) === n) commit(n, true, false);
2350
+ });
2351
+ scope.on(input, "change", () => {
2352
+ if (Number.isFinite(typed())) setValue(typed());
2353
+ else render();
2354
+ });
2355
+ scope.on(input, "blur", () => render());
2356
+ if (input.form) scope.on(input.form, "reset", (event) => {
2357
+ render();
2358
+ pendingReset = event;
2359
+ scope.timeout(() => {
2360
+ if (pendingReset === event) render();
2361
+ }, 0);
2362
+ });
2363
+ scope.add(() => {
2364
+ input.value = original;
2365
+ });
2366
+ render();
2367
+ return { setValue, get value() {
2368
+ return value;
2369
+ }, destroy: () => scope.dispose() };
2370
+ }
2371
+
2372
+ // src/components/pagination/engine.ts
2373
+ var positive = (n, fallback) => Number.isFinite(n) ? Math.max(1, Math.min(Number.MAX_SAFE_INTEGER - 32, Math.floor(n))) : fallback;
2374
+ function createPagination(root, options = {}) {
2375
+ const pages = root?.querySelector("[data-mk-pagination-pages]");
2376
+ if (!root || !pages) return inert({ setPage() {
2377
+ }, setTotalPages() {
2378
+ }, page: 1, totalPages: 1 });
2379
+ const scope = createScope();
2380
+ const original = [...pages.childNodes];
2381
+ const previous = root.querySelector("[data-mk-pagination-previous]");
2382
+ const next = root.querySelector("[data-mk-pagination-next]");
2383
+ let total = positive(options.totalPages, 10);
2384
+ let page = Math.min(total, positive(options.page, 1));
2385
+ const siblings = Math.min(10, Math.max(0, Number.isFinite(options.siblings) ? Math.floor(options.siblings) : 1));
2386
+ scope.attr(root, "data-mk-ready", "");
2387
+ const render = () => {
2388
+ const hadFocus = pages.contains(document.activeElement);
2389
+ const selected = /* @__PURE__ */ new Set([1, total]);
2390
+ for (let n = Math.max(1, page - siblings); n <= Math.min(total, page + siblings); n++) selected.add(n);
2391
+ const fragment = document.createDocumentFragment();
2392
+ let last = 0;
2393
+ for (const n of [...selected].sort((a, b) => a - b)) {
2394
+ if (last && n - last > 1) {
2395
+ const gap = document.createElement("span");
2396
+ gap.className = "mk-pagination__gap";
2397
+ gap.textContent = "\u2026";
2398
+ gap.setAttribute("aria-hidden", "true");
2399
+ fragment.append(gap);
2400
+ }
2401
+ const button = document.createElement("button");
2402
+ button.type = "button";
2403
+ button.dataset.mkPage = String(n);
2404
+ button.textContent = String(n);
2405
+ button.setAttribute("aria-label", options.pageLabel?.(n) ?? `P\xE1gina ${n}`);
2406
+ if (n === page) button.setAttribute("aria-current", "page");
2407
+ fragment.append(button);
2408
+ last = n;
2409
+ }
2410
+ pages.replaceChildren(fragment);
2411
+ if (hadFocus) pages.querySelector("[aria-current]")?.focus();
2412
+ if (previous) scope.attr(previous, "disabled", page === 1 ? "" : null);
2413
+ if (next) scope.attr(next, "disabled", page === total ? "" : null);
2414
+ };
2415
+ const setPage = (value, notify = true) => {
2416
+ if (scope.disposed || !Number.isFinite(value)) return;
2417
+ const candidate = Math.max(1, Math.min(total, Math.round(value)));
2418
+ if (candidate === page) return;
2419
+ const focused = pages.contains(document.activeElement);
2420
+ page = candidate;
2421
+ render();
2422
+ if (focused) pages.querySelector("[aria-current]")?.focus();
2423
+ if (notify) {
2424
+ options.onChange?.(page);
2425
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { page, totalPages: total } }));
2426
+ }
2427
+ };
2428
+ scope.on(root, "click", (event) => {
2429
+ const target = event.target.closest("button");
2430
+ if (!target || target.disabled) return;
2431
+ if (target === previous) setPage(page - 1);
2432
+ else if (target === next) setPage(page + 1);
2433
+ else if (target.dataset.mkPage) setPage(Number(target.dataset.mkPage));
2434
+ });
2435
+ scope.on(root, "keydown", (event) => {
2436
+ if (!(event.target instanceof HTMLButtonElement)) return;
2437
+ const to = event.key === "ArrowRight" ? page + 1 : event.key === "ArrowLeft" ? page - 1 : event.key === "Home" ? 1 : event.key === "End" ? total : null;
2438
+ if (to === null) return;
2439
+ event.preventDefault();
2440
+ setPage(to);
2441
+ pages.querySelector("[aria-current]")?.focus();
2442
+ });
2443
+ scope.add(() => pages.replaceChildren(...original));
2444
+ render();
2445
+ return {
2446
+ setPage,
2447
+ setTotalPages(value) {
2448
+ if (scope.disposed || !Number.isFinite(value)) return;
2449
+ total = positive(value, 1);
2450
+ if (page > total) setPage(total);
2451
+ else render();
2452
+ },
2453
+ get page() {
2454
+ return page;
2455
+ },
2456
+ get totalPages() {
2457
+ return total;
2458
+ },
2459
+ destroy: () => scope.dispose()
2460
+ };
2461
+ }
2462
+
2463
+ // src/components/hover-card/engine.ts
2464
+ var sequence = 0;
2465
+ function createHoverCard(root, options = {}) {
2466
+ const trigger = root?.querySelector("[data-mk-hover-trigger]");
2467
+ const panel = root?.querySelector("[data-mk-hover-panel]");
2468
+ if (!root || !trigger || !panel) return inert({ open() {
2469
+ }, close() {
2470
+ }, isOpen: false });
2471
+ const scope = createScope();
2472
+ const openDelay = Number.isFinite(options.openDelay) ? Math.max(0, options.openDelay) : 120;
2473
+ const closeDelay = Number.isFinite(options.closeDelay) ? Math.max(0, options.closeDelay) : 140;
2474
+ let opened = false;
2475
+ let timer;
2476
+ let pointerInside = false;
2477
+ let id = panel.id;
2478
+ if (!id) {
2479
+ do {
2480
+ id = `mk-hover-${++sequence}`;
2481
+ } while (document.getElementById(id));
2482
+ }
2483
+ scope.attr(panel, "id", id);
2484
+ scope.attr(trigger, "aria-controls", id);
2485
+ scope.attr(root, "data-mk-placement", options.placement ?? "top");
2486
+ scope.attr(root, "data-mk-ready", "");
2487
+ const cancel = () => {
2488
+ clearTimeout(timer);
2489
+ timer = void 0;
2490
+ };
2491
+ const set = (value) => {
2492
+ cancel();
2493
+ if (scope.disposed) return;
2494
+ const changed = value !== opened;
2495
+ opened = value;
2496
+ scope.attr(trigger, "aria-expanded", String(value));
2497
+ scope.attr(panel, "hidden", value ? null : "");
2498
+ scope.attr(root, "data-mk-open", value ? "" : null);
2499
+ if (changed) {
2500
+ options.onOpenChange?.(value);
2501
+ root.dispatchEvent(new CustomEvent("mk:open-change", { bubbles: true, detail: { open: value } }));
2502
+ }
2503
+ };
2504
+ const schedule = (value, delay) => {
2505
+ cancel();
2506
+ timer = setTimeout(() => set(value), delay);
2507
+ };
2508
+ scope.on(root, "pointerenter", () => {
2509
+ pointerInside = true;
2510
+ schedule(true, openDelay);
2511
+ });
2512
+ scope.on(root, "pointerleave", () => {
2513
+ pointerInside = false;
2514
+ if (!root.contains(document.activeElement)) schedule(false, closeDelay);
2515
+ });
2516
+ scope.on(root, "focusin", () => set(true));
2517
+ scope.on(root, "focusout", (event) => {
2518
+ if (!pointerInside && !root.contains(event.relatedTarget)) schedule(false, closeDelay);
2519
+ });
2520
+ scope.on(trigger, "click", () => set(true));
2521
+ scope.on(document, "pointerdown", (event) => {
2522
+ if (!root.contains(event.target)) set(false);
2523
+ });
2524
+ scope.on(root, "keydown", (event) => {
2525
+ if (event.key !== "Escape" || !opened) return;
2526
+ event.preventDefault();
2527
+ trigger.focus();
2528
+ set(false);
2529
+ });
2530
+ scope.add(cancel);
2531
+ set(false);
2532
+ return { open: () => set(true), close: () => set(false), get isOpen() {
2533
+ return opened;
2534
+ }, destroy: () => scope.dispose() };
2535
+ }
2536
+
2537
+ // src/components/input-otp/engine.ts
2538
+ function createInputOtp(root, options = {}) {
2539
+ const input = root?.querySelector("[data-mk-otp-input]");
2540
+ const slots = root?.querySelector("[data-mk-otp-slots]");
2541
+ if (!root || !input || !slots) return inert({ setValue() {
2542
+ }, focus() {
2543
+ }, value: "" });
2544
+ const scope = createScope();
2545
+ const length = Number.isFinite(options.length) ? Math.min(16, Math.max(1, Math.round(options.length))) : 6;
2546
+ const clean = (text) => text.replace(/[^0-9]/g, "").slice(0, length);
2547
+ const original = input.value;
2548
+ const originalNodes = [...slots.childNodes];
2549
+ let value = clean(options.value ?? input.value);
2550
+ let pendingReset = null;
2551
+ const cells = Array.from({ length }, () => {
2552
+ const cell = document.createElement("span");
2553
+ cell.className = "mk-input-otp__slot";
2554
+ return cell;
2555
+ });
2556
+ slots.replaceChildren(...cells);
2557
+ scope.attr(slots, "aria-hidden", "true");
2558
+ scope.attr(input, "type", "text");
2559
+ scope.attr(input, "inputmode", "numeric");
2560
+ scope.attr(input, "autocomplete", "one-time-code");
2561
+ scope.attr(input, "maxlength", String(length));
2562
+ scope.attr(input, "pattern", `[0-9]{${length}}`);
2563
+ scope.attr(root, "data-mk-ready", "");
2564
+ const render = () => {
2565
+ if (pendingReset) {
2566
+ if (pendingReset.eventPhase !== 0) return;
2567
+ if (!pendingReset.defaultPrevented) value = clean(input.value);
2568
+ pendingReset = null;
2569
+ }
2570
+ input.value = value;
2571
+ const active = document.activeElement === input ? Math.min(length - 1, input.selectionStart ?? value.length) : -1;
2572
+ cells.forEach((cell, i) => {
2573
+ const text = value[i] ? options.mask ? "\u2022" : value[i] : "";
2574
+ if (cell.textContent !== text) cell.textContent = text;
2575
+ cell.toggleAttribute("data-mk-active", i === active);
2576
+ cell.toggleAttribute("data-mk-filled", i < value.length);
2577
+ });
2578
+ scope.attr(root, "data-mk-complete", value.length === length ? "" : null);
2579
+ };
2580
+ const setValue = (next, notify = true) => {
2581
+ if (scope.disposed) return;
2582
+ if (pendingReset?.eventPhase === 0) pendingReset = null;
2583
+ const previous = value;
2584
+ value = clean(String(next));
2585
+ render();
2586
+ if (notify && value !== previous) {
2587
+ options.onChange?.(value);
2588
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { value, complete: value.length === length } }));
2589
+ if (value.length === length) {
2590
+ options.onComplete?.(value);
2591
+ root.dispatchEvent(new CustomEvent("mk:complete", { bubbles: true, detail: { value } }));
2592
+ }
2593
+ }
2594
+ };
2595
+ scope.on(input, "input", (event) => {
2596
+ if (event.isComposing) return;
2597
+ const caret = clean(input.value.slice(0, input.selectionStart ?? input.value.length)).length;
2598
+ setValue(input.value);
2599
+ input.setSelectionRange(caret, caret);
2600
+ render();
2601
+ });
2602
+ scope.on(input, "compositionend", () => setValue(input.value));
2603
+ scope.on(input, "paste", (event) => {
2604
+ const text = event.clipboardData?.getData("text");
2605
+ if (text === void 0) return;
2606
+ event.preventDefault();
2607
+ const start = input.selectionStart ?? value.length;
2608
+ const end = input.selectionEnd ?? start;
2609
+ const inserted = clean(text);
2610
+ setValue(value.slice(0, start) + inserted + value.slice(end));
2611
+ const caret = Math.min(length, start + inserted.length);
2612
+ input.setSelectionRange(caret, caret);
2613
+ render();
2614
+ });
2615
+ scope.on(input, "focus", render);
2616
+ scope.on(input, "blur", render);
2617
+ scope.on(input, "keyup", render);
2618
+ scope.on(input, "click", render);
2619
+ scope.on(document, "selectionchange", () => {
2620
+ if (document.activeElement === input) render();
2621
+ });
2622
+ if (input.form) scope.on(input.form, "reset", (event) => {
2623
+ render();
2624
+ pendingReset = event;
2625
+ scope.timeout(() => {
2626
+ if (pendingReset === event) render();
2627
+ }, 0);
2628
+ });
2629
+ scope.add(() => {
2630
+ slots.replaceChildren(...originalNodes);
2631
+ input.value = original;
2632
+ });
2633
+ render();
2634
+ return { setValue, focus: () => {
2635
+ if (!scope.disposed) input.focus();
2636
+ }, get value() {
2637
+ return value;
2638
+ }, destroy: () => scope.dispose() };
2639
+ }
2640
+
2641
+ // src/components/studio-dock/engine.ts
2642
+ var nextId = 0;
2643
+ var PANEL_OFFSET = 76;
2644
+ var VIEWPORT_GAP = 12;
2645
+ var MIN_SPACE = 320;
2646
+ var FOCUSABLE = 'a[href],button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),video[controls],[tabindex]:not([tabindex="-1"])';
2647
+ function createStudioDock(root, options = {}) {
2648
+ const toggleButton = root?.querySelector("[data-mk-studio-toggle]");
2649
+ const panel = root?.querySelector("[data-mk-studio-panel]");
2650
+ if (!root || !toggleButton || !panel) return inert({ open() {
2651
+ }, close() {
2652
+ }, toggle() {
2653
+ }, selectPage() {
2654
+ }, state: { open: false, view: "menu", page: 0 } });
2655
+ registerMotion();
2656
+ const scope = createScope();
2657
+ const context = gsap.context(() => {
2658
+ }, root);
2659
+ scope.add(() => context.revert());
2660
+ const views = [...panel.querySelectorAll("[data-mk-studio-view]")];
2661
+ const pages = [...panel.querySelectorAll("[data-mk-studio-page]")];
2662
+ const pageButtons = [...root.querySelectorAll("[data-mk-studio-page-to]")];
2663
+ const slide = root.querySelector("[data-mk-studio-slide]");
2664
+ const tracked = [root, panel, ...slide ? [slide] : []];
2665
+ tracked.forEach((el) => {
2666
+ const style = el.getAttribute("style");
2667
+ scope.add(() => style === null ? el.removeAttribute("style") : el.setAttribute("style", style));
2668
+ });
2669
+ scope.attr(panel, "id", panel.id || `mk-studio-panel-${++nextId}`);
2670
+ scope.attr(panel, "role", panel.getAttribute("role") || "dialog");
2671
+ scope.attr(panel, "aria-label", panel.getAttribute("aria-label") || "Studio navigation");
2672
+ scope.attr(panel, "tabindex", "-1");
2673
+ scope.attr(toggleButton, "aria-controls", panel.id);
2674
+ scope.attr(toggleButton, "aria-expanded", "false");
2675
+ scope.attr(panel, "hidden", "");
2676
+ scope.attr(panel, "aria-hidden", "true");
2677
+ scope.attr(root, "data-mk-ready", "");
2678
+ let state = { open: false, view: "menu", page: 0 };
2679
+ let previousFocus = null;
2680
+ let animation;
2681
+ let slideStart = null;
2682
+ let slideDistance = 0;
2683
+ let slideMoved = false;
2684
+ let suppressSlideClick = false;
2685
+ const place2 = (decide = false) => {
2686
+ const view = root.ownerDocument.defaultView;
2687
+ if (!state.open || !view) return;
2688
+ const rect = root.getBoundingClientRect();
2689
+ const offset = parseFloat(view.getComputedStyle(root).getPropertyValue("--mk-studio-dock-offset")) || PANEL_OFFSET;
2690
+ const above = rect.bottom - offset - VIEWPORT_GAP;
2691
+ const below = view.innerHeight - rect.top - offset - VIEWPORT_GAP;
2692
+ if (decide) scope.attr(root, "data-mk-studio-below", above < Math.min(panel.scrollHeight || MIN_SPACE, MIN_SPACE) && below > above ? "" : null);
2693
+ const flip = root.hasAttribute("data-mk-studio-below");
2694
+ root.style.setProperty("--mk-studio-dock-space", `${Math.max(MIN_SPACE / 2, Math.floor(flip ? below : above))}px`);
2695
+ };
2696
+ const hidden = () => root.hasAttribute("data-mk-studio-below") ? { clipPath: "inset(0% 0% 100% 0% round 18px)", y: -16, opacity: 0 } : { clipPath: "inset(100% 0% 0% 0% round 18px)", y: 16, opacity: 0 };
2697
+ const notify = () => {
2698
+ const value = { ...state };
2699
+ options.onChange?.(value);
2700
+ root.dispatchEvent(new CustomEvent("mk:studio-dock", { bubbles: true, detail: value }));
2701
+ };
2702
+ const isTabbable = (el) => el.tabIndex >= 0 && !el.closest("[hidden], [inert]") && el.getAttribute("aria-disabled") !== "true";
2703
+ const visibleFocus = () => [...panel.querySelectorAll(FOCUSABLE)].filter(isTabbable);
2704
+ const focusView = () => {
2705
+ if (options.focusOnOpen !== false) (visibleFocus()[0] ?? panel).focus({ preventScroll: true });
2706
+ };
2707
+ const setView = (view) => {
2708
+ state.view = views.length && !views.some((el) => el.dataset.mkStudioView === view) ? "menu" : view;
2709
+ views.forEach((el) => scope.attr(el, "hidden", el.dataset.mkStudioView === state.view ? null : ""));
2710
+ scope.attr(root, "data-mk-studio-active", state.view);
2711
+ panel.querySelectorAll("video").forEach((video) => {
2712
+ if (state.view !== "reel") video.pause();
2713
+ });
2714
+ };
2715
+ const selectPage = (index, announce = true) => {
2716
+ if (scope.disposed || !pages.length || !Number.isFinite(index)) return;
2717
+ state.page = (Math.round(index) % pages.length + pages.length) % pages.length;
2718
+ pages.forEach((el, i) => scope.attr(el, "hidden", i === state.page ? null : ""));
2719
+ pageButtons.forEach((el) => scope.attr(el, "aria-current", Number(el.dataset.mkStudioPageTo) === state.page ? "true" : null));
2720
+ if (announce) notify();
2721
+ };
2722
+ const open = (view = "menu") => {
2723
+ if (scope.disposed) return;
2724
+ const wasOpen = state.open;
2725
+ if (wasOpen && state.view === view) return;
2726
+ if (!wasOpen) {
2727
+ const active = root.ownerDocument.activeElement;
2728
+ previousFocus = active instanceof HTMLElement && active !== root.ownerDocument.body && !panel.contains(active) ? active : toggleButton;
2729
+ }
2730
+ animation?.kill();
2731
+ state.open = true;
2732
+ scope.attr(panel, "hidden", null);
2733
+ scope.attr(panel, "inert", null);
2734
+ scope.attr(panel, "aria-hidden", "false");
2735
+ scope.attr(root, "data-mk-studio-open", "");
2736
+ scope.attr(toggleButton, "aria-expanded", "true");
2737
+ setView(view);
2738
+ place2(!wasOpen);
2739
+ if (!reduced()) context.add(() => {
2740
+ animation = gsap.fromTo(panel, hidden(), { clipPath: "inset(0% 0% 0% 0% round 18px)", y: 0, opacity: 1, duration: Math.max(0, options.duration ?? 1.3), ease: options.ease ?? "back.out(0.52)", overwrite: true });
2741
+ });
2742
+ else context.add(() => {
2743
+ gsap.set(panel, { clipPath: "inset(0% round 18px)", y: 0, opacity: 1 });
2744
+ });
2745
+ focusView();
2746
+ notify();
2747
+ };
2748
+ const close = (restoreFocus = true) => {
2749
+ if (scope.disposed || !state.open) return;
2750
+ animation?.kill();
2751
+ state.open = false;
2752
+ scope.attr(toggleButton, "aria-expanded", "false");
2753
+ scope.attr(root, "data-mk-studio-open", null);
2754
+ scope.attr(panel, "inert", "");
2755
+ scope.attr(panel, "aria-hidden", "true");
2756
+ if (reduced()) scope.attr(panel, "hidden", "");
2757
+ else context.add(() => {
2758
+ animation = gsap.to(panel, { ...hidden(), duration: Math.max(0, options.duration ?? 1.3), ease: options.ease ?? "back.out(0.52)", overwrite: true, onComplete: () => {
2759
+ if (!scope.disposed && !state.open) scope.attr(panel, "hidden", "");
2760
+ } });
2761
+ });
2762
+ panel.querySelectorAll("video").forEach((video) => video.pause());
2763
+ if (restoreFocus) (previousFocus?.isConnected ? previousFocus : toggleButton).focus({ preventScroll: true });
2764
+ notify();
2765
+ };
2766
+ scope.on(root, "click", (event) => {
2767
+ const target = event.target instanceof Element ? event.target : null;
2768
+ if (!target) return;
2769
+ if (target.closest("[data-mk-studio-toggle]") === toggleButton) state.open ? close() : open();
2770
+ else if (target.closest("[data-mk-studio-close]")) close();
2771
+ else if (target.closest("[data-mk-studio-slide]")) {
2772
+ if (suppressSlideClick) {
2773
+ event.preventDefault();
2774
+ suppressSlideClick = false;
2775
+ } else open("contact");
2776
+ } else {
2777
+ const view = target.closest("[data-mk-studio-to]")?.dataset.mkStudioTo;
2778
+ if (view === "menu" || view === "contact" || view === "reel") open(view);
2779
+ const page = target.closest("[data-mk-studio-page-to]");
2780
+ if (page) selectPage(Number(page.dataset.mkStudioPageTo));
2781
+ }
2782
+ });
2783
+ if (root.ownerDocument.defaultView) scope.on(root.ownerDocument.defaultView, "resize", () => place2());
2784
+ scope.on(root.ownerDocument, "scroll", () => place2(), { passive: true, capture: true });
2785
+ scope.on(root.ownerDocument, "pointerdown", (event) => {
2786
+ if (state.open && event.target instanceof Node && !root.contains(event.target)) close(false);
2787
+ });
2788
+ scope.on(root.ownerDocument, "keydown", (event) => {
2789
+ if (!state.open || event.defaultPrevented) return;
2790
+ if (event.key === "Escape") {
2791
+ event.preventDefault();
2792
+ close();
2793
+ return;
2794
+ }
2795
+ if (!(event.target instanceof Node) || !root.contains(event.target)) return;
2796
+ if ((event.key === "ArrowLeft" || event.key === "ArrowRight") && event.target.closest("[data-mk-studio-pages]")) {
2797
+ event.preventDefault();
2798
+ selectPage(state.page + (event.key === "ArrowRight" ? 1 : -1));
2799
+ pageButtons.find((el) => Number(el.dataset.mkStudioPageTo) === state.page)?.focus();
2800
+ }
2801
+ if (event.key === "Tab" && options.trapFocus !== false) {
2802
+ const elements = [...root.querySelectorAll(FOCUSABLE)].filter((el) => (el === toggleButton || panel.contains(el)) && isTabbable(el));
2803
+ if (!elements.length) {
2804
+ event.preventDefault();
2805
+ panel.focus();
2806
+ return;
2807
+ }
2808
+ const first = elements[0], last = elements.at(-1);
2809
+ if (event.shiftKey && (root.ownerDocument.activeElement === first || root.ownerDocument.activeElement === panel)) {
2810
+ event.preventDefault();
2811
+ last.focus();
2812
+ } else if (!event.shiftKey && root.ownerDocument.activeElement === last) {
2813
+ event.preventDefault();
2814
+ first.focus();
2815
+ }
2816
+ }
2817
+ });
2818
+ if (slide) {
2819
+ scope.on(slide, "pointerdown", (event) => {
2820
+ if (event.button !== 0) return;
2821
+ slideStart = event.clientX;
2822
+ slideDistance = 0;
2823
+ slideMoved = false;
2824
+ });
2825
+ scope.on(root.ownerDocument, "pointermove", (event) => {
2826
+ if (slideStart === null) return;
2827
+ const width = Math.max(0, (slide.parentElement?.clientWidth ?? 0) - slide.offsetWidth);
2828
+ slideMoved ||= Math.abs(event.clientX - slideStart) > 5;
2829
+ slideDistance = Math.max(0, Math.min(width, event.clientX - slideStart));
2830
+ if (!reduced()) slide.style.setProperty("--mk-studio-drag", `${slideDistance}px`);
2831
+ });
2832
+ const release = (cancel = false) => {
2833
+ if (slideStart === null) return;
2834
+ const width = Math.max(0, (slide.parentElement?.clientWidth ?? 0) - slide.offsetWidth);
2835
+ suppressSlideClick = slideMoved;
2836
+ slideStart = null;
2837
+ slide.style.removeProperty("--mk-studio-drag");
2838
+ if (!cancel && width > 0 && slideDistance / width >= 0.7) open("contact");
2839
+ scope.timeout(() => {
2840
+ suppressSlideClick = false;
2841
+ }, 150);
2842
+ };
2843
+ scope.on(root.ownerDocument, "pointerup", () => release());
2844
+ scope.on(root.ownerDocument, "pointercancel", () => release(true));
2845
+ }
2846
+ const clocks = [...root.querySelectorAll("[data-mk-studio-timezone]")];
2847
+ const clockOriginals = clocks.map((el) => ({ el, text: el.textContent, style: el.getAttribute("style") }));
2848
+ const tick = () => clocks.forEach((el) => {
2849
+ try {
2850
+ el.textContent = new Intl.DateTimeFormat(void 0, { hour: "2-digit", minute: "2-digit", timeZone: el.dataset.mkStudioTimezone }).format(/* @__PURE__ */ new Date());
2851
+ } catch {
2852
+ }
2853
+ });
2854
+ if (clocks.length) {
2855
+ tick();
2856
+ const timer = setInterval(tick, 6e4);
2857
+ scope.add(() => clearInterval(timer));
2858
+ }
2859
+ scope.add(() => clockOriginals.forEach(({ el, text, style }) => {
2860
+ el.textContent = text;
2861
+ if (style === null) el.removeAttribute("style");
2862
+ else el.setAttribute("style", style);
2863
+ }));
2864
+ setView("menu");
2865
+ selectPage(0, false);
2866
+ return { open, close, toggle: () => state.open ? close() : open(), selectPage, get state() {
2867
+ return { ...state };
2868
+ }, destroy() {
2869
+ if (scope.disposed) return;
2870
+ const focused = root.contains(root.ownerDocument.activeElement);
2871
+ animation?.kill();
2872
+ panel.querySelectorAll("video").forEach((video) => video.pause());
2873
+ scope.dispose();
2874
+ if (focused) toggleButton.focus({ preventScroll: true });
2875
+ } };
2876
+ }
2877
+
2878
+ // src/components/trailer/engine.ts
2879
+ var time = (value) => {
2880
+ const seconds = Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
2881
+ return `${Math.floor(seconds / 60).toString().padStart(2, "0")}:${(seconds % 60).toString().padStart(2, "0")}`;
2882
+ };
2883
+ function createTrailer(root, options = {}) {
2884
+ const video = root?.querySelector("video");
2885
+ if (!root || !video || root.tagName !== "DIALOG") return inert({ open() {
2886
+ }, close() {
2887
+ }, toggle() {
2888
+ }, play: async () => false, pause() {
2889
+ }, seek() {
2890
+ }, setVolume() {
2891
+ }, isOpen: false });
2892
+ const scope = createScope();
2893
+ const get = (name) => root.querySelector(`[data-mk-trailer-${name}]`);
2894
+ const playButton = get("play");
2895
+ const muteButton = get("mute");
2896
+ const fullButton = get("fullscreen");
2897
+ const fullTarget = get("stage") ?? video;
2898
+ const captionsButton = get("captions");
2899
+ const seekInput = get("seek");
2900
+ const volumeInput = get("volume");
2901
+ const output = get("time");
2902
+ const status = get("status");
2903
+ const originalText = [output, status].filter((el) => !!el).map((el) => [el, el.textContent]);
2904
+ scope.add(() => originalText.forEach(([el, text]) => {
2905
+ el.textContent = text;
2906
+ }));
2907
+ scope.attr(root, "data-mk-trailer-ready", "");
2908
+ scope.attr(root, "data-mk-trailer-state", "paused");
2909
+ const controls = video.controls;
2910
+ if (playButton && muteButton && seekInput && (!video.querySelector("track") || captionsButton)) video.controls = false;
2911
+ scope.add(() => {
2912
+ video.controls = controls;
2913
+ });
2914
+ for (const input of [seekInput, volumeInput]) {
2915
+ if (!input) continue;
2916
+ const initialValue = input.value;
2917
+ scope.add(() => {
2918
+ input.value = initialValue;
2919
+ });
2920
+ scope.attr(input, "min", "0");
2921
+ scope.attr(input, "max", "1");
2922
+ scope.attr(input, "step", input === volumeInput ? ".01" : ".1");
2923
+ scope.attr(input, "aria-label", input.getAttribute("aria-label") ?? (input === volumeInput ? "Volumen" : "Posici\xF3n del video"));
2924
+ }
2925
+ if (status) scope.attr(status, "role", "status");
2926
+ const tell = (message) => {
2927
+ if (!scope.disposed && status) status.textContent = message;
2928
+ };
2929
+ const sync = () => {
2930
+ if (scope.disposed) return;
2931
+ const duration = Number.isFinite(video.duration) ? Math.max(0, video.duration) : 0;
2932
+ scope.attr(root, "data-mk-trailer-state", video.ended ? "ended" : video.paused ? "paused" : "playing");
2933
+ if (playButton) {
2934
+ scope.attr(playButton, "aria-label", video.paused || video.ended ? "Reproducir" : "Pausar");
2935
+ scope.attr(playButton, "aria-pressed", String(!video.paused && !video.ended));
2936
+ }
2937
+ if (muteButton) {
2938
+ scope.attr(muteButton, "aria-label", video.muted ? "Activar sonido" : "Silenciar");
2939
+ scope.attr(muteButton, "aria-pressed", String(video.muted));
2940
+ }
2941
+ if (seekInput) {
2942
+ scope.attr(seekInput, "max", String(duration || 1));
2943
+ scope.attr(seekInput, "disabled", duration ? null : "");
2944
+ scope.attr(seekInput, "aria-valuetext", `${time(video.currentTime)} de ${time(duration)}`);
2945
+ seekInput.value = String(Number.isFinite(video.currentTime) ? video.currentTime : 0);
2946
+ }
2947
+ if (volumeInput) volumeInput.value = String(video.muted ? 0 : video.volume);
2948
+ if (captionsButton) {
2949
+ scope.attr(captionsButton, "disabled", video.textTracks.length ? null : "");
2950
+ scope.attr(captionsButton, "aria-pressed", String(video.textTracks[0]?.mode === "showing"));
2951
+ }
2952
+ if (output) output.textContent = `${time(video.currentTime)} / ${time(duration)}`;
2953
+ };
2954
+ let playRequest = 0;
2955
+ let wantsPlayback = false;
2956
+ const pause = () => {
2957
+ if (!scope.disposed) {
2958
+ wantsPlayback = false;
2959
+ ++playRequest;
2960
+ video.pause();
2961
+ sync();
2962
+ }
2963
+ };
2964
+ const play = async () => {
2965
+ if (scope.disposed) return false;
2966
+ wantsPlayback = true;
2967
+ const request = ++playRequest;
2968
+ try {
2969
+ await video.play();
2970
+ if (scope.disposed || request !== playRequest) {
2971
+ if (scope.disposed || !wantsPlayback) video.pause();
2972
+ return false;
2973
+ }
2974
+ tell("");
2975
+ sync();
2976
+ return true;
2977
+ } catch {
2978
+ if (scope.disposed || request !== playRequest) return false;
2979
+ wantsPlayback = false;
2980
+ tell("No se pudo reproducir el video. Revisa la fuente y vuelve a intentarlo.");
2981
+ sync();
2982
+ return false;
2983
+ }
2984
+ };
2985
+ const seek = (seconds) => {
2986
+ if (scope.disposed || !Number.isFinite(seconds) || !Number.isFinite(video.duration) || video.duration <= 0) return;
2987
+ video.currentTime = Math.max(0, Math.min(video.duration, seconds));
2988
+ sync();
2989
+ };
2990
+ const setVolume = (volume) => {
2991
+ if (scope.disposed || !Number.isFinite(volume)) return;
2992
+ video.volume = Math.max(0, Math.min(1, volume));
2993
+ video.muted = volume <= 0;
2994
+ sync();
2995
+ };
2996
+ const exitFullscreen = () => {
2997
+ if (document.fullscreenElement !== fullTarget) return;
2998
+ void document.exitFullscreen?.().catch(() => {
2999
+ });
3000
+ };
3001
+ const dialog = createDialog(root, {
3002
+ triggers: options.triggers,
3003
+ closeOnBackdrop: options.closeOnBackdrop ?? true,
3004
+ drag: false,
3005
+ autoResize: false,
3006
+ animateContent: false,
3007
+ onOpen: () => {
3008
+ sync();
3009
+ if (options.autoplay) void play();
3010
+ options.onOpen?.();
3011
+ },
3012
+ onClose: () => {
3013
+ ++playRequest;
3014
+ pause();
3015
+ exitFullscreen();
3016
+ options.onClose?.();
3017
+ }
3018
+ });
3019
+ if (playButton) scope.on(playButton, "click", () => video.paused || video.ended ? void play() : pause());
3020
+ if (muteButton) scope.on(muteButton, "click", () => {
3021
+ video.muted = !video.muted;
3022
+ sync();
3023
+ });
3024
+ if (seekInput) scope.on(seekInput, "input", () => seek(Number(seekInput.value)));
3025
+ if (volumeInput) scope.on(volumeInput, "input", () => setVolume(Number(volumeInput.value)));
3026
+ if (captionsButton) scope.on(captionsButton, "click", () => {
3027
+ const track = video.textTracks[0];
3028
+ if (track) track.mode = track.mode === "showing" ? "hidden" : "showing";
3029
+ sync();
3030
+ });
3031
+ const fullscreen = async () => {
3032
+ if (scope.disposed) return;
3033
+ try {
3034
+ if (document.fullscreenElement === fullTarget) await document.exitFullscreen?.();
3035
+ else if (fullTarget.requestFullscreen) {
3036
+ await fullTarget.requestFullscreen();
3037
+ if (scope.disposed || !dialog.isOpen) exitFullscreen();
3038
+ } else tell("La pantalla completa no est\xE1 disponible en este navegador.");
3039
+ } catch {
3040
+ tell("No se pudo abrir la pantalla completa.");
3041
+ }
3042
+ };
3043
+ if (fullButton) {
3044
+ scope.attr(fullButton, "aria-label", "Pantalla completa");
3045
+ scope.on(fullButton, "click", () => {
3046
+ void fullscreen();
3047
+ });
3048
+ scope.on(document, "fullscreenchange", () => {
3049
+ scope.attr(fullButton, "aria-label", document.fullscreenElement === fullTarget ? "Salir de pantalla completa" : "Pantalla completa");
3050
+ });
3051
+ }
3052
+ for (const event of ["loadedmetadata", "durationchange", "timeupdate", "play", "pause", "ended", "volumechange"]) scope.on(video, event, sync);
3053
+ scope.on(video, "error", () => {
3054
+ tell("El video no est\xE1 disponible.");
3055
+ scope.attr(root, "data-mk-trailer-state", "error");
3056
+ });
3057
+ scope.on(root, "keydown", (event) => {
3058
+ if (!dialog.isOpen || event.target instanceof Element && event.target.closest("button, input, select, textarea, a, [contenteditable]")) return;
3059
+ if (event.key === " " || event.key.toLowerCase() === "k") {
3060
+ event.preventDefault();
3061
+ video.paused ? void play() : pause();
3062
+ } else if (event.key === "ArrowRight" || event.key === "ArrowLeft") {
3063
+ event.preventDefault();
3064
+ seek(video.currentTime + (event.key === "ArrowRight" ? 5 : -5));
3065
+ } else if (event.key.toLowerCase() === "m") {
3066
+ video.muted = !video.muted;
3067
+ sync();
3068
+ }
3069
+ });
3070
+ sync();
3071
+ return {
3072
+ open: (origin) => {
3073
+ if (!scope.disposed) dialog.open(origin);
3074
+ },
3075
+ close: () => {
3076
+ if (!scope.disposed) dialog.close();
3077
+ },
3078
+ toggle: (origin) => {
3079
+ if (!scope.disposed) dialog.toggle(origin);
3080
+ },
3081
+ play,
3082
+ pause,
3083
+ seek,
3084
+ setVolume,
3085
+ get isOpen() {
3086
+ return dialog.isOpen;
3087
+ },
3088
+ destroy() {
3089
+ if (scope.disposed) return;
3090
+ wantsPlayback = false;
3091
+ ++playRequest;
3092
+ video.pause();
3093
+ exitFullscreen();
3094
+ dialog.destroy();
3095
+ scope.dispose();
3096
+ }
3097
+ };
3098
+ }
3099
+
3100
+ // src/core/dates.ts
3101
+ function toDate(input, fallback = /* @__PURE__ */ new Date()) {
3102
+ if (input instanceof Date) return Number.isNaN(input.getTime()) ? startOfDay(fallback) : startOfDay(input);
3103
+ if (typeof input === "string") {
3104
+ const day = /^(\d{4})-(\d{2})-(\d{2})$/.exec(input.trim());
3105
+ if (day) return new Date(Number(day[1]), Number(day[2]) - 1, Number(day[3]));
3106
+ }
3107
+ if (typeof input === "string" || typeof input === "number") {
3108
+ const parsed = new Date(input);
3109
+ if (!Number.isNaN(parsed.getTime())) return startOfDay(parsed);
3110
+ }
3111
+ return startOfDay(fallback);
3112
+ }
3113
+ function toDateTime(input) {
3114
+ if (input instanceof Date) return Number.isNaN(input.getTime()) ? null : input;
3115
+ if (typeof input === "string" && /^\d{4}-\d{2}-\d{2}$/.test(input.trim())) return toDate(input);
3116
+ const parsed = new Date(input);
3117
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
3118
+ }
3119
+ var startOfDay = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate());
3120
+ var addDays = (date, days) => new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);
3121
+ function addMonths(date, months) {
3122
+ const target = new Date(date.getFullYear(), date.getMonth() + months, 1);
3123
+ const last = new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate();
3124
+ return new Date(target.getFullYear(), target.getMonth(), Math.min(date.getDate(), last));
3125
+ }
3126
+ var startOfMonth = (date) => new Date(date.getFullYear(), date.getMonth(), 1);
3127
+ function startOfWeek(date, firstDay = 0) {
3128
+ const shift = (date.getDay() - firstDay + 7) % 7;
3129
+ return addDays(startOfDay(date), -shift);
3130
+ }
3131
+ var sameDay = (a, b) => !!a && !!b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
3132
+ var sameMonth = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
3133
+ var pad = (n) => String(n).padStart(2, "0");
3134
+ var dayKey = (date) => `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
3135
+ function monthWeeks(date, firstDay = 0) {
3136
+ const first = startOfMonth(date);
3137
+ const last = new Date(date.getFullYear(), date.getMonth() + 1, 0);
3138
+ const weeks = [];
3139
+ for (let start = startOfWeek(first, firstDay); start <= last; start = addDays(start, 7)) {
3140
+ weeks.push(Array.from({ length: 7 }, (_, i) => addDays(start, i)));
3141
+ }
3142
+ return weeks;
3143
+ }
3144
+ var weekDays = (date, firstDay = 0) => Array.from({ length: 7 }, (_, i) => addDays(startOfWeek(date, firstDay), i));
3145
+ function weekdayNames(locale, firstDay = 0, width = "short") {
3146
+ const format = safeFormat(locale, { weekday: width });
3147
+ return Array.from({ length: 7 }, (_, i) => format.format(new Date(2024, 8, 1 + (firstDay + i) % 7)));
3148
+ }
3149
+ function safeFormat(locale, options) {
3150
+ try {
3151
+ return new Intl.DateTimeFormat(locale, options);
3152
+ } catch {
3153
+ return new Intl.DateTimeFormat(void 0, options);
3154
+ }
3155
+ }
3156
+ var capitalize = (text) => text.charAt(0).toLocaleUpperCase() + text.slice(1);
3157
+ function fromJson(value) {
3158
+ if (typeof value !== "string") return value;
3159
+ try {
3160
+ return JSON.parse(value);
3161
+ } catch {
3162
+ return void 0;
3163
+ }
3164
+ }
3165
+ var clampFirstDay = (n) => Number.isInteger(n) && n >= 0 && n <= 6 ? n : 0;
3166
+
3167
+ // src/components/calendar/engine.ts
3168
+ var SLIDE = 30;
3169
+ var SLIDE_OUT = 0.12;
3170
+ var SLIDE_GAP = 0.1;
3171
+ var SLIDE_DURATION = 0.25;
3172
+ var CELL_STAGGER = 5e-3;
3173
+ var EVENT_STAGGER = 0.02;
3174
+ function createCalendar(root, options = {}) {
3175
+ const grid = root?.querySelector("[data-mk-calendar-grid]");
3176
+ if (!root || !grid) {
3177
+ const now = toDate(null);
3178
+ return inert({
3179
+ next() {
3180
+ },
3181
+ prev() {
3182
+ },
3183
+ goToday() {
3184
+ },
3185
+ setDate() {
3186
+ },
3187
+ setView() {
3188
+ },
3189
+ setEvents() {
3190
+ },
3191
+ select() {
3192
+ },
3193
+ date: now,
3194
+ view: "month",
3195
+ selected: null,
3196
+ range: { start: now, end: now, view: "month" }
3197
+ });
3198
+ }
3199
+ registerMotion();
3200
+ const scope = createScope();
3201
+ const ctx = gsap.context(() => {
3202
+ });
3203
+ scope.add(() => ctx.revert());
3204
+ const locale = options.locale ?? "es";
3205
+ const firstDay = clampFirstDay(options.firstDay);
3206
+ const maxEvents = Number.isFinite(options.maxEvents) ? Math.max(0, Math.floor(options.maxEvents)) : 3;
3207
+ const labels = {
3208
+ more: options.labels?.more ?? ((n) => `+${n} m\xE1s`),
3209
+ events: options.labels?.events ?? ((n) => n === 1 ? "1 evento" : `${n} eventos`),
3210
+ status: { pending: "pendiente", done: "completado", cancelled: "cancelado", ...options.labels?.status }
3211
+ };
3212
+ let date = toDate(options.date);
3213
+ let view = options.view === "week" ? "week" : "month";
3214
+ let selected = options.selected ? toDate(options.selected) : null;
3215
+ let focusDay = selected ?? date;
3216
+ let events = [];
3217
+ let byDay = /* @__PURE__ */ new Map();
3218
+ let first = true;
3219
+ const today = () => toDate(options.today ?? null);
3220
+ const title = root.querySelector("[data-mk-calendar-title]");
3221
+ const prevButton = root.querySelector("[data-mk-calendar-prev]");
3222
+ const nextButton = root.querySelector("[data-mk-calendar-next]");
3223
+ const todayButton = root.querySelector("[data-mk-calendar-today]");
3224
+ const viewButtons = [...root.querySelectorAll("[data-mk-calendar-view]")];
3225
+ const originalGrid = [...grid.childNodes];
3226
+ const originalTitle = title ? [...title.childNodes] : [];
3227
+ scope.add(() => {
3228
+ grid.replaceChildren(...originalGrid);
3229
+ title?.replaceChildren(...originalTitle);
3230
+ });
3231
+ scope.attr(root, "data-mk-ready", "");
3232
+ scope.attr(grid, "role", "grid");
3233
+ if (title) {
3234
+ if (!title.id) scope.attr(title, "id", `mk-calendar-${Math.random().toString(36).slice(2, 8)}`);
3235
+ scope.attr(grid, "aria-labelledby", title.id);
3236
+ }
3237
+ const monthTitle = safeFormat(locale, { month: "long", year: "numeric" });
3238
+ const rangeTitle = safeFormat(locale, { day: "numeric", month: "short", year: "numeric" });
3239
+ const fullDay = safeFormat(locale, { weekday: "long", day: "numeric", month: "long", year: "numeric" });
3240
+ const timeFormat = safeFormat(locale, { hour: "numeric", minute: "2-digit" });
3241
+ const index = (list2) => {
3242
+ events = Array.isArray(list2) ? list2.filter((e) => e && toDateTime(e.start)) : [];
3243
+ byDay = /* @__PURE__ */ new Map();
3244
+ const sorted = [...events].sort((a, b) => toDateTime(a.start).getTime() - toDateTime(b.start).getTime());
3245
+ for (const event of sorted) {
3246
+ const start = toDate(toDateTime(event.start));
3247
+ const endTime = event.end ? toDateTime(event.end) : null;
3248
+ const end = endTime && endTime > start ? toDate(endTime) : start;
3249
+ for (let day = start, n = 0; day <= end && n < 62; day = addDays(day, 1), n++) {
3250
+ const key = dayKey(day);
3251
+ byDay.set(key, [...byDay.get(key) ?? [], event]);
3252
+ }
3253
+ }
3254
+ };
3255
+ index(fromJson(options.events) ?? []);
3256
+ const days = () => view === "week" ? [weekDays(date, firstDay)] : monthWeeks(date, firstDay);
3257
+ const range = () => {
3258
+ const weeks = days();
3259
+ return { start: weeks[0][0], end: weeks[weeks.length - 1][6], view };
3260
+ };
3261
+ const inRange = (day) => {
3262
+ const r = range();
3263
+ return day >= r.start && day <= r.end;
3264
+ };
3265
+ const header = () => {
3266
+ const row = document.createElement("div");
3267
+ row.className = "mk-calendar__head";
3268
+ row.setAttribute("role", "row");
3269
+ const long = weekdayNames(locale, firstDay, "short");
3270
+ const narrow = weekdayNames(locale, firstDay, "narrow");
3271
+ long.forEach((name, i) => {
3272
+ const cell = document.createElement("div");
3273
+ cell.className = "mk-calendar__weekday";
3274
+ cell.setAttribute("role", "columnheader");
3275
+ cell.innerHTML = '<span class="mk-calendar__weekday-long"></span><span class="mk-calendar__weekday-narrow" aria-hidden="true"></span>';
3276
+ cell.firstElementChild.textContent = name;
3277
+ cell.lastElementChild.textContent = narrow[i];
3278
+ row.append(cell);
3279
+ });
3280
+ return row;
3281
+ };
3282
+ const chip = (event) => {
3283
+ const button = document.createElement("button");
3284
+ button.type = "button";
3285
+ button.className = "mk-calendar__event";
3286
+ button.dataset.mkEvent = String(event.id);
3287
+ const status = event.status ?? "pending";
3288
+ button.dataset.state = status;
3289
+ if (event.color) button.style.setProperty("--mk-calendar-event-color", event.color);
3290
+ const start = toDateTime(event.start);
3291
+ const time2 = event.allDay ? "" : timeFormat.format(start);
3292
+ button.innerHTML = '<span class="mk-calendar__status" aria-hidden="true"></span><span class="mk-calendar__event-title"></span><span class="mk-calendar__event-time"></span>';
3293
+ button.children[1].textContent = event.title;
3294
+ button.children[2].textContent = time2;
3295
+ button.setAttribute("aria-label", [event.title, time2, labels.status[status]].filter(Boolean).join(", "));
3296
+ return button;
3297
+ };
3298
+ const body = () => {
3299
+ const wrap = document.createElement("div");
3300
+ wrap.className = "mk-calendar__body";
3301
+ wrap.dataset.view = view;
3302
+ wrap.setAttribute("role", "rowgroup");
3303
+ const now = today();
3304
+ const focusKey = dayKey(focusDay);
3305
+ for (const week of days()) {
3306
+ const row = document.createElement("div");
3307
+ row.className = "mk-calendar__week";
3308
+ row.setAttribute("role", "row");
3309
+ for (const day of week) {
3310
+ const key = dayKey(day);
3311
+ const cell = document.createElement("div");
3312
+ cell.className = "mk-calendar__day";
3313
+ cell.setAttribute("role", "gridcell");
3314
+ cell.dataset.mkDate = key;
3315
+ if (view === "month" && !sameMonth(day, date)) cell.dataset.outside = "";
3316
+ if (sameDay(day, now)) cell.dataset.today = "";
3317
+ const isSelected = sameDay(day, selected);
3318
+ cell.setAttribute("aria-selected", String(isSelected));
3319
+ const list2 = byDay.get(key) ?? [];
3320
+ const number = document.createElement("button");
3321
+ number.type = "button";
3322
+ number.className = "mk-calendar__number";
3323
+ number.dataset.mkDay = key;
3324
+ number.textContent = view === "week" ? `${day.getDate()}` : String(day.getDate());
3325
+ number.tabIndex = key === focusKey ? 0 : -1;
3326
+ number.setAttribute("aria-label", `${capitalize(fullDay.format(day))}${list2.length ? `, ${labels.events(list2.length)}` : ""}`);
3327
+ if (sameDay(day, now)) number.setAttribute("aria-current", "date");
3328
+ cell.append(number);
3329
+ if (list2.length) {
3330
+ const box = document.createElement("div");
3331
+ box.className = "mk-calendar__events";
3332
+ const shown2 = view === "week" ? list2 : list2.slice(0, maxEvents);
3333
+ for (const event of shown2) box.append(chip(event));
3334
+ if (shown2.length < list2.length) {
3335
+ const more = document.createElement("button");
3336
+ more.type = "button";
3337
+ more.className = "mk-calendar__more";
3338
+ more.dataset.mkMore = key;
3339
+ more.textContent = labels.more(list2.length - shown2.length);
3340
+ box.append(more);
3341
+ }
3342
+ cell.append(box);
3343
+ }
3344
+ row.append(cell);
3345
+ }
3346
+ wrap.append(row);
3347
+ }
3348
+ return wrap;
3349
+ };
3350
+ let current2 = null;
3351
+ const leaving = /* @__PURE__ */ new Set();
3352
+ scope.add(() => leaving.forEach((el) => el.remove()));
3353
+ const syncChrome = () => {
3354
+ if (title) {
3355
+ const r = range();
3356
+ let text = capitalize(monthTitle.format(date));
3357
+ if (view === "week") {
3358
+ const format = rangeTitle;
3359
+ text = format.formatRange ? format.formatRange(r.start, r.end) : `${rangeTitle.format(r.start)} \u2013 ${rangeTitle.format(r.end)}`;
3360
+ }
3361
+ title.textContent = text;
3362
+ }
3363
+ for (const button of viewButtons) {
3364
+ scope.attr(button, "aria-pressed", String(button.dataset.mkCalendarView === view));
3365
+ }
3366
+ };
3367
+ const render = (direction) => {
3368
+ const next = body();
3369
+ const motion = !reduced();
3370
+ if (!current2) {
3371
+ grid.replaceChildren(header(), next);
3372
+ } else if (motion && direction !== 0) {
3373
+ const old = current2;
3374
+ old.style.top = `${old.offsetTop}px`;
3375
+ old.classList.add("mk-calendar__body--leaving");
3376
+ old.setAttribute("aria-hidden", "true");
3377
+ old.querySelectorAll("button").forEach((b) => b.tabIndex = -1);
3378
+ leaving.add(old);
3379
+ grid.append(next);
3380
+ ctx.add(() => {
3381
+ gsap.to(old, { x: -SLIDE * direction, opacity: 0, duration: SLIDE_OUT, ease: "power1.in", onComplete: () => {
3382
+ old.remove();
3383
+ leaving.delete(old);
3384
+ } });
3385
+ gsap.fromTo(next, { x: SLIDE * direction, opacity: 0 }, { x: 0, opacity: 1, duration: SLIDE_DURATION, delay: SLIDE_GAP, ease: "power2.out", clearProps: "transform,opacity" });
3386
+ });
3387
+ } else {
3388
+ current2.replaceWith(next);
3389
+ }
3390
+ current2 = next;
3391
+ syncChrome();
3392
+ if (motion) {
3393
+ ctx.add(() => {
3394
+ if (first) flowIn(next, { target: ".mk-calendar__day", stagger: CELL_STAGGER });
3395
+ flowIn(next, { target: ".mk-calendar__event, .mk-calendar__more", stagger: EVENT_STAGGER, delay: first ? 0.1 : direction ? SLIDE_GAP + SLIDE_DURATION * 0.5 : 0 });
3396
+ });
3397
+ }
3398
+ first = false;
3399
+ };
3400
+ const focusButton = () => grid.querySelector(`.mk-calendar__body:not(.mk-calendar__body--leaving) [data-mk-day="${dayKey(focusDay)}"]`);
3401
+ const navigate = (to, focus = false) => {
3402
+ if (scope.disposed) return;
3403
+ const from = date;
3404
+ const moved = view === "week" ? !sameDay(startOfWeek(to, firstDay), startOfWeek(from, firstDay)) : !sameMonth(to, from);
3405
+ date = to;
3406
+ focusDay = to;
3407
+ if (moved) {
3408
+ render(to > from ? 1 : -1);
3409
+ const r = range();
3410
+ options.onNavigate?.(r);
3411
+ root.dispatchEvent(new CustomEvent("mk:navigate", { bubbles: true, detail: r }));
3412
+ } else {
3413
+ grid.querySelectorAll("[data-mk-day]").forEach((b) => b.tabIndex = b.dataset.mkDay === dayKey(to) ? 0 : -1);
3414
+ }
3415
+ if (focus) focusButton()?.focus();
3416
+ };
3417
+ const select = (value, notify = true) => {
3418
+ if (scope.disposed) return;
3419
+ selected = value === null ? null : toDate(value);
3420
+ grid.querySelectorAll(".mk-calendar__day").forEach((cell) => cell.setAttribute("aria-selected", String(!!selected && cell.dataset.mkDate === dayKey(selected))));
3421
+ if (selected && notify) {
3422
+ options.onSelect?.(selected);
3423
+ root.dispatchEvent(new CustomEvent("mk:select", { bubbles: true, detail: { date: selected, key: dayKey(selected) } }));
3424
+ }
3425
+ };
3426
+ scope.on(root, "click", (e) => {
3427
+ const target = e.target.closest("button");
3428
+ if (!target || !root.contains(target) || target.disabled) return;
3429
+ if (target === prevButton) navigate(view === "week" ? addDays(date, -7) : addMonths(date, -1));
3430
+ else if (target === nextButton) navigate(view === "week" ? addDays(date, 7) : addMonths(date, 1));
3431
+ else if (target === todayButton) navigate(today(), true);
3432
+ else if (target.dataset.mkCalendarView) setView(target.dataset.mkCalendarView);
3433
+ else if (target.dataset.mkEvent !== void 0) {
3434
+ const event = events.find((ev) => String(ev.id) === target.dataset.mkEvent);
3435
+ if (event) {
3436
+ options.onEventClick?.(event);
3437
+ root.dispatchEvent(new CustomEvent("mk:event", { bubbles: true, detail: { event } }));
3438
+ }
3439
+ } else if (target.dataset.mkDay || target.dataset.mkMore) {
3440
+ const day = toDate(target.dataset.mkDay ?? target.dataset.mkMore);
3441
+ focusDay = day;
3442
+ grid.querySelectorAll("[data-mk-day]").forEach((b) => b.tabIndex = b.dataset.mkDay === dayKey(day) ? 0 : -1);
3443
+ select(day);
3444
+ }
3445
+ });
3446
+ scope.on(grid, "keydown", (e) => {
3447
+ const event = e;
3448
+ const target = event.target;
3449
+ if (!target.dataset?.mkDay) return;
3450
+ const day = toDate(target.dataset.mkDay);
3451
+ const map = {
3452
+ ArrowLeft: () => addDays(day, -1),
3453
+ ArrowRight: () => addDays(day, 1),
3454
+ ArrowUp: () => addDays(day, -7),
3455
+ ArrowDown: () => addDays(day, 7),
3456
+ Home: () => startOfWeek(day, firstDay),
3457
+ End: () => addDays(startOfWeek(day, firstDay), 6),
3458
+ PageUp: () => addMonths(day, event.shiftKey ? -12 : -1),
3459
+ PageDown: () => addMonths(day, event.shiftKey ? 12 : 1)
3460
+ };
3461
+ const to = map[event.key]?.();
3462
+ if (!to) return;
3463
+ event.preventDefault();
3464
+ if (!event.key.startsWith("Page") && inRange(to)) {
3465
+ focusDay = to;
3466
+ grid.querySelectorAll("[data-mk-day]").forEach((b) => b.tabIndex = b.dataset.mkDay === dayKey(to) ? 0 : -1);
3467
+ focusButton()?.focus();
3468
+ } else navigate(to, true);
3469
+ });
3470
+ const setView = (next) => {
3471
+ if (scope.disposed || next !== "month" && next !== "week" || next === view) return;
3472
+ view = next;
3473
+ date = focusDay;
3474
+ render(0);
3475
+ const r = range();
3476
+ options.onNavigate?.(r);
3477
+ root.dispatchEvent(new CustomEvent("mk:navigate", { bubbles: true, detail: r }));
3478
+ };
3479
+ render(0);
3480
+ return {
3481
+ next: () => navigate(view === "week" ? addDays(date, 7) : addMonths(date, 1)),
3482
+ prev: () => navigate(view === "week" ? addDays(date, -7) : addMonths(date, -1)),
3483
+ goToday: () => navigate(today()),
3484
+ setDate: (value) => navigate(toDate(value, date)),
3485
+ setView,
3486
+ setEvents(list2) {
3487
+ if (scope.disposed) return;
3488
+ const hadFocus = grid.contains(document.activeElement);
3489
+ index(fromJson(list2) ?? []);
3490
+ const fresh = body();
3491
+ current2?.replaceWith(fresh);
3492
+ current2 = fresh;
3493
+ if (hadFocus) focusButton()?.focus();
3494
+ },
3495
+ select,
3496
+ get date() {
3497
+ return date;
3498
+ },
3499
+ get view() {
3500
+ return view;
3501
+ },
3502
+ get selected() {
3503
+ return selected;
3504
+ },
3505
+ get range() {
3506
+ return range();
3507
+ },
3508
+ destroy: () => scope.dispose()
3509
+ };
3510
+ }
3511
+
3512
+ // src/components/slot-picker/engine.ts
3513
+ var SLIDE2 = 30;
3514
+ var SLIDE_DURATION2 = 0.25;
3515
+ var slotEaseReady = false;
3516
+ function createSlotPicker(root, options = {}) {
3517
+ const daysHost = root?.querySelector("[data-mk-slot-days]");
3518
+ const timesHost = root?.querySelector("[data-mk-slot-times]");
3519
+ if (!root || !daysHost || !timesHost) {
3520
+ return inert({ selectDate() {
3521
+ }, selectTime() {
3522
+ }, setSlots() {
3523
+ }, date: null, time: null, value: null });
3524
+ }
3525
+ registerMotion();
3526
+ if (!slotEaseReady && typeof window !== "undefined") {
3527
+ CustomEase.create("mk-slot-in", ".38,.49,0,1.1");
3528
+ slotEaseReady = true;
3529
+ }
3530
+ const scope = createScope();
3531
+ const ctx = gsap.context(() => {
3532
+ });
3533
+ scope.add(() => ctx.revert());
3534
+ const locale = options.locale ?? "es";
3535
+ const firstDay = clampFirstDay(options.firstDay);
3536
+ const labels = {
3537
+ placeholder: options.labels?.placeholder ?? "Elige un d\xEDa para ver los horarios.",
3538
+ empty: options.labels?.empty ?? "No hay horarios este d\xEDa.",
3539
+ loading: options.labels?.loading ?? "Cargando horarios\u2026",
3540
+ heading: options.labels?.heading ?? ((d) => capitalize(safeFormat(locale, { weekday: "long", day: "numeric", month: "long" }).format(d)))
3541
+ };
3542
+ const min = options.min !== void 0 ? toDate(options.min) : null;
3543
+ const max = options.max !== void 0 ? toDate(options.max) : null;
3544
+ const closedList = fromJson(options.closedDays);
3545
+ const closed = new Set((Array.isArray(closedList) ? closedList : []).filter((n) => Number.isInteger(n)));
3546
+ let slots = fromJson(options.slots) ?? [];
3547
+ const initial = (() => {
3548
+ const v = options.value;
3549
+ if (typeof v === "string") {
3550
+ const match = /^(\d{4}-\d{2}-\d{2})(?:T(\d{1,2}:\d{2}))?/.exec(v);
3551
+ return match ? { date: toDate(match[1]), time: match[2] ?? null } : null;
3552
+ }
3553
+ return v ? { date: toDate(v.date), time: v.time ?? null } : null;
3554
+ })();
3555
+ let month = initial?.date ?? toDate(options.date);
3556
+ let date = initial?.date ?? (options.date !== void 0 ? toDate(options.date) : null);
3557
+ let time2 = initial?.time ?? null;
3558
+ let focusDay = date ?? month;
3559
+ let times = [];
3560
+ let request = 0;
3561
+ const title = root.querySelector("[data-mk-slot-title]");
3562
+ const heading = root.querySelector("[data-mk-slot-heading]");
3563
+ const prev = root.querySelector("[data-mk-slot-prev]");
3564
+ const next = root.querySelector("[data-mk-slot-next]");
3565
+ const output = root.querySelector("[data-mk-slot-value]");
3566
+ const originals = [daysHost, timesHost, title, heading].filter(Boolean).map((el) => [el, [...el.childNodes]]);
3567
+ scope.add(() => originals.forEach(([el, nodes]) => el.replaceChildren(...nodes)));
3568
+ if (output) {
3569
+ const before = output.value;
3570
+ scope.add(() => {
3571
+ output.value = before;
3572
+ });
3573
+ }
3574
+ scope.attr(root, "data-mk-ready", "");
3575
+ scope.attr(daysHost, "role", "grid");
3576
+ scope.attr(timesHost, "role", "radiogroup");
3577
+ if (heading) {
3578
+ if (!heading.id) scope.attr(heading, "id", `mk-slot-${Math.random().toString(36).slice(2, 8)}`);
3579
+ scope.attr(timesHost, "aria-labelledby", heading.id);
3580
+ }
3581
+ if (title) {
3582
+ if (!title.id) scope.attr(title, "id", `mk-slot-month-${Math.random().toString(36).slice(2, 8)}`);
3583
+ scope.attr(daysHost, "aria-labelledby", title.id);
3584
+ }
3585
+ const monthTitle = safeFormat(locale, { month: "long", year: "numeric" });
3586
+ const fullDay = safeFormat(locale, { weekday: "long", day: "numeric", month: "long", year: "numeric" });
3587
+ const disabled = (d) => min && d < min || max && d > max || closed.has(d.getDay()) || !!options.isDisabled?.(d);
3588
+ let daysBody = null;
3589
+ const leaving = /* @__PURE__ */ new Set();
3590
+ scope.add(() => leaving.forEach((el) => el.remove()));
3591
+ const buildDays = () => {
3592
+ const wrap = document.createElement("div");
3593
+ wrap.className = "mk-slot-picker__days";
3594
+ wrap.setAttribute("role", "rowgroup");
3595
+ const head = document.createElement("div");
3596
+ head.className = "mk-slot-picker__weekdays";
3597
+ head.setAttribute("role", "row");
3598
+ for (const name of weekdayNames(locale, firstDay, "short")) {
3599
+ const cell = document.createElement("span");
3600
+ cell.setAttribute("role", "columnheader");
3601
+ cell.textContent = name.slice(0, 2);
3602
+ head.append(cell);
3603
+ }
3604
+ wrap.append(head);
3605
+ const focusKey = dayKey(focusDay);
3606
+ for (const week of monthWeeks(month, firstDay)) {
3607
+ const row = document.createElement("div");
3608
+ row.className = "mk-slot-picker__week";
3609
+ row.setAttribute("role", "row");
3610
+ for (const d of week) {
3611
+ const cell = document.createElement("span");
3612
+ cell.setAttribute("role", "gridcell");
3613
+ if (!sameMonth(d, month)) {
3614
+ row.append(cell);
3615
+ continue;
3616
+ }
3617
+ const button = document.createElement("button");
3618
+ button.type = "button";
3619
+ button.className = "mk-slot-picker__day";
3620
+ button.dataset.mkSlotDay = dayKey(d);
3621
+ button.textContent = String(d.getDate());
3622
+ button.tabIndex = dayKey(d) === focusKey ? 0 : -1;
3623
+ button.setAttribute("aria-label", capitalize(fullDay.format(d)));
3624
+ if (disabled(d)) button.disabled = true;
3625
+ if (sameDay(d, /* @__PURE__ */ new Date())) button.setAttribute("aria-current", "date");
3626
+ cell.setAttribute("aria-selected", String(sameDay(d, date)));
3627
+ cell.append(button);
3628
+ row.append(cell);
3629
+ }
3630
+ wrap.append(row);
3631
+ }
3632
+ return wrap;
3633
+ };
3634
+ const renderDays = (direction) => {
3635
+ const fresh = buildDays();
3636
+ if (title) title.textContent = capitalize(monthTitle.format(month));
3637
+ if (prev) scope.attr(prev, "disabled", min && new Date(month.getFullYear(), month.getMonth(), 0) < min ? "" : null);
3638
+ if (next) scope.attr(next, "disabled", max && new Date(month.getFullYear(), month.getMonth() + 1, 1) > max ? "" : null);
3639
+ if (daysBody && direction && !reduced()) {
3640
+ const old = daysBody;
3641
+ old.style.top = `${old.offsetTop}px`;
3642
+ old.classList.add("mk-slot-picker__leaving");
3643
+ old.setAttribute("aria-hidden", "true");
3644
+ leaving.add(old);
3645
+ daysHost.append(fresh);
3646
+ ctx.add(() => {
3647
+ gsap.to(old, { x: -SLIDE2 * direction, opacity: 0, duration: SLIDE_DURATION2, ease: "power1.out", onComplete: () => {
3648
+ old.remove();
3649
+ leaving.delete(old);
3650
+ } });
3651
+ gsap.fromTo(fresh, { x: SLIDE2 * direction, opacity: 0 }, { x: 0, opacity: 1, duration: SLIDE_DURATION2, ease: "power1.out", clearProps: "transform,opacity" });
3652
+ });
3653
+ } else if (daysBody) daysBody.replaceWith(fresh);
3654
+ else daysHost.replaceChildren(fresh);
3655
+ daysBody = fresh;
3656
+ };
3657
+ const dayButton = (d) => daysHost.querySelector(`.mk-slot-picker__days:not(.mk-slot-picker__leaving) [data-mk-slot-day="${dayKey(d)}"]`);
3658
+ const moveFocus = (to, focus) => {
3659
+ focusDay = to;
3660
+ if (!sameMonth(to, month)) {
3661
+ const direction = to > month ? 1 : -1;
3662
+ month = to;
3663
+ renderDays(direction);
3664
+ } else daysHost.querySelectorAll("[data-mk-slot-day]").forEach((b) => b.tabIndex = b.dataset.mkSlotDay === dayKey(to) ? 0 : -1);
3665
+ if (focus) dayButton(to)?.focus();
3666
+ };
3667
+ let timesBody = null;
3668
+ let firstList = true;
3669
+ const buildTimes = (state) => {
3670
+ const wrap = document.createElement("div");
3671
+ wrap.className = "mk-slot-picker__list";
3672
+ if (state !== "ready" || !times.length) {
3673
+ const note = document.createElement("p");
3674
+ note.className = "mk-slot-picker__note";
3675
+ note.textContent = state === "placeholder" ? labels.placeholder : state === "loading" ? labels.loading : labels.empty;
3676
+ wrap.append(note);
3677
+ return wrap;
3678
+ }
3679
+ const focusTime = time2 && times.includes(time2) ? time2 : times[0];
3680
+ for (const t of times) {
3681
+ const button = document.createElement("button");
3682
+ button.type = "button";
3683
+ button.className = "mk-slot-picker__time";
3684
+ button.setAttribute("role", "radio");
3685
+ button.dataset.mkSlotTime = t;
3686
+ button.textContent = t;
3687
+ button.setAttribute("aria-checked", String(t === time2));
3688
+ button.tabIndex = t === focusTime ? 0 : -1;
3689
+ wrap.append(button);
3690
+ }
3691
+ return wrap;
3692
+ };
3693
+ const renderTimes = (state, direction) => {
3694
+ const fresh = buildTimes(state);
3695
+ scope.attr(timesHost, "aria-busy", state === "loading" ? "true" : null);
3696
+ const motion = !reduced();
3697
+ if (timesBody && direction && motion) {
3698
+ const old = timesBody;
3699
+ old.style.top = `${old.offsetTop}px`;
3700
+ old.classList.add("mk-slot-picker__leaving");
3701
+ old.setAttribute("aria-hidden", "true");
3702
+ old.querySelectorAll("button").forEach((b) => b.tabIndex = -1);
3703
+ leaving.add(old);
3704
+ timesHost.append(fresh);
3705
+ ctx.add(() => {
3706
+ gsap.to(old, { x: -SLIDE2 * direction, opacity: 0, duration: SLIDE_DURATION2, ease: "power1.out", onComplete: () => {
3707
+ old.remove();
3708
+ leaving.delete(old);
3709
+ } });
3710
+ gsap.fromTo(fresh, { x: SLIDE2 * direction, opacity: 0 }, { x: 0, opacity: 1, duration: SLIDE_DURATION2, ease: "power1.out", clearProps: "transform,opacity" });
3711
+ });
3712
+ } else if (timesBody) timesBody.replaceWith(fresh);
3713
+ else timesHost.replaceChildren(fresh);
3714
+ timesBody = fresh;
3715
+ if (state === "ready" && times.length && motion && firstList) {
3716
+ firstList = false;
3717
+ ctx.add(() => flowIn(fresh, { target: ".mk-slot-picker__time", style: 2, startScale: 0.7, blur: 32, duration: 0.3, stagger: 0.02, ease: "mk-slot-in" }));
3718
+ }
3719
+ };
3720
+ const resolve = (d) => {
3721
+ const source = slots;
3722
+ if (Array.isArray(source)) return source;
3723
+ if (typeof source === "function") return source(d);
3724
+ return source?.[dayKey(d)] ?? [];
3725
+ };
3726
+ const clean = (list2) => Array.isArray(list2) ? [...new Set(list2.filter((t) => typeof t === "string" && /^\d{1,2}:\d{2}$/.test(t)))] : [];
3727
+ const load = (direction) => {
3728
+ if (!date) {
3729
+ times = [];
3730
+ renderTimes("placeholder", 0);
3731
+ return;
3732
+ }
3733
+ const mine = ++request;
3734
+ let result;
3735
+ try {
3736
+ result = resolve(date);
3737
+ } catch {
3738
+ result = [];
3739
+ }
3740
+ if (result && typeof result.then === "function") {
3741
+ renderTimes("loading", direction);
3742
+ result.then(
3743
+ (list2) => {
3744
+ if (mine === request && !scope.disposed) {
3745
+ times = clean(list2);
3746
+ renderTimes("ready", 0);
3747
+ }
3748
+ },
3749
+ () => {
3750
+ if (mine === request && !scope.disposed) {
3751
+ times = [];
3752
+ renderTimes("ready", 0);
3753
+ }
3754
+ }
3755
+ );
3756
+ } else {
3757
+ times = clean(result);
3758
+ if (time2 && !times.includes(time2)) time2 = null;
3759
+ renderTimes("ready", direction);
3760
+ }
3761
+ };
3762
+ const syncHeading = () => {
3763
+ if (!heading) return;
3764
+ if (date) {
3765
+ heading.textContent = labels.heading(date);
3766
+ if (!heading.hasAttribute("data-mk-shown")) scope.attr(heading, "data-mk-shown", "");
3767
+ }
3768
+ };
3769
+ const emit = () => {
3770
+ const key = date ? dayKey(date) : "";
3771
+ const value = date && time2 ? `${key}T${time2}` : null;
3772
+ if (output) {
3773
+ output.value = value ?? "";
3774
+ output.dispatchEvent(new Event("input", { bubbles: true }));
3775
+ output.dispatchEvent(new Event("change", { bubbles: true }));
3776
+ }
3777
+ if (date && time2 && value) {
3778
+ const detail = { date, time: time2, key, value };
3779
+ options.onChange?.(detail);
3780
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail }));
3781
+ }
3782
+ };
3783
+ const selectDate = (input, notify = true) => {
3784
+ if (scope.disposed) return;
3785
+ const d = toDate(input);
3786
+ if (disabled(d)) return;
3787
+ const direction = date ? Math.sign(d.getTime() - date.getTime()) : 0;
3788
+ if (sameDay(d, date)) return;
3789
+ date = d;
3790
+ time2 = null;
3791
+ focusDay = d;
3792
+ if (!sameMonth(d, month)) {
3793
+ const dir = d > month ? 1 : -1;
3794
+ month = d;
3795
+ renderDays(dir);
3796
+ }
3797
+ daysHost.querySelectorAll('[role="gridcell"]').forEach((cell) => {
3798
+ const b = cell.querySelector("[data-mk-slot-day]");
3799
+ if (b) {
3800
+ cell.setAttribute("aria-selected", String(b.dataset.mkSlotDay === dayKey(d)));
3801
+ b.tabIndex = b.dataset.mkSlotDay === dayKey(d) ? 0 : -1;
3802
+ }
3803
+ });
3804
+ syncHeading();
3805
+ load(direction);
3806
+ if (notify) {
3807
+ options.onDateChange?.(d);
3808
+ emit();
3809
+ }
3810
+ };
3811
+ const selectTime = (t, notify = true) => {
3812
+ if (scope.disposed || !date) return;
3813
+ if (t !== null && !times.includes(t)) return;
3814
+ time2 = t;
3815
+ timesHost.querySelectorAll("[data-mk-slot-time]").forEach((b) => {
3816
+ b.setAttribute("aria-checked", String(b.dataset.mkSlotTime === t));
3817
+ b.tabIndex = (t ? b.dataset.mkSlotTime === t : b === timesHost.querySelector("[data-mk-slot-time]")) ? 0 : -1;
3818
+ });
3819
+ if (notify) emit();
3820
+ };
3821
+ scope.on(root, "click", (e) => {
3822
+ const target = e.target.closest("button");
3823
+ if (!target || target.disabled || !root.contains(target)) return;
3824
+ if (target === prev) moveFocus(addMonths(month, -1), false);
3825
+ else if (target === next) moveFocus(addMonths(month, 1), false);
3826
+ else if (target.dataset.mkSlotDay) selectDate(target.dataset.mkSlotDay);
3827
+ else if (target.dataset.mkSlotTime) selectTime(target.dataset.mkSlotTime);
3828
+ });
3829
+ scope.on(daysHost, "keydown", (e) => {
3830
+ const event = e;
3831
+ const key = event.target.dataset?.mkSlotDay;
3832
+ if (!key) return;
3833
+ const d = toDate(key);
3834
+ const to = {
3835
+ ArrowLeft: () => addDays(d, -1),
3836
+ ArrowRight: () => addDays(d, 1),
3837
+ ArrowUp: () => addDays(d, -7),
3838
+ ArrowDown: () => addDays(d, 7),
3839
+ Home: () => startOfWeek(d, firstDay),
3840
+ End: () => addDays(startOfWeek(d, firstDay), 6),
3841
+ PageUp: () => addMonths(d, -1),
3842
+ PageDown: () => addMonths(d, 1)
3843
+ }[event.key]?.();
3844
+ if (!to) return;
3845
+ event.preventDefault();
3846
+ moveFocus(to, true);
3847
+ });
3848
+ scope.on(timesHost, "keydown", (e) => {
3849
+ const event = e;
3850
+ const current2 = event.target.dataset?.mkSlotTime;
3851
+ if (!current2) return;
3852
+ const i = times.indexOf(current2);
3853
+ const to = { ArrowRight: i + 1, ArrowDown: i + 1, ArrowLeft: i - 1, ArrowUp: i - 1, Home: 0, End: times.length - 1 }[event.key];
3854
+ if (to === void 0) return;
3855
+ event.preventDefault();
3856
+ const t = times[(to + times.length) % times.length];
3857
+ selectTime(t);
3858
+ timesHost.querySelector(`[data-mk-slot-time="${t}"]`)?.focus();
3859
+ });
3860
+ renderDays(0);
3861
+ if (date) {
3862
+ syncHeading();
3863
+ load(0);
3864
+ if (time2 && !times.includes(time2)) time2 = null;
3865
+ } else renderTimes("placeholder", 0);
3866
+ return {
3867
+ selectDate: (d) => selectDate(d),
3868
+ selectTime: (t) => selectTime(t),
3869
+ setSlots(source) {
3870
+ if (scope.disposed) return;
3871
+ slots = fromJson(source) ?? [];
3872
+ load(0);
3873
+ },
3874
+ get date() {
3875
+ return date;
3876
+ },
3877
+ get time() {
3878
+ return time2;
3879
+ },
3880
+ get value() {
3881
+ return date && time2 ? `${dayKey(date)}T${time2}` : null;
3882
+ },
3883
+ destroy: () => scope.dispose()
3884
+ };
3885
+ }
3886
+
2294
3887
  export {
2295
3888
  PATHS,
2296
3889
  springPath,
@@ -2369,6 +3962,16 @@ export {
2369
3962
  pushUnderlay,
2370
3963
  releaseUnderlay,
2371
3964
  createDialog,
2372
- createMenu
3965
+ createMenu,
3966
+ createQuantity,
3967
+ createPagination,
3968
+ createHoverCard,
3969
+ createInputOtp,
3970
+ createStudioDock,
3971
+ createTrailer,
3972
+ toDate,
3973
+ dayKey,
3974
+ createCalendar,
3975
+ createSlotPicker
2373
3976
  };
2374
- //# sourceMappingURL=chunk-34XYOXHG.js.map
3977
+ //# sourceMappingURL=chunk-TFNRIZHU.js.map