@yewdiel21/motion-kit 0.9.1 → 0.14.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 (458) hide show
  1. package/README.md +72 -0
  2. package/dist/auto/index.d.ts +72 -3
  3. package/dist/auto/index.js +139 -3
  4. package/dist/auto/index.js.map +1 -1
  5. package/dist/{chunk-BFC27F2G.js → chunk-6P4P7NU6.js} +2 -218
  6. package/dist/chunk-6P4P7NU6.js.map +1 -0
  7. package/dist/chunk-CU6SXW3E.js +20334 -0
  8. package/dist/chunk-CU6SXW3E.js.map +1 -0
  9. package/dist/{chunk-XDWBVFHQ.js → chunk-EY4BJKC4.js} +1203 -29
  10. package/dist/chunk-EY4BJKC4.js.map +1 -0
  11. package/dist/chunk-QP4QJOEN.js +72 -0
  12. package/dist/chunk-QP4QJOEN.js.map +1 -0
  13. package/dist/css/components/activity-feed.css +240 -0
  14. package/dist/css/components/attachment.css +266 -0
  15. package/dist/css/components/breadcrumb.css +110 -0
  16. package/dist/css/components/calendar.css +159 -0
  17. package/dist/css/components/chart-tooltip.css +168 -0
  18. package/dist/css/components/chart.css +296 -0
  19. package/dist/css/components/code-block.css +264 -0
  20. package/dist/css/components/color-area.css +82 -0
  21. package/dist/css/components/color-field.css +67 -0
  22. package/dist/css/components/color-picker.css +131 -0
  23. package/dist/css/components/color-slider.css +113 -0
  24. package/dist/css/components/command-search.css +252 -0
  25. package/dist/css/components/context-menu.css +23 -0
  26. package/dist/css/components/credit-card.css +288 -0
  27. package/dist/css/components/data-table.css +591 -0
  28. package/dist/css/components/date-range-picker.css +168 -0
  29. package/dist/css/components/date-time-picker.css +178 -0
  30. package/dist/css/components/drawer.css +58 -0
  31. package/dist/css/components/editable-table.css +201 -0
  32. package/dist/css/components/empty-state.css +61 -0
  33. package/dist/css/components/file-explorer.css +633 -0
  34. package/dist/css/components/filter-builder.css +232 -0
  35. package/dist/css/components/hold-confirm.css +87 -0
  36. package/dist/css/components/hover-card.css +20 -0
  37. package/dist/css/components/image-preview.css +195 -0
  38. package/dist/css/components/input-otp.css +10 -0
  39. package/dist/css/components/json-viewer.css +272 -0
  40. package/dist/css/components/like-button.css +78 -0
  41. package/dist/css/components/link-preview.css +275 -0
  42. package/dist/css/components/loading-button.css +77 -0
  43. package/dist/css/components/multi-select.css +267 -0
  44. package/dist/css/components/notification-bell.css +127 -0
  45. package/dist/css/components/pagination.css +11 -0
  46. package/dist/css/components/password-strength.css +183 -0
  47. package/dist/css/components/popover.css +25 -0
  48. package/dist/css/components/progress.css +140 -0
  49. package/dist/css/components/quantity.css +16 -0
  50. package/dist/css/components/questionnaire.css +217 -0
  51. package/dist/css/components/range-calendar.css +186 -0
  52. package/dist/css/components/range-slider.css +192 -0
  53. package/dist/css/components/resizable-panel.css +243 -0
  54. package/dist/css/components/rich-text-editor.css +284 -0
  55. package/dist/css/components/scratch-card.css +75 -0
  56. package/dist/css/components/skeleton.css +108 -0
  57. package/dist/css/components/slot-picker.css +126 -0
  58. package/dist/css/components/split-view.css +19 -0
  59. package/dist/css/components/star-rating.css +80 -0
  60. package/dist/css/components/stat-card.css +164 -0
  61. package/dist/css/components/studio-dock.css +35 -0
  62. package/dist/css/components/swipe-actions.css +105 -0
  63. package/dist/css/components/tag-input.css +244 -0
  64. package/dist/css/components/time-field.css +88 -0
  65. package/dist/css/components/timeline.css +219 -0
  66. package/dist/css/components/tooltip.css +79 -0
  67. package/dist/css/components/trailer.css +37 -0
  68. package/dist/css/components/tree-view.css +210 -0
  69. package/dist/css/components/virtual-list.css +195 -0
  70. package/dist/css/controls.css +65 -0
  71. package/dist/css/tokens.css +185 -181
  72. package/dist/elements/index.d.ts +742 -5
  73. package/dist/elements/index.js +1527 -8
  74. package/dist/elements/index.js.map +1 -1
  75. package/dist/{engine-GDGwQnJE.d.ts → engine-Cn6IhE3z.d.ts} +1 -1
  76. package/dist/engine-QECQnGz1.d.ts +33 -0
  77. package/dist/index.css +10113 -181
  78. package/dist/index.d.ts +89 -5
  79. package/dist/index.js +285 -9
  80. package/dist/index.js.map +1 -1
  81. package/dist/react/index.d.ts +678 -23
  82. package/dist/react/index.js +2389 -7
  83. package/dist/react/index.js.map +1 -1
  84. package/dist/{reduced-B98f8LPs.d.ts → reduced-BBUusld6.d.ts} +206 -2
  85. package/dist/reveal-DEvp6U6T.d.ts +2381 -0
  86. package/dist/{store-pHiUvxP8.d.ts → store-DjkTBX7f.d.ts} +2 -2
  87. package/package.json +1 -1
  88. package/registry.json +583 -104
  89. package/skills/motion-kit/SKILL.md +209 -189
  90. package/src/auto/auto-init.ts +136 -0
  91. package/src/components/activity-feed/README.md +56 -0
  92. package/src/components/activity-feed/activity-feed.css +239 -0
  93. package/src/components/activity-feed/element.ts +36 -0
  94. package/src/components/activity-feed/engine.ts +351 -0
  95. package/src/components/activity-feed/react.tsx +32 -0
  96. package/src/components/attachment/README.md +27 -0
  97. package/src/components/attachment/attachment.css +265 -0
  98. package/src/components/attachment/element.ts +50 -0
  99. package/src/components/attachment/engine.ts +469 -0
  100. package/src/components/attachment/react.tsx +65 -0
  101. package/src/components/breadcrumb/README.md +38 -0
  102. package/src/components/breadcrumb/breadcrumb.css +109 -0
  103. package/src/components/breadcrumb/element.ts +27 -0
  104. package/src/components/breadcrumb/engine.ts +249 -0
  105. package/src/components/breadcrumb/react.tsx +30 -0
  106. package/src/components/calendar/README.md +82 -0
  107. package/src/components/calendar/calendar.css +158 -0
  108. package/src/components/calendar/element.ts +27 -0
  109. package/src/components/calendar/engine.ts +412 -0
  110. package/src/components/calendar/react.tsx +69 -0
  111. package/src/components/chart/README.md +24 -0
  112. package/src/components/chart/chart.css +295 -0
  113. package/src/components/chart/element.ts +41 -0
  114. package/src/components/chart/engine.ts +811 -0
  115. package/src/components/chart/react.tsx +50 -0
  116. package/src/components/chart-tooltip/README.md +53 -0
  117. package/src/components/chart-tooltip/chart-tooltip.css +167 -0
  118. package/src/components/chart-tooltip/element.ts +37 -0
  119. package/src/components/chart-tooltip/engine.ts +442 -0
  120. package/src/components/chart-tooltip/react.tsx +47 -0
  121. package/src/components/code-block/README.md +19 -0
  122. package/src/components/code-block/code-block.css +263 -0
  123. package/src/components/code-block/element.ts +34 -0
  124. package/src/components/code-block/engine.ts +254 -0
  125. package/src/components/code-block/highlight.ts +244 -0
  126. package/src/components/code-block/react.tsx +94 -0
  127. package/src/components/color-area/README.md +50 -0
  128. package/src/components/color-area/color-area.css +81 -0
  129. package/src/components/color-area/element.ts +26 -0
  130. package/src/components/color-area/engine.ts +246 -0
  131. package/src/components/color-area/react.tsx +42 -0
  132. package/src/components/color-field/README.md +43 -0
  133. package/src/components/color-field/color-field.css +66 -0
  134. package/src/components/color-field/element.ts +26 -0
  135. package/src/components/color-field/engine.ts +174 -0
  136. package/src/components/color-field/react.tsx +42 -0
  137. package/src/components/color-picker/README.md +45 -0
  138. package/src/components/color-picker/color-picker.css +130 -0
  139. package/src/components/color-picker/element.ts +45 -0
  140. package/src/components/color-picker/engine.ts +314 -0
  141. package/src/components/color-picker/react.tsx +47 -0
  142. package/src/components/color-slider/README.md +55 -0
  143. package/src/components/color-slider/color-slider.css +112 -0
  144. package/src/components/color-slider/element.ts +26 -0
  145. package/src/components/color-slider/engine.ts +234 -0
  146. package/src/components/color-slider/react.tsx +45 -0
  147. package/src/components/command-search/README.md +15 -0
  148. package/src/components/command-search/command-search.css +251 -0
  149. package/src/components/command-search/element.ts +36 -0
  150. package/src/components/command-search/engine.ts +356 -0
  151. package/src/components/command-search/match.ts +53 -0
  152. package/src/components/command-search/react.tsx +66 -0
  153. package/src/components/context-menu/README.md +31 -0
  154. package/src/components/context-menu/context-menu.css +22 -0
  155. package/src/components/context-menu/element.ts +40 -0
  156. package/src/components/context-menu/engine.ts +153 -0
  157. package/src/components/context-menu/react.tsx +57 -0
  158. package/src/components/credit-card/README.md +20 -0
  159. package/src/components/credit-card/card.ts +77 -0
  160. package/src/components/credit-card/credit-card.css +287 -0
  161. package/src/components/credit-card/element.ts +33 -0
  162. package/src/components/credit-card/engine.ts +410 -0
  163. package/src/components/credit-card/react.tsx +36 -0
  164. package/src/components/data-table/README.md +83 -0
  165. package/src/components/data-table/data-table.css +590 -0
  166. package/src/components/data-table/element.ts +54 -0
  167. package/src/components/data-table/engine.ts +1059 -0
  168. package/src/components/data-table/react.tsx +94 -0
  169. package/src/components/date-range-picker/README.md +51 -0
  170. package/src/components/date-range-picker/date-range-picker.css +167 -0
  171. package/src/components/date-range-picker/element.ts +52 -0
  172. package/src/components/date-range-picker/engine.ts +352 -0
  173. package/src/components/date-range-picker/react.tsx +57 -0
  174. package/src/components/date-time-picker/README.md +48 -0
  175. package/src/components/date-time-picker/date-time-picker.css +177 -0
  176. package/src/components/date-time-picker/element.ts +47 -0
  177. package/src/components/date-time-picker/engine.ts +350 -0
  178. package/src/components/date-time-picker/react.tsx +54 -0
  179. package/src/components/dialog/README.md +103 -102
  180. package/src/components/dialog/element.ts +123 -118
  181. package/src/components/dialog/engine.ts +449 -432
  182. package/src/components/drawer/README.md +28 -0
  183. package/src/components/drawer/drawer.css +57 -0
  184. package/src/components/drawer/element.ts +21 -0
  185. package/src/components/drawer/engine.ts +56 -0
  186. package/src/components/drawer/react.tsx +85 -0
  187. package/src/components/editable-table/README.md +67 -0
  188. package/src/components/editable-table/editable-table.css +200 -0
  189. package/src/components/editable-table/element.ts +45 -0
  190. package/src/components/editable-table/engine.ts +775 -0
  191. package/src/components/editable-table/react.tsx +79 -0
  192. package/src/components/empty-state/README.md +41 -0
  193. package/src/components/empty-state/element.ts +23 -0
  194. package/src/components/empty-state/empty-state.css +60 -0
  195. package/src/components/empty-state/engine.ts +232 -0
  196. package/src/components/empty-state/react.tsx +34 -0
  197. package/src/components/file-explorer/README.md +67 -0
  198. package/src/components/file-explorer/element.ts +39 -0
  199. package/src/components/file-explorer/engine.ts +1307 -0
  200. package/src/components/file-explorer/file-explorer.css +632 -0
  201. package/src/components/file-explorer/react.tsx +77 -0
  202. package/src/components/filter-builder/README.md +47 -0
  203. package/src/components/filter-builder/element.ts +34 -0
  204. package/src/components/filter-builder/engine.ts +365 -0
  205. package/src/components/filter-builder/filter-builder.css +231 -0
  206. package/src/components/filter-builder/react.tsx +36 -0
  207. package/src/components/hold-confirm/README.md +13 -0
  208. package/src/components/hold-confirm/element.ts +24 -0
  209. package/src/components/hold-confirm/engine.ts +216 -0
  210. package/src/components/hold-confirm/hold-confirm.css +86 -0
  211. package/src/components/hold-confirm/react.tsx +28 -0
  212. package/src/components/hover-card/README.md +20 -0
  213. package/src/components/hover-card/element.ts +8 -0
  214. package/src/components/hover-card/engine.ts +131 -0
  215. package/src/components/hover-card/hover-card.css +19 -0
  216. package/src/components/hover-card/react.tsx +19 -0
  217. package/src/components/image-preview/README.md +16 -0
  218. package/src/components/image-preview/element.ts +26 -0
  219. package/src/components/image-preview/engine.ts +325 -0
  220. package/src/components/image-preview/image-preview.css +194 -0
  221. package/src/components/image-preview/react.tsx +43 -0
  222. package/src/components/input-otp/README.md +18 -0
  223. package/src/components/input-otp/element.ts +14 -0
  224. package/src/components/input-otp/engine.ts +106 -0
  225. package/src/components/input-otp/input-otp.css +9 -0
  226. package/src/components/input-otp/react.tsx +21 -0
  227. package/src/components/json-viewer/README.md +56 -0
  228. package/src/components/json-viewer/element.ts +37 -0
  229. package/src/components/json-viewer/engine.ts +440 -0
  230. package/src/components/json-viewer/json-viewer.css +271 -0
  231. package/src/components/json-viewer/react.tsx +56 -0
  232. package/src/components/like-button/README.md +13 -0
  233. package/src/components/like-button/element.ts +47 -0
  234. package/src/components/like-button/engine.ts +145 -0
  235. package/src/components/like-button/like-button.css +77 -0
  236. package/src/components/like-button/react.tsx +39 -0
  237. package/src/components/link-preview/README.md +19 -0
  238. package/src/components/link-preview/element.ts +29 -0
  239. package/src/components/link-preview/engine.ts +192 -0
  240. package/src/components/link-preview/link-preview.css +274 -0
  241. package/src/components/link-preview/react.tsx +101 -0
  242. package/src/components/loading-button/README.md +45 -0
  243. package/src/components/loading-button/element.ts +34 -0
  244. package/src/components/loading-button/engine.ts +201 -0
  245. package/src/components/loading-button/loading-button.css +76 -0
  246. package/src/components/loading-button/react.tsx +43 -0
  247. package/src/components/multi-select/README.md +48 -0
  248. package/src/components/multi-select/element.ts +28 -0
  249. package/src/components/multi-select/engine.ts +294 -0
  250. package/src/components/multi-select/multi-select.css +266 -0
  251. package/src/components/multi-select/react.tsx +39 -0
  252. package/src/components/notification-bell/README.md +14 -0
  253. package/src/components/notification-bell/element.ts +48 -0
  254. package/src/components/notification-bell/engine.ts +202 -0
  255. package/src/components/notification-bell/notification-bell.css +126 -0
  256. package/src/components/notification-bell/react.tsx +57 -0
  257. package/src/components/pagination/README.md +17 -0
  258. package/src/components/pagination/element.ts +14 -0
  259. package/src/components/pagination/engine.ts +102 -0
  260. package/src/components/pagination/pagination.css +10 -0
  261. package/src/components/pagination/react.tsx +22 -0
  262. package/src/components/password-strength/README.md +17 -0
  263. package/src/components/password-strength/element.ts +22 -0
  264. package/src/components/password-strength/engine.ts +212 -0
  265. package/src/components/password-strength/password-strength.css +182 -0
  266. package/src/components/password-strength/react.tsx +36 -0
  267. package/src/components/password-strength/score.ts +62 -0
  268. package/src/components/popover/README.md +44 -0
  269. package/src/components/popover/element.ts +31 -0
  270. package/src/components/popover/engine.ts +114 -0
  271. package/src/components/popover/popover.css +24 -0
  272. package/src/components/popover/react.tsx +50 -0
  273. package/src/components/progress/README.md +17 -0
  274. package/src/components/progress/element.ts +30 -0
  275. package/src/components/progress/engine.ts +173 -0
  276. package/src/components/progress/progress.css +139 -0
  277. package/src/components/progress/react.tsx +35 -0
  278. package/src/components/quantity/README.md +20 -0
  279. package/src/components/quantity/element.ts +14 -0
  280. package/src/components/quantity/engine.ts +85 -0
  281. package/src/components/quantity/quantity.css +15 -0
  282. package/src/components/quantity/react.tsx +21 -0
  283. package/src/components/questionnaire/README.md +32 -0
  284. package/src/components/questionnaire/element.ts +118 -0
  285. package/src/components/questionnaire/engine.ts +255 -0
  286. package/src/components/questionnaire/questionnaire.css +216 -0
  287. package/src/components/questionnaire/react.tsx +140 -0
  288. package/src/components/range-calendar/README.md +58 -0
  289. package/src/components/range-calendar/element.ts +42 -0
  290. package/src/components/range-calendar/engine.ts +390 -0
  291. package/src/components/range-calendar/range-calendar.css +185 -0
  292. package/src/components/range-calendar/react.tsx +56 -0
  293. package/src/components/range-slider/README.md +23 -0
  294. package/src/components/range-slider/element.ts +53 -0
  295. package/src/components/range-slider/engine.ts +316 -0
  296. package/src/components/range-slider/range-slider.css +191 -0
  297. package/src/components/range-slider/react.tsx +66 -0
  298. package/src/components/resizable-panel/README.md +61 -0
  299. package/src/components/resizable-panel/element.ts +36 -0
  300. package/src/components/resizable-panel/engine.ts +551 -0
  301. package/src/components/resizable-panel/react.tsx +74 -0
  302. package/src/components/resizable-panel/resizable-panel.css +242 -0
  303. package/src/components/rich-text-editor/README.md +57 -0
  304. package/src/components/rich-text-editor/element.ts +34 -0
  305. package/src/components/rich-text-editor/engine.ts +673 -0
  306. package/src/components/rich-text-editor/react.tsx +60 -0
  307. package/src/components/rich-text-editor/rich-text-editor.css +283 -0
  308. package/src/components/scratch-card/README.md +15 -0
  309. package/src/components/scratch-card/element.ts +30 -0
  310. package/src/components/scratch-card/engine.ts +257 -0
  311. package/src/components/scratch-card/react.tsx +40 -0
  312. package/src/components/scratch-card/scratch-card.css +74 -0
  313. package/src/components/skeleton/README.md +15 -0
  314. package/src/components/skeleton/element.ts +32 -0
  315. package/src/components/skeleton/engine.ts +104 -0
  316. package/src/components/skeleton/react.tsx +41 -0
  317. package/src/components/skeleton/skeleton.css +107 -0
  318. package/src/components/slot-picker/README.md +68 -0
  319. package/src/components/slot-picker/element.ts +27 -0
  320. package/src/components/slot-picker/engine.ts +412 -0
  321. package/src/components/slot-picker/react.tsx +76 -0
  322. package/src/components/slot-picker/slot-picker.css +125 -0
  323. package/src/components/split-view/README.md +50 -0
  324. package/src/components/split-view/element.ts +34 -0
  325. package/src/components/split-view/engine.ts +114 -0
  326. package/src/components/split-view/react.tsx +63 -0
  327. package/src/components/split-view/split-view.css +18 -0
  328. package/src/components/star-rating/README.md +14 -0
  329. package/src/components/star-rating/element.ts +26 -0
  330. package/src/components/star-rating/engine.ts +217 -0
  331. package/src/components/star-rating/react.tsx +33 -0
  332. package/src/components/star-rating/star-rating.css +79 -0
  333. package/src/components/stat-card/README.md +42 -0
  334. package/src/components/stat-card/element.ts +40 -0
  335. package/src/components/stat-card/engine.ts +283 -0
  336. package/src/components/stat-card/react.tsx +36 -0
  337. package/src/components/stat-card/stat-card.css +163 -0
  338. package/src/components/studio-dock/README.md +44 -0
  339. package/src/components/studio-dock/element.ts +11 -0
  340. package/src/components/studio-dock/engine.ts +212 -0
  341. package/src/components/studio-dock/react.tsx +23 -0
  342. package/src/components/studio-dock/studio-dock.css +34 -0
  343. package/src/components/swipe-actions/README.md +19 -0
  344. package/src/components/swipe-actions/element.ts +26 -0
  345. package/src/components/swipe-actions/engine.ts +260 -0
  346. package/src/components/swipe-actions/react.tsx +80 -0
  347. package/src/components/swipe-actions/swipe-actions.css +104 -0
  348. package/src/components/tag-input/README.md +42 -0
  349. package/src/components/tag-input/element.ts +39 -0
  350. package/src/components/tag-input/engine.ts +313 -0
  351. package/src/components/tag-input/react.tsx +54 -0
  352. package/src/components/tag-input/tag-input.css +243 -0
  353. package/src/components/time-field/README.md +54 -0
  354. package/src/components/time-field/element.ts +38 -0
  355. package/src/components/time-field/engine.ts +110 -0
  356. package/src/components/time-field/react.tsx +45 -0
  357. package/src/components/time-field/time-field.css +87 -0
  358. package/src/components/timeline/README.md +57 -0
  359. package/src/components/timeline/element.ts +31 -0
  360. package/src/components/timeline/engine.ts +300 -0
  361. package/src/components/timeline/react.tsx +59 -0
  362. package/src/components/timeline/timeline.css +218 -0
  363. package/src/components/tooltip/README.md +46 -0
  364. package/src/components/tooltip/element.ts +22 -0
  365. package/src/components/tooltip/engine.ts +288 -0
  366. package/src/components/tooltip/react.tsx +30 -0
  367. package/src/components/tooltip/tooltip.css +78 -0
  368. package/src/components/trailer/README.md +28 -0
  369. package/src/components/trailer/element.ts +13 -0
  370. package/src/components/trailer/engine.ts +189 -0
  371. package/src/components/trailer/react.tsx +16 -0
  372. package/src/components/trailer/trailer.css +36 -0
  373. package/src/components/tree-view/README.md +61 -0
  374. package/src/components/tree-view/element.ts +32 -0
  375. package/src/components/tree-view/engine.ts +569 -0
  376. package/src/components/tree-view/react.tsx +78 -0
  377. package/src/components/tree-view/tree-view.css +209 -0
  378. package/src/components/virtual-list/README.md +81 -0
  379. package/src/components/virtual-list/element.ts +42 -0
  380. package/src/components/virtual-list/engine.ts +678 -0
  381. package/src/components/virtual-list/react.tsx +101 -0
  382. package/src/components/virtual-list/virtual-list.css +194 -0
  383. package/src/core/chips.ts +196 -0
  384. package/src/core/color.ts +304 -0
  385. package/src/core/date-range.ts +67 -0
  386. package/src/core/dates.ts +108 -0
  387. package/src/core/files.ts +107 -0
  388. package/src/core/filter.ts +229 -0
  389. package/src/core/gsap.ts +80 -65
  390. package/src/core/listbox.ts +332 -0
  391. package/src/core/mark.ts +29 -0
  392. package/src/core/position.ts +89 -0
  393. package/src/core/relative-time.ts +77 -0
  394. package/src/core/segment-field.ts +373 -0
  395. package/src/core/segments.ts +153 -0
  396. package/src/core/tree.ts +116 -0
  397. package/src/core/virtual.ts +79 -0
  398. package/src/css/controls/README.md +14 -0
  399. package/src/css/controls/status.css +63 -0
  400. package/src/css/tokens.css +186 -182
  401. package/src/elements/index.ts +171 -0
  402. package/src/index.ts +97 -0
  403. package/src/motion/micro.ts +248 -0
  404. package/src/motion/sheet.ts +88 -65
  405. package/src/motion/surface.ts +9 -0
  406. package/src/react/index.ts +78 -0
  407. package/src/react/use-action-button.ts +6 -0
  408. package/src/react/use-editorial-reveal.ts +7 -0
  409. package/src/react/use-film-hero.ts +6 -0
  410. package/src/react/use-font-cycle.ts +7 -0
  411. package/src/react/use-image-zoom.ts +5 -0
  412. package/src/react/use-joined-cta.ts +5 -0
  413. package/src/react/use-local-clock.ts +5 -0
  414. package/src/react/use-scroll-dock.ts +5 -0
  415. package/src/react/use-sticker.ts +5 -0
  416. package/src/react/use-studio-dock.ts +8 -0
  417. package/src/react/use-thumbnail-nav.ts +7 -0
  418. package/src/react/use-trailer.ts +6 -0
  419. package/src/react/use-weight-hover.ts +5 -0
  420. package/src/recipes/action-button/README.md +31 -0
  421. package/src/recipes/action-button/action-button.css +113 -0
  422. package/src/recipes/action-button/create-action-button.ts +56 -0
  423. package/src/recipes/editorial-reveal/README.md +35 -0
  424. package/src/recipes/editorial-reveal/create-editorial-reveal.ts +91 -0
  425. package/src/recipes/editorial-reveal/editorial-reveal.css +17 -0
  426. package/src/recipes/film-hero/README.md +23 -0
  427. package/src/recipes/film-hero/create-film-hero.ts +65 -0
  428. package/src/recipes/film-hero/film-hero.css +29 -0
  429. package/src/recipes/font-cycle/README.md +11 -0
  430. package/src/recipes/font-cycle/create-font-cycle.ts +126 -0
  431. package/src/recipes/font-cycle/font-cycle.css +36 -0
  432. package/src/recipes/image-zoom/README.md +16 -0
  433. package/src/recipes/image-zoom/create-image-zoom.ts +27 -0
  434. package/src/recipes/image-zoom/image-zoom.css +7 -0
  435. package/src/recipes/joined-cta/README.md +13 -0
  436. package/src/recipes/joined-cta/create-joined-cta.ts +22 -0
  437. package/src/recipes/joined-cta/joined-cta.css +17 -0
  438. package/src/recipes/local-clock/README.md +31 -0
  439. package/src/recipes/local-clock/create-local-clock.ts +61 -0
  440. package/src/recipes/scroll-dock/README.md +46 -0
  441. package/src/recipes/scroll-dock/create-scroll-dock.ts +72 -0
  442. package/src/recipes/scroll-dock/scroll-dock.css +70 -0
  443. package/src/recipes/sticker/README.md +59 -0
  444. package/src/recipes/sticker/create-sticker.ts +490 -0
  445. package/src/recipes/sticker/sticker.css +112 -0
  446. package/src/recipes/thumbnail-nav/README.md +16 -0
  447. package/src/recipes/thumbnail-nav/create-thumbnail-nav.ts +165 -0
  448. package/src/recipes/thumbnail-nav/thumbnail-nav.css +108 -0
  449. package/src/recipes/weight-hover/README.md +37 -0
  450. package/src/recipes/weight-hover/create-weight-hover.ts +136 -0
  451. package/src/recipes/weight-hover/weight-hover.css +7 -0
  452. package/dist/chunk-BFC27F2G.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-JQMJQSXD.js +0 -2374
  456. package/dist/chunk-JQMJQSXD.js.map +0 -1
  457. package/dist/chunk-XDWBVFHQ.js.map +0 -1
  458. package/dist/reveal-C0hCDcB_.d.ts +0 -415
