@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,838 @@
1
+ import { gsap, EASE, registerMotion } from '../../core/gsap';
2
+ import { requestFrame } from '../../core/frame';
3
+ import { reduced } from '../../core/reduced';
4
+ import { createScope } from '../../core/scope';
5
+ import { inert, warnOnce, type Instance } from '../../core/types';
6
+
7
+ /*
8
+ * Chart: line, area and bar (grouped or stacked) drawn as SVG from the app's
9
+ * data — no chart runtime. The look is Melon Mind's Indicadores: one series is
10
+ * monochrome (the text colour, 2.5 px), only the zero baseline is drawn (value
11
+ * labels on request), the last value sits in a pill at the end of the line with
12
+ * its point ringed in the surface colour, the selection is a dotted guide with
13
+ * markers that pop, and the tooltip is the inverse glass. Bars are up to 24 px
14
+ * wide with 3 px rounded ends, 2 px gaps and the stack total above.
15
+ * Motion: lines wipe in (700 ms, .38,.49,0,1), bars grow from the baseline,
16
+ * and new data glides from the drawn values to the new ones (scale included).
17
+ * Pointer, touch and keyboard (arrows, Home, End, Escape) select a point; a
18
+ * table carries every value for screen readers. Resizes with its container.
19
+ */
20
+
21
+ export type ChartType = 'line' | 'area' | 'bar' | 'composed';
22
+
23
+ export interface ChartPoint {
24
+ label: string;
25
+ value: number | null;
26
+ }
27
+
28
+ export interface ChartSeries {
29
+ name: string;
30
+ /** One value per label; null is a gap (no data). */
31
+ values: Array<number | null>;
32
+ /** Per-series mark in a composed chart (default line). */
33
+ type?: 'line' | 'area' | 'bar';
34
+ /** An area's lower boundary; values is the upper boundary. Nulls leave gaps. */
35
+ lowerValues?: Array<number | null>;
36
+ /** Any CSS colour; default: monochrome for one series, else the --mk-chart-N slot. */
37
+ color?: string;
38
+ /** Lines: an SVG dash pattern, e.g. '5 5' (a pace or goal) or '1 6' (a projection). */
39
+ dash?: string;
40
+ }
41
+
42
+ export interface ChartOptions {
43
+ type?: ChartType;
44
+ labels?: string[];
45
+ series?: ChartSeries[];
46
+ /** One series as label/value pairs (instead of labels + series). */
47
+ points?: ChartPoint[];
48
+ /** Bars only: stack the series. */
49
+ stacked?: boolean;
50
+ formatValue?: (value: number) => string;
51
+ /** Accessible name (and table caption). */
52
+ label?: string;
53
+ /** Plot height in px (default 240). */
54
+ height?: number;
55
+ emptyLabel?: string;
56
+ /** Legend (default: two or more series). */
57
+ legend?: boolean;
58
+ /** Value labels and hairlines on the y axis (default false: the baseline only). */
59
+ axis?: boolean;
60
+ /** Lines: the last value of the first series in a pill at its end (default true). */
61
+ endLabel?: boolean;
62
+ /** The built-in tooltip card (default true); false keeps the guide and markers for chart-tooltip. */
63
+ tooltip?: boolean;
64
+ onSelect?: (index: number | null) => void;
65
+ }
66
+
67
+ export interface ChartInstance extends Instance {
68
+ /** Merge new options and draw again (keeps the selection when it still exists). */
69
+ update(options: ChartOptions): void;
70
+ select(index: number | null): void;
71
+ readonly selected: number | null;
72
+ }
73
+
74
+ const SVG = 'http://www.w3.org/2000/svg';
75
+ const SLOTS = 8;
76
+ const BAR_MAX = 24;
77
+ const GAP = 2;
78
+ const END_RADIUS = 3;
79
+ let sequence = 0;
80
+
81
+ const svg = <K extends keyof SVGElementTagNameMap>(tag: K, attrs: Record<string, string | number> = {}) => {
82
+ const element = document.createElementNS(SVG, tag);
83
+ for (const [name, value] of Object.entries(attrs)) element.setAttribute(name, String(value));
84
+ return element;
85
+ };
86
+ const finite = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value);
87
+ const round = (n: number) => Math.round(n * 100) / 100;
88
+
89
+ /** 1, 2, 2.5 or 5 × 10ⁿ just above `raw`. */
90
+ function niceStep(raw: number) {
91
+ const power = 10 ** Math.floor(Math.log10(raw));
92
+ const fraction = raw / power;
93
+ return (fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 2.5 ? 2.5 : fraction <= 5 ? 5 : 10) * power;
94
+ }
95
+
96
+ /** Bar path from the baseline `base` to `end`, rounded only at the data end. */
97
+ function barPath(x: number, width: number, base: number, end: number, rounded: boolean) {
98
+ const height = Math.abs(base - end);
99
+ const r = rounded ? Math.min(END_RADIUS, width / 2, height) : 0;
100
+ const dir = end < base ? 1 : -1;
101
+ if (!r) return `M${round(x)},${round(base)}V${round(end)}H${round(x + width)}V${round(base)}Z`;
102
+ return `M${round(x)},${round(base)}V${round(end + dir * r)}Q${round(x)},${round(end)} ${round(x + r)},${round(end)}H${round(x + width - r)}Q${round(x + width)},${round(end)} ${round(x + width)},${round(end + dir * r)}V${round(base)}Z`;
103
+ }
104
+
105
+ interface Model {
106
+ labels: string[];
107
+ series: Array<ChartSeries & { color: string }>;
108
+ }
109
+
110
+ function modelOf(options: ChartOptions): Model {
111
+ const fromPoints = options.points?.length ? { labels: options.points.map((point) => String(point.label)), series: [{ name: options.label ?? '', values: options.points.map((point) => point.value) }] } : null;
112
+ const labels = fromPoints?.labels ?? (options.labels ?? []).map(String);
113
+ const raw: ChartSeries[] = fromPoints?.series ?? options.series ?? [];
114
+ if (raw.length > SLOTS) warnOnce(`chart: ${raw.length} series; past ${SLOTS} they share a neutral colour — fold the rest into "Other"`);
115
+ const count = Math.max(labels.length, ...raw.map((series) => series.values.length), 0);
116
+ const fullLabels = Array.from({ length: count }, (_, i) => labels[i] ?? String(i + 1));
117
+ const mono = raw.length === 1;
118
+ const series = raw.map((series, i) => ({
119
+ name: String(series.name ?? ''),
120
+ values: Array.from({ length: count }, (_, j) => (finite(series.values[j]) ? series.values[j]! : null)),
121
+ color: series.color ?? (mono ? 'var(--mk-chart-mono)' : i < SLOTS ? `var(--mk-chart-${i + 1})` : 'var(--mk-chart-other)'),
122
+ dash: series.dash,
123
+ type: series.type,
124
+ lowerValues: series.lowerValues ? Array.from({ length: count }, (_, j) => finite(series.lowerValues![j]) ? series.lowerValues![j]! : null) : undefined,
125
+ }));
126
+ return { labels: fullLabels, series };
127
+ }
128
+
129
+ type Values = Array<Array<number | null>>;
130
+
131
+ export function createChart(root: HTMLElement | null, initial: ChartOptions = {}): ChartInstance {
132
+ if (!root) return inert({ update() {}, select() {}, selected: null });
133
+ registerMotion();
134
+ const scope = createScope();
135
+ const uid = `mk-chart-${++sequence}`;
136
+ let options: ChartOptions = { ...initial };
137
+ let selected: number | null = null;
138
+ let model = modelOf(options);
139
+
140
+ const made = <K extends keyof HTMLElementTagNameMap>(tag: K, parent: Element = root) => {
141
+ const element = document.createElement(tag);
142
+ parent.append(element);
143
+ scope.add(() => element.remove());
144
+ return element;
145
+ };
146
+ const plot = made('div');
147
+ plot.dataset.mkChartPlot = '';
148
+ const canvas = svg('svg');
149
+ canvas.dataset.mkChartSvg = '';
150
+ canvas.setAttribute('role', 'img');
151
+ canvas.setAttribute('tabindex', '0');
152
+ canvas.setAttribute('focusable', 'true');
153
+ plot.append(canvas);
154
+ const pill = made('span', plot);
155
+ pill.dataset.mkChartEnd = '';
156
+ pill.setAttribute('aria-hidden', 'true');
157
+ pill.hidden = true;
158
+ const tooltip = made('div', plot);
159
+ tooltip.dataset.mkChartTooltip = '';
160
+ tooltip.setAttribute('aria-hidden', 'true');
161
+ tooltip.hidden = true;
162
+ const empty = made('p');
163
+ empty.dataset.mkChartEmpty = '';
164
+ empty.hidden = true;
165
+ const legend = made('ul');
166
+ legend.dataset.mkChartLegend = '';
167
+ const table = made('table');
168
+ table.dataset.mkChartTable = '';
169
+ table.className = 'mk-sr-only';
170
+ const live = made('span');
171
+ live.className = 'mk-sr-only';
172
+ live.setAttribute('role', 'status');
173
+ scope.attr(root, 'data-mk-ready', '');
174
+
175
+ // Layout of the last paint, for selection.
176
+ let geometry = { width: 0, height: 0, top: 0, bottom: 0, left: 0, right: 0, xs: [] as number[], y: (n: number) => n, base: 0 };
177
+ let cursor: SVGGElement | null = null;
178
+ let band: SVGRectElement | null = null;
179
+ /** What is drawn now: values and domain (they trail the model while gliding). */
180
+ let shown: { values: Values; lower: Values; lo: number; hi: number; type: ChartType; stacked: boolean } | null = null;
181
+ let glide: gsap.core.Tween | null = null;
182
+ const effects = new Set<gsap.core.Animation>();
183
+ const keep = (animation: gsap.core.Animation) => {
184
+ effects.add(animation);
185
+ // Finished ones leave as new ones arrive: the animation's own onComplete stays untouched.
186
+ for (const effect of effects) if (effect.totalProgress() === 1) effects.delete(effect);
187
+ };
188
+ scope.add(() => {
189
+ glide?.kill();
190
+ for (const effect of effects) effect.kill();
191
+ effects.clear();
192
+ gsap.killTweensOf(tooltip);
193
+ });
194
+
195
+ const format = (value: number) => {
196
+ if (options.formatValue) return options.formatValue(value);
197
+ return new Intl.NumberFormat(undefined, { maximumFractionDigits: 2 }).format(value);
198
+ };
199
+ const type = (): ChartType => (options.type === 'bar' || options.type === 'area' || options.type === 'composed' ? options.type : 'line');
200
+ const seriesType = (index: number) => type() === 'composed' ? model.series[index]!.type ?? 'line' : type();
201
+ const hasBars = () => model.series.some((_, index) => seriesType(index) === 'bar');
202
+ const stacked = () => type() === 'bar' && Boolean(options.stacked) && model.series.length > 1;
203
+ const hasData = () => model.labels.length > 0 && model.series.some((series) => series.values.some(finite));
204
+
205
+ const totalsOf = (values: Values, index: number) => {
206
+ let up = 0;
207
+ let down = 0;
208
+ for (const list of values) {
209
+ const value = list[index];
210
+ if (!finite(value)) continue;
211
+ if (value >= 0) up += value;
212
+ else down += value;
213
+ }
214
+ return { up, down };
215
+ };
216
+ const targetValues = (): Values => model.series.map((series) => series.values);
217
+ const lowerValues = (): Values => model.series.map((series) => series.lowerValues ?? []);
218
+ const rangeText = (series: Model['series'][number], index: number) => {
219
+ const value = series.values[index];
220
+ const lower = series.lowerValues?.[index];
221
+ if (!finite(value)) return '—';
222
+ return finite(lower) ? `${format(lower)} – ${format(value)}` : format(value);
223
+ };
224
+ const totals = (index: number) => totalsOf(targetValues(), index);
225
+
226
+ const domainOf = (values: Values) => {
227
+ let lo = 0;
228
+ let hi = 0;
229
+ model.labels.forEach((_, i) => {
230
+ if (stacked()) {
231
+ const { up, down } = totalsOf(values, i);
232
+ hi = Math.max(hi, up);
233
+ lo = Math.min(lo, down);
234
+ } else {
235
+ for (const list of values) {
236
+ const value = list[i];
237
+ if (!finite(value)) continue;
238
+ hi = Math.max(hi, value);
239
+ lo = Math.min(lo, value);
240
+ }
241
+ }
242
+ for (const list of lowerValues()) {
243
+ if (finite(list[i])) { lo = Math.min(lo, list[i]!); hi = Math.max(hi, list[i]!); }
244
+ }
245
+ });
246
+ if (hi === lo) hi = lo + 1;
247
+ const step = niceStep((hi - lo) / 4);
248
+ // With value labels the scale rounds to them; without, it is the data ×1.04 (Melonmind).
249
+ if (!options.axis) return { lo: lo * 1.04, hi: hi * 1.04, step: Math.max(hi * 1.04 - lo * 1.04, 1e-9) };
250
+ return { lo: Math.floor(lo / step + 1e-9) * step, hi: Math.ceil(hi / step - 1e-9) * step, step };
251
+ };
252
+
253
+ const describe = () => {
254
+ const name = options.label ?? 'Gráfica';
255
+ if (!hasData()) return `${name}: ${options.emptyLabel ?? 'sin datos'}`;
256
+ const names = model.series.map((series) => series.name).filter(Boolean).join(', ');
257
+ return `${name}. ${model.labels.length} ${model.labels.length === 1 ? 'punto' : 'puntos'}, de ${model.labels[0]} a ${model.labels[model.labels.length - 1]}${names ? `. Series: ${names}` : ''}. Usa las flechas para recorrer los valores.`;
258
+ };
259
+
260
+ const renderTable = () => {
261
+ table.replaceChildren();
262
+ const caption = document.createElement('caption');
263
+ caption.textContent = options.label ?? 'Gráfica';
264
+ const head = document.createElement('thead');
265
+ const headRow = document.createElement('tr');
266
+ const corner = document.createElement('th');
267
+ corner.scope = 'col';
268
+ corner.textContent = 'Etiqueta';
269
+ headRow.append(corner);
270
+ for (const series of model.series) {
271
+ const th = document.createElement('th');
272
+ th.scope = 'col';
273
+ th.textContent = series.name || 'Valor';
274
+ headRow.append(th);
275
+ }
276
+ if (stacked()) {
277
+ const th = document.createElement('th');
278
+ th.scope = 'col';
279
+ th.textContent = 'Total';
280
+ headRow.append(th);
281
+ }
282
+ head.append(headRow);
283
+ const body = document.createElement('tbody');
284
+ model.labels.forEach((label, i) => {
285
+ const row = document.createElement('tr');
286
+ const th = document.createElement('th');
287
+ th.scope = 'row';
288
+ th.textContent = label;
289
+ row.append(th);
290
+ for (const series of model.series) {
291
+ const td = document.createElement('td');
292
+ const value = series.values[i];
293
+ td.textContent = rangeText(series, i);
294
+ row.append(td);
295
+ }
296
+ if (stacked()) {
297
+ const td = document.createElement('td');
298
+ const { up, down } = totals(i);
299
+ td.textContent = format(up + down);
300
+ row.append(td);
301
+ }
302
+ body.append(row);
303
+ });
304
+ table.append(caption, head, body);
305
+ };
306
+
307
+ const renderLegend = () => {
308
+ legend.replaceChildren();
309
+ const show = options.legend ?? model.series.length > 1;
310
+ legend.hidden = !show || !hasData();
311
+ if (legend.hidden) return;
312
+ for (const [index, series] of model.series.entries()) {
313
+ const item = document.createElement('li');
314
+ const swatch = document.createElement('span');
315
+ swatch.dataset.mkChartSwatch = '';
316
+ swatch.dataset.mkType = seriesType(index);
317
+ swatch.style.background = series.color;
318
+ swatch.style.color = series.color;
319
+ if (series.dash) swatch.dataset.mkDash = '';
320
+ swatch.setAttribute('aria-hidden', 'true');
321
+ const name = document.createElement('span');
322
+ name.textContent = series.name;
323
+ item.append(swatch, name);
324
+ legend.append(item);
325
+ }
326
+ };
327
+
328
+ const lastPoint = (list: Array<number | null> | undefined) => {
329
+ if (!list) return -1;
330
+ for (let i = list.length - 1; i >= 0; i--) if (finite(list[i])) return i;
331
+ return -1;
332
+ };
333
+
334
+ /** Draw `values` on the domain lo…hi (called every frame while gliding). */
335
+ const paint = (values: Values, lo: number, hi: number, step: number, lower: Values = lowerValues()) => {
336
+ canvas.replaceChildren();
337
+ const width = Math.max(120, Math.round(plot.clientWidth || root.clientWidth || 600));
338
+ const height = Math.max(80, Math.round(finite(options.height) ? options.height : 240));
339
+ canvas.setAttribute('viewBox', `0 0 ${width} ${height}`);
340
+ canvas.setAttribute('width', String(width));
341
+ canvas.setAttribute('height', String(height));
342
+ const bar = hasBars();
343
+ const axis = Boolean(options.axis);
344
+ const ticks: number[] = [];
345
+ for (let t = lo; t <= hi + step / 2; t += step) ticks.push(Number(t.toPrecision(12)));
346
+ const tickText = ticks.map(format);
347
+ const withEnd = seriesType(0) !== 'bar' && options.endLabel !== false && lastPoint(values[0]) >= 0;
348
+ const left = axis ? Math.min(96, Math.max(28, Math.max(...tickText.map((text) => text.length)) * 7 + 12)) : 4;
349
+ const top = 16;
350
+ const right = withEnd ? Math.min(120, Math.max(48, format(values[0]![lastPoint(values[0])]!).length * 7.5 + 28)) : 8;
351
+ const bottom = 30;
352
+ const plotW = width - left - right;
353
+ const plotH = height - top - bottom;
354
+ const y = (n: number) => top + plotH - ((n - lo) / (hi - lo || 1)) * plotH;
355
+ const base = y(0);
356
+ const n = model.labels.length;
357
+ const slot = plotW / n;
358
+ const xs = model.labels.map((_, i) => (bar ? left + slot * (i + 0.5) : n === 1 ? left + plotW / 2 : left + (plotW * i) / (n - 1)));
359
+ geometry = { width, height, top, bottom: top + plotH, left, right: width - right, xs, y, base };
360
+
361
+ // Baseline (and, with `axis`, hairlines with their values).
362
+ const grid = svg('g', { 'data-mk-part': 'grid' });
363
+ if (!axis) {
364
+ const zero = svg('line', { x1: left, x2: width - right, y1: round(base), y2: round(base) });
365
+ zero.dataset.mkZero = '';
366
+ grid.append(zero);
367
+ }
368
+ if (axis) ticks.forEach((tick, i) => {
369
+ const at = round(y(tick));
370
+ const line = svg('line', { x1: left, x2: width - right, y1: at, y2: at });
371
+ if (tick === 0) line.dataset.mkZero = '';
372
+ grid.append(line);
373
+ const text = svg('text', { x: left - 8, y: at, 'text-anchor': 'end', 'dominant-baseline': 'middle' });
374
+ text.textContent = tickText[i]!;
375
+ grid.append(text);
376
+ });
377
+ canvas.append(grid);
378
+
379
+ // X labels, thinned to what fits.
380
+ const xAxis = svg('g', { 'data-mk-part': 'x-axis' });
381
+ const longest = Math.max(...model.labels.map((label) => label.length));
382
+ const every = Math.max(1, Math.ceil((n * (longest * 6.5 + 16)) / plotW));
383
+ model.labels.forEach((label, i) => {
384
+ if (i % every) return;
385
+ const anchor = bar || n === 1 ? 'middle' : i === 0 ? 'start' : 'middle';
386
+ const text = svg('text', { x: round(xs[i]!), y: height - 8, 'text-anchor': anchor });
387
+ text.textContent = label;
388
+ xAxis.append(text);
389
+ });
390
+ canvas.append(xAxis);
391
+
392
+ band = null;
393
+ if (bar) {
394
+ band = svg('rect', { 'data-mk-part': 'band', y: top, height: plotH, rx: 12 });
395
+ band.style.display = 'none';
396
+ canvas.append(band);
397
+ }
398
+
399
+ const marks = svg('g', { 'data-mk-part': 'series' });
400
+ const defs = svg('defs');
401
+ if (bar) {
402
+ const barIndices = model.series.flatMap((_, index) => seriesType(index) === 'bar' ? [index] : []);
403
+ const groups = stacked() ? 1 : barIndices.length;
404
+ const barWidth = Math.max(2, Math.min(BAR_MAX, (slot * 0.62 - GAP * (groups - 1)) / groups));
405
+ const totalsLayer = svg('g', { 'data-mk-part': 'totals' });
406
+ model.labels.forEach((_, i) => {
407
+ if (stacked()) {
408
+ let up = 0;
409
+ let down = 0;
410
+ const outer = { up: -1, down: -1 };
411
+ values.forEach((list, k) => {
412
+ const value = list[i];
413
+ if (finite(value) && value > 0) outer.up = k;
414
+ if (finite(value) && value < 0) outer.down = k;
415
+ });
416
+ values.forEach((list, k) => {
417
+ const value = list[i];
418
+ if (!finite(value) || value === 0) return;
419
+ const from = value > 0 ? up : down;
420
+ const to = from + value;
421
+ if (value > 0) up = to;
422
+ else down = to;
423
+ // A 2 px surface gap between touching segments.
424
+ const start = y(from) + (from !== 0 ? (value > 0 ? -GAP : GAP) : 0);
425
+ const end = y(to);
426
+ if ((value > 0 && end >= start) || (value < 0 && end <= start)) return;
427
+ const path = svg('path', { d: barPath(xs[i]! - barWidth / 2, barWidth, start, end, k === (value > 0 ? outer.up : outer.down)), 'data-mk-index': i, 'data-mk-series': k });
428
+ path.style.fill = model.series[k]!.color;
429
+ marks.append(path);
430
+ });
431
+ // The stack total above it, when the columns have room.
432
+ if (slot >= 22 && up > 0) {
433
+ const total = totals(i);
434
+ const text = svg('text', { x: round(xs[i]!), y: round(y(up) - 6), 'text-anchor': 'middle', 'data-mk-part': 'total' });
435
+ text.textContent = format(total.up + total.down);
436
+ totalsLayer.append(text);
437
+ }
438
+ } else {
439
+ const groupWidth = groups * barWidth + GAP * (groups - 1);
440
+ values.forEach((list, k) => {
441
+ if (seriesType(k) !== 'bar') return;
442
+ const value = list[i];
443
+ if (!finite(value) || value === 0) return;
444
+ const x = xs[i]! - groupWidth / 2 + barIndices.indexOf(k) * (barWidth + GAP);
445
+ const path = svg('path', { d: barPath(x, barWidth, base, y(value), true), 'data-mk-index': i, 'data-mk-series': k });
446
+ path.style.fill = model.series[k]!.color;
447
+ marks.append(path);
448
+ });
449
+ }
450
+ });
451
+ if (totalsLayer.childNodes.length) canvas.append(totalsLayer);
452
+ }
453
+ if (model.series.some((_, index) => seriesType(index) !== 'bar')) {
454
+ values.forEach((list, k) => {
455
+ if (seriesType(k) === 'bar') return;
456
+ const series = model.series[k]!;
457
+ const runs: Array<Array<[number, number, number]>> = [];
458
+ let run: Array<[number, number, number]> = [];
459
+ list.forEach((value, i) => {
460
+ const bottomValue = lower[k]?.[i];
461
+ if (finite(value) && (!series.lowerValues || finite(bottomValue))) run.push([xs[i]!, y(value), finite(bottomValue) ? y(bottomValue) : base]);
462
+ else if (run.length) {
463
+ runs.push(run);
464
+ run = [];
465
+ }
466
+ });
467
+ if (run.length) runs.push(run);
468
+ if (seriesType(k) === 'area') {
469
+ const gradient = svg('linearGradient', { id: `${uid}-fill-${k}`, x1: 0, x2: 0, y1: 0, y2: 1 });
470
+ const stop = (offset: string, opacity: string) => {
471
+ const element = svg('stop', { offset });
472
+ element.style.stopColor = series.color;
473
+ element.style.stopOpacity = opacity;
474
+ return element;
475
+ };
476
+ gradient.append(stop('0', '0.25'), stop('1', '0'));
477
+ defs.append(gradient);
478
+ for (const points of runs) {
479
+ if (points.length < 2) continue;
480
+ const d = `M${points.map(([px, py]) => `${round(px)},${round(py)}`).join('L')}L${[...points].reverse().map(([px, , py]) => `${round(px)},${round(py)}`).join('L')}Z`;
481
+ const area = svg('path', { d, 'data-mk-part': 'area', 'data-mk-series': k });
482
+ area.style.fill = `url(#${uid}-fill-${k})`;
483
+ marks.append(area);
484
+ }
485
+ }
486
+ for (const points of runs) {
487
+ if (points.length === 1) {
488
+ // A lone point has no line: a marker shows it.
489
+ const dot = svg('circle', { cx: round(points[0]![0]), cy: round(points[0]![1]), r: 4, 'data-mk-part': 'dot' });
490
+ dot.style.fill = series.color;
491
+ marks.append(dot);
492
+ continue;
493
+ }
494
+ const line = svg('path', { d: `M${points.map(([px, py]) => `${round(px)},${round(py)}`).join('L')}`, 'data-mk-part': 'line' });
495
+ line.style.stroke = series.color;
496
+ // Dotted patterns (a first dash of 1 or less) draw round dots; dashes stay thin.
497
+ const dotted = Boolean(series.dash) && Number(series.dash!.trim().split(/[\s,]+/)[0]) <= 1;
498
+ line.style.strokeWidth = dotted ? '2.5' : series.dash ? '1.5' : k === 0 ? '2.5' : '2';
499
+ if (series.dash) line.style.strokeDasharray = series.dash;
500
+ marks.append(line);
501
+ }
502
+ });
503
+ // The last value of the first series: a ringed point and its pill.
504
+ const last = lastPoint(values[0]);
505
+ if (last >= 0 && seriesType(0) !== 'bar' && !model.series[0]!.dash) {
506
+ const point = svg('circle', { cx: round(xs[last]!), cy: round(y(values[0]![last]!)), r: 5, 'data-mk-part': 'end' });
507
+ point.style.fill = model.series[0]!.color;
508
+ marks.append(point);
509
+ }
510
+ }
511
+ if (defs.childNodes.length) canvas.append(defs);
512
+ canvas.append(marks);
513
+ cursor = svg('g', { 'data-mk-part': 'cursor' });
514
+ canvas.append(cursor);
515
+
516
+ const last = withEnd ? lastPoint(values[0]) : -1;
517
+ pill.hidden = last < 0;
518
+ if (last >= 0) {
519
+ pill.textContent = format(values[0]![last]!);
520
+ const pillH = pill.offsetHeight || 22;
521
+ pill.style.left = `${round(width - right + 10)}px`;
522
+ pill.style.top = `${round(y(values[0]![last]!) - pillH / 2)}px`;
523
+ }
524
+ };
525
+
526
+ let markerIndex: number | null = null;
527
+ /** Where the selection points, in plot px (for mk:select). */
528
+ let anchor = { x: 0, y: 0 };
529
+ const paintSelection = (announce: boolean) => {
530
+ if (!cursor) return;
531
+ cursor.replaceChildren();
532
+ if (band) band.style.display = 'none';
533
+ for (const mark of canvas.querySelectorAll('[data-mk-index]')) mark.removeAttribute('data-mk-dim');
534
+ if (selected === null || !hasData()) {
535
+ if (!tooltip.hidden && !reduced()) {
536
+ gsap.killTweensOf(tooltip, 'opacity,scale');
537
+ keep(gsap.to(tooltip, { opacity: 0, scale: 0.94, duration: 0.15, ease: 'power2.in', onComplete: () => {
538
+ tooltip.hidden = true;
539
+ } }));
540
+ } else tooltip.hidden = true;
541
+ markerIndex = null;
542
+ return;
543
+ }
544
+ const i = selected;
545
+ const x = geometry.xs[i]!;
546
+ const bar = type() === 'bar';
547
+ const fresh = markerIndex !== i;
548
+ markerIndex = i;
549
+ let anchorY = geometry.bottom;
550
+ if (bar && band) {
551
+ const slot = (geometry.right - geometry.left) / model.labels.length;
552
+ band.setAttribute('x', String(round(x - slot / 2 + 2)));
553
+ band.setAttribute('width', String(round(Math.max(0, slot - 4))));
554
+ band.style.display = '';
555
+ for (const mark of canvas.querySelectorAll<SVGElement>('[data-mk-index]')) if (mark.getAttribute('data-mk-index') !== String(i)) mark.setAttribute('data-mk-dim', '');
556
+ const { up, down } = totals(i);
557
+ anchorY = stacked() ? geometry.y(up || down) : Math.min(...model.series.map((series) => (finite(series.values[i]) ? geometry.y(series.values[i]!) : geometry.bottom)));
558
+ } else {
559
+ cursor.append(svg('line', { x1: round(x), x2: round(x), y1: geometry.top, y2: geometry.bottom, 'data-mk-part': 'guide' }));
560
+ model.series.forEach((series) => {
561
+ const value = series.values[i];
562
+ if (!finite(value)) return;
563
+ const cy = geometry.y(value);
564
+ anchorY = Math.min(anchorY, cy);
565
+ const dot = svg('circle', { cx: round(x), cy: round(cy), r: 5, 'data-mk-part': 'marker' });
566
+ dot.style.fill = series.color;
567
+ cursor!.append(dot);
568
+ if (fresh && !reduced()) keep(gsap.fromTo(dot, { attr: { r: 0 } }, { attr: { r: 5 }, duration: 0.3, ease: EASE.pop }));
569
+ });
570
+ }
571
+ // Tooltip: label, one row per series (text in text colours, a swatch for identity).
572
+ tooltip.replaceChildren();
573
+ const title = document.createElement('strong');
574
+ title.textContent = model.labels[i]!;
575
+ tooltip.append(title);
576
+ const rows: string[] = [];
577
+ const shownSeries = model.series.filter((series) => finite(series.values[i]));
578
+ for (const series of shownSeries.length ? shownSeries : model.series) {
579
+ const value = series.values[i];
580
+ const row = document.createElement('span');
581
+ row.dataset.mkChartRow = '';
582
+ const swatch = document.createElement('i');
583
+ // Text-coloured series would vanish on the inverse glass: they show as a line in its ink.
584
+ if (/--mk-(text|chart-mono|muted)/.test(series.color)) swatch.dataset.mkMono = '';
585
+ else swatch.style.background = series.color;
586
+ if (series.dash) swatch.dataset.mkDash = '';
587
+ const name = document.createElement('span');
588
+ name.textContent = series.name;
589
+ const amount = document.createElement('b');
590
+ amount.textContent = rangeText(series, i);
591
+ row.append(swatch, name, amount);
592
+ tooltip.append(row);
593
+ rows.push(`${series.name ? `${series.name}: ` : ''}${finite(value) ? rangeText(series, i) : 'sin dato'}`);
594
+ }
595
+ if (stacked()) {
596
+ const { up, down } = totals(i);
597
+ const row = document.createElement('span');
598
+ row.dataset.mkChartRow = 'total';
599
+ const name = document.createElement('span');
600
+ name.textContent = 'Total';
601
+ const amount = document.createElement('b');
602
+ amount.textContent = format(up + down);
603
+ row.append(document.createElement('i'), name, amount);
604
+ tooltip.append(row);
605
+ rows.push(`Total: ${format(up + down)}`);
606
+ }
607
+ anchor = { x: round(x), y: round(anchorY) };
608
+ if (options.tooltip === false) {
609
+ tooltip.hidden = true;
610
+ if (announce) live.textContent = `${model.labels[i]}. ${rows.join('. ')}`;
611
+ return;
612
+ }
613
+ const appearing = tooltip.hidden;
614
+ tooltip.hidden = false;
615
+ // Beside the point, towards the middle of the plot, inside it.
616
+ const tipW = tooltip.offsetWidth || 160;
617
+ const tipH = tooltip.offsetHeight || 60;
618
+ const towardsLeft = x > geometry.width / 2;
619
+ const left = round(Math.max(0, Math.min(geometry.width - tipW, towardsLeft ? x - 16 - tipW : x + 16)));
620
+ const top = round(Math.max(0, Math.min(geometry.height - tipH, anchorY - tipH - 12)));
621
+ if (appearing || reduced()) {
622
+ gsap.killTweensOf(tooltip);
623
+ gsap.set(tooltip, { x: left, y: top });
624
+ if (!reduced()) keep(gsap.fromTo(tooltip, { opacity: 0, scale: 0.9 }, { opacity: 1, scale: 1, duration: 0.25, ease: EASE.pop }));
625
+ else gsap.set(tooltip, { opacity: 1, scale: 1 });
626
+ } else {
627
+ gsap.killTweensOf(tooltip, 'opacity,scale');
628
+ gsap.set(tooltip, { opacity: 1, scale: 1 });
629
+ keep(gsap.to(tooltip, { x: left, y: top, duration: 0.25, ease: 'power3.out', overwrite: 'auto' }));
630
+ }
631
+ if (announce) live.textContent = `${model.labels[i]}. ${rows.join('. ')}`;
632
+ };
633
+
634
+ /** A resize while gliding waits for the glide to end. */
635
+ let resized = false;
636
+ const settle = () => {
637
+ if (!resized || scope.disposed) return;
638
+ resized = false;
639
+ draw(false);
640
+ };
641
+
642
+ /** Rebuild everything for the model; `animate` glides from what is drawn. */
643
+ const draw = (animate: boolean) => {
644
+ glide?.kill();
645
+ canvas.setAttribute('aria-label', describe());
646
+ scope.attr(root, 'data-mk-chart-type', type());
647
+ renderTable();
648
+ renderLegend();
649
+ const ok = hasData();
650
+ empty.hidden = ok;
651
+ empty.textContent = options.emptyLabel ?? 'Sin datos para mostrar';
652
+ plot.hidden = !ok;
653
+ if (!ok) {
654
+ canvas.replaceChildren();
655
+ cursor = null;
656
+ tooltip.hidden = true;
657
+ pill.hidden = true;
658
+ selected = null;
659
+ shown = null;
660
+ return;
661
+ }
662
+ if (selected !== null && selected >= model.labels.length) selected = null;
663
+ const target = targetValues();
664
+ const domain = domainOf(target);
665
+ const finish = () => {
666
+ shown = { values: target, lower: lowerValues(), lo: domain.lo, hi: domain.hi, type: type(), stacked: stacked() };
667
+ paint(target, domain.lo, domain.hi, domain.step);
668
+ paintSelection(false);
669
+ };
670
+ if (!animate || reduced()) return finish();
671
+ const comparable = shown && shown.type === type() && shown.stacked === stacked() && shown.values.length === target.length && shown.values.every((list, k) => list.length === target[k]!.length);
672
+ if (comparable) {
673
+ // New data: values and scale glide from what is drawn.
674
+ const from = shown!;
675
+ const state = { t: 0 };
676
+ glide = gsap.to(state, {
677
+ t: 1,
678
+ duration: 0.6,
679
+ ease: type() === 'bar' ? EASE.swatch : 'power3.out',
680
+ onUpdate: () => {
681
+ const t = state.t;
682
+ const values = target.map((list, k) => list.map((value, i) => {
683
+ const before = from.values[k]![i];
684
+ return finite(value) && finite(before) ? before + (value - before) * t : value;
685
+ }));
686
+ const lower = lowerValues().map((list, k) => list.map((value, i) => {
687
+ const before = from.lower[k]?.[i];
688
+ return finite(value) && finite(before) ? before + (value - before) * t : value;
689
+ }));
690
+ paint(values, from.lo + (domain.lo - from.lo) * t, from.hi + (domain.hi - from.hi) * t, domain.step, lower);
691
+ paintSelection(false);
692
+ },
693
+ onComplete: () => {
694
+ finish();
695
+ settle();
696
+ },
697
+ });
698
+ return;
699
+ }
700
+ // First appearance: bars grow from the baseline, lines wipe in from the left.
701
+ finish();
702
+ if (type() === 'bar') {
703
+ const state = { t: 0 };
704
+ glide = gsap.to(state, {
705
+ t: 1,
706
+ duration: 0.7,
707
+ ease: EASE.swatch,
708
+ onUpdate: () => paint(target.map((list) => list.map((value) => (finite(value) ? value * state.t : value))), domain.lo, domain.hi, domain.step),
709
+ onComplete: () => {
710
+ finish();
711
+ settle();
712
+ },
713
+ });
714
+ return;
715
+ }
716
+ const clip = svg('clipPath', { id: `${uid}-wipe` });
717
+ const rect = svg('rect', { x: 0, y: 0, width: 0, height: geometry.height });
718
+ clip.append(rect);
719
+ canvas.prepend(clip);
720
+ const series = canvas.querySelector('[data-mk-part="series"]');
721
+ series?.setAttribute('clip-path', `url(#${uid}-wipe)`);
722
+ pill.style.opacity = '0';
723
+ glide = gsap.to(rect, {
724
+ attr: { width: geometry.width },
725
+ duration: 0.7,
726
+ ease: EASE.wipe,
727
+ onComplete: () => {
728
+ series?.removeAttribute('clip-path');
729
+ clip.remove();
730
+ keep(gsap.fromTo(pill, { opacity: 0, x: -6 }, { opacity: 1, x: 0, duration: 0.3, ease: EASE.pop, clearProps: 'opacity,transform' }));
731
+ settle();
732
+ },
733
+ onInterrupt: () => {
734
+ pill.style.removeProperty('opacity');
735
+ },
736
+ });
737
+ };
738
+
739
+ const select = (index: number | null, announce = false) => {
740
+ if (scope.disposed) return;
741
+ const next = index === null || !hasData() ? null : Math.max(0, Math.min(model.labels.length - 1, Math.round(index)));
742
+ const changed = next !== selected;
743
+ selected = next;
744
+ paintSelection(announce);
745
+ if (!changed) return;
746
+ options.onSelect?.(selected);
747
+ root.dispatchEvent(
748
+ new CustomEvent('mk:select', {
749
+ bubbles: true,
750
+ detail: {
751
+ index: selected,
752
+ label: selected === null ? null : model.labels[selected],
753
+ values: selected === null ? [] : model.series.map((series) => series.values[selected!]),
754
+ // Where the selection points (plot px) and each series there, for chart-tooltip.
755
+ x: selected === null ? null : anchor.x,
756
+ y: selected === null ? null : anchor.y,
757
+ series:
758
+ selected === null
759
+ ? []
760
+ : model.series.map((series) => ({ name: series.name, color: series.color, value: series.values[selected!], previous: selected! > 0 ? series.values[selected! - 1] : null })),
761
+ },
762
+ }),
763
+ );
764
+ };
765
+
766
+ const indexAt = (clientX: number) => {
767
+ const box = canvas.getBoundingClientRect();
768
+ const scale = box.width ? geometry.width / box.width : 1;
769
+ const x = (clientX - box.left) * scale;
770
+ let best = 0;
771
+ geometry.xs.forEach((candidate, i) => {
772
+ if (Math.abs(candidate - x) < Math.abs(geometry.xs[best]! - x)) best = i;
773
+ });
774
+ return best;
775
+ };
776
+ scope.on(canvas, 'pointermove', (event) => select(indexAt((event as PointerEvent).clientX)));
777
+ scope.on(canvas, 'pointerdown', (event) => select(indexAt((event as PointerEvent).clientX)));
778
+ // Touch keeps its selection when the finger lifts; a mouse leaving clears it.
779
+ scope.on(canvas, 'pointerleave', (event) => {
780
+ if ((event as PointerEvent).pointerType === 'mouse') select(null);
781
+ });
782
+ scope.on(canvas, 'focus', () => {
783
+ if (selected === null && hasData()) select(0, true);
784
+ });
785
+ scope.on(canvas, 'blur', () => select(null));
786
+ scope.on(canvas, 'keydown', (event) => {
787
+ const key = (event as KeyboardEvent).key;
788
+ const last = model.labels.length - 1;
789
+ const moves: Record<string, number | null> = {
790
+ ArrowRight: Math.min(last, (selected ?? -1) + 1),
791
+ ArrowUp: Math.min(last, (selected ?? -1) + 1),
792
+ ArrowLeft: Math.max(0, (selected ?? 1) - 1),
793
+ ArrowDown: Math.max(0, (selected ?? 1) - 1),
794
+ Home: 0,
795
+ End: last,
796
+ Escape: null,
797
+ };
798
+ if (!(key in moves) || !hasData()) return;
799
+ event.preventDefault();
800
+ select(moves[key]!, true);
801
+ });
802
+
803
+ if (typeof ResizeObserver === 'function') {
804
+ let width = 0;
805
+ let cancel = () => {};
806
+ const observer = scope.observe(
807
+ new ResizeObserver(() => {
808
+ const next = Math.round(plot.clientWidth || root.clientWidth);
809
+ if (!next || next === width) return;
810
+ width = next;
811
+ if (next === geometry.width) return;
812
+ if (glide?.isActive()) {
813
+ resized = true;
814
+ return;
815
+ }
816
+ cancel();
817
+ cancel = requestFrame(() => draw(false));
818
+ }),
819
+ );
820
+ observer.observe(root);
821
+ scope.add(() => cancel());
822
+ }
823
+ draw(true);
824
+
825
+ return {
826
+ update(next) {
827
+ if (scope.disposed) return;
828
+ options = { ...options, ...next };
829
+ model = modelOf(options);
830
+ draw(true);
831
+ },
832
+ select: (index) => select(index),
833
+ get selected() {
834
+ return selected;
835
+ },
836
+ destroy: () => scope.dispose(),
837
+ };
838
+ }