@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,442 @@
1
+ import { gsap, EASE, registerMotion } from '../../core/gsap';
2
+ import { reduced } from '../../core/reduced';
3
+ import { createScope } from '../../core/scope';
4
+ import { inert, type Instance } from '../../core/types';
5
+ import { numberFormat } from '../../core/dates';
6
+ import { rollDigits } from '../../motion/micro';
7
+
8
+ /*
9
+ * Chart tooltip: an advanced card for charts. Over the kit's chart (created
10
+ * with tooltip: false) it follows the chart's selection — mk:select brings the
11
+ * point, each series and its previous value — and leaves the guide and markers
12
+ * to the chart. Over any other chart it tracks the pointer itself across
13
+ * `labels` (edge to edge for lines, slot centres for bars, inside `inset`),
14
+ * drawing a dotted guide and, with `min`/`max`, a marker per series; the
15
+ * keyboard moves it too (arrows, Home, End, Escape). The card is Melon Mind's
16
+ * inverse glass: the label, one row per series with its value, the change from
17
+ * the previous point (▲ ▼ %) and optionally its share, a total, rows sorted by
18
+ * value on request. It pops in (.25 s, pop), glides between points (.25 s,
19
+ * power3.out) on the side with room, and changed values roll in their
20
+ * direction. A click pins it: it stays when the pointer leaves (the pin pops
21
+ * in); another click or Escape releases it.
22
+ */
23
+
24
+ export interface ChartTooltipSeries {
25
+ name: string;
26
+ values: Array<number | null>;
27
+ /** Any CSS colour (default: the --mk-chart-N slot). */
28
+ color?: string;
29
+ }
30
+
31
+ export interface ChartTooltipOptions {
32
+ /** Standalone: the x labels, one per point. */
33
+ labels?: string[];
34
+ series?: ChartTooltipSeries[];
35
+ /** Standalone: points edge to edge (lines, default) or at slot centres (bars). */
36
+ align?: 'edge' | 'center';
37
+ /** Standalone: the plot inside the root, in px from each side (default 0). */
38
+ inset?: { top?: number; right?: number; bottom?: number; left?: number };
39
+ /** Standalone: the y scale; with it a marker sits on each series. */
40
+ min?: number;
41
+ max?: number;
42
+ formatValue?: (value: number) => string;
43
+ /** The change from the previous point (default true). */
44
+ delta?: boolean;
45
+ /** Each row's share of the total (default false). */
46
+ share?: boolean;
47
+ /** A total row (default: two or more series). */
48
+ total?: boolean;
49
+ /** Rows by value, largest first (default false). */
50
+ sort?: boolean;
51
+ /** A click pins the card (default true). */
52
+ pin?: boolean;
53
+ /** Standalone: accessible name of the focusable plot. */
54
+ label?: string;
55
+ onIndexChange?: (index: number | null) => void;
56
+ }
57
+
58
+ export interface ChartTooltipInstance extends Instance {
59
+ show(index: number): void;
60
+ hide(): void;
61
+ update(options: ChartTooltipOptions): void;
62
+ readonly index: number | null;
63
+ readonly pinned: boolean;
64
+ }
65
+
66
+ interface Row {
67
+ name: string;
68
+ color: string;
69
+ value: number | null;
70
+ previous: number | null;
71
+ }
72
+
73
+ const finite = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value);
74
+ const PIN = '<svg aria-hidden="true" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 4h6l-1 6 3 3H7l3-3z"/><path d="M12 13v7"/></svg>';
75
+
76
+ export function createChartTooltip(root: HTMLElement | null, initial: ChartTooltipOptions = {}): ChartTooltipInstance {
77
+ if (!root) return inert({ show() {}, hide() {}, update() {}, index: null, pinned: false });
78
+ registerMotion();
79
+ const scope = createScope();
80
+ let options: ChartTooltipOptions = { ...initial };
81
+ const effects = new Set<gsap.core.Animation>();
82
+ const keep = (animation: gsap.core.Animation | null) => {
83
+ if (!animation) return;
84
+ effects.add(animation);
85
+ // Finished ones leave as new ones arrive: the animation's own onComplete stays untouched.
86
+ for (const effect of effects) if (effect.totalProgress() === 1) effects.delete(effect);
87
+ };
88
+ const number = numberFormat(root, { maximumFractionDigits: 2 });
89
+ const percent = numberFormat(root, { maximumFractionDigits: 1, minimumFractionDigits: 1 });
90
+ const format = (value: number) => (options.formatValue ? options.formatValue(value) : number.format(value));
91
+
92
+ const layer = document.createElement('div');
93
+ layer.dataset.mkCtLayer = '';
94
+ layer.setAttribute('aria-hidden', 'true');
95
+ const guide = document.createElement('span');
96
+ guide.dataset.mkCtGuide = '';
97
+ guide.hidden = true;
98
+ const markers = document.createElement('span');
99
+ markers.dataset.mkCtMarkers = '';
100
+ const card = document.createElement('div');
101
+ card.dataset.mkCtCard = '';
102
+ card.hidden = true;
103
+ const head = document.createElement('div');
104
+ head.dataset.mkCtHead = '';
105
+ const title = document.createElement('strong');
106
+ title.dataset.mkCtTitle = '';
107
+ const pin = document.createElement('span');
108
+ pin.dataset.mkCtPin = '';
109
+ pin.innerHTML = PIN;
110
+ pin.hidden = true;
111
+ head.append(title, pin);
112
+ const rowsHost = document.createElement('div');
113
+ rowsHost.dataset.mkCtRows = '';
114
+ card.append(head, rowsHost);
115
+ layer.append(guide, markers, card);
116
+ const live = document.createElement('span');
117
+ live.className = 'mk-sr-only';
118
+ live.setAttribute('role', 'status');
119
+ root.append(layer, live);
120
+ scope.add(() => {
121
+ for (const effect of effects) effect.kill();
122
+ effects.clear();
123
+ gsap.killTweensOf([card, guide]);
124
+ layer.remove();
125
+ live.remove();
126
+ });
127
+ scope.attr(root, 'data-mk-ready', '');
128
+
129
+ /** A kit chart inside: follow its selection instead of tracking the pointer. */
130
+ const linked = () => root.querySelector<HTMLElement>('[data-mk-chart-plot]');
131
+ if (!linked() && !root.matches('a[href], button, [tabindex]')) {
132
+ scope.attr(root, 'tabindex', '0');
133
+ scope.attr(root, 'role', 'group');
134
+ scope.attr(root, 'aria-label', options.label ?? 'Gráfica');
135
+ }
136
+
137
+ let index: number | null = null;
138
+ let pinned = false;
139
+ let rows: Row[] = [];
140
+ let label = '';
141
+
142
+ const plot = () => {
143
+ const width = root.clientWidth;
144
+ const height = root.clientHeight;
145
+ const inset = options.inset ?? {};
146
+ return { left: inset.left ?? 0, right: width - (inset.right ?? 0), top: inset.top ?? 0, bottom: height - (inset.bottom ?? 0), width, height };
147
+ };
148
+ const count = () => Math.max(options.labels?.length ?? 0, ...(options.series ?? []).map((series) => series.values.length), 0);
149
+ const xOf = (i: number) => {
150
+ const box = plot();
151
+ const n = count();
152
+ if (options.align === 'center') return box.left + ((i + 0.5) * (box.right - box.left)) / Math.max(1, n);
153
+ return n <= 1 ? (box.left + box.right) / 2 : box.left + (i * (box.right - box.left)) / (n - 1);
154
+ };
155
+ const scaled = () => finite(options.min) && finite(options.max) && options.max! > options.min!;
156
+ const yOf = (value: number) => {
157
+ const box = plot();
158
+ return box.top + (1 - (value - options.min!) / (options.max! - options.min!)) * (box.bottom - box.top);
159
+ };
160
+ const rowsAt = (i: number): Row[] =>
161
+ (options.series ?? []).map((series, k) => ({
162
+ name: series.name,
163
+ color: series.color ?? `var(--mk-chart-${(k % 8) + 1})`,
164
+ value: finite(series.values[i]) ? series.values[i]! : null,
165
+ previous: i > 0 && finite(series.values[i - 1]) ? series.values[i - 1]! : null,
166
+ }));
167
+
168
+ const deltaOf = (row: Row) => {
169
+ if (row.value === null || row.previous === null || row.previous === 0) return null;
170
+ return ((row.value - row.previous) / Math.abs(row.previous)) * 100;
171
+ };
172
+
173
+ /**
174
+ * A colour as the chart draws it: variables (the --mk-chart-N slots) resolve where the chart defines them, so a
175
+ * chart recoloured by its own CSS shows the same colours in the card.
176
+ */
177
+ const resolveColor = (color: string) => {
178
+ if (!color.includes('var(')) return color;
179
+ const probe = document.createElement('span');
180
+ probe.style.color = color;
181
+ (linked() ?? root).append(probe);
182
+ const value = getComputedStyle(probe).color;
183
+ probe.remove();
184
+ return value && !value.includes('var(') ? value : color;
185
+ };
186
+
187
+ /** Write the card's rows, rolling values that changed. */
188
+ const paintRows = () => {
189
+ const showTotal = options.total ?? rows.length > 1;
190
+ const total = rows.reduce((sum, row) => sum + (row.value ?? 0), 0);
191
+ const ordered = options.sort ? [...rows].sort((a, b) => (b.value ?? -Infinity) - (a.value ?? -Infinity)) : rows;
192
+ const existing = [...rowsHost.querySelectorAll<HTMLElement>('[data-mk-ct-row]:not([data-mk-ct-row="total"])')];
193
+ const reuse = existing.length === ordered.length && existing.every((element, k) => element.dataset.mkName === ordered[k]!.name);
194
+ const lines: string[] = [];
195
+ const write = (element: HTMLElement, text: string, value: number | null) => {
196
+ const before = Number(element.dataset.mkValue);
197
+ element.dataset.mkValue = value === null ? '' : String(value);
198
+ if (reuse && !reduced() && element.textContent !== text && value !== null && Number.isFinite(before)) keep(rollDigits(element, text, value >= before ? 1 : -1, 0.28));
199
+ else element.textContent = text;
200
+ };
201
+ const elements = ordered.map((row, k) => {
202
+ const element = reuse ? existing[k]! : document.createElement('div');
203
+ if (!reuse) {
204
+ element.dataset.mkCtRow = '';
205
+ element.dataset.mkName = row.name;
206
+ const swatch = document.createElement('i');
207
+ swatch.dataset.mkCtSwatch = '';
208
+ const name = document.createElement('span');
209
+ name.dataset.mkCtName = '';
210
+ name.textContent = row.name;
211
+ const value = document.createElement('b');
212
+ value.dataset.mkCtValue = '';
213
+ const delta = document.createElement('span');
214
+ delta.dataset.mkCtDelta = '';
215
+ element.append(swatch, name, value, delta);
216
+ }
217
+ // Text-coloured series would vanish on the inverse glass: they show as a line in its ink.
218
+ const swatch = element.querySelector<HTMLElement>('[data-mk-ct-swatch]')!;
219
+ if (/--mk-(text|chart-mono|muted)/.test(row.color)) swatch.dataset.mkMono = '';
220
+ else swatch.style.background = resolveColor(row.color);
221
+ write(element.querySelector<HTMLElement>('[data-mk-ct-value]')!, row.value === null ? '—' : format(row.value), row.value);
222
+ const deltaElement = element.querySelector<HTMLElement>('[data-mk-ct-delta]')!;
223
+ const change = options.delta === false ? null : deltaOf(row);
224
+ const parts: string[] = [];
225
+ if (change !== null) {
226
+ const trend = Math.abs(change) < 0.05 ? 'flat' : change > 0 ? 'up' : 'down';
227
+ deltaElement.dataset.mkTrend = trend;
228
+ parts.push(`${trend === 'up' ? '▲' : trend === 'down' ? '▼' : '='} ${percent.format(Math.abs(change))} %`);
229
+ }
230
+ if (options.share && row.value !== null && total) parts.push(`${percent.format((row.value / total) * 100)} % del total`);
231
+ deltaElement.textContent = parts.join(' · ');
232
+ deltaElement.hidden = !parts.length;
233
+ lines.push(`${row.name ? `${row.name}: ` : ''}${row.value === null ? 'sin dato' : format(row.value)}${change !== null ? `, ${change >= 0 ? 'sube' : 'baja'} ${percent.format(Math.abs(change))} %` : ''}`);
234
+ return element;
235
+ });
236
+ let totalElement = rowsHost.querySelector<HTMLElement>('[data-mk-ct-row="total"]');
237
+ if (showTotal) {
238
+ if (!totalElement) {
239
+ totalElement = document.createElement('div');
240
+ totalElement.dataset.mkCtRow = 'total';
241
+ const name = document.createElement('span');
242
+ name.dataset.mkCtName = '';
243
+ name.textContent = 'Total';
244
+ const value = document.createElement('b');
245
+ value.dataset.mkCtValue = '';
246
+ totalElement.append(document.createElement('i'), name, value);
247
+ }
248
+ write(totalElement.querySelector<HTMLElement>('[data-mk-ct-value]')!, format(total), total);
249
+ lines.push(`Total: ${format(total)}`);
250
+ }
251
+ rowsHost.replaceChildren(...elements, ...(showTotal && totalElement ? [totalElement] : []));
252
+ return lines;
253
+ };
254
+
255
+ /** Place the card beside x, towards the middle, above the highest point, inside the root. */
256
+ const placeCard = (x: number, anchorY: number, appearing: boolean) => {
257
+ const width = root.clientWidth;
258
+ const height = root.clientHeight;
259
+ const cardW = card.offsetWidth || 180;
260
+ const cardH = card.offsetHeight || 80;
261
+ const towardsLeft = x > width / 2;
262
+ const left = Math.round(Math.max(0, Math.min(width - cardW, towardsLeft ? x - 16 - cardW : x + 16)));
263
+ const top = Math.round(Math.max(0, Math.min(height - cardH, anchorY - cardH - 12)));
264
+ if (appearing || reduced()) {
265
+ gsap.killTweensOf(card);
266
+ gsap.set(card, { x: left, y: top, transformOrigin: towardsLeft ? '100% 100%' : '0% 100%' });
267
+ if (!reduced()) keep(gsap.fromTo(card, { opacity: 0, scale: 0.9, filter: 'blur(6px)' }, { opacity: 1, scale: 1, filter: 'blur(0px)', duration: 0.25, ease: EASE.pop }));
268
+ else gsap.set(card, { opacity: 1, scale: 1 });
269
+ } else {
270
+ gsap.killTweensOf(card, 'opacity,scale,filter');
271
+ gsap.set(card, { opacity: 1, scale: 1, filter: 'blur(0px)' });
272
+ keep(gsap.to(card, { x: left, y: top, duration: 0.25, ease: 'power3.out', overwrite: 'auto' }));
273
+ }
274
+ };
275
+
276
+ /** Standalone: the dotted guide and a marker per series. */
277
+ const paintGuide = (x: number, appearing: boolean) => {
278
+ const box = plot();
279
+ guide.hidden = false;
280
+ gsap.set(guide, { top: box.top, height: Math.max(0, box.bottom - box.top) });
281
+ if (appearing || reduced()) gsap.set(guide, { x });
282
+ else keep(gsap.to(guide, { x, duration: 0.25, ease: 'power3.out', overwrite: 'auto' }));
283
+ if (!scaled()) {
284
+ markers.replaceChildren();
285
+ return box.top + 8 + (card.offsetHeight || 80) + 12;
286
+ }
287
+ const fresh = markers.children.length !== rows.length;
288
+ if (fresh) {
289
+ markers.replaceChildren(
290
+ ...rows.map((row) => {
291
+ const dot = document.createElement('span');
292
+ dot.dataset.mkCtMarker = '';
293
+ dot.style.background = row.color;
294
+ return dot;
295
+ }),
296
+ );
297
+ }
298
+ let highest = box.bottom;
299
+ rows.forEach((row, k) => {
300
+ const dot = markers.children[k] as HTMLElement;
301
+ dot.hidden = row.value === null;
302
+ if (row.value === null) return;
303
+ const y = yOf(row.value);
304
+ highest = Math.min(highest, y);
305
+ if (appearing || fresh || reduced()) {
306
+ gsap.set(dot, { x, y });
307
+ if (!reduced()) keep(gsap.fromTo(dot, { scale: 0 }, { scale: 1, duration: 0.3, ease: EASE.pop }));
308
+ } else keep(gsap.to(dot, { x, y, duration: 0.25, ease: 'power3.out', overwrite: 'auto' }));
309
+ });
310
+ return highest;
311
+ };
312
+
313
+ const emit = () => {
314
+ options.onIndexChange?.(index);
315
+ root.dispatchEvent(new CustomEvent('mk:index-change', { bubbles: true, detail: { index, pinned } }));
316
+ };
317
+
318
+ /** Show the card for point `i`: x and anchorY in root px. */
319
+ const present = (i: number, x: number, anchorY: number | null, announce: boolean) => {
320
+ const appearing = card.hidden;
321
+ const changed = i !== index;
322
+ index = i;
323
+ title.textContent = label;
324
+ const lines = paintRows();
325
+ card.hidden = false;
326
+ const top = anchorY ?? paintGuide(x, appearing);
327
+ placeCard(x, top, appearing);
328
+ if (announce) live.textContent = `${label}. ${lines.join('. ')}`;
329
+ if (changed) emit();
330
+ };
331
+
332
+ const hide = (force = false) => {
333
+ if (pinned && !force) return;
334
+ if (force) setPinned(false);
335
+ if (index === null && card.hidden) return;
336
+ index = null;
337
+ guide.hidden = true;
338
+ markers.replaceChildren();
339
+ if (!card.hidden && !reduced()) {
340
+ gsap.killTweensOf(card, 'opacity,scale,filter');
341
+ keep(gsap.to(card, { opacity: 0, scale: 0.94, duration: 0.15, ease: 'power2.in', onComplete: () => void (card.hidden = true) }));
342
+ } else card.hidden = true;
343
+ emit();
344
+ };
345
+
346
+ const setPinned = (next: boolean) => {
347
+ if (pinned === next) return;
348
+ pinned = next;
349
+ root.toggleAttribute('data-mk-pinned', pinned);
350
+ pin.hidden = !pinned;
351
+ if (pinned && !reduced()) keep(gsap.fromTo(pin, { scale: 0.4, rotation: -30 }, { scale: 1, rotation: 0, duration: 0.35, ease: EASE.click, clearProps: 'transform' }));
352
+ root.dispatchEvent(new CustomEvent('mk:index-change', { bubbles: true, detail: { index, pinned } }));
353
+ };
354
+ scope.attr(root, 'data-mk-pinned', null);
355
+
356
+ /** Standalone: show point i from the options' data. */
357
+ const showStandalone = (i: number, announce = false) => {
358
+ const n = count();
359
+ if (!n) return;
360
+ const clamped = Math.max(0, Math.min(n - 1, Math.round(i)));
361
+ rows = rowsAt(clamped);
362
+ label = options.labels?.[clamped] ?? String(clamped + 1);
363
+ present(clamped, xOf(clamped), null, announce);
364
+ };
365
+
366
+ const indexAt = (clientX: number) => {
367
+ const rect = root.getBoundingClientRect();
368
+ const x = clientX - rect.left;
369
+ let best = 0;
370
+ for (let i = 1; i < count(); i++) if (Math.abs(xOf(i) - x) < Math.abs(xOf(best) - x)) best = i;
371
+ return best;
372
+ };
373
+
374
+ // Linked: the kit chart tells where its selection is.
375
+ scope.on(root, 'mk:select', (event) => {
376
+ const plotElement = linked();
377
+ if (!plotElement || event.target === root) return;
378
+ const detail = (event as CustomEvent<{ index: number | null; label: string | null; x: number | null; y: number | null; series?: Array<{ name: string; color: string; value: number | null; previous: number | null }> }>).detail;
379
+ if (detail.index === null || detail.x === null || detail.y === null) return hide();
380
+ const rootBox = root.getBoundingClientRect();
381
+ const plotBox = plotElement.getBoundingClientRect();
382
+ rows = (detail.series ?? []).map((row) => ({ name: row.name, color: row.color, value: finite(row.value) ? row.value : null, previous: finite(row.previous) ? row.previous : null }));
383
+ label = detail.label ?? '';
384
+ present(detail.index, plotBox.left - rootBox.left + detail.x, plotBox.top - rootBox.top + detail.y, false);
385
+ });
386
+
387
+ scope.on(root, 'pointermove', (event) => {
388
+ if (linked()) return;
389
+ showStandalone(indexAt((event as PointerEvent).clientX));
390
+ });
391
+ scope.on(root, 'pointerleave', (event) => {
392
+ if (linked() || (event as PointerEvent).pointerType === 'touch') return;
393
+ hide();
394
+ });
395
+ scope.on(root, 'click', (event) => {
396
+ if (options.pin === false || card.hidden) return;
397
+ const target = event.target as Element | null;
398
+ if (target?.closest('a, button, input, select, textarea')) return;
399
+ setPinned(!pinned);
400
+ });
401
+ scope.on(root, 'keydown', (event) => {
402
+ const key = (event as KeyboardEvent).key;
403
+ if (key === 'Escape') {
404
+ if (index !== null || pinned) {
405
+ event.preventDefault();
406
+ hide(true);
407
+ }
408
+ return;
409
+ }
410
+ if (linked()) return;
411
+ const last = count() - 1;
412
+ const moves: Record<string, number> = { ArrowRight: Math.min(last, (index ?? -1) + 1), ArrowLeft: Math.max(0, (index ?? 1) - 1), Home: 0, End: last };
413
+ if (!(key in moves) || last < 0) return;
414
+ event.preventDefault();
415
+ showStandalone(moves[key]!, true);
416
+ });
417
+ scope.on(root, 'focus', () => {
418
+ if (!linked() && index === null && count()) showStandalone(0, true);
419
+ });
420
+ scope.on(root, 'blur', () => {
421
+ if (!linked()) hide();
422
+ });
423
+
424
+ return {
425
+ show(i) {
426
+ if (!linked()) showStandalone(i, true);
427
+ },
428
+ hide: () => hide(true),
429
+ update(next) {
430
+ if (scope.disposed) return;
431
+ options = { ...options, ...next };
432
+ if (index !== null && !linked()) showStandalone(index);
433
+ },
434
+ get index() {
435
+ return index;
436
+ },
437
+ get pinned() {
438
+ return pinned;
439
+ },
440
+ destroy: () => scope.dispose(),
441
+ };
442
+ }
@@ -0,0 +1,47 @@
1
+ 'use client';
2
+ import { useRef, type HTMLAttributes } from 'react';
3
+ import { useIsomorphicLayoutEffect, useLatest } from '../../react/use-recipe';
4
+ import { createChartTooltip, type ChartTooltipInstance, type ChartTooltipOptions } from './engine';
5
+
6
+ export interface ChartTooltipProps extends HTMLAttributes<HTMLDivElement>, ChartTooltipOptions {}
7
+
8
+ /**
9
+ * <ChartTooltip share><Chart tooltip={false} … /></ChartTooltip>, or over any chart with labels, series,
10
+ * inset, min and max.
11
+ */
12
+ export function ChartTooltip({ labels, series, align, inset, min, max, formatValue, delta, share, total, sort, pin, label, onIndexChange, className, children, ...props }: ChartTooltipProps) {
13
+ const ref = useRef<HTMLDivElement>(null);
14
+ const instance = useRef<ChartTooltipInstance | null>(null);
15
+ const format = useLatest(formatValue);
16
+ const change = useLatest(onIndexChange);
17
+ const data = { labels, series, align, inset, min, max, delta, share, total, sort, pin, label };
18
+ const key = JSON.stringify(data);
19
+ const options = (): ChartTooltipOptions => ({
20
+ ...data,
21
+ formatValue: formatValue ? (value) => format.current?.(value) ?? String(value) : undefined,
22
+ onIndexChange: (index) => change.current?.(index),
23
+ });
24
+ useIsomorphicLayoutEffect(() => {
25
+ const created = createChartTooltip(ref.current, options());
26
+ instance.current = created;
27
+ return () => {
28
+ created.destroy();
29
+ instance.current = null;
30
+ };
31
+ // eslint-disable-next-line react-hooks/exhaustive-deps
32
+ }, []);
33
+ const first = useRef(true);
34
+ useIsomorphicLayoutEffect(() => {
35
+ if (first.current) {
36
+ first.current = false;
37
+ return;
38
+ }
39
+ instance.current?.update(options());
40
+ // eslint-disable-next-line react-hooks/exhaustive-deps
41
+ }, [key, Boolean(formatValue)]);
42
+ return (
43
+ <div {...props} ref={ref} className={['mk-chart-tooltip', className].filter(Boolean).join(' ')}>
44
+ {children}
45
+ </div>
46
+ );
47
+ }
@@ -0,0 +1,19 @@
1
+ # code-block
2
+
3
+ Bloque de código con título y lenguaje opcionales, números de línea y botón copiar con confirmación. El código siempre se trata como texto: una cadena que parece HTML se muestra como código, nunca se interpreta.
4
+
5
+ ```html
6
+ <mk-code-block class="mk-code-block" title="Instalar" language="bash">
7
+ <pre><code>npm install @yewdiel21/motion-kit gsap</code></pre>
8
+ </mk-code-block>
9
+ ```
10
+
11
+ `defineElements()`, `createCodeBlock(root, options)` o `<CodeBlock code={source} language="ts" title="main.ts" lineNumbers />`.
12
+
13
+ Opciones: `code` (sin ella se usa y se copia el texto actual de `<code>`), `language`, `title`, `lineNumbers`, `highlight` (colorea la sintaxis; por defecto cuando el lenguaje está soportado), `highlightLines` (líneas a marcar, desde 1), `copyLabel='Copiar'`, `copiedLabel='Copiado'`, `errorLabel='No se pudo copiar'`, `onCopy(ok)`. API: `setCode(text)`, `copy(): Promise<boolean>`, `code`, `destroy()`. Evento `mk:copy` con `{ok, code}`.
14
+
15
+ Copiar usa la Clipboard API con el texto exacto (espacios, tabs y saltos de línea). El resultado se anuncia en un estado educado y se refleja en el botón (`data-mk-copied` / `data-mk-copy-error` durante 2 s). Si el portapapeles no está disponible o lo deniega, el código queda seleccionado para copiarlo a mano. Una copia que termina después de `destroy()` no toca el DOM.
16
+
17
+ El marcado propio se respeta: `pre > code`, `[data-mk-code-copy]`, `[data-mk-code-status]`, `[data-mk-code-header]`; las piezas que faltan se crean y `destroy()` las quita y restaura texto y atributos. El clic de copiar es delegado, así que un framework puede volver a renderizar el botón. Los números de línea son un contador CSS que no se selecciona ni se copia. El resaltado es propio y sin dependencias: ts/js/tsx/jsx, json, css, html/xml/svg/astro/vue y shell; cada token es un `span` creado con `textContent`, así que el código nunca se interpreta como HTML. Siempre es un editor oscuro (también en tema claro): barra con tres puntos, título, lenguaje y botón copiar; radio de 12px para que las líneas largas no choquen con una esquina curva (se desplazan en horizontal).
18
+
19
+ Variables: `--mk-code-radius` (12px), `--mk-code-bg`, `--mk-code-bar`, `--mk-code-text` y los colores de sintaxis `--mk-code-keyword`, `--mk-code-string`, `--mk-code-number`, `--mk-code-comment`, `--mk-code-function`, `--mk-code-tag`, `--mk-code-attr`, `--mk-code-property`; el botón muestra la etiqueta de éxito o error mediante `data-mk-feedback`. Movimiento reducido quita la escala al pulsar.