@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,243 @@
1
+ /* tag-input — a 12 px field on surface-3 with 8 px chips and the input; the reason a tag was refused sits under it in
2
+ the error colour. The chips and the listbox rules below are shared with multi-select (each stylesheet works alone). */
3
+ .mk-tag-input,
4
+ mk-tag-input {
5
+ display: block;
6
+ min-width: 0;
7
+ }
8
+
9
+ [data-mk-tag-field] {
10
+ display: flex;
11
+ flex-wrap: wrap;
12
+ align-items: center;
13
+ gap: 0.35rem;
14
+ box-sizing: border-box;
15
+ min-height: 2.75rem;
16
+ padding: 0.35rem 0.5rem;
17
+ border-radius: 12px;
18
+ background: var(--mk-surface-3);
19
+ color: var(--mk-text);
20
+ cursor: text;
21
+ transition: box-shadow 0.2s ease;
22
+ }
23
+
24
+ [data-mk-tag-field]:focus-within {
25
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--mk-accent) 35%, transparent);
26
+ }
27
+
28
+ [data-mk-tag-field]:has([aria-invalid='true']) {
29
+ box-shadow: 0 0 0 2px var(--mk-error, #c62828);
30
+ }
31
+
32
+ [data-mk-tag-input] {
33
+ flex: 1;
34
+ min-width: 8ch;
35
+ height: 1.75rem;
36
+ padding: 0 0.25rem;
37
+ border: 0;
38
+ background: transparent;
39
+ color: inherit;
40
+ font: inherit;
41
+ outline: none;
42
+ }
43
+
44
+ [data-mk-tag-input]::placeholder {
45
+ color: var(--mk-muted);
46
+ }
47
+
48
+ [data-mk-tag-error] {
49
+ margin: 0.4rem 0 0;
50
+ color: var(--mk-error, #c62828);
51
+ font-size: 0.8125rem;
52
+ }
53
+
54
+ [data-mk-tag-error][hidden] {
55
+ display: none;
56
+ }
57
+
58
+ @media (prefers-reduced-motion: reduce) {
59
+ [data-mk-tag-field] {
60
+ transition: none;
61
+ }
62
+ }
63
+
64
+ /* Chips (core/chips.ts): 8 px, accent-soft, a round remove button; the armed one (next Backspace) gets a ring. */
65
+ [data-mk-chips] {
66
+ display: contents;
67
+ margin: 0;
68
+ padding: 0;
69
+ list-style: none;
70
+ }
71
+
72
+ [data-mk-chip] {
73
+ display: inline-flex;
74
+ flex: none;
75
+ align-items: center;
76
+ gap: 0.15rem;
77
+ box-sizing: border-box;
78
+ max-width: 100%;
79
+ height: 1.75rem;
80
+ padding: 0 0.2rem 0 0.6rem;
81
+ overflow: hidden;
82
+ border-radius: 8px;
83
+ background: var(--mk-accent-soft);
84
+ color: var(--mk-on-accent-soft, var(--mk-text));
85
+ font-size: 0.8125rem;
86
+ font-weight: 500;
87
+ white-space: nowrap;
88
+ outline: none;
89
+ transition: box-shadow 0.2s ease;
90
+ }
91
+
92
+ [data-mk-chip-label] {
93
+ overflow: hidden;
94
+ text-overflow: ellipsis;
95
+ }
96
+
97
+ [data-mk-chip]:focus-visible,
98
+ [data-mk-chip][data-mk-armed] {
99
+ box-shadow: 0 0 0 2px var(--mk-accent);
100
+ }
101
+
102
+ [data-mk-chip-remove] {
103
+ display: grid;
104
+ flex: none;
105
+ place-items: center;
106
+ width: 1.25rem;
107
+ height: 1.25rem;
108
+ padding: 0;
109
+ border: 0;
110
+ border-radius: 50%;
111
+ background: transparent;
112
+ color: inherit;
113
+ cursor: pointer;
114
+ opacity: 0.7;
115
+ transition: background-color 0.15s ease, opacity 0.15s ease;
116
+ }
117
+
118
+ [data-mk-chip-remove]:hover {
119
+ background: color-mix(in srgb, currentColor 14%, transparent);
120
+ opacity: 1;
121
+ }
122
+
123
+ /* Listbox (core/listbox.ts): a 16 px panel in the top layer under the field; the active option sits on a pill. */
124
+ [data-mk-listbox] {
125
+ position: fixed;
126
+ inset: auto;
127
+ z-index: 2147482000;
128
+ box-sizing: border-box;
129
+ max-height: min(18rem, 50vh);
130
+ margin: 0;
131
+ padding: 0.35rem;
132
+ overflow: auto;
133
+ border: 1px solid var(--mk-outline-soft);
134
+ border-radius: 16px;
135
+ background: var(--mk-surface-1);
136
+ color: var(--mk-text);
137
+ box-shadow: 0 16px 40px -14px color-mix(in srgb, var(--mk-shadow-color, #000) 35%, transparent);
138
+ font: 0.9375rem/1.3 var(--mk-font, system-ui, sans-serif);
139
+ overscroll-behavior: contain;
140
+ }
141
+
142
+ [data-mk-listbox][hidden] {
143
+ display: none;
144
+ }
145
+
146
+ [data-mk-listbox-items] {
147
+ position: relative;
148
+ display: grid;
149
+ gap: 2px;
150
+ }
151
+
152
+ [data-mk-listbox-pill] {
153
+ position: absolute;
154
+ top: 0.35rem;
155
+ right: 0.35rem;
156
+ left: 0.35rem;
157
+ border-radius: 10px;
158
+ background: var(--mk-accent-soft);
159
+ opacity: 0;
160
+ pointer-events: none;
161
+ }
162
+
163
+ [data-mk-option] {
164
+ position: relative;
165
+ z-index: 1;
166
+ display: flex;
167
+ align-items: center;
168
+ gap: 0.6rem;
169
+ min-height: 2.5rem;
170
+ padding: 0 0.75rem;
171
+ border-radius: 10px;
172
+ cursor: pointer;
173
+ user-select: none;
174
+ }
175
+
176
+ [data-mk-option][aria-disabled='true'] {
177
+ color: var(--mk-muted);
178
+ cursor: not-allowed;
179
+ opacity: 0.55;
180
+ }
181
+
182
+ [data-mk-option-label] {
183
+ flex: 1;
184
+ min-width: 0;
185
+ overflow-wrap: anywhere;
186
+ }
187
+
188
+ [data-mk-option-label] mark {
189
+ background: transparent;
190
+ color: inherit;
191
+ font-weight: 700;
192
+ text-decoration: underline;
193
+ text-decoration-color: var(--mk-accent);
194
+ text-decoration-thickness: 2px;
195
+ text-underline-offset: 3px;
196
+ }
197
+
198
+ [data-mk-option-hint] {
199
+ color: var(--mk-muted);
200
+ font-size: 0.8125rem;
201
+ }
202
+
203
+ [data-mk-option-check] {
204
+ display: grid;
205
+ flex: none;
206
+ place-items: center;
207
+ width: 1.15rem;
208
+ height: 1.15rem;
209
+ border: 1.5px solid var(--mk-outline);
210
+ border-radius: 5px;
211
+ color: transparent;
212
+ transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
213
+ }
214
+
215
+ [data-mk-option][aria-selected='true'] [data-mk-option-check] {
216
+ border-color: var(--mk-accent);
217
+ background: var(--mk-accent);
218
+ color: var(--mk-on-accent);
219
+ }
220
+
221
+ [data-mk-listbox-group] {
222
+ padding: 0.6rem 0.75rem 0.25rem;
223
+ color: var(--mk-muted);
224
+ font-size: 0.75rem;
225
+ font-weight: 600;
226
+ letter-spacing: 0.02em;
227
+ text-transform: uppercase;
228
+ }
229
+
230
+ [data-mk-listbox-empty] {
231
+ padding: 0.75rem;
232
+ color: var(--mk-muted);
233
+ font-size: 0.875rem;
234
+ text-align: center;
235
+ }
236
+
237
+ @media (prefers-reduced-motion: reduce) {
238
+ [data-mk-chip],
239
+ [data-mk-chip-remove],
240
+ [data-mk-option-check] {
241
+ transition: none;
242
+ }
243
+ }
@@ -0,0 +1,54 @@
1
+ # time-field
2
+
3
+ Hora por segmentos: hora, minutos (y segundos) en el orden del idioma, con a. m./p. m. donde el idioma escribe 12 horas (`es`: 24 h; `en-US`: 12 h). El valor siempre es texto de 24 h («13:05»).
4
+
5
+ Cada segmento es un `role="spinbutton"`. Las flechas cambian el valor con vuelta y los dígitos ruedan en la dirección del cambio; al teclear se rellena el segmento y se pasa al siguiente; una píldora se desliza tras el segmento con foco (curva swing). En el móvil se abre el teclado numérico (`inputmode="numeric"`), pero el componente escribe siempre el texto: no se cuela nada raro. `min` y `max` marcan el grupo como no válido (una sacudida al pasar a no válido), aunque el valor se sigue informando, como en un input nativo.
6
+
7
+ ## HTML / Astro
8
+
9
+ ```html
10
+ <mk-time-field class="mk-time-field" value="09:30" minute-step="15" min="09:00" max="20:00" name="hora"></mk-time-field>
11
+ <mk-time-field class="mk-time-field" locale="en-US" seconds></mk-time-field>
12
+ ```
13
+
14
+ ## React
15
+
16
+ ```tsx
17
+ const [time, setTime] = useState<string | null>('09:30');
18
+ <TimeField value={time} onChange={setTime} minuteStep={15} />
19
+ ```
20
+
21
+ ## Opciones
22
+
23
+ | Opción | Atributo | Por defecto | Qué hace |
24
+ |---|---|---|---|
25
+ | `value` | `value` | vacío | `'HH:MM'` o `'HH:MM:SS'` (24 h). |
26
+ | `locale` | `locale` | `lang` de la página, o `es` | Orden de los segmentos y formato de 12/24 h. |
27
+ | `hourCycle` | `hour-cycle` | el del idioma | `12` o `24`. |
28
+ | `seconds` | `seconds` | `false` | Añade los segundos. |
29
+ | `minuteStep` | `minute-step` | `1` | Paso de las flechas en minutos (y segundos). |
30
+ | `min`, `max` | `min`, `max` | — | `'HH:MM'`; fuera de rango marca `aria-invalid`. |
31
+ | `label` | `label` | `'Hora'` | Nombre accesible del grupo. |
32
+ | `name` | `name` | — | Input oculto con el texto de 24 h. |
33
+ | `disabled`, `readOnly` | `disabled`, `read-only` | `false` | Estados. |
34
+ | `onChange(value)` | — | — | Cada cambio; `null` mientras falte algún segmento. |
35
+
36
+ ## Teclado
37
+
38
+ | Tecla | Acción |
39
+ |---|---|
40
+ | ↑ / ↓ | Cambia el segmento (con vuelta: 23 → 00) |
41
+ | RePág / AvPág | Saltos grandes (3 horas, 15 minutos) |
42
+ | Inicio / Fin | Mínimo / máximo del segmento |
43
+ | ← / → | Segmento anterior / siguiente |
44
+ | Dígitos | Rellenan el segmento y pasan al siguiente |
45
+ | Retroceso / Supr | Vacía el segmento; si ya está vacío, vuelve al anterior |
46
+ | «a» / «p» | a. m. / p. m. |
47
+
48
+ ## API y eventos
49
+
50
+ `setValue(value | null, animate = true)`, `focus()`, `value`, `destroy()`. Evento `mk:change` con `{ value }`.
51
+
52
+ ## Estilos
53
+
54
+ Campo de 12 px sobre `--mk-surface-3`, cifras tabulares, píldora de foco de 6 px en `--mk-accent-soft`; los segmentos vacíos se ven atenuados; no válido dibuja un anillo de `--mk-error`. Con movimiento reducido no hay rodillo ni píldora: el segmento con foco toma el color directamente.
@@ -0,0 +1,38 @@
1
+ import { MkElement, defineElement, type OptionType } from '../../elements/base';
2
+ import { createTimeField, type TimeFieldInstance } from './engine';
3
+
4
+ /**
5
+ * <mk-time-field class="mk-time-field" value="09:30" minute-step="15" name="hora"></mk-time-field>
6
+ * Emits mk:change ({value}: 24 h text, null while incomplete).
7
+ */
8
+ export class MkTimeFieldElement extends MkElement<TimeFieldInstance> {
9
+ static options: Record<string, OptionType> = {
10
+ value: 'string',
11
+ locale: 'string',
12
+ hourCycle: 'number',
13
+ seconds: 'boolean',
14
+ minuteStep: 'number',
15
+ min: 'string',
16
+ max: 'string',
17
+ label: 'string',
18
+ name: 'string',
19
+ disabled: 'boolean',
20
+ readOnly: 'boolean',
21
+ };
22
+
23
+ protected create(options: Record<string, unknown>) {
24
+ return createTimeField(this, options);
25
+ }
26
+
27
+ attributeChangedCallback(name: string, previous: string | null, next: string | null) {
28
+ if (previous === next || !this.instance) return;
29
+ if (name === 'value') this.instance.setValue(next);
30
+ else super.attributeChangedCallback(name, previous, next);
31
+ }
32
+
33
+ get value() {
34
+ return this.instance?.value ?? null;
35
+ }
36
+ }
37
+
38
+ export const defineTimeField = () => defineElement('mk-time-field', MkTimeFieldElement);
@@ -0,0 +1,110 @@
1
+ import { createScope } from '../../core/scope';
2
+ import { registerMotion } from '../../core/gsap';
3
+ import { inert, type Instance } from '../../core/types';
4
+ import { formatTime, parseTime, timeMinutes, to12, to24 } from '../../core/segments';
5
+ import { createSegmentField, type SegmentValues } from '../../core/segment-field';
6
+
7
+ /*
8
+ * Time field: hour, minute (and second) segments in the locale's order, with
9
+ * a.m./p.m. where the locale writes 12 hours. The value is always 24 h text
10
+ * ("13:05"). Arrows step with wrap and the digits roll; typing fills and moves
11
+ * on; a pill glides to the focused segment (core/segment-field.ts). min/max
12
+ * mark the group invalid (one shake when it becomes invalid) but the value is
13
+ * still reported, like a native input.
14
+ */
15
+
16
+ export interface TimeFieldOptions {
17
+ /** 'HH:MM' or 'HH:MM:SS' (24 h). */
18
+ value?: string | null;
19
+ locale?: string;
20
+ /** 12 or 24; default: the locale's. */
21
+ hourCycle?: 12 | 24;
22
+ seconds?: boolean;
23
+ /** Arrow step of the minutes (and seconds). */
24
+ minuteStep?: number;
25
+ min?: string;
26
+ max?: string;
27
+ /** Accessible name of the group (default 'Hora'). */
28
+ label?: string;
29
+ /** Hidden input with the 24 h text. */
30
+ name?: string;
31
+ disabled?: boolean;
32
+ readOnly?: boolean;
33
+ onChange?: (value: string | null) => void;
34
+ }
35
+
36
+ export interface TimeFieldInstance extends Instance {
37
+ setValue(value: string | null, animate?: boolean): void;
38
+ focus(): void;
39
+ readonly value: string | null;
40
+ }
41
+
42
+ export function createTimeField(root: HTMLElement | null, options: TimeFieldOptions = {}): TimeFieldInstance {
43
+ if (!root) return inert({ setValue() {}, focus() {}, value: null });
44
+ registerMotion();
45
+ const scope = createScope();
46
+ const locale = options.locale ?? root.closest('[lang]')?.getAttribute('lang') ?? 'es';
47
+ const seconds = Boolean(options.seconds);
48
+ const step = options.minuteStep && options.minuteStep > 0 ? Math.round(options.minuteStep) : 1;
49
+ const min = parseTime(options.min);
50
+ const max = parseTime(options.max);
51
+ let value: string | null = null;
52
+ let invalid = false;
53
+
54
+ const hidden = options.name ? document.createElement('input') : null;
55
+ const field = createSegmentField(root, {
56
+ kind: 'time',
57
+ locale,
58
+ hour12: options.hourCycle ? options.hourCycle === 12 : undefined,
59
+ seconds,
60
+ steps: { minute: step, second: step },
61
+ disabled: options.disabled,
62
+ readOnly: options.readOnly,
63
+ onChange: (values) => {
64
+ update(values);
65
+ options.onChange?.(value);
66
+ root.dispatchEvent(new CustomEvent('mk:change', { bubbles: true, detail: { value } }));
67
+ },
68
+ });
69
+ scope.add(() => field.destroy());
70
+ field.element.setAttribute('aria-label', options.label ?? 'Hora');
71
+ if (hidden) {
72
+ hidden.type = 'hidden';
73
+ hidden.name = options.name!;
74
+ root.append(hidden);
75
+ scope.add(() => hidden.remove());
76
+ }
77
+ scope.attr(root, 'data-mk-ready', '');
78
+ const twelve = field.element.querySelector('[data-mk-segment="dayPeriod"]') !== null;
79
+
80
+ const update = (values: SegmentValues, initial = false) => {
81
+ const complete = values.hour != null && values.minute != null && (!seconds || values.second != null) && (!twelve || values.dayPeriod != null);
82
+ const time = complete ? { hour: twelve ? to24(values.hour!, values.dayPeriod!) : values.hour!, minute: values.minute!, second: values.second ?? 0 } : null;
83
+ value = time ? formatTime(time, seconds) : null;
84
+ if (hidden) hidden.value = value ?? '';
85
+ const out = !!time && ((!!min && timeMinutes(time) < timeMinutes(min)) || (!!max && timeMinutes(time) > timeMinutes(max)));
86
+ field.invalid(out, out && !invalid && !initial);
87
+ invalid = out;
88
+ };
89
+
90
+ const setValue = (next: string | null, animate = true) => {
91
+ if (scope.disposed) return;
92
+ const time = parseTime(next);
93
+ if (!time) field.setValues({ hour: null, minute: null, second: null, dayPeriod: null }, animate);
94
+ else if (twelve) {
95
+ const { hour, period } = to12(time.hour);
96
+ field.setValues({ hour, dayPeriod: period, minute: time.minute, second: time.second }, animate);
97
+ } else field.setValues({ hour: time.hour, minute: time.minute, second: time.second }, animate);
98
+ update(field.values(), true);
99
+ };
100
+ setValue(options.value ?? null, false);
101
+
102
+ return {
103
+ setValue,
104
+ focus: () => field.focus('first'),
105
+ get value() {
106
+ return value;
107
+ },
108
+ destroy: () => scope.dispose(),
109
+ };
110
+ }
@@ -0,0 +1,45 @@
1
+ 'use client';
2
+ import { useRef, type HTMLAttributes } from 'react';
3
+ import { useIsomorphicLayoutEffect, useLatest } from '../../react/use-recipe';
4
+ import { createTimeField, type TimeFieldInstance, type TimeFieldOptions } from './engine';
5
+
6
+ export interface TimeFieldProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>, Omit<TimeFieldOptions, 'value'> {
7
+ /** Controlled time ('HH:MM', 24 h); without it the field keeps its own (defaultValue). */
8
+ value?: string | null;
9
+ defaultValue?: string | null;
10
+ }
11
+
12
+ /** <TimeField value={time} onChange={setTime} minuteStep={15} />. */
13
+ export function TimeField({ value, defaultValue, locale, hourCycle, seconds, minuteStep, min, max, label, name, disabled, readOnly, onChange, className, ...props }: TimeFieldProps) {
14
+ const ref = useRef<HTMLDivElement>(null);
15
+ const instance = useRef<TimeFieldInstance | null>(null);
16
+ const change = useLatest(onChange);
17
+ const start = useRef(value !== undefined ? value : (defaultValue ?? null));
18
+ useIsomorphicLayoutEffect(() => {
19
+ const created = createTimeField(ref.current, {
20
+ value: value !== undefined ? value : start.current,
21
+ locale,
22
+ hourCycle,
23
+ seconds,
24
+ minuteStep,
25
+ min,
26
+ max,
27
+ label,
28
+ name,
29
+ disabled,
30
+ readOnly,
31
+ onChange: (next) => change.current?.(next),
32
+ });
33
+ instance.current = created;
34
+ return () => {
35
+ start.current = created.value;
36
+ created.destroy();
37
+ instance.current = null;
38
+ };
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40
+ }, [locale, hourCycle, seconds, minuteStep, min, max, label, name, disabled, readOnly]);
41
+ useIsomorphicLayoutEffect(() => {
42
+ if (value !== undefined && instance.current && instance.current.value !== value) instance.current.setValue(value);
43
+ }, [value]);
44
+ return <div {...props} ref={ref} className={['mk-time-field', className].filter(Boolean).join(' ')} />;
45
+ }
@@ -0,0 +1,87 @@
1
+ /* time-field — a 12 px field on surface-3; tabular digits; the focused segment sits on a 6 px accent-soft pill that
2
+ glides between segments; empty segments are muted dashes; invalid draws an error ring. */
3
+ .mk-time-field,
4
+ mk-time-field {
5
+ display: inline-block;
6
+ max-width: 100%;
7
+ }
8
+
9
+ :is(.mk-time-field, mk-time-field) [data-mk-segments] {
10
+ position: relative;
11
+ display: inline-flex;
12
+ align-items: center;
13
+ min-height: 2.75rem;
14
+ padding: 0 0.75rem;
15
+ border-radius: 12px;
16
+ background: var(--mk-surface-3);
17
+ color: var(--mk-text);
18
+ font-variant-numeric: tabular-nums;
19
+ white-space: nowrap;
20
+ transition: box-shadow 0.2s ease;
21
+ }
22
+
23
+ :is(.mk-time-field, mk-time-field) [data-mk-segments]:focus-within {
24
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--mk-accent) 35%, transparent);
25
+ }
26
+
27
+ :is(.mk-time-field, mk-time-field) [data-mk-segments][aria-invalid='true'] {
28
+ box-shadow: 0 0 0 2px var(--mk-error, #d93025);
29
+ }
30
+
31
+ :is(.mk-time-field, mk-time-field) [data-mk-segments][aria-disabled='true'] {
32
+ opacity: 0.5;
33
+ }
34
+
35
+ :is(.mk-time-field, mk-time-field) [data-mk-segment] {
36
+ position: relative;
37
+ z-index: 1;
38
+ padding: 0.2rem 0.15rem;
39
+ border-radius: 6px;
40
+ caret-color: transparent;
41
+ outline: none;
42
+ cursor: default;
43
+ }
44
+
45
+ :is(.mk-time-field, mk-time-field) [data-mk-segment][data-mk-empty] {
46
+ color: var(--mk-muted);
47
+ }
48
+
49
+ :is(.mk-time-field, mk-time-field) [data-mk-segment]:focus {
50
+ color: var(--mk-on-accent-soft, var(--mk-text));
51
+ }
52
+
53
+ :is(.mk-time-field, mk-time-field) [data-mk-segment]::selection {
54
+ background: transparent;
55
+ }
56
+
57
+ :is(.mk-time-field, mk-time-field) [data-mk-segment-literal] {
58
+ padding: 0 0.05rem;
59
+ color: var(--mk-muted);
60
+ }
61
+
62
+ :is(.mk-time-field, mk-time-field) [data-mk-segment-focus] {
63
+ position: absolute;
64
+ top: 50%;
65
+ left: 0;
66
+ height: 1.75rem;
67
+ margin-top: -0.875rem;
68
+ border-radius: 6px;
69
+ background: var(--mk-accent-soft);
70
+ opacity: 0;
71
+ pointer-events: none;
72
+ }
73
+
74
+ /* Without motion the pill is not drawn: the focused segment gets the colour directly. */
75
+ @media (prefers-reduced-motion: reduce) {
76
+ :is(.mk-time-field, mk-time-field) [data-mk-segment]:focus {
77
+ background: var(--mk-accent-soft);
78
+ }
79
+
80
+ :is(.mk-time-field, mk-time-field) [data-mk-segment-focus] {
81
+ display: none;
82
+ }
83
+
84
+ :is(.mk-time-field, mk-time-field) [data-mk-segments] {
85
+ transition: none;
86
+ }
87
+ }
@@ -0,0 +1,57 @@
1
+ # timeline
2
+
3
+ Línea de tiempo para historiales de actividades, cambios y eventos: cada evento es un punto sobre un riel, con su hora («hace 2 h», con la fecha completa en el título; se actualiza cada minuto), un título, una descripción y un dato pequeño. El punto lleva un icono o el color de su estado: hecho, en curso (su anillo respira), pendiente (con borde punteado) o con error. El tramo recorrido del riel se rellena con el acento hasta el evento en curso.
4
+
5
+ Al entrar en pantalla, el riel se dibuja desde el primer punto (.8 s, curva wipe) y los eventos aparecen en cascada saliendo de un blur, 60 ms entre uno y otro. `add()` mete un evento al principio o al final: los demás se deslizan para hacerle sitio (el riel los sigue), el nuevo entra desde un blur, su punto hace pop y un resaltado suave se apaga detrás de él. `update()` lo cambia en su sitio (un estado nuevo vuelve a hacer pop) y `remove()` lo pliega. Con `layout="alternate"`, cuando la línea de tiempo mide 520 px o más, los eventos se reparten a los dos lados del riel; `group` pone cada día como una etiqueta sobre el riel («Hoy», «Ayer», «Lunes, 16 de noviembre»).
6
+
7
+ ## HTML / Astro
8
+
9
+ ```html
10
+ <!-- Eventos en JSON… -->
11
+ <mk-timeline class="mk-timeline" group
12
+ events='[{"id":"1","title":"Pedido recibido","time":"2026-11-23T09:12","status":"done","icon":"✓"},
13
+ {"id":"2","title":"En camino","time":"2026-11-23T14:30","status":"current","description":"Salió de Monterrey"},
14
+ {"id":"3","title":"Entrega","status":"upcoming","meta":"Estimada: jueves"}]'></mk-timeline>
15
+
16
+ <!-- …o escritos: el texto del <li> es el título y el <p>, la descripción. -->
17
+ <mk-timeline class="mk-timeline">
18
+ <ol>
19
+ <li data-status="done" data-time="2026-11-20">Alta de la cuenta<p>Plan Pro, facturación mensual</p></li>
20
+ <li data-status="current" data-time="2026-11-21T10:00" data-icon="★">Primer proyecto</li>
21
+ </ol>
22
+ </mk-timeline>
23
+
24
+ <script>
25
+ const timeline = document.querySelector('mk-timeline');
26
+ timeline.add({ id: '4', title: 'Entregado', status: 'done', time: new Date() });
27
+ </script>
28
+ ```
29
+
30
+ ## React
31
+
32
+ ```tsx
33
+ <Timeline events={history} layout="alternate" group />
34
+ ```
35
+
36
+ Cambiar `events` actualiza en su sitio: un evento nuevo en un extremo entra con su animación, uno que cambia de estado vuelve a colorear su punto y uno que desaparece se pliega.
37
+
38
+ ## Opciones
39
+
40
+ | Opción | Atributo | Por defecto | Qué hace |
41
+ |---|---|---|---|
42
+ | `events` | `events` (JSON) | los `<li>` escritos | `{ id, title, description?, time?, status?, icon?, meta? }[]`; `status`: `done`, `current`, `upcoming` o `error`. |
43
+ | `layout` | `layout` | `'start'` | `'alternate'` reparte los eventos a los dos lados del riel cuando la línea mide 520 px o más. |
44
+ | `group` | `group` | `false` | Un encabezado por día. |
45
+ | `relative` | `relative` | `true` | Horas relativas («hace 5 min»); `false` muestra fecha y hora. |
46
+ | `locale` | `locale` | el `lang` más cercano | Idioma de las fechas. |
47
+ | `label` | `label` | `'Historial'` | Nombre accesible de la lista. |
48
+
49
+ `time` acepta un `Date`, una cadena ISO (`2026-11-23` o `2026-11-23T09:12`) o una marca de tiempo.
50
+
51
+ ## API
52
+
53
+ `add(event, 'start' | 'end')`, `update(id, cambios)`, `remove(id)`, `setEvents(events)`, `events`, `destroy()`.
54
+
55
+ ## Accesibilidad
56
+
57
+ Una lista ordenada con nombre propio; cada hora es un `<time datetime>` con la fecha completa en su título, y el estado de cada evento («En curso», «Pendiente», «Con error») se lee después del título. Los encabezados de día son de presentación. Con movimiento reducido no hay animación de entrada y los cambios ocurren sin transición.
@@ -0,0 +1,31 @@
1
+ import { MkElement, defineElement, type OptionType } from '../../elements/base';
2
+ import { createTimeline, type TimelineEvent, type TimelineInstance } from './engine';
3
+
4
+ /**
5
+ * <mk-timeline class="mk-timeline" events='[{"id":"1","title":"Pedido recibido","time":"2026-11-23T09:12","status":"done"}]'>
6
+ * </mk-timeline> — or authored <ol><li data-status data-time>Title<p>Description</p></li></ol>.
7
+ */
8
+ export class MkTimelineElement extends MkElement<TimelineInstance> {
9
+ static options: Record<string, OptionType> = { events: 'json', layout: 'string', group: 'boolean', relative: 'boolean', locale: 'string', label: 'string' };
10
+
11
+ protected create(options: Record<string, unknown>) {
12
+ return createTimeline(this, options);
13
+ }
14
+
15
+ attributeChangedCallback(name: string, previous: string | null, next: string | null) {
16
+ if (previous === next || !this.instance) return;
17
+ if (name === 'events') {
18
+ try {
19
+ this.instance.setEvents(JSON.parse(next ?? '[]') as TimelineEvent[]);
20
+ } catch {
21
+ // Malformed JSON: keep the current events.
22
+ }
23
+ } else super.attributeChangedCallback(name, previous, next);
24
+ }
25
+
26
+ add(event: TimelineEvent, at?: 'start' | 'end') {
27
+ this.instance?.add(event, at);
28
+ }
29
+ }
30
+
31
+ export const defineTimeline = () => defineElement('mk-timeline', MkTimelineElement);