@yewdiel21/motion-kit 0.10.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (459) hide show
  1. package/README.md +81 -0
  2. package/bin/motion-kit.mjs +3 -3
  3. package/dist/auto/index.d.ts +56 -3
  4. package/dist/auto/index.js +107 -3
  5. package/dist/auto/index.js.map +1 -1
  6. package/dist/{chunk-XAKC2QY7.js → chunk-6IRJYXJU.js} +3 -28
  7. package/dist/chunk-6IRJYXJU.js.map +1 -0
  8. package/dist/chunk-A6QQCF6V.js +21333 -0
  9. package/dist/chunk-A6QQCF6V.js.map +1 -0
  10. package/dist/chunk-JXRS3OEA.js +3638 -0
  11. package/dist/chunk-JXRS3OEA.js.map +1 -0
  12. package/dist/chunk-QP4QJOEN.js +72 -0
  13. package/dist/chunk-QP4QJOEN.js.map +1 -0
  14. package/dist/css/components/activity-feed.css +240 -0
  15. package/dist/css/components/add-to-cart.css +72 -0
  16. package/dist/css/components/attachment.css +266 -0
  17. package/dist/css/components/bidirectional-slider.css +168 -0
  18. package/dist/css/components/breadcrumb.css +110 -0
  19. package/dist/css/components/chart-tooltip.css +168 -0
  20. package/dist/css/components/chart.css +296 -0
  21. package/dist/css/components/code-block.css +264 -0
  22. package/dist/css/components/color-area.css +82 -0
  23. package/dist/css/components/color-field.css +67 -0
  24. package/dist/css/components/color-picker.css +131 -0
  25. package/dist/css/components/color-slider.css +113 -0
  26. package/dist/css/components/command-search.css +252 -0
  27. package/dist/css/components/context-menu.css +23 -0
  28. package/dist/css/components/credit-card.css +288 -0
  29. package/dist/css/components/data-table.css +686 -0
  30. package/dist/css/components/date-range-picker.css +168 -0
  31. package/dist/css/components/date-time-picker.css +178 -0
  32. package/dist/css/components/drawer.css +58 -0
  33. package/dist/css/components/editable-table.css +201 -0
  34. package/dist/css/components/empty-state.css +61 -0
  35. package/dist/css/components/file-explorer.css +633 -0
  36. package/dist/css/components/filter-builder.css +227 -0
  37. package/dist/css/components/heatmap-chart.css +391 -0
  38. package/dist/css/components/hold-confirm.css +87 -0
  39. package/dist/css/components/hover-card.css +19 -7
  40. package/dist/css/components/image-preview.css +283 -0
  41. package/dist/css/components/json-viewer.css +304 -0
  42. package/dist/css/components/like-button.css +78 -0
  43. package/dist/css/components/link-preview.css +275 -0
  44. package/dist/css/components/loading-button.css +77 -0
  45. package/dist/css/components/multi-select.css +267 -0
  46. package/dist/css/components/nav.css +102 -102
  47. package/dist/css/components/notification-bell.css +127 -0
  48. package/dist/css/components/orbit-menu.css +130 -0
  49. package/dist/css/components/pagination.css +10 -5
  50. package/dist/css/components/password-strength.css +183 -0
  51. package/dist/css/components/pie-chart.css +390 -0
  52. package/dist/css/components/pill-button.css +135 -0
  53. package/dist/css/components/popover.css +25 -0
  54. package/dist/css/components/progress.css +140 -0
  55. package/dist/css/components/questionnaire.css +217 -0
  56. package/dist/css/components/radar-chart.css +370 -0
  57. package/dist/css/components/radial-chart.css +398 -0
  58. package/dist/css/components/range-calendar.css +186 -0
  59. package/dist/css/components/range-slider.css +192 -0
  60. package/dist/css/components/resizable-panel.css +243 -0
  61. package/dist/css/components/rich-text-editor.css +284 -0
  62. package/dist/css/components/sankey-chart.css +358 -0
  63. package/dist/css/components/scratch-card.css +75 -0
  64. package/dist/css/components/scroll-island.css +111 -0
  65. package/dist/css/components/select.css +136 -0
  66. package/dist/css/components/skeleton.css +108 -0
  67. package/dist/css/components/split-view.css +19 -0
  68. package/dist/css/components/star-rating.css +80 -0
  69. package/dist/css/components/stat-card.css +164 -0
  70. package/dist/css/components/swipe-actions.css +105 -0
  71. package/dist/css/components/tag-input.css +244 -0
  72. package/dist/css/components/time-field.css +88 -0
  73. package/dist/css/components/timeline.css +219 -0
  74. package/dist/css/components/toolbar.css +122 -0
  75. package/dist/css/components/tooltip.css +79 -0
  76. package/dist/css/components/tree-view.css +289 -0
  77. package/dist/css/components/virtual-list.css +195 -0
  78. package/dist/css/components/voice-dots.css +70 -0
  79. package/dist/css/tokens.css +185 -181
  80. package/dist/elements/index.d.ts +849 -7
  81. package/dist/elements/index.js +1642 -8
  82. package/dist/elements/index.js.map +1 -1
  83. package/dist/{engine-GDGwQnJE.d.ts → engine-5zRIssTO.d.ts} +11 -1
  84. package/dist/engine-QECQnGz1.d.ts +33 -0
  85. package/dist/index.css +10890 -311
  86. package/dist/index.d.ts +89 -5
  87. package/dist/index.js +273 -9
  88. package/dist/index.js.map +1 -1
  89. package/dist/react/index.d.ts +686 -24
  90. package/dist/react/index.js +2345 -9
  91. package/dist/react/index.js.map +1 -1
  92. package/dist/{reduced-BmBzKH94.d.ts → reduced-6X_bns60.d.ts} +9 -2
  93. package/dist/reveal-BfyKKsw4.d.ts +2474 -0
  94. package/dist/store-CA2Qcun_.d.ts +453 -0
  95. package/package.json +9 -16
  96. package/registry.json +1096 -543
  97. package/src/auto/auto-init.ts +104 -0
  98. package/src/components/activity-feed/README.md +56 -0
  99. package/src/components/activity-feed/activity-feed.css +239 -0
  100. package/src/components/activity-feed/element.ts +36 -0
  101. package/src/components/activity-feed/engine.ts +351 -0
  102. package/src/components/activity-feed/react.tsx +32 -0
  103. package/src/components/add-to-cart/README.md +34 -0
  104. package/src/components/add-to-cart/add-to-cart.css +71 -0
  105. package/src/components/add-to-cart/element.ts +20 -0
  106. package/src/components/add-to-cart/engine.ts +206 -0
  107. package/src/components/add-to-cart/react.tsx +29 -0
  108. package/src/components/attachment/README.md +27 -0
  109. package/src/components/attachment/attachment.css +265 -0
  110. package/src/components/attachment/element.ts +50 -0
  111. package/src/components/attachment/engine.ts +469 -0
  112. package/src/components/attachment/react.tsx +65 -0
  113. package/src/components/bidirectional-slider/README.md +46 -0
  114. package/src/components/bidirectional-slider/bidirectional-slider.css +167 -0
  115. package/src/components/bidirectional-slider/element.ts +42 -0
  116. package/src/components/bidirectional-slider/engine.ts +289 -0
  117. package/src/components/bidirectional-slider/react.tsx +45 -0
  118. package/src/components/breadcrumb/README.md +38 -0
  119. package/src/components/breadcrumb/breadcrumb.css +109 -0
  120. package/src/components/breadcrumb/element.ts +27 -0
  121. package/src/components/breadcrumb/engine.ts +249 -0
  122. package/src/components/breadcrumb/react.tsx +30 -0
  123. package/src/components/chart/README.md +34 -0
  124. package/src/components/chart/chart.css +295 -0
  125. package/src/components/chart/element.ts +43 -0
  126. package/src/components/chart/engine.ts +838 -0
  127. package/src/components/chart/parts.ts +237 -0
  128. package/src/components/chart/react.tsx +50 -0
  129. package/src/components/chart/use-chart.ts +55 -0
  130. package/src/components/chart-tooltip/README.md +53 -0
  131. package/src/components/chart-tooltip/chart-tooltip.css +167 -0
  132. package/src/components/chart-tooltip/element.ts +37 -0
  133. package/src/components/chart-tooltip/engine.ts +442 -0
  134. package/src/components/chart-tooltip/react.tsx +47 -0
  135. package/src/components/code-block/README.md +19 -0
  136. package/src/components/code-block/code-block.css +263 -0
  137. package/src/components/code-block/element.ts +34 -0
  138. package/src/components/code-block/engine.ts +254 -0
  139. package/src/components/code-block/highlight.ts +244 -0
  140. package/src/components/code-block/react.tsx +94 -0
  141. package/src/components/color-area/README.md +50 -0
  142. package/src/components/color-area/color-area.css +81 -0
  143. package/src/components/color-area/element.ts +26 -0
  144. package/src/components/color-area/engine.ts +246 -0
  145. package/src/components/color-area/react.tsx +42 -0
  146. package/src/components/color-field/README.md +43 -0
  147. package/src/components/color-field/color-field.css +66 -0
  148. package/src/components/color-field/element.ts +26 -0
  149. package/src/components/color-field/engine.ts +174 -0
  150. package/src/components/color-field/react.tsx +42 -0
  151. package/src/components/color-picker/README.md +45 -0
  152. package/src/components/color-picker/color-picker.css +130 -0
  153. package/src/components/color-picker/element.ts +45 -0
  154. package/src/components/color-picker/engine.ts +314 -0
  155. package/src/components/color-picker/react.tsx +47 -0
  156. package/src/components/color-slider/README.md +55 -0
  157. package/src/components/color-slider/color-slider.css +112 -0
  158. package/src/components/color-slider/element.ts +26 -0
  159. package/src/components/color-slider/engine.ts +234 -0
  160. package/src/components/color-slider/react.tsx +45 -0
  161. package/src/components/command-search/README.md +15 -0
  162. package/src/components/command-search/command-search.css +251 -0
  163. package/src/components/command-search/element.ts +36 -0
  164. package/src/components/command-search/engine.ts +356 -0
  165. package/src/components/command-search/match.ts +53 -0
  166. package/src/components/command-search/react.tsx +66 -0
  167. package/src/components/context-menu/README.md +31 -0
  168. package/src/components/context-menu/context-menu.css +22 -0
  169. package/src/components/context-menu/element.ts +40 -0
  170. package/src/components/context-menu/engine.ts +153 -0
  171. package/src/components/context-menu/react.tsx +57 -0
  172. package/src/components/credit-card/README.md +20 -0
  173. package/src/components/credit-card/card.ts +77 -0
  174. package/src/components/credit-card/credit-card.css +287 -0
  175. package/src/components/credit-card/element.ts +33 -0
  176. package/src/components/credit-card/engine.ts +410 -0
  177. package/src/components/credit-card/react.tsx +36 -0
  178. package/src/components/data-table/README.md +83 -0
  179. package/src/components/data-table/data-table.css +685 -0
  180. package/src/components/data-table/element.ts +54 -0
  181. package/src/components/data-table/engine.ts +1111 -0
  182. package/src/components/data-table/react.tsx +94 -0
  183. package/src/components/date-range-picker/README.md +51 -0
  184. package/src/components/date-range-picker/date-range-picker.css +167 -0
  185. package/src/components/date-range-picker/element.ts +52 -0
  186. package/src/components/date-range-picker/engine.ts +352 -0
  187. package/src/components/date-range-picker/react.tsx +57 -0
  188. package/src/components/date-time-picker/README.md +48 -0
  189. package/src/components/date-time-picker/date-time-picker.css +177 -0
  190. package/src/components/date-time-picker/element.ts +47 -0
  191. package/src/components/date-time-picker/engine.ts +350 -0
  192. package/src/components/date-time-picker/react.tsx +54 -0
  193. package/src/components/dialog/README.md +103 -102
  194. package/src/components/dialog/element.ts +123 -118
  195. package/src/components/dialog/engine.ts +449 -432
  196. package/src/components/drawer/README.md +28 -0
  197. package/src/components/drawer/drawer.css +57 -0
  198. package/src/components/drawer/element.ts +21 -0
  199. package/src/components/drawer/engine.ts +56 -0
  200. package/src/components/drawer/react.tsx +85 -0
  201. package/src/components/editable-table/README.md +67 -0
  202. package/src/components/editable-table/editable-table.css +200 -0
  203. package/src/components/editable-table/element.ts +45 -0
  204. package/src/components/editable-table/engine.ts +831 -0
  205. package/src/components/editable-table/react.tsx +79 -0
  206. package/src/components/empty-state/README.md +41 -0
  207. package/src/components/empty-state/element.ts +23 -0
  208. package/src/components/empty-state/empty-state.css +60 -0
  209. package/src/components/empty-state/engine.ts +232 -0
  210. package/src/components/empty-state/react.tsx +34 -0
  211. package/src/components/file-explorer/README.md +67 -0
  212. package/src/components/file-explorer/element.ts +39 -0
  213. package/src/components/file-explorer/engine.ts +1307 -0
  214. package/src/components/file-explorer/file-explorer.css +632 -0
  215. package/src/components/file-explorer/react.tsx +77 -0
  216. package/src/components/filter-builder/README.md +47 -0
  217. package/src/components/filter-builder/element.ts +34 -0
  218. package/src/components/filter-builder/engine.ts +396 -0
  219. package/src/components/filter-builder/filter-builder.css +226 -0
  220. package/src/components/filter-builder/react.tsx +36 -0
  221. package/src/components/heatmap-chart/README.md +48 -0
  222. package/src/components/heatmap-chart/element.ts +21 -0
  223. package/src/components/heatmap-chart/engine.ts +281 -0
  224. package/src/components/heatmap-chart/heatmap-chart.css +93 -0
  225. package/src/components/heatmap-chart/react.tsx +14 -0
  226. package/src/components/hold-confirm/README.md +13 -0
  227. package/src/components/hold-confirm/element.ts +24 -0
  228. package/src/components/hold-confirm/engine.ts +216 -0
  229. package/src/components/hold-confirm/hold-confirm.css +86 -0
  230. package/src/components/hold-confirm/react.tsx +28 -0
  231. package/src/components/hover-card/README.md +6 -2
  232. package/src/components/hover-card/engine.ts +98 -7
  233. package/src/components/hover-card/hover-card.css +19 -7
  234. package/src/components/image-preview/README.md +16 -0
  235. package/src/components/image-preview/element.ts +26 -0
  236. package/src/components/image-preview/engine.ts +405 -0
  237. package/src/components/image-preview/image-preview.css +282 -0
  238. package/src/components/image-preview/react.tsx +43 -0
  239. package/src/components/json-viewer/README.md +56 -0
  240. package/src/components/json-viewer/element.ts +37 -0
  241. package/src/components/json-viewer/engine.ts +449 -0
  242. package/src/components/json-viewer/json-viewer.css +303 -0
  243. package/src/components/json-viewer/react.tsx +56 -0
  244. package/src/components/like-button/README.md +13 -0
  245. package/src/components/like-button/element.ts +47 -0
  246. package/src/components/like-button/engine.ts +145 -0
  247. package/src/components/like-button/like-button.css +77 -0
  248. package/src/components/like-button/react.tsx +39 -0
  249. package/src/components/link-preview/README.md +19 -0
  250. package/src/components/link-preview/element.ts +29 -0
  251. package/src/components/link-preview/engine.ts +192 -0
  252. package/src/components/link-preview/link-preview.css +274 -0
  253. package/src/components/link-preview/react.tsx +101 -0
  254. package/src/components/loading-button/README.md +45 -0
  255. package/src/components/loading-button/element.ts +34 -0
  256. package/src/components/loading-button/engine.ts +201 -0
  257. package/src/components/loading-button/loading-button.css +76 -0
  258. package/src/components/loading-button/react.tsx +43 -0
  259. package/src/components/multi-select/README.md +48 -0
  260. package/src/components/multi-select/element.ts +28 -0
  261. package/src/components/multi-select/engine.ts +294 -0
  262. package/src/components/multi-select/multi-select.css +266 -0
  263. package/src/components/multi-select/react.tsx +39 -0
  264. package/src/components/nav/README.md +12 -10
  265. package/src/components/nav/element.ts +5 -5
  266. package/src/components/nav/engine.ts +21 -14
  267. package/src/components/nav/nav.css +102 -102
  268. package/src/components/nav/react.tsx +4 -4
  269. package/src/components/notification-bell/README.md +14 -0
  270. package/src/components/notification-bell/element.ts +48 -0
  271. package/src/components/notification-bell/engine.ts +202 -0
  272. package/src/components/notification-bell/notification-bell.css +126 -0
  273. package/src/components/notification-bell/react.tsx +57 -0
  274. package/src/components/orbit-menu/README.md +46 -0
  275. package/src/components/orbit-menu/element.ts +27 -0
  276. package/src/components/orbit-menu/engine.ts +179 -0
  277. package/src/components/orbit-menu/orbit-menu.css +129 -0
  278. package/src/components/orbit-menu/react.tsx +44 -0
  279. package/src/components/pagination/README.md +1 -1
  280. package/src/components/pagination/engine.ts +50 -4
  281. package/src/components/pagination/pagination.css +10 -5
  282. package/src/components/password-strength/README.md +17 -0
  283. package/src/components/password-strength/element.ts +22 -0
  284. package/src/components/password-strength/engine.ts +212 -0
  285. package/src/components/password-strength/password-strength.css +182 -0
  286. package/src/components/password-strength/react.tsx +36 -0
  287. package/src/components/password-strength/score.ts +62 -0
  288. package/src/components/pie-chart/README.md +48 -0
  289. package/src/components/pie-chart/element.ts +30 -0
  290. package/src/components/pie-chart/engine.ts +283 -0
  291. package/src/components/pie-chart/pie-chart.css +92 -0
  292. package/src/components/pie-chart/react.tsx +14 -0
  293. package/src/components/pill-button/README.md +46 -0
  294. package/src/components/pill-button/element.ts +16 -0
  295. package/src/components/pill-button/engine.ts +77 -0
  296. package/src/components/pill-button/pill-button.css +134 -0
  297. package/src/components/pill-button/react.tsx +32 -0
  298. package/src/components/popover/README.md +44 -0
  299. package/src/components/popover/element.ts +31 -0
  300. package/src/components/popover/engine.ts +114 -0
  301. package/src/components/popover/popover.css +24 -0
  302. package/src/components/popover/react.tsx +50 -0
  303. package/src/components/progress/README.md +17 -0
  304. package/src/components/progress/element.ts +30 -0
  305. package/src/components/progress/engine.ts +173 -0
  306. package/src/components/progress/progress.css +139 -0
  307. package/src/components/progress/react.tsx +35 -0
  308. package/src/components/questionnaire/README.md +32 -0
  309. package/src/components/questionnaire/element.ts +118 -0
  310. package/src/components/questionnaire/engine.ts +255 -0
  311. package/src/components/questionnaire/questionnaire.css +216 -0
  312. package/src/components/questionnaire/react.tsx +140 -0
  313. package/src/components/radar-chart/README.md +48 -0
  314. package/src/components/radar-chart/element.ts +30 -0
  315. package/src/components/radar-chart/engine.ts +327 -0
  316. package/src/components/radar-chart/radar-chart.css +72 -0
  317. package/src/components/radar-chart/react.tsx +14 -0
  318. package/src/components/radial-chart/README.md +48 -0
  319. package/src/components/radial-chart/element.ts +30 -0
  320. package/src/components/radial-chart/engine.ts +290 -0
  321. package/src/components/radial-chart/radial-chart.css +100 -0
  322. package/src/components/radial-chart/react.tsx +14 -0
  323. package/src/components/range-calendar/README.md +58 -0
  324. package/src/components/range-calendar/element.ts +42 -0
  325. package/src/components/range-calendar/engine.ts +390 -0
  326. package/src/components/range-calendar/range-calendar.css +185 -0
  327. package/src/components/range-calendar/react.tsx +56 -0
  328. package/src/components/range-slider/README.md +23 -0
  329. package/src/components/range-slider/element.ts +53 -0
  330. package/src/components/range-slider/engine.ts +316 -0
  331. package/src/components/range-slider/range-slider.css +191 -0
  332. package/src/components/range-slider/react.tsx +66 -0
  333. package/src/components/resizable-panel/README.md +61 -0
  334. package/src/components/resizable-panel/element.ts +36 -0
  335. package/src/components/resizable-panel/engine.ts +551 -0
  336. package/src/components/resizable-panel/react.tsx +74 -0
  337. package/src/components/resizable-panel/resizable-panel.css +242 -0
  338. package/src/components/rich-text-editor/README.md +57 -0
  339. package/src/components/rich-text-editor/element.ts +34 -0
  340. package/src/components/rich-text-editor/engine.ts +673 -0
  341. package/src/components/rich-text-editor/react.tsx +60 -0
  342. package/src/components/rich-text-editor/rich-text-editor.css +283 -0
  343. package/src/components/sankey-chart/README.md +48 -0
  344. package/src/components/sankey-chart/element.ts +31 -0
  345. package/src/components/sankey-chart/engine.ts +401 -0
  346. package/src/components/sankey-chart/react.tsx +14 -0
  347. package/src/components/sankey-chart/sankey-chart.css +60 -0
  348. package/src/components/scratch-card/README.md +15 -0
  349. package/src/components/scratch-card/element.ts +30 -0
  350. package/src/components/scratch-card/engine.ts +257 -0
  351. package/src/components/scratch-card/react.tsx +40 -0
  352. package/src/components/scratch-card/scratch-card.css +74 -0
  353. package/src/components/scroll-island/README.md +34 -0
  354. package/src/components/scroll-island/element.ts +16 -0
  355. package/src/components/scroll-island/engine.ts +252 -0
  356. package/src/components/scroll-island/react.tsx +26 -0
  357. package/src/components/scroll-island/scroll-island.css +110 -0
  358. package/src/components/select/README.md +34 -0
  359. package/src/components/select/element.ts +26 -0
  360. package/src/components/select/engine.ts +267 -0
  361. package/src/components/select/react.tsx +33 -0
  362. package/src/components/select/select.css +135 -0
  363. package/src/components/skeleton/README.md +15 -0
  364. package/src/components/skeleton/element.ts +32 -0
  365. package/src/components/skeleton/engine.ts +104 -0
  366. package/src/components/skeleton/react.tsx +41 -0
  367. package/src/components/skeleton/skeleton.css +107 -0
  368. package/src/components/split-view/README.md +50 -0
  369. package/src/components/split-view/element.ts +34 -0
  370. package/src/components/split-view/engine.ts +114 -0
  371. package/src/components/split-view/react.tsx +63 -0
  372. package/src/components/split-view/split-view.css +18 -0
  373. package/src/components/star-rating/README.md +14 -0
  374. package/src/components/star-rating/element.ts +26 -0
  375. package/src/components/star-rating/engine.ts +217 -0
  376. package/src/components/star-rating/react.tsx +33 -0
  377. package/src/components/star-rating/star-rating.css +79 -0
  378. package/src/components/stat-card/README.md +42 -0
  379. package/src/components/stat-card/element.ts +40 -0
  380. package/src/components/stat-card/engine.ts +283 -0
  381. package/src/components/stat-card/react.tsx +36 -0
  382. package/src/components/stat-card/stat-card.css +163 -0
  383. package/src/components/swipe-actions/README.md +19 -0
  384. package/src/components/swipe-actions/element.ts +26 -0
  385. package/src/components/swipe-actions/engine.ts +260 -0
  386. package/src/components/swipe-actions/react.tsx +80 -0
  387. package/src/components/swipe-actions/swipe-actions.css +104 -0
  388. package/src/components/tag-input/README.md +42 -0
  389. package/src/components/tag-input/element.ts +39 -0
  390. package/src/components/tag-input/engine.ts +313 -0
  391. package/src/components/tag-input/react.tsx +54 -0
  392. package/src/components/tag-input/tag-input.css +243 -0
  393. package/src/components/time-field/README.md +54 -0
  394. package/src/components/time-field/element.ts +38 -0
  395. package/src/components/time-field/engine.ts +110 -0
  396. package/src/components/time-field/react.tsx +45 -0
  397. package/src/components/time-field/time-field.css +87 -0
  398. package/src/components/timeline/README.md +57 -0
  399. package/src/components/timeline/element.ts +31 -0
  400. package/src/components/timeline/engine.ts +300 -0
  401. package/src/components/timeline/react.tsx +59 -0
  402. package/src/components/timeline/timeline.css +218 -0
  403. package/src/components/toolbar/README.md +46 -0
  404. package/src/components/toolbar/element.ts +30 -0
  405. package/src/components/toolbar/engine.ts +230 -0
  406. package/src/components/toolbar/react.tsx +34 -0
  407. package/src/components/toolbar/toolbar.css +121 -0
  408. package/src/components/tooltip/README.md +46 -0
  409. package/src/components/tooltip/element.ts +22 -0
  410. package/src/components/tooltip/engine.ts +288 -0
  411. package/src/components/tooltip/react.tsx +30 -0
  412. package/src/components/tooltip/tooltip.css +78 -0
  413. package/src/components/tree-view/README.md +61 -0
  414. package/src/components/tree-view/element.ts +32 -0
  415. package/src/components/tree-view/engine.ts +743 -0
  416. package/src/components/tree-view/react.tsx +82 -0
  417. package/src/components/tree-view/tree-view.css +288 -0
  418. package/src/components/virtual-list/README.md +81 -0
  419. package/src/components/virtual-list/element.ts +42 -0
  420. package/src/components/virtual-list/engine.ts +678 -0
  421. package/src/components/virtual-list/react.tsx +101 -0
  422. package/src/components/virtual-list/virtual-list.css +194 -0
  423. package/src/components/voice-dots/README.md +48 -0
  424. package/src/components/voice-dots/element.ts +45 -0
  425. package/src/components/voice-dots/engine.ts +243 -0
  426. package/src/components/voice-dots/react.tsx +52 -0
  427. package/src/components/voice-dots/voice-dots.css +69 -0
  428. package/src/core/chips.ts +196 -0
  429. package/src/core/color.ts +304 -0
  430. package/src/core/date-range.ts +67 -0
  431. package/src/core/dates.ts +11 -1
  432. package/src/core/files.ts +107 -0
  433. package/src/core/filter.ts +229 -0
  434. package/src/core/gsap.ts +80 -65
  435. package/src/core/listbox.ts +332 -0
  436. package/src/core/mark.ts +29 -0
  437. package/src/core/position.ts +89 -0
  438. package/src/core/relative-time.ts +77 -0
  439. package/src/core/segment-field.ts +373 -0
  440. package/src/core/segments.ts +153 -0
  441. package/src/core/tree.ts +116 -0
  442. package/src/core/virtual.ts +79 -0
  443. package/src/css/tokens.css +186 -182
  444. package/src/elements/index.ts +186 -0
  445. package/src/index.ts +88 -0
  446. package/src/motion/liquid.ts +14 -4
  447. package/src/motion/micro.ts +248 -0
  448. package/src/motion/sheet.ts +88 -65
  449. package/src/motion/surface.ts +9 -0
  450. package/src/react/index.ts +71 -1
  451. package/dist/chunk-IKQ5FODN.js +0 -1617
  452. package/dist/chunk-IKQ5FODN.js.map +0 -1
  453. package/dist/chunk-J6OCFNGU.js +0 -177
  454. package/dist/chunk-J6OCFNGU.js.map +0 -1
  455. package/dist/chunk-TFNRIZHU.js +0 -3977
  456. package/dist/chunk-TFNRIZHU.js.map +0 -1
  457. package/dist/chunk-XAKC2QY7.js.map +0 -1
  458. package/dist/reveal-jsX-uwUz.d.ts +0 -625
  459. package/dist/store-DYb3tTsZ.d.ts +0 -195
