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