@@ -0,0 +1,27 @@
1
+ import { MkElement, defineElement, type OptionType } from '../../elements/base';
2
+ import { createBreadcrumb, type BreadcrumbInstance, type BreadcrumbItem } from './engine';
3
+
4
+ /**
5
+ * <mk-breadcrumb class="mk-breadcrumb" items='[{"label":"Inicio","href":"/"},{"label":"Proyectos","href":"/p"},{"label":"Melon"}]'>
6
+ * </mk-breadcrumb> — or authored <a>/<span> children. Emits mk:navigate ({item, index}, cancelable).
7
+ */
8
+ export class MkBreadcrumbElement extends MkElement<BreadcrumbInstance> {
9
+ static options: Record<string, OptionType> = { items: 'json', label: 'string', maxItems: 'number' };
10
+
11
+ protected create(options: Record<string, unknown>) {
12
+ return createBreadcrumb(this, options);
13
+ }
14
+
15
+ attributeChangedCallback(name: string, previous: string | null, next: string | null) {
16
+ if (previous === next || !this.instance) return;
17
+ if (name === 'items') {
18
+ try {
19
+ this.instance.setItems(JSON.parse(next ?? '[]') as BreadcrumbItem[]);
20
+ } catch {
21
+ // Malformed JSON: keep the current path.
22
+ }
23
+ } else super.attributeChangedCallback(name, previous, next);
24
+ }
25
+ }
26
+
27
+ export const defineBreadcrumb = () => defineElement('mk-breadcrumb', MkBreadcrumbElement);
@@ -0,0 +1,249 @@
1
+ import { gsap, EASE, Flip, registerMotion } from '../../core/gsap';
2
+ import { reduced } from '../../core/reduced';
3
+ import { createScope } from '../../core/scope';
4
+ import { TIMING } from '../../core/timing';
5
+ import { inert, type Instance } from '../../core/types';
6
+
7
+ /*
8
+ * Breadcrumb: the path to the current page as an ordered list in a
9
+ * <nav aria-label>; the last item is the page itself (aria-current="page").
10
+ * When the items do not fit (or pass maxItems) the middle ones fold into a
11
+ * "…" button; pressing it shows them in place, flowing in from the left
12
+ * (blur 16 → 0, 40 ms apart) while the rest glides to make room. setItems()
13
+ * keeps the shared start of the path: the items that stay glide to their new
14
+ * place (layout reflow), new ones grow in, and the old current page turns into
15
+ * a link. Links underline from the left on hover; activating one emits a
16
+ * cancelable mk:navigate (onNavigate) before the browser follows it.
17
+ */
18
+
19
+ export interface BreadcrumbItem {
20
+ label: string;
21
+ href?: string;
22
+ }
23
+
24
+ export interface BreadcrumbOptions {
25
+ /** The path; without it, the authored <ol> or <a>/<span> children are read. */
26
+ items?: BreadcrumbItem[];
27
+ /** Accessible name of the navigation (default 'Ruta de navegación'). */
28
+ label?: string;
29
+ /** 'auto' (default) folds the middle when it does not fit; a number keeps at most that many items. */
30
+ maxItems?: number | 'auto';
31
+ /** Called before following a link; event.preventDefault() keeps the browser where it is (SPA routing). */
32
+ onNavigate?: (item: BreadcrumbItem, index: number, event: Event) => void;
33
+ }
34
+
35
+ export interface BreadcrumbInstance extends Instance {
36
+ setItems(items: BreadcrumbItem[]): void;
37
+ readonly items: BreadcrumbItem[];
38
+ }
39
+
40
+ const readAuthored = (root: HTMLElement): BreadcrumbItem[] =>
41
+ [...root.querySelectorAll<HTMLElement>('li, :scope > a, :scope > span')]
42
+ .map((element) => {
43
+ const link = element.matches('a') ? (element as HTMLAnchorElement) : element.querySelector<HTMLAnchorElement>('a');
44
+ return { label: (link ?? element).textContent?.trim() ?? '', href: link?.getAttribute('href') ?? undefined };
45
+ })
46
+ .filter((item) => item.label);
47
+
48
+ /** A crumb is the same one at the same place with the same label (a current page that turns into a link stays). */
49
+ const key = (item: BreadcrumbItem, index: number) => `${index}:${item.label}`;
50
+
51
+ export function createBreadcrumb(root: HTMLElement | null, options: BreadcrumbOptions = {}): BreadcrumbInstance {
52
+ if (!root) return inert({ setItems() {}, items: [] });
53
+ registerMotion();
54
+ const scope = createScope();
55
+ let items = (options.items ?? readAuthored(root)).map((item) => ({ ...item }));
56
+ const maxItems = typeof options.maxItems === 'number' && options.maxItems >= 2 ? Math.floor(options.maxItems) : 'auto';
57
+ const effects = new Set<gsap.core.Animation>();
58
+ const keep = (animation: gsap.core.Animation | null) => {
59
+ if (!animation) return;
60
+ effects.add(animation);
61
+ // Finished ones leave as new ones arrive: the animation's own onComplete stays untouched.
62
+ for (const effect of effects) if (effect.totalProgress() === 1) effects.delete(effect);
63
+ };
64
+
65
+ // Authored markup stays in the DOM but out of sight; the engine draws its own list.
66
+ const authored = [...root.childNodes];
67
+ const holder = document.createElement('div');
68
+ holder.hidden = true;
69
+ holder.append(...authored);
70
+ const nav = document.createElement('nav');
71
+ nav.dataset.mkBreadcrumbNav = '';
72
+ nav.setAttribute('aria-label', options.label ?? 'Ruta de navegación');
73
+ const list = document.createElement('ol');
74
+ list.dataset.mkBreadcrumbList = '';
75
+ nav.append(list);
76
+ root.append(nav);
77
+ scope.add(() => {
78
+ for (const effect of effects) effect.kill();
79
+ effects.clear();
80
+ nav.remove();
81
+ root.append(...holder.childNodes);
82
+ });
83
+ scope.attr(root, 'data-mk-ready', '');
84
+
85
+ /**
86
+ * The items that stay glide to their new place (layout reflow spring); the new ones come in from the side of
87
+ * travel out of a blur (from the left when the folded middle opens, from the right when the path grows).
88
+ */
89
+ const reflow = (change: () => void, from: 'left' | 'right') => {
90
+ const crumbs = () => [...list.querySelectorAll<HTMLElement>('[data-mk-crumb]')];
91
+ if (reduced()) return change();
92
+ const state = Flip.getState(crumbs());
93
+ change();
94
+ keep(
95
+ Flip.from(state, {
96
+ targets: crumbs(),
97
+ duration: TIMING.layoutTravel,
98
+ ease: EASE.layoutReflow,
99
+ onEnter: (entering) =>
100
+ gsap.fromTo(
101
+ entering,
102
+ { opacity: 0, x: from === 'left' ? -12 : 12, filter: 'blur(8px)' },
103
+ { opacity: 1, x: 0, filter: 'blur(0px)', duration: 0.35, stagger: 0.04, ease: 'power2.out', clearProps: 'opacity,transform,filter' },
104
+ ),
105
+ }),
106
+ );
107
+ };
108
+
109
+ /** Fold the middle when collapsed: which indexes are hidden. */
110
+ let expanded = false;
111
+ let hidden: number[] = [];
112
+
113
+ const crumb = (item: BreadcrumbItem, index: number) => {
114
+ const li = document.createElement('li');
115
+ li.dataset.mkCrumb = '';
116
+ li.dataset.flipId = key(item, index);
117
+ const last = index === items.length - 1;
118
+ if (last) {
119
+ const span = document.createElement('span');
120
+ span.dataset.mkCrumbCurrent = '';
121
+ span.setAttribute('aria-current', 'page');
122
+ span.textContent = item.label;
123
+ li.append(span);
124
+ } else if (item.href !== undefined) {
125
+ const link = document.createElement('a');
126
+ link.dataset.mkCrumbLink = '';
127
+ link.href = item.href;
128
+ link.dataset.mkIndex = String(index);
129
+ link.textContent = item.label;
130
+ li.append(link);
131
+ } else {
132
+ const span = document.createElement('span');
133
+ span.dataset.mkCrumbText = '';
134
+ span.textContent = item.label;
135
+ li.append(span);
136
+ }
137
+ return li;
138
+ };
139
+
140
+ const more = () => {
141
+ const li = document.createElement('li');
142
+ li.dataset.mkCrumb = '';
143
+ li.dataset.flipId = 'more';
144
+ const button = document.createElement('button');
145
+ button.type = 'button';
146
+ button.dataset.mkCrumbMore = '';
147
+ button.setAttribute('aria-expanded', 'false');
148
+ button.setAttribute('aria-label', hidden.length === 1 ? 'Mostrar 1 nivel oculto' : `Mostrar ${hidden.length} niveles ocultos`);
149
+ button.textContent = '…';
150
+ li.append(button);
151
+ return li;
152
+ };
153
+
154
+ const render = () => {
155
+ const nodes: HTMLElement[] = [];
156
+ items.forEach((item, index) => {
157
+ if (hidden.includes(index)) {
158
+ if (index === hidden[0]) nodes.push(more());
159
+ return;
160
+ }
161
+ nodes.push(crumb(item, index));
162
+ });
163
+ list.replaceChildren(...nodes);
164
+ nav.toggleAttribute('data-mk-expanded', expanded);
165
+ };
166
+
167
+ /** The middle indexes to fold, keeping the first item and the last `keepEnd`. */
168
+ const fold = (keepEnd: number) => {
169
+ const end = Math.max(1, items.length - keepEnd);
170
+ return Array.from({ length: Math.max(0, end - 1) }, (_, i) => i + 1);
171
+ };
172
+
173
+ const fits = () => list.scrollWidth <= list.clientWidth + 1;
174
+
175
+ const layout = () => {
176
+ if (expanded || items.length <= 2) {
177
+ hidden = [];
178
+ render();
179
+ return;
180
+ }
181
+ if (maxItems !== 'auto') {
182
+ hidden = items.length > maxItems ? fold(maxItems - 1) : [];
183
+ render();
184
+ return;
185
+ }
186
+ // Fold from the middle until the row fits with the current page whole (jsdom has no layout: it always fits);
187
+ // only when even the shortest fold is too long does the current page ellipsize.
188
+ nav.setAttribute('data-mk-measuring', '');
189
+ hidden = [];
190
+ render();
191
+ for (let keepEnd = items.length - 2; keepEnd >= 1 && !fits(); keepEnd--) {
192
+ hidden = fold(keepEnd);
193
+ render();
194
+ }
195
+ nav.removeAttribute('data-mk-measuring');
196
+ };
197
+
198
+ scope.on(list, 'click', (event) => {
199
+ const target = event.target as Element | null;
200
+ if (target?.closest('[data-mk-crumb-more]')) {
201
+ const shown = hidden.map((index) => key(items[index]!, index));
202
+ reflow(() => {
203
+ expanded = true;
204
+ hidden = [];
205
+ render();
206
+ }, 'left');
207
+ // The button is gone: the focus moves to the first level it revealed.
208
+ const first = [...list.querySelectorAll<HTMLElement>('[data-mk-crumb]')].find((li) => shown.includes(li.dataset.flipId ?? ''));
209
+ first?.querySelector<HTMLElement>('a')?.focus();
210
+ return;
211
+ }
212
+ const link = target?.closest<HTMLAnchorElement>('a[data-mk-crumb-link]');
213
+ if (!link) return;
214
+ const index = Number(link.dataset.mkIndex);
215
+ const item = items[index]!;
216
+ options.onNavigate?.(item, index, event);
217
+ const navigate = new CustomEvent('mk:navigate', { bubbles: true, cancelable: true, detail: { item, index } });
218
+ if (!root.dispatchEvent(navigate)) event.preventDefault();
219
+ });
220
+
221
+ if (typeof ResizeObserver === 'function') {
222
+ let width = 0;
223
+ scope.observe(
224
+ new ResizeObserver(() => {
225
+ const next = nav.clientWidth;
226
+ if (Math.abs(next - width) < 1) return;
227
+ width = next;
228
+ if (!expanded) layout();
229
+ }),
230
+ ).observe(nav);
231
+ }
232
+
233
+ layout();
234
+
235
+ return {
236
+ setItems(next) {
237
+ if (scope.disposed) return;
238
+ reflow(() => {
239
+ items = next.map((item) => ({ ...item }));
240
+ expanded = false;
241
+ layout();
242
+ }, 'right');
243
+ },
244
+ get items() {
245
+ return items.map((item) => ({ ...item }));
246
+ },
247
+ destroy: () => scope.dispose(),
248
+ };
249
+ }
@@ -0,0 +1,30 @@
1
+ 'use client';
2
+ import { useRef, type HTMLAttributes } from 'react';
3
+ import { useIsomorphicLayoutEffect, useLatest } from '../../react/use-recipe';
4
+ import { createBreadcrumb, type BreadcrumbInstance, type BreadcrumbItem, type BreadcrumbOptions } from './engine';
5
+
6
+ export interface BreadcrumbProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'>, Omit<BreadcrumbOptions, 'items'> {
7
+ items: BreadcrumbItem[];
8
+ }
9
+
10
+ /** <Breadcrumb items={path} onNavigate={(item, i, event) => { event.preventDefault(); go(item.href) }} />. */
11
+ export function Breadcrumb({ items, label, maxItems, onNavigate, className, ...props }: BreadcrumbProps) {
12
+ const ref = useRef<HTMLDivElement>(null);
13
+ const instance = useRef<BreadcrumbInstance | null>(null);
14
+ const navigate = useLatest(onNavigate);
15
+ const key = JSON.stringify(items);
16
+ useIsomorphicLayoutEffect(() => {
17
+ const created = createBreadcrumb(ref.current, { items, label, maxItems, onNavigate: (item, index, event) => navigate.current?.(item, index, event) });
18
+ instance.current = created;
19
+ return () => {
20
+ created.destroy();
21
+ instance.current = null;
22
+ };
23
+ // eslint-disable-next-line react-hooks/exhaustive-deps
24
+ }, [label, maxItems]);
25
+ useIsomorphicLayoutEffect(() => {
26
+ if (instance.current && JSON.stringify(instance.current.items) !== key) instance.current.setItems(items);
27
+ // eslint-disable-next-line react-hooks/exhaustive-deps
28
+ }, [key]);
29
+ return <div {...props} ref={ref} className={['mk-breadcrumb', className].filter(Boolean).join(' ')} />;
30
+ }
@@ -0,0 +1,82 @@
1
+ # calendar
2
+
3
+ El calendario de Melon Mind. Tiene vista de mes y de semana, día de hoy marcado y eventos como chips con estado (pendiente, completado o cancelado), hora y color propio.
4
+
5
+ - **Al cargar:** los días entran desde arriba con blur (y −20 px, blur 16 → 0, 0.5 s), 5 ms uno tras otro, y después los eventos, 20 ms uno tras otro. Es el `flowChilds` del `CalendarComponent` original.
6
+ - **Cambiar de mes o semana:** la rejilla vieja sale 30 px hacia un lado (0.12 s) y, cuando ya casi no se ve, la nueva entra 30 px desde el otro (0.25 s `ease-out`), como los horarios de su selector de citas. Van en secuencia, sin fundido cruzado, para que no se mezclen dos meses llenos de eventos. Luego vuelven a entrar los eventos.
7
+ - **Hover:** el fondo del día cambia en 0.3 s y el número tiene resorte de radio y escala (`cubic-bezier(.38,.49,0,2)`).
8
+
9
+ Origen: patrón observado en la app de Melon Mind.
10
+
11
+ ## HTML / Astro
12
+
13
+ ```html
14
+ <mk-calendar class="mk-calendar" locale="es" first-day="0"
15
+ events='[{"id":1,"title":"Ana","start":"2026-10-23T10:00","status":"pending"}]'>
16
+ <div class="mk-calendar__header">
17
+ <h3 class="mk-calendar__title" data-mk-calendar-title>Calendario</h3>
18
+ <div class="mk-calendar__views" role="group" aria-label="Vista">
19
+ <button type="button" data-mk-calendar-view="month">Mes</button>
20
+ <button type="button" data-mk-calendar-view="week">Semana</button>
21
+ </div>
22
+ <button type="button" class="mk-calendar__nav" data-mk-calendar-prev aria-label="Anterior">←</button>
23
+ <button type="button" class="mk-calendar__nav" data-mk-calendar-today>Hoy</button>
24
+ <button type="button" class="mk-calendar__nav" data-mk-calendar-next aria-label="Siguiente">→</button>
25
+ </div>
26
+ <div data-mk-calendar-grid></div>
27
+ </mk-calendar>
28
+ <script>
29
+ import { defineElements } from '@yewdiel21/motion-kit/elements';
30
+ defineElements(['mk-calendar']);
31
+ </script>
32
+ ```
33
+
34
+ Sólo `[data-mk-calendar-grid]` es obligatorio. Las demás piezas del header son opcionales. Si cambias el atributo `events`, los eventos se actualizan sin perder el mes ni el foco. Sin custom element: `createCalendar(root, opciones)`.
35
+
36
+ ## React
37
+
38
+ ```tsx
39
+ <Calendar
40
+ events={citas}
41
+ onSelect={(day) => abrirDia(day)}
42
+ onEventClick={(event) => abrirCita(event.id)}
43
+ />
44
+ ```
45
+
46
+ `events` y `selected` se actualizan en el sitio. `date` y `view` son iniciales: el usuario navega libremente.
47
+
48
+ ## Opciones
49
+
50
+ | Opción | Atributo | Por defecto | Qué hace |
51
+ |---|---|---|---|
52
+ | `date` | `date` | hoy | Mes o semana inicial (`Date` o `"2026-10-23"`) |
53
+ | `view` | `view` | `'month'` | `'month'` o `'week'` |
54
+ | `firstDay` | `first-day` | `0` | Primer día de la semana (0 = domingo) |
55
+ | `locale` | `locale` | `'es'` | Nombres de mes y día, formato de hora |
56
+ | `events` | `events` (JSON) | `[]` | `{ id, title, start, end?, allDay?, status?, color? }` |
57
+ | `maxEvents` | `max-events` | `3` | Chips por día en la vista de mes antes de «+N más» |
58
+ | `selected` | `selected` | — | Día seleccionado |
59
+ | `today` | `today` | — | Fija «hoy» (demos, pruebas) |
60
+ | `labels` | — | español | `more(n)`, `events(n)`, `status` |
61
+ | `onSelect(date)`, `onEventClick(event)`, `onNavigate({start, end, view})` | — | — | Callbacks |
62
+
63
+ API: `next()`, `prev()`, `goToday()`, `setDate(d)`, `setView(v)`, `setEvents(list)`, `select(d | null, notify)`, `date`, `view`, `selected`, `range`, `destroy()`. Eventos DOM: `mk:select` `{date, key}`, `mk:event` `{event}` y `mk:navigate` `{start, end, view}`.
64
+
65
+ Un evento con `end` en otro día aparece en cada día que cubre, hasta dos meses.
66
+
67
+ ## Variables CSS
68
+
69
+ `--mk-calendar-gap`, `--mk-calendar-radius`, `--mk-calendar-day-height` y `--mk-calendar-event-color` (por evento, con `color`).
70
+
71
+ ## Accesibilidad
72
+
73
+ Rejilla ARIA (`grid` / `row` / `columnheader` / `gridcell`) con un solo botón de día en el orden de tabulación:
74
+
75
+ | Tecla | Acción |
76
+ |---|---|
77
+ | Flechas | Día anterior/siguiente, misma semana anterior/siguiente |
78
+ | Inicio / Fin | Principio/fin de semana |
79
+ | RePág / AvPág | Mes anterior/siguiente (con Mayúsculas, año) |
80
+ | Enter / Espacio | Seleccionar el día |
81
+
82
+ Cada día anuncia la fecha completa y cuántos eventos tiene. Hoy lleva `aria-current="date"`. Los chips son botones con título, hora y estado. En móvil (< 680 px) los chips del mes se reducen a puntos de color. Con movimiento reducido no hay entradas, deslizamiento ni transiciones.
@@ -0,0 +1,158 @@
1
+ /* calendar — Melon Mind's month/week grid on the --mk-* tokens; parts are .mk-calendar__*. */
2
+ .mk-calendar,
3
+ mk-calendar {
4
+ --mk-calendar-gap: 6px;
5
+ --mk-calendar-radius: var(--mk-radius-lg);
6
+ --mk-calendar-day-height: 112px;
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: var(--mk-space-3);
10
+ color: var(--mk-text);
11
+ }
12
+ .mk-calendar__header {
13
+ display: flex;
14
+ flex-wrap: wrap;
15
+ align-items: center;
16
+ gap: var(--mk-space-2);
17
+ }
18
+ .mk-calendar__title { margin: 0 auto 0 0; font-size: clamp(1.4rem, 2.6vw, 2rem); font-weight: 400; letter-spacing: -0.01em; }
19
+ .mk-calendar__views { display: inline-flex; padding: 4px; gap: 2px; border-radius: var(--mk-radius-full); background: var(--mk-surface-3); }
20
+ .mk-calendar__views button,
21
+ .mk-calendar__nav {
22
+ display: inline-grid;
23
+ place-items: center;
24
+ min-width: 44px;
25
+ height: 44px;
26
+ padding: 0 12px;
27
+ border: 0;
28
+ border-radius: var(--mk-radius-full);
29
+ background: transparent;
30
+ color: var(--mk-muted);
31
+ font: inherit;
32
+ cursor: pointer;
33
+ transition: background 0.2s, color 0.2s, transform 0.3s var(--mk-ease-nav-move);
34
+ }
35
+ .mk-calendar__views button[aria-pressed='true'] { background: var(--mk-surface-5); color: var(--mk-text); }
36
+ .mk-calendar__nav { background: var(--mk-surface-3); color: var(--mk-text); }
37
+ .mk-calendar__nav:active { transform: scale(0.92); }
38
+ :is(.mk-calendar__views button, .mk-calendar__nav):focus-visible { outline: 2px solid var(--mk-accent); outline-offset: 2px; }
39
+
40
+ [data-mk-calendar-grid] { position: relative; display: flex; flex-direction: column; gap: var(--mk-calendar-gap); }
41
+ .mk-calendar__head,
42
+ .mk-calendar__week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--mk-calendar-gap); }
43
+ .mk-calendar__body { display: flex; flex-direction: column; gap: var(--mk-calendar-gap); }
44
+ .mk-calendar__body--leaving { position: absolute; left: 0; right: 0; pointer-events: none; }
45
+ .mk-calendar__weekday {
46
+ padding: 8px 4px;
47
+ border-radius: var(--mk-radius-md);
48
+ background: var(--mk-surface-2);
49
+ text-align: center;
50
+ font-size: 0.95rem;
51
+ }
52
+ .mk-calendar__weekday-narrow { display: none; }
53
+
54
+ .mk-calendar__day {
55
+ position: relative;
56
+ display: flex;
57
+ flex-direction: column;
58
+ gap: 4px;
59
+ min-width: 0;
60
+ min-height: var(--mk-calendar-day-height);
61
+ padding: 6px;
62
+ border-radius: var(--mk-calendar-radius);
63
+ background: var(--mk-surface-3);
64
+ transition: background 0.3s, box-shadow 0.3s;
65
+ container-type: inline-size;
66
+ }
67
+ .mk-calendar__body[data-view='week'] .mk-calendar__day { min-height: calc(var(--mk-calendar-day-height) * 3); }
68
+ .mk-calendar__day[data-outside] { background: var(--mk-surface-1); color: var(--mk-muted); }
69
+ .mk-calendar__day:hover { background: var(--mk-surface-4); }
70
+ .mk-calendar__day[aria-selected='true'] { box-shadow: inset 0 0 0 2px var(--mk-accent); }
71
+ .mk-calendar__number {
72
+ align-self: flex-end;
73
+ min-width: 2.2rem;
74
+ height: 2.2rem;
75
+ padding: 0 0.4rem;
76
+ border: 0;
77
+ border-radius: var(--mk-radius-full);
78
+ background: transparent;
79
+ color: inherit;
80
+ font: inherit;
81
+ font-size: 1.15rem;
82
+ cursor: pointer;
83
+ transition: background 0.3s, color 0.3s, border-radius 0.3s var(--mk-ease-nav-radius), transform 0.3s var(--mk-ease-nav-radius);
84
+ }
85
+ .mk-calendar__number:hover { background: var(--mk-surface-5); }
86
+ .mk-calendar__number:active { transform: scale(0.9); }
87
+ .mk-calendar__number:focus-visible { outline: 2px solid var(--mk-accent); outline-offset: 2px; }
88
+ .mk-calendar__day[data-today] .mk-calendar__number { background: var(--mk-accent); color: var(--mk-on-accent); }
89
+
90
+ .mk-calendar__events { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
91
+ .mk-calendar__event,
92
+ .mk-calendar__more {
93
+ --mk-calendar-event-color: var(--mk-accent);
94
+ display: flex;
95
+ align-items: center;
96
+ gap: 6px;
97
+ width: 100%;
98
+ min-width: 0;
99
+ padding: 5px 8px;
100
+ border: 0;
101
+ border-radius: 10px;
102
+ background: var(--mk-surface-4);
103
+ color: var(--mk-text);
104
+ font: inherit;
105
+ font-size: 0.85rem;
106
+ text-align: left;
107
+ cursor: pointer;
108
+ transition: background 0.2s, transform 0.3s var(--mk-ease-nav-move);
109
+ }
110
+ .mk-calendar__event[data-state='pending'] {
111
+ background: color-mix(in srgb, var(--mk-calendar-event-color) 30%, var(--mk-surface-3));
112
+ }
113
+ .mk-calendar__event:hover,
114
+ .mk-calendar__more:hover { transform: translateY(-1px); background: var(--mk-surface-5); }
115
+ .mk-calendar__event:focus-visible,
116
+ .mk-calendar__more:focus-visible { outline: 2px solid var(--mk-accent); outline-offset: 1px; }
117
+ .mk-calendar__status {
118
+ flex: none;
119
+ width: 0.8rem;
120
+ height: 0.8rem;
121
+ border: 2px solid currentColor;
122
+ border-radius: 50%;
123
+ }
124
+ .mk-calendar__event[data-state='done'] .mk-calendar__status { background: currentColor; box-shadow: inset 0 0 0 2px var(--mk-surface-4); }
125
+ .mk-calendar__event[data-state='cancelled'] .mk-calendar__event-title { text-decoration: line-through; opacity: 0.6; }
126
+ .mk-calendar__event-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
127
+ .mk-calendar__event-time { flex: none; font-variant-numeric: tabular-nums; opacity: 0.85; }
128
+ .mk-calendar__more { justify-content: center; background: transparent; color: var(--mk-muted); }
129
+
130
+ /* Narrow day cells: the month keeps the title (the time stays in the label); the week stacks the time under it. */
131
+ @container (max-width: 150px) {
132
+ .mk-calendar__body[data-view='month'] .mk-calendar__event-time { display: none; }
133
+ .mk-calendar__body[data-view='week'] .mk-calendar__event { flex-wrap: wrap; column-gap: 5px; row-gap: 1px; }
134
+ .mk-calendar__body[data-view='week'] .mk-calendar__event-title { flex: 1 1 0; }
135
+ .mk-calendar__body[data-view='week'] .mk-calendar__event-time { flex-basis: 100%; padding-left: calc(0.8rem + 5px); font-size: 0.72rem; }
136
+ }
137
+ @media (max-width: 680px) {
138
+ .mk-calendar,
139
+ mk-calendar { --mk-calendar-day-height: 64px; --mk-calendar-gap: 4px; --mk-calendar-radius: var(--mk-radius-sm); }
140
+ .mk-calendar__weekday-long { display: none; }
141
+ .mk-calendar__weekday-narrow { display: inline; }
142
+ .mk-calendar__number { align-self: center; font-size: 0.95rem; }
143
+ .mk-calendar__body[data-view='month'] .mk-calendar__events { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 3px; }
144
+ .mk-calendar__body[data-view='month'] :is(.mk-calendar__event, .mk-calendar__more) {
145
+ width: 7px;
146
+ height: 7px;
147
+ padding: 0;
148
+ border-radius: 50%;
149
+ background: var(--mk-calendar-event-color);
150
+ font-size: 0;
151
+ }
152
+ .mk-calendar__body[data-view='month'] .mk-calendar__status { display: none; }
153
+ .mk-calendar__body[data-view='week'] .mk-calendar__event-time { display: none; }
154
+ }
155
+ @media (prefers-reduced-motion: reduce) {
156
+ .mk-calendar *,
157
+ mk-calendar * { transition: none !important; }
158
+ }
@@ -0,0 +1,27 @@
1
+ import { MkElement, defineElement, type OptionType } from '../../elements/base';
2
+ import { createCalendar, type CalendarEvent, type CalendarInstance } from './engine';
3
+
4
+ /** Light DOM: supply the header and the [data-mk-calendar-grid] shown in the README. */
5
+ export class MkCalendarElement extends MkElement<CalendarInstance> {
6
+ static options: Record<string, OptionType> = {
7
+ date: 'string', view: 'string', firstDay: 'number', locale: 'string', maxEvents: 'number', events: 'json', selected: 'string', today: 'string',
8
+ };
9
+
10
+ protected create(options: Record<string, unknown>) {
11
+ return createCalendar(this, options);
12
+ }
13
+
14
+ attributeChangedCallback(name: string, previous: string | null, next: string | null) {
15
+ if (previous === next || !this.isConnected || !this.instance) return;
16
+ if (name === 'events') {
17
+ this.instance.setEvents((this.options.events as CalendarEvent[] | undefined) ?? []);
18
+ return;
19
+ }
20
+ // Keep where the visitor is unless the changed attribute says otherwise.
21
+ const { date, view, selected } = this.instance;
22
+ this.instance.destroy();
23
+ this.instance = this.create({ date, view, selected, ...this.options });
24
+ }
25
+ }
26
+
27
+ export const defineCalendar = () => defineElement('mk-calendar', MkCalendarElement);