@@ -0,0 +1,59 @@
1
+ 'use client';
2
+ import { useRef, type HTMLAttributes } from 'react';
3
+ import { useIsomorphicLayoutEffect } from '../../react/use-recipe';
4
+ import { createTimeline, type TimelineEvent, type TimelineInstance, type TimelineOptions } from './engine';
5
+
6
+ export interface TimelineProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'>, Omit<TimelineOptions, 'events'> {
7
+ events: TimelineEvent[];
8
+ }
9
+
10
+ /**
11
+ * <Timeline events={history} group />. Changing `events` updates in place: an event added at either end grows in,
12
+ * one that changes state recolours its dot, one that goes folds away.
13
+ */
14
+ export function Timeline({ events, layout, group, relative, locale, label, className, ...props }: TimelineProps) {
15
+ const ref = useRef<HTMLDivElement>(null);
16
+ const instance = useRef<TimelineInstance | null>(null);
17
+ const shown = useRef<TimelineEvent[]>(events);
18
+ useIsomorphicLayoutEffect(() => {
19
+ const created = createTimeline(ref.current, { events: shown.current, layout, group, relative, locale, label });
20
+ instance.current = created;
21
+ return () => {
22
+ created.destroy();
23
+ instance.current = null;
24
+ };
25
+ // eslint-disable-next-line react-hooks/exhaustive-deps
26
+ }, [layout, group, relative, locale, label]);
27
+ const key = JSON.stringify(events);
28
+ useIsomorphicLayoutEffect(() => {
29
+ const timeline = instance.current;
30
+ const before = shown.current;
31
+ shown.current = events;
32
+ if (!timeline || JSON.stringify(timeline.events) === key) return;
33
+ const ids = new Set(before.map((event) => event.id));
34
+ const fresh = events.filter((event) => !ids.has(event.id));
35
+ const kept = events.filter((event) => ids.has(event.id));
36
+ const gone = before.filter((old) => !events.some((event) => event.id === old.id));
37
+ const stayed = before.filter((old) => !gone.includes(old));
38
+ const sameOrder = kept.every((event, i) => stayed[i]?.id === event.id);
39
+ /** The events that stayed take their changes (a new state recolours a dot). */
40
+ const patch = () => {
41
+ for (const event of kept) {
42
+ const old = before.find((entry) => entry.id === event.id);
43
+ // Keys the new version dropped are cleared too.
44
+ if (old && JSON.stringify(old) !== JSON.stringify(event)) timeline.update(event.id, { ...Object.fromEntries(Object.keys(old).map((name) => [name, undefined])), ...event });
45
+ }
46
+ };
47
+ const first = events[0]?.id;
48
+ const last = events[events.length - 1]?.id;
49
+ // One event added at an end grows in; one taken out folds away; anything else is redrawn.
50
+ if (sameOrder && !gone.length && fresh.length === 1 && (fresh[0]!.id === first || fresh[0]!.id === last)) {
51
+ patch();
52
+ timeline.add(fresh[0]!, fresh[0]!.id === first ? 'start' : 'end');
53
+ } else if (sameOrder && !fresh.length && gone.length <= 1) {
54
+ patch();
55
+ if (gone[0]) timeline.remove(gone[0].id);
56
+ } else timeline.setEvents(events);
57
+ }, [key]);
58
+ return <div {...props} ref={ref} className={['mk-timeline', className].filter(Boolean).join(' ')} />;
59
+ }
@@ -0,0 +1,218 @@
1
+ /* timeline — a 2 px rail (outline-soft) behind 2rem dots, its done stretch in the accent; dots by state (done: accent,
2
+ current: accent-soft with a ring that breathes, upcoming: dashed, error: error); a muted time, a 600 title, a muted
3
+ description; days are chips on the rail. 'alternate' puts the events on both sides of a centred rail when the timeline
4
+ is 520 px wide or more. */
5
+ .mk-timeline,
6
+ mk-timeline {
7
+ container-type: inline-size;
8
+ display: block;
9
+ min-width: 0;
10
+ color: var(--mk-text);
11
+ }
12
+
13
+ [data-mk-tl-wrap] {
14
+ position: relative;
15
+ }
16
+
17
+ [data-mk-timeline-list] {
18
+ display: grid;
19
+ gap: 1.1rem;
20
+ margin: 0;
21
+ padding: 0;
22
+ list-style: none;
23
+ }
24
+
25
+ [data-mk-tl-rail] {
26
+ position: absolute;
27
+ left: calc(1rem - 1px);
28
+ width: 2px;
29
+ overflow: hidden;
30
+ border-radius: 2px;
31
+ background: var(--mk-outline-soft);
32
+ }
33
+
34
+ [data-mk-tl-rail][hidden] {
35
+ display: none;
36
+ }
37
+
38
+ [data-mk-tl-progress] {
39
+ display: block;
40
+ width: 100%;
41
+ border-radius: inherit;
42
+ background: var(--mk-accent);
43
+ transition: height 0.5s cubic-bezier(0.38, 0.49, 0, 1);
44
+ }
45
+
46
+ [data-mk-tl-item] {
47
+ display: grid;
48
+ grid-template-columns: 2rem minmax(0, 1fr);
49
+ align-items: start;
50
+ column-gap: 0.85rem;
51
+ }
52
+
53
+ [data-mk-tl-dot] {
54
+ position: relative;
55
+ z-index: 1;
56
+ display: grid;
57
+ place-items: center;
58
+ width: 2rem;
59
+ height: 2rem;
60
+ border-radius: 50%;
61
+ background: var(--mk-accent);
62
+ color: var(--mk-on-accent);
63
+ box-shadow: 0 0 0 4px var(--mk-surface-1, var(--mk-bg));
64
+ font-size: 0.8125rem;
65
+ font-weight: 700;
66
+ line-height: 1;
67
+ }
68
+
69
+ [data-mk-tl-dot]:empty::after {
70
+ content: '';
71
+ width: 0.5rem;
72
+ height: 0.5rem;
73
+ border-radius: 50%;
74
+ background: currentColor;
75
+ }
76
+
77
+ [data-mk-tl-item][data-status='current'] [data-mk-tl-dot] {
78
+ background: var(--mk-accent-soft);
79
+ color: var(--mk-on-accent-soft, var(--mk-text));
80
+ animation: mk-tl-breathe 2.2s ease-in-out infinite;
81
+ }
82
+
83
+ [data-mk-tl-item][data-status='upcoming'] [data-mk-tl-dot] {
84
+ background: var(--mk-surface-1, var(--mk-bg));
85
+ color: var(--mk-muted);
86
+ outline: 2px dashed var(--mk-outline);
87
+ outline-offset: -2px;
88
+ }
89
+
90
+ [data-mk-tl-item][data-status='error'] [data-mk-tl-dot] {
91
+ background: var(--mk-error, #c62828);
92
+ color: var(--mk-on-error, #fff);
93
+ }
94
+
95
+ @keyframes mk-tl-breathe {
96
+ 0%,
97
+ 100% {
98
+ box-shadow: 0 0 0 4px var(--mk-surface-1, var(--mk-bg)), 0 0 0 4px color-mix(in srgb, var(--mk-accent) 45%, transparent);
99
+ }
100
+
101
+ 50% {
102
+ box-shadow: 0 0 0 4px var(--mk-surface-1, var(--mk-bg)), 0 0 0 9px color-mix(in srgb, var(--mk-accent) 0%, transparent);
103
+ }
104
+ }
105
+
106
+ [data-mk-tl-body] {
107
+ position: relative;
108
+ isolation: isolate;
109
+ display: grid;
110
+ justify-self: start;
111
+ gap: 0.2rem;
112
+ min-width: 0;
113
+ padding-top: 0.25rem;
114
+ }
115
+
116
+ /* A new event: a soft accent highlight behind it that fades. */
117
+ [data-mk-tl-fresh] [data-mk-tl-body]::before {
118
+ content: '';
119
+ position: absolute;
120
+ inset: -0.125rem -0.625rem -0.375rem;
121
+ z-index: -1;
122
+ border-radius: 12px;
123
+ background: var(--mk-accent-soft);
124
+ animation: mk-tl-fresh 1.8s ease-out both;
125
+ pointer-events: none;
126
+ }
127
+
128
+ @keyframes mk-tl-fresh {
129
+ from {
130
+ opacity: 0.75;
131
+ }
132
+
133
+ to {
134
+ opacity: 0;
135
+ }
136
+ }
137
+
138
+ [data-mk-tl-time],
139
+ [data-mk-tl-meta] {
140
+ color: var(--mk-muted);
141
+ font-size: 0.75rem;
142
+ }
143
+
144
+ [data-mk-tl-title] {
145
+ font-weight: 600;
146
+ line-height: 1.35;
147
+ overflow-wrap: anywhere;
148
+ }
149
+
150
+ [data-mk-tl-item][data-status='upcoming'] [data-mk-tl-title] {
151
+ color: var(--mk-muted);
152
+ }
153
+
154
+ [data-mk-tl-description] {
155
+ margin: 0;
156
+ color: var(--mk-muted);
157
+ font-size: 0.875rem;
158
+ line-height: 1.5;
159
+ overflow-wrap: anywhere;
160
+ }
161
+
162
+ /* A day is a small chip on the rail (it hides the line behind it). */
163
+ [data-mk-tl-day] {
164
+ position: relative;
165
+ z-index: 1;
166
+ justify-self: start;
167
+ margin-top: 0.35rem;
168
+ padding: 0.25rem 0.625rem;
169
+ border-radius: 8px;
170
+ background: var(--mk-surface-3);
171
+ color: var(--mk-muted);
172
+ font-size: 0.6875rem;
173
+ font-weight: 700;
174
+ letter-spacing: 0.04em;
175
+ text-transform: uppercase;
176
+ }
177
+
178
+ @container (min-width: 520px) {
179
+ :is(.mk-timeline, mk-timeline)[data-mk-layout='alternate'] [data-mk-tl-rail] {
180
+ left: calc(50% - 1px);
181
+ }
182
+
183
+ :is(.mk-timeline, mk-timeline)[data-mk-layout='alternate'] [data-mk-tl-item] {
184
+ grid-template-columns: minmax(0, 1fr) 2rem minmax(0, 1fr);
185
+ }
186
+
187
+ :is(.mk-timeline, mk-timeline)[data-mk-layout='alternate'] [data-mk-tl-dot] {
188
+ grid-row: 1;
189
+ grid-column: 2;
190
+ }
191
+
192
+ :is(.mk-timeline, mk-timeline)[data-mk-layout='alternate'] [data-mk-tl-item][data-side='start'] [data-mk-tl-body] {
193
+ grid-row: 1;
194
+ grid-column: 1;
195
+ justify-self: end;
196
+ text-align: end;
197
+ }
198
+
199
+ :is(.mk-timeline, mk-timeline)[data-mk-layout='alternate'] [data-mk-tl-item][data-side='end'] [data-mk-tl-body] {
200
+ grid-row: 1;
201
+ grid-column: 3;
202
+ }
203
+
204
+ :is(.mk-timeline, mk-timeline)[data-mk-layout='alternate'] [data-mk-tl-day] {
205
+ justify-self: center;
206
+ }
207
+ }
208
+
209
+ @media (prefers-reduced-motion: reduce) {
210
+ [data-mk-tl-item][data-status='current'] [data-mk-tl-dot] {
211
+ animation: none;
212
+ box-shadow: 0 0 0 4px var(--mk-surface-1, var(--mk-bg)), 0 0 0 6px color-mix(in srgb, var(--mk-accent) 45%, transparent);
213
+ }
214
+
215
+ [data-mk-tl-progress] {
216
+ transition: none;
217
+ }
218
+ }
@@ -0,0 +1,46 @@
1
+ # toolbar
2
+
3
+ Barra de herramientas con selector elástico tipo slime, etiquetas flotantes y navegación con flechas.
4
+
5
+ ## Instalación
6
+
7
+ ```tsx
8
+ import '@yewdiel21/motion-kit/css';
9
+ import { Toolbar } from '@yewdiel21/motion-kit/react';
10
+ ```
11
+
12
+ ```sh
13
+ npx @yewdiel21/motion-kit add toolbar --react --elements
14
+ ```
15
+
16
+ ## React
17
+
18
+ ```tsx
19
+ <Toolbar value={tool} onChange={setTool} aria-label="Herramientas"><button data-mk-tool="draw" aria-label="Dibujar">✎</button><button data-mk-tool="erase" aria-label="Borrar">⌫</button></Toolbar>
20
+ ```
21
+
22
+ Los callbacks del ejemplo (`ask`, `run`, `setTool`, `setVolume`) pertenecen a tu aplicación. React acepta `className`, `style` y atributos HTML. Los componentes con estado exponen `instanceRef` (excepto PillButton).
23
+
24
+ ## HTML / Astro
25
+
26
+ ```html
27
+ <mk-toolbar aria-label="Herramientas" value="draw"><button data-mk-tool="draw" aria-label="Dibujar">✎</button><button data-mk-tool="erase" aria-label="Borrar">⌫</button></mk-toolbar>
28
+ <script type="module">
29
+ import { defineElements } from '@yewdiel21/motion-kit/elements';
30
+ defineElements(['mk-toolbar']);
31
+ </script>
32
+ ```
33
+
34
+ En Astro usa un `<script>` procesado por Astro. En HTML directo el import requiere bundler o import map. También puedes usar `import { createToolbar } from '@yewdiel21/motion-kit'` y llamar a la factory con el contenedor y las mismas opciones. Al desmontar, llama a `instance.destroy()`.
35
+
36
+ ## Opciones
37
+
38
+ value: data-mk-tool elegido. orientation: vertical (por defecto) u horizontal. tips: etiquetas (true). onChange(value): selección del usuario. Instancia: setValue(value, notify?), value.
39
+
40
+ Los nombres camelCase se escriben como atributos kebab-case. Los arrays y objetos se pasan como JSON. Los booleanos aceptan atributo vacío o `"false"`.
41
+
42
+ ## Estilos y accesibilidad
43
+
44
+ Variables: --mk-toolbar-tool, --mk-toolbar-rail, --mk-toolbar-blob, --mk-toolbar-on-rail, --mk-toolbar-on-blob.
45
+
46
+ Respeta los colores del tema, foco visible y `prefers-reduced-motion`. Los gráficos incluyen una tabla accesible y selección con flechas, Home, End y Escape. Heatmap usa arriba/abajo para un día e izquierda/derecha para una semana. Toolbar usa flechas y Home/End; OrbitMenu cierra con Escape y devuelve el foco. Los controles conservan nombres accesibles; VoiceDots anuncia los estados sin leer cada fotograma.
@@ -0,0 +1,30 @@
1
+ import { MkElement, defineElement, type OptionType } from '../../elements/base';
2
+ import { createToolbar, type ToolbarInstance } from './engine';
3
+
4
+ /**
5
+ * <mk-toolbar class="mk-toolbar" aria-label="Herramientas" value="lapiz">
6
+ * <button data-mk-tool="lapiz" aria-label="Lápiz">…svg…</button> …
7
+ * </mk-toolbar>
8
+ * The chosen tool's blob stretches like slime to the next one. Emits mk:change ({value}).
9
+ */
10
+ export class MkToolbarElement extends MkElement<ToolbarInstance> {
11
+ static options: Record<string, OptionType> = { value: 'string', orientation: 'string', tips: 'boolean' };
12
+
13
+ protected create(options: Record<string, unknown>) {
14
+ return createToolbar(this, options);
15
+ }
16
+
17
+ get value() {
18
+ return this.instance?.value ?? '';
19
+ }
20
+
21
+ set value(next: string) { this.instance?.setValue(next); }
22
+ setValue(value: string, notify = false) { this.instance?.setValue(value, notify); }
23
+
24
+ attributeChangedCallback(name: string, previous: string | null, next: string | null) {
25
+ if (name === 'value' && this.instance) { if (next !== null) this.instance.setValue(next); return; }
26
+ super.attributeChangedCallback(name, previous, next);
27
+ }
28
+ }
29
+
30
+ export const defineToolbar = () => defineElement('mk-toolbar', MkToolbarElement);
@@ -0,0 +1,230 @@
1
+ import { gsap, EASE, registerMotion } from '../../core/gsap';
2
+ import { reduced } from '../../core/reduced';
3
+ import { createScope } from '../../core/scope';
4
+ import { inert, warnOnce, type Instance } from '../../core/types';
5
+ import { press } from '../../motion/micro';
6
+
7
+ /*
8
+ * Toolbar: a rail of tools where one is chosen, marked by a light blob under
9
+ * its icon. Choosing another stretches the blob like slime: its leading edge
10
+ * reaches the new tool first (.2 s) while it narrows, then the trailing edge
11
+ * lets go and catches up on the swatch curve (.38,.49,0,1.5), so it wobbles
12
+ * into place; choosing the same tool squeezes it. A label slides out beside
13
+ * the tool under the pointer (or focus) and glides between tools. A toolbar
14
+ * for the keyboard: arrows and Home/End move and choose (roving tabindex),
15
+ * each tool says aria-pressed. Vertical by default, or horizontal.
16
+ */
17
+
18
+ export interface ToolbarOptions {
19
+ /** The chosen tool (its data-mk-tool, else its position); default: the first one. */
20
+ value?: string;
21
+ /** Default 'vertical'. */
22
+ orientation?: 'vertical' | 'horizontal';
23
+ /** The label beside the tool under the pointer or focus (default true). */
24
+ tips?: boolean;
25
+ onChange?: (value: string) => void;
26
+ }
27
+
28
+ export interface ToolbarInstance extends Instance {
29
+ setValue(value: string, notify?: boolean): void;
30
+ readonly value: string;
31
+ }
32
+
33
+ export function createToolbar(root: HTMLElement | null, options: ToolbarOptions = {}): ToolbarInstance {
34
+ const tools = root ? [...root.querySelectorAll<HTMLButtonElement>('button')] : [];
35
+ if (!root || !tools.length) {
36
+ if (root) warnOnce('toolbar: needs at least one <button>');
37
+ return inert({ setValue() {}, value: '' });
38
+ }
39
+ registerMotion();
40
+ const scope = createScope();
41
+ const vertical = options.orientation !== 'horizontal';
42
+ const valueOf = (tool: HTMLElement) => tool.dataset.mkTool ?? String(tools.indexOf(tool as HTMLButtonElement));
43
+ const labelOf = (tool: HTMLElement) => tool.getAttribute('aria-label') ?? tool.title ?? tool.textContent?.trim() ?? '';
44
+
45
+ scope.attr(root, 'role', 'toolbar');
46
+ scope.attr(root, 'aria-orientation', vertical ? 'vertical' : 'horizontal');
47
+ scope.attr(root, 'data-mk-orientation', vertical ? 'vertical' : 'horizontal');
48
+ for (const tool of tools) {
49
+ scope.attr(tool, 'type', tool.getAttribute('type') ?? 'button');
50
+ scope.attr(tool, 'aria-pressed', 'false');
51
+ scope.attr(tool, 'tabindex', '-1');
52
+ // A title would show the browser's own tooltip over ours.
53
+ if (options.tips !== false && tool.title) {
54
+ scope.attr(tool, 'aria-label', tool.getAttribute('aria-label') ?? tool.title);
55
+ scope.attr(tool, 'title', null);
56
+ }
57
+ }
58
+
59
+ const blob = document.createElement('span');
60
+ blob.dataset.mkToolbarBlob = '';
61
+ blob.setAttribute('aria-hidden', 'true');
62
+ root.prepend(blob);
63
+ const tip = document.createElement('span');
64
+ tip.dataset.mkToolbarTip = '';
65
+ tip.setAttribute('aria-hidden', 'true');
66
+ tip.hidden = true;
67
+ if (options.tips !== false) root.append(tip);
68
+ scope.add(() => {
69
+ gsap.killTweensOf([blob, tip]);
70
+ blob.remove();
71
+ tip.remove();
72
+ });
73
+ scope.attr(root, 'data-mk-ready', '');
74
+
75
+ const find = (value: string | undefined) => tools.find((tool) => valueOf(tool) === value);
76
+ let current = find(options.value) ?? tools.find((tool) => !tool.disabled) ?? tools[0]!;
77
+
78
+ /** Where a tool sits inside the rail (offsets, so transforms on the rail do not count). */
79
+ const box = (tool: HTMLElement) => ({ start: vertical ? tool.offsetTop : tool.offsetLeft, size: vertical ? tool.offsetHeight : tool.offsetWidth, cross: vertical ? tool.offsetLeft : tool.offsetTop, crossSize: vertical ? tool.offsetWidth : tool.offsetHeight });
80
+ const along = vertical ? 'y' : 'x';
81
+ const across = vertical ? 'x' : 'y';
82
+ const length = vertical ? 'height' : 'width';
83
+ const thickness = vertical ? 'width' : 'height';
84
+
85
+ let timeline: gsap.core.Timeline | null = null;
86
+ const place = () => {
87
+ const at = box(current);
88
+ timeline?.kill();
89
+ gsap.set(blob, { [along]: at.start, [across]: at.cross, [length]: at.size, [thickness]: at.crossSize, scaleX: 1, scaleY: 1 });
90
+ };
91
+
92
+ /** The slime: the leading edge reaches the tool, then the trailing edge lets go and wobbles in. */
93
+ const slide = (from: HTMLElement, to: HTMLElement) => {
94
+ if (reduced() || from === to) return place();
95
+ const a = box(from);
96
+ const b = box(to);
97
+ const forward = b.start > a.start;
98
+ const reach = forward ? b.start + b.size - a.start : a.start + a.size - b.start;
99
+ const squeeze = vertical ? { scaleX: 0.84 } : { scaleY: 0.84 };
100
+ const relax = vertical ? { scaleX: 1 } : { scaleY: 1 };
101
+ timeline?.kill();
102
+ timeline = gsap.timeline();
103
+ timeline.to(blob, { [along]: forward ? a.start : b.start, [length]: reach, ...squeeze, duration: 0.2, ease: 'power2.in' }, 0);
104
+ timeline.to(blob, { [along]: b.start, [length]: b.size, duration: 0.42, ease: EASE.swatch }, 0.16);
105
+ timeline.to(blob, { ...relax, duration: 0.5, ease: 'elastic.out(1, 0.45)' }, 0.18);
106
+ };
107
+
108
+ const squish = () => {
109
+ if (reduced()) return;
110
+ timeline?.kill();
111
+ place();
112
+ timeline = gsap.timeline();
113
+ timeline.to(blob, { scaleX: 0.88, scaleY: 0.88, duration: 0.1, ease: 'power2.out' }).to(blob, { scaleX: 1, scaleY: 1, duration: 0.45, ease: 'elastic.out(1, 0.4)' });
114
+ };
115
+
116
+ const paint = () => {
117
+ for (const tool of tools) {
118
+ tool.setAttribute('aria-pressed', String(tool === current));
119
+ tool.setAttribute('tabindex', tool === current ? '0' : '-1');
120
+ }
121
+ };
122
+
123
+ // ── The label beside a tool ───────────────────────────────────────────────
124
+ let tipFor: HTMLElement | null = null;
125
+ let tipTimer: ReturnType<typeof setTimeout> | undefined;
126
+ scope.add(() => clearTimeout(tipTimer));
127
+ const showTip = (tool: HTMLElement, linger = 0) => {
128
+ if (options.tips === false) return;
129
+ clearTimeout(tipTimer);
130
+ const text = labelOf(tool);
131
+ if (!text) return hideTip();
132
+ const at = box(tool);
133
+ const appearing = tip.hidden;
134
+ const changed = tipFor !== tool;
135
+ tipFor = tool;
136
+ tip.textContent = text;
137
+ tip.hidden = false;
138
+ const tipSize = vertical ? tip.offsetHeight : tip.offsetWidth;
139
+ const spot = at.start + at.size / 2 - tipSize / 2;
140
+ if (appearing || reduced()) {
141
+ gsap.killTweensOf(tip);
142
+ gsap.set(tip, { [along]: spot });
143
+ if (!reduced()) gsap.fromTo(tip, { opacity: 0, [across]: -8, filter: 'blur(4px)', scale: 0.9 }, { opacity: 1, [across]: 0, filter: 'blur(0px)', scale: 1, duration: 0.28, ease: EASE.pop });
144
+ else gsap.set(tip, { opacity: 1, [across]: 0, scale: 1, filter: 'none' });
145
+ } else if (changed) {
146
+ gsap.to(tip, { [along]: spot, opacity: 1, [across]: 0, scale: 1, filter: 'blur(0px)', duration: 0.32, ease: EASE.swatch, overwrite: 'auto' });
147
+ }
148
+ if (linger) tipTimer = setTimeout(hideTip, linger);
149
+ };
150
+ const hideTip = () => {
151
+ clearTimeout(tipTimer);
152
+ tipFor = null;
153
+ if (tip.hidden) return;
154
+ if (reduced()) {
155
+ tip.hidden = true;
156
+ return;
157
+ }
158
+ gsap.to(tip, { opacity: 0, [across]: -6, filter: 'blur(4px)', scale: 0.92, duration: 0.18, ease: 'power2.in', overwrite: 'auto', onComplete: () => {
159
+ tip.hidden = true;
160
+ } });
161
+ };
162
+
163
+ const choose = (tool: HTMLElement, notify: boolean) => {
164
+ if ((tool as HTMLButtonElement).disabled) return;
165
+ const previous = current;
166
+ current = tool as HTMLButtonElement;
167
+ paint();
168
+ if (previous === current) squish();
169
+ else slide(previous, current);
170
+ if (previous === current || !notify) return;
171
+ const value = valueOf(current);
172
+ options.onChange?.(value);
173
+ root.dispatchEvent(new CustomEvent('mk:change', { bubbles: true, detail: { value } }));
174
+ };
175
+
176
+ scope.on(root, 'click', (event) => {
177
+ const tool = (event.target as Element).closest<HTMLButtonElement>('button');
178
+ if (!tool || !tools.includes(tool)) return;
179
+ press(tool);
180
+ choose(tool, true);
181
+ showTip(tool, 1200);
182
+ });
183
+ scope.on(root, 'pointerover', (event) => {
184
+ const tool = (event.target as Element).closest<HTMLButtonElement>('button');
185
+ if (tool && tools.includes(tool) && (event as PointerEvent).pointerType !== 'touch') showTip(tool);
186
+ });
187
+ scope.on(root, 'pointerleave', () => {
188
+ tipTimer = setTimeout(hideTip, 120);
189
+ });
190
+ scope.on(root, 'focusin', (event) => {
191
+ const tool = event.target as HTMLElement;
192
+ if (tools.includes(tool as HTMLButtonElement) && tool.matches(':focus-visible')) showTip(tool);
193
+ });
194
+ scope.on(root, 'focusout', (event) => {
195
+ if (!root.contains((event as FocusEvent).relatedTarget as Node)) hideTip();
196
+ });
197
+ scope.on(root, 'keydown', (event) => {
198
+ const key = (event as KeyboardEvent).key;
199
+ const enabled = tools.filter((tool) => !tool.disabled);
200
+ const at = enabled.indexOf(document.activeElement as HTMLButtonElement);
201
+ if (at < 0) return;
202
+ const next =
203
+ key === 'ArrowDown' || key === 'ArrowRight' ? enabled[(at + 1) % enabled.length]
204
+ : key === 'ArrowUp' || key === 'ArrowLeft' ? enabled[(at - 1 + enabled.length) % enabled.length]
205
+ : key === 'Home' ? enabled[0]
206
+ : key === 'End' ? enabled[enabled.length - 1]
207
+ : null;
208
+ if (!next) return;
209
+ event.preventDefault();
210
+ choose(next, true);
211
+ next.focus();
212
+ showTip(next, 1200);
213
+ });
214
+
215
+ if (typeof ResizeObserver === 'function') scope.observe(new ResizeObserver(() => place())).observe(root);
216
+
217
+ paint();
218
+ place();
219
+
220
+ return {
221
+ setValue(value, notify = false) {
222
+ const tool = find(value);
223
+ if (tool) choose(tool, notify);
224
+ },
225
+ get value() {
226
+ return valueOf(current);
227
+ },
228
+ destroy: () => scope.dispose(),
229
+ };
230
+ }
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+ import { useRef, type HTMLAttributes, type MutableRefObject } from 'react';
3
+ import { useIsomorphicLayoutEffect, useLatest } from '../../react/use-recipe';
4
+ import { createToolbar, type ToolbarInstance, type ToolbarOptions } from './engine';
5
+
6
+ export interface ToolbarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'>, ToolbarOptions {
7
+ instanceRef?: MutableRefObject<ToolbarInstance | null>;
8
+ }
9
+
10
+ /** <Toolbar aria-label="Herramientas" value={tool} onChange={setTool}><button data-mk-tool="lapiz" aria-label="Lápiz">…</button></Toolbar> */
11
+ export function Toolbar({ value, orientation, tips, onChange, instanceRef, className, children, ...props }: ToolbarProps) {
12
+ const ref = useRef<HTMLDivElement>(null);
13
+ const changed = useLatest(onChange);
14
+ const instance = useRef<ToolbarInstance | null>(null);
15
+ useIsomorphicLayoutEffect(() => {
16
+ const created = createToolbar(ref.current, { value, orientation, tips, onChange: (next) => changed.current?.(next) });
17
+ instance.current = created;
18
+ if (instanceRef) instanceRef.current = created;
19
+ return () => {
20
+ created.destroy();
21
+ instance.current = null;
22
+ if (instanceRef) instanceRef.current = null;
23
+ };
24
+ // eslint-disable-next-line react-hooks/exhaustive-deps
25
+ }, [orientation, tips]);
26
+ useIsomorphicLayoutEffect(() => {
27
+ if (value !== undefined && instance.current && instance.current.value !== value) instance.current.setValue(value);
28
+ }, [value]);
29
+ return (
30
+ <div {...props} ref={ref} className={['mk-toolbar', className].filter(Boolean).join(' ')}>
31
+ {children}
32
+ </div>
33
+ );
34
+ }