@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,246 @@
1
+ import { gsap, EASE, registerMotion } from '../../core/gsap';
2
+ import { reduced } from '../../core/reduced';
3
+ import { createScope } from '../../core/scope';
4
+ import { inert, type Instance } from '../../core/types';
5
+ import { numberFormat } from '../../core/dates';
6
+ import { CHANNEL_LABELS, areaBackground, channelText, formatColor, sameColor, toHex, toHsva, type Hsva } from '../../core/color';
7
+
8
+ /*
9
+ * Color area: the saturation (x) × brightness (y) square at the current hue.
10
+ * Pressing jumps the thumb there (swing glide, .35 s), then it follows the
11
+ * pointer tightly (.1 s); release commits. Two visually hidden range inputs
12
+ * (Saturación, Brillo) carry the value for assistive tech and the keyboard:
13
+ * ←/→ saturation, ↑/↓ brightness, Shift ×10, PageUp/PageDown brightness ±10,
14
+ * Home/End saturation min/max. Grabbing grows the thumb (click curve) and pops
15
+ * a loupe with the colour, like color-slider; near the top edge the loupe flips
16
+ * below the thumb ([data-mk-loupe-below]), so a panel that clips its content
17
+ * (the color-picker popover) never cuts it. Vars: --mk-color-area,
18
+ * --mk-color-thumb, --mk-color-x, --mk-color-y.
19
+ */
20
+
21
+ export interface ColorAreaOptions {
22
+ value?: string | Hsva;
23
+ /** Accessible name of the group (default 'Color'). */
24
+ label?: string;
25
+ /** Default 1. */
26
+ step?: number;
27
+ name?: string;
28
+ disabled?: boolean;
29
+ onInput?: (value: string, color: Hsva) => void;
30
+ onChange?: (value: string, color: Hsva) => void;
31
+ }
32
+
33
+ export interface ColorAreaInstance extends Instance {
34
+ setColor(color: string | Hsva, notify?: boolean): void;
35
+ readonly value: string;
36
+ readonly color: Hsva;
37
+ }
38
+
39
+ /** Room the loupe needs above the thumb's centre (thumb half, gap, loupe), in px. */
40
+ const LOUPE_ROOM = 70;
41
+
42
+ const KEYS: Record<string, ['s' | 'v', number]> = {
43
+ ArrowLeft: ['s', -1],
44
+ ArrowRight: ['s', 1],
45
+ ArrowUp: ['v', 1],
46
+ ArrowDown: ['v', -1],
47
+ PageUp: ['v', 10],
48
+ PageDown: ['v', -10],
49
+ Home: ['s', -Infinity],
50
+ End: ['s', Infinity],
51
+ };
52
+
53
+ export function createColorArea(root: HTMLElement | null, options: ColorAreaOptions = {}): ColorAreaInstance {
54
+ if (!root) return inert({ setColor() {}, value: '', color: { h: 0, s: 0, v: 0, a: 1 } });
55
+ registerMotion();
56
+ const scope = createScope();
57
+ const effects = new Set<gsap.core.Animation>();
58
+ const keep = (animation: gsap.core.Animation | null) => {
59
+ if (!animation) return;
60
+ effects.add(animation);
61
+ // Finished ones leave as new ones arrive: the animation's own onComplete stays untouched.
62
+ for (const effect of effects) if (effect.totalProgress() === 1) effects.delete(effect);
63
+ };
64
+ scope.add(() => {
65
+ for (const effect of effects) effect.kill();
66
+ effects.clear();
67
+ });
68
+ scope.attr(root, 'style', root.getAttribute('style'));
69
+
70
+ const step = options.step && options.step > 0 ? options.step : 1;
71
+ let color = toHsva(options.value ?? 'hsl(0 100% 50%)');
72
+ const format = numberFormat(root, { maximumFractionDigits: 0 });
73
+
74
+ const made: Element[] = [];
75
+ const surface = document.createElement('div');
76
+ surface.dataset.mkColorAreaSurface = '';
77
+ surface.setAttribute('role', 'group');
78
+ surface.setAttribute('aria-label', options.label ?? 'Color');
79
+ const thumb = document.createElement('span');
80
+ thumb.dataset.mkColorThumb = '';
81
+ thumb.setAttribute('aria-hidden', 'true');
82
+ const loupe = document.createElement('span');
83
+ loupe.dataset.mkColorLoupe = '';
84
+ thumb.append(loupe);
85
+ surface.append(thumb);
86
+ const range = (axis: 'x' | 'y', label: string) => {
87
+ const input = document.createElement('input');
88
+ input.type = 'range';
89
+ input.className = 'mk-sr-only';
90
+ input.dataset.mkColorInput = axis;
91
+ input.min = '0';
92
+ input.max = '100';
93
+ input.step = String(step);
94
+ input.disabled = Boolean(options.disabled);
95
+ input.setAttribute('aria-label', label);
96
+ input.setAttribute('aria-roledescription', 'selector de color 2D');
97
+ surface.append(input);
98
+ return input;
99
+ };
100
+ const inputs = { x: range('x', CHANNEL_LABELS.saturation), y: range('y', CHANNEL_LABELS.brightness) };
101
+ root.append(surface);
102
+ made.push(surface);
103
+ let hidden: HTMLInputElement | null = null;
104
+ if (options.name) {
105
+ hidden = document.createElement('input');
106
+ hidden.type = 'hidden';
107
+ hidden.name = options.name;
108
+ root.append(hidden);
109
+ made.push(hidden);
110
+ }
111
+ scope.add(() => made.forEach((node) => node.remove()));
112
+ scope.attr(root, 'data-mk-grabbing', null);
113
+ scope.attr(root, 'data-mk-loupe-below', null);
114
+ scope.attr(root, 'data-mk-ready', '');
115
+
116
+ const snap = (n: number) => Math.min(100, Math.max(0, Math.round(n / step) * step));
117
+ const shown = { x: 0, y: 0 };
118
+ let glide: gsap.core.Tween | null = null;
119
+ scope.add(() => {
120
+ glide?.kill();
121
+ gsap.killTweensOf([thumb, loupe]);
122
+ });
123
+ const place = () => {
124
+ root.style.setProperty('--mk-color-x', String(Number(shown.x.toFixed(4))));
125
+ root.style.setProperty('--mk-color-y', String(Number(shown.y.toFixed(4))));
126
+ };
127
+ const paint = (mode: 'set' | 'drag' | 'glide') => {
128
+ const text = `${CHANNEL_LABELS.saturation} ${channelText('saturation', color.s, format)}, ${CHANNEL_LABELS.brightness.toLowerCase()} ${channelText('brightness', color.v, format)}`;
129
+ root.style.setProperty('--mk-color-area', areaBackground(color.h));
130
+ root.style.setProperty('--mk-color-thumb', formatColor(color, 'rgb'));
131
+ inputs.x.value = String(color.s);
132
+ inputs.y.value = String(color.v);
133
+ for (const input of [inputs.x, inputs.y]) input.setAttribute('aria-valuetext', text);
134
+ if (hidden) hidden.value = toHex(color);
135
+ const target = { x: color.s / 100, y: 1 - color.v / 100 };
136
+ const height = surface.getBoundingClientRect().height;
137
+ root.toggleAttribute('data-mk-loupe-below', height > 0 && target.y * height < LOUPE_ROOM);
138
+ glide?.kill();
139
+ if (mode === 'set' || reduced()) {
140
+ Object.assign(shown, target);
141
+ place();
142
+ return;
143
+ }
144
+ glide = gsap.to(shown, { ...target, duration: mode === 'drag' ? 0.1 : 0.35, ease: mode === 'drag' ? 'power3.out' : EASE.swatch, onUpdate: place });
145
+ };
146
+
147
+ const emit = (type: 'input' | 'change') => {
148
+ const value = toHex(color);
149
+ (type === 'input' ? options.onInput : options.onChange)?.(value, { ...color });
150
+ root.dispatchEvent(new CustomEvent(`mk:${type}`, { bubbles: true, detail: { value, color: { ...color } } }));
151
+ };
152
+
153
+ let grabbed = false;
154
+ const grab = (on: boolean) => {
155
+ if (grabbed === on) return;
156
+ grabbed = on;
157
+ root.toggleAttribute('data-mk-grabbing', on);
158
+ if (reduced()) return;
159
+ keep(gsap.to(thumb, { scale: on ? 1.25 : 1, duration: 0.25, ease: EASE.click }));
160
+ if (on) keep(gsap.fromTo(loupe, { scale: 0.6, opacity: 0, filter: 'blur(6px)' }, { scale: 1, opacity: 1, filter: 'blur(0px)', duration: 0.3, ease: EASE.pop }));
161
+ else keep(gsap.to(loupe, { scale: 0.8, opacity: 0, filter: 'blur(6px)', duration: 0.2, ease: 'power2.in' }));
162
+ };
163
+
164
+ const fromPoint = (event: PointerEvent) => {
165
+ const rect = surface.getBoundingClientRect();
166
+ if (!rect.width || !rect.height) return;
167
+ const s = ((event.clientX - rect.left) / rect.width) * 100;
168
+ const v = (1 - (event.clientY - rect.top) / rect.height) * 100;
169
+ color = { ...color, s: snap(s), v: snap(v) };
170
+ };
171
+ let dragging = false;
172
+ scope.on(surface, 'pointerdown', (event) => {
173
+ const down = event as PointerEvent;
174
+ if (options.disabled || down.button !== 0 || down.target instanceof HTMLInputElement) return;
175
+ down.preventDefault();
176
+ try {
177
+ surface.setPointerCapture(down.pointerId);
178
+ } catch {
179
+ // jsdom and synthetic events have no active pointer to capture.
180
+ }
181
+ dragging = true;
182
+ grab(true);
183
+ fromPoint(down);
184
+ paint('glide');
185
+ emit('input');
186
+ inputs.x.focus({ preventScroll: true });
187
+ });
188
+ scope.on(surface, 'pointermove', (event) => {
189
+ if (!dragging) return;
190
+ fromPoint(event as PointerEvent);
191
+ paint('drag');
192
+ emit('input');
193
+ });
194
+ const release = () => {
195
+ if (!dragging) return;
196
+ dragging = false;
197
+ grab(false);
198
+ emit('change');
199
+ };
200
+ for (const type of ['pointerup', 'pointercancel', 'lostpointercapture']) scope.on(surface, type, release);
201
+
202
+ for (const input of [inputs.x, inputs.y]) {
203
+ scope.on(input, 'keydown', (event) => {
204
+ const key = event as KeyboardEvent;
205
+ const move = KEYS[key.key];
206
+ if (!move || options.disabled) return;
207
+ key.preventDefault();
208
+ const [axis, amount] = move;
209
+ const delta = Number.isFinite(amount) ? amount * step * (key.shiftKey ? 10 : 1) : amount;
210
+ color = { ...color, [axis]: snap(Math.min(100, Math.max(0, color[axis] + delta))) };
211
+ paint('glide');
212
+ emit('input');
213
+ emit('change');
214
+ });
215
+ // Assistive tech can set a range's value directly.
216
+ scope.on(input, 'input', () => {
217
+ color = { ...color, s: snap(Number(inputs.x.value)), v: snap(Number(inputs.y.value)) };
218
+ paint('glide');
219
+ emit('input');
220
+ });
221
+ scope.on(input, 'change', () => emit('change'));
222
+ }
223
+
224
+ paint('set');
225
+
226
+ return {
227
+ setColor(next, notify = true) {
228
+ if (scope.disposed) return;
229
+ const target = toHsva(next, color);
230
+ if (sameColor(target, color) && target.h === color.h) return;
231
+ color = target;
232
+ paint('glide');
233
+ if (notify) {
234
+ emit('input');
235
+ emit('change');
236
+ }
237
+ },
238
+ get value() {
239
+ return toHex(color);
240
+ },
241
+ get color() {
242
+ return { ...color };
243
+ },
244
+ destroy: () => scope.dispose(),
245
+ };
246
+ }
@@ -0,0 +1,42 @@
1
+ 'use client';
2
+ import { useRef, type HTMLAttributes } from 'react';
3
+ import { useIsomorphicLayoutEffect, useLatest } from '../../react/use-recipe';
4
+ import { toHex, toHsva } from '../../core/color';
5
+ import { createColorArea, type ColorAreaInstance, type ColorAreaOptions } from './engine';
6
+
7
+ export interface ColorAreaProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onInput' | 'onChange' | 'defaultValue'>, Omit<ColorAreaOptions, 'value'> {
8
+ /** Controlled colour; without it the area keeps its own (defaultValue). */
9
+ value?: string;
10
+ defaultValue?: string;
11
+ }
12
+
13
+ /** <ColorArea value={color} onInput={setColor} />. */
14
+ export function ColorArea({ value, defaultValue, label, step, name, disabled, onInput, onChange, className, ...props }: ColorAreaProps) {
15
+ const ref = useRef<HTMLDivElement>(null);
16
+ const instance = useRef<ColorAreaInstance | null>(null);
17
+ const input = useLatest(onInput);
18
+ const change = useLatest(onChange);
19
+ const start = useRef(value ?? defaultValue);
20
+ useIsomorphicLayoutEffect(() => {
21
+ const created = createColorArea(ref.current, {
22
+ value: value ?? start.current,
23
+ label,
24
+ step,
25
+ name,
26
+ disabled,
27
+ onInput: (hex, color) => input.current?.(hex, color),
28
+ onChange: (hex, color) => change.current?.(hex, color),
29
+ });
30
+ instance.current = created;
31
+ return () => {
32
+ start.current = created.value;
33
+ created.destroy();
34
+ instance.current = null;
35
+ };
36
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37
+ }, [label, step, name, disabled]);
38
+ useIsomorphicLayoutEffect(() => {
39
+ if (value !== undefined && instance.current && instance.current.value !== toHex(toHsva(value))) instance.current.setColor(value, false);
40
+ }, [value]);
41
+ return <div {...props} ref={ref} className={['mk-color-area', className].filter(Boolean).join(' ')} />;
42
+ }
@@ -0,0 +1,43 @@
1
+ # color-field
2
+
3
+ Campo de texto para colores con una muestra al lado. Acepta todo lo que lee `parseColor`: `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()`/`rgba()` y `hsl()`/`hsla()` (con comas o espacios y `/ alfa`).
4
+
5
+ Mientras escribes, un color válido pinta la muestra (transición de 0,25 s); un texto que aún no es color marca la muestra con un borde discontinuo. Enter o salir del campo lo confirman: un color válido se reescribe en el formato elegido y la muestra rebota (curva pop); uno no válido o vacío sacude el campo, vuelve al último color válido y un estado discreto anuncia «Color no válido». Escape devuelve el último color.
6
+
7
+ ## HTML / Astro
8
+
9
+ ```html
10
+ <mk-color-field class="mk-color-field" value="#ff8800"></mk-color-field>
11
+ <mk-color-field class="mk-color-field" value="#ff8800" format="rgb" alpha></mk-color-field>
12
+
13
+ <!-- Con tu propio input y etiqueta: se reutiliza y se devuelve tal cual al destruir. -->
14
+ <label class="mk-color-field" data-mk="color-field">Fondo <input name="fondo" value="#123456" /></label>
15
+ ```
16
+
17
+ ## React
18
+
19
+ ```tsx
20
+ <ColorField value={color} onChange={setColor} format="hsl" />
21
+ ```
22
+
23
+ ## Opciones
24
+
25
+ | Opción | Atributo | Por defecto | Qué hace |
26
+ |---|---|---|---|
27
+ | `value` | `value` | el valor del input, o negro | Color de partida. |
28
+ | `format` | `format` | `'hex'` | Cómo se escribe al confirmar: `hex`, `rgb` o `hsl`. |
29
+ | `alpha` | `alpha` | `false` | Conserva la transparencia; sin él, los colores se confirman opacos. |
30
+ | `label` | `label` | `'Color'` | `aria-label` si el input no tiene etiqueta propia. |
31
+ | `name` | `name` | — | Nombre del input en el formulario (envía el texto). |
32
+ | `disabled`, `readOnly` | `disabled`, `read-only` | `false` | Estados del input. |
33
+ | `onChange(hex, hsva)` | — | — | Al confirmar un color nuevo. |
34
+
35
+ ## API y eventos
36
+
37
+ `setColor(color, notify = true)`, `value` (hex), `color` (HSVA), `destroy()`. Evento `mk:change` con `{ value, color }`.
38
+
39
+ ## Variables CSS
40
+
41
+ `--mk-color-checker` (damero bajo los colores translúcidos). El motor escribe `--mk-color-swatch`. Campo de 12 px, muestra de 8 px.
42
+
43
+ Con movimiento reducido no hay sacudida ni rebote: el texto vuelve igual y el estado lo anuncia.
@@ -0,0 +1,66 @@
1
+ /* color-field — a 12 px field on surface-3 with a colour swatch (8 px corners, checkerboard under translucent colours)
2
+ and a mono text input; focus draws a 3 px accent ring; an unparsed text dashes the swatch. */
3
+ .mk-color-field,
4
+ mk-color-field {
5
+ --mk-color-checker: repeating-conic-gradient(#d4d4d4 0 25%, #fff 0 50%) 0 0 / 8px 8px;
6
+ display: flex;
7
+ align-items: center;
8
+ gap: 0.6rem;
9
+ min-width: 0;
10
+ height: 2.75rem;
11
+ padding: 0 0.75rem 0 0.5rem;
12
+ border-radius: 12px;
13
+ background: var(--mk-surface-3);
14
+ color: var(--mk-text);
15
+ transition: box-shadow 0.2s ease;
16
+ }
17
+
18
+ :is(.mk-color-field, mk-color-field):focus-within {
19
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--mk-accent) 35%, transparent);
20
+ }
21
+
22
+ :is(.mk-color-field, mk-color-field) [data-mk-color-swatch] {
23
+ flex: none;
24
+ width: 1.75rem;
25
+ height: 1.75rem;
26
+ border-radius: 8px;
27
+ background: linear-gradient(var(--mk-color-swatch), var(--mk-color-swatch)), var(--mk-color-checker);
28
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mk-text) 22%, transparent);
29
+ transition: background 0.25s ease;
30
+ }
31
+
32
+ :is(.mk-color-field, mk-color-field)[data-mk-unparsed] [data-mk-color-swatch] {
33
+ outline: 2px dashed var(--mk-muted);
34
+ outline-offset: 2px;
35
+ }
36
+
37
+ :is(.mk-color-field, mk-color-field) [data-mk-color-text] {
38
+ flex: 1;
39
+ min-width: 0;
40
+ border: 0;
41
+ background: transparent;
42
+ color: inherit;
43
+ font: 500 0.9375rem/1 var(--mk-font-mono, ui-monospace, monospace);
44
+ text-overflow: ellipsis;
45
+ outline: none;
46
+ }
47
+
48
+ :is(.mk-color-field, mk-color-field) [data-mk-color-status] {
49
+ position: absolute;
50
+ width: 1px;
51
+ height: 1px;
52
+ margin: -1px;
53
+ overflow: hidden;
54
+ clip-path: inset(50%);
55
+ white-space: nowrap;
56
+ }
57
+
58
+ @media (prefers-reduced-motion: reduce) {
59
+ :is(.mk-color-field, mk-color-field) {
60
+ transition: none;
61
+ }
62
+
63
+ :is(.mk-color-field, mk-color-field) [data-mk-color-swatch] {
64
+ transition: none;
65
+ }
66
+ }
@@ -0,0 +1,26 @@
1
+ import { MkElement, defineElement, type OptionType } from '../../elements/base';
2
+ import { createColorField, type ColorFieldInstance } from './engine';
3
+
4
+ /**
5
+ * <mk-color-field class="mk-color-field" value="#ff8800" format="hex"></mk-color-field>
6
+ * Emits mk:change ({value, color}) when a new colour is committed.
7
+ */
8
+ export class MkColorFieldElement extends MkElement<ColorFieldInstance> {
9
+ static options: Record<string, OptionType> = { value: 'string', format: 'string', alpha: 'boolean', label: 'string', name: 'string', disabled: 'boolean', readOnly: 'boolean' };
10
+
11
+ protected create(options: Record<string, unknown>) {
12
+ return createColorField(this, options);
13
+ }
14
+
15
+ attributeChangedCallback(name: string, previous: string | null, next: string | null) {
16
+ if (previous === next || !this.instance) return;
17
+ if (name === 'value' && next) this.instance.setColor(next, false);
18
+ else super.attributeChangedCallback(name, previous, next);
19
+ }
20
+
21
+ get value() {
22
+ return this.instance?.value ?? '';
23
+ }
24
+ }
25
+
26
+ export const defineColorField = () => defineElement('mk-color-field', MkColorFieldElement);
@@ -0,0 +1,174 @@
1
+ import { gsap, EASE, registerMotion } from '../../core/gsap';
2
+ import { reduced } from '../../core/reduced';
3
+ import { createScope } from '../../core/scope';
4
+ import { inert, type Instance } from '../../core/types';
5
+ import { formatColor, parseColor, sameColor, toHex, toHsva, type ColorFormat, type Hsva } from '../../core/color';
6
+ import { shake } from '../../motion/micro';
7
+
8
+ /*
9
+ * Color field: a text input that takes any colour parseColor reads (hex, rgb(),
10
+ * hsl()) beside a swatch. While typing, a readable colour paints the swatch
11
+ * (CSS transition .25 s). Enter or blur commits: a valid colour is rewritten in
12
+ * `format` and the swatch pops (pop curve); an invalid or empty text shakes the
13
+ * field, goes back to the last valid colour and a polite status says
14
+ * "Color no válido". Escape puts the last colour back. Without `alpha`, colours
15
+ * are committed opaque. Var: --mk-color-swatch.
16
+ */
17
+
18
+ export interface ColorFieldOptions {
19
+ value?: string | Hsva;
20
+ format?: ColorFormat;
21
+ /** Keep transparency (default false: committed colours are opaque). */
22
+ alpha?: boolean;
23
+ /** aria-label when the input has no label of its own (default 'Color'). */
24
+ label?: string;
25
+ name?: string;
26
+ disabled?: boolean;
27
+ readOnly?: boolean;
28
+ onChange?: (value: string, color: Hsva) => void;
29
+ }
30
+
31
+ export interface ColorFieldInstance extends Instance {
32
+ setColor(color: string | Hsva, notify?: boolean): void;
33
+ readonly value: string;
34
+ readonly color: Hsva;
35
+ }
36
+
37
+ export function createColorField(root: HTMLElement | null, options: ColorFieldOptions = {}): ColorFieldInstance {
38
+ if (!root) return inert({ setColor() {}, value: '', color: { h: 0, s: 0, v: 0, a: 1 } });
39
+ registerMotion();
40
+ const scope = createScope();
41
+ const effects = new Set<gsap.core.Animation>();
42
+ const keep = (animation: gsap.core.Animation | null) => {
43
+ if (!animation) return;
44
+ effects.add(animation);
45
+ // Finished ones leave as new ones arrive: the animation's own onComplete stays untouched.
46
+ for (const effect of effects) if (effect.totalProgress() === 1) effects.delete(effect);
47
+ };
48
+ scope.add(() => {
49
+ for (const effect of effects) effect.kill();
50
+ effects.clear();
51
+ });
52
+ scope.attr(root, 'style', root.getAttribute('style'));
53
+
54
+ const format: ColorFormat = options.format === 'rgb' || options.format === 'hsl' ? options.format : 'hex';
55
+ const alpha = Boolean(options.alpha);
56
+
57
+ let input = root.querySelector('input');
58
+ if (!input) {
59
+ input = document.createElement('input');
60
+ input.type = 'text';
61
+ root.append(input);
62
+ const created = input;
63
+ scope.add(() => created.remove());
64
+ }
65
+ const field = input;
66
+ const original = field.value;
67
+ scope.add(() => {
68
+ field.value = original;
69
+ });
70
+ scope.attr(field, 'data-mk-color-text', '');
71
+ scope.attr(field, 'autocomplete', 'off');
72
+ scope.attr(field, 'spellcheck', 'false');
73
+ scope.attr(field, 'autocapitalize', 'off');
74
+ if (options.name) scope.attr(field, 'name', options.name);
75
+ if (options.disabled) scope.attr(field, 'disabled', '');
76
+ if (options.readOnly) scope.attr(field, 'readonly', '');
77
+ const labelled = field.closest('label') || field.labels?.length || field.hasAttribute('aria-label') || field.hasAttribute('aria-labelledby');
78
+ if (!labelled) scope.attr(field, 'aria-label', options.label ?? 'Color');
79
+
80
+ const swatch = document.createElement('span');
81
+ swatch.dataset.mkColorSwatch = '';
82
+ swatch.setAttribute('aria-hidden', 'true');
83
+ field.before(swatch);
84
+ const status = document.createElement('span');
85
+ status.className = 'mk-sr-only';
86
+ status.dataset.mkColorStatus = '';
87
+ status.setAttribute('role', 'status');
88
+ root.append(status);
89
+ scope.add(() => {
90
+ swatch.remove();
91
+ status.remove();
92
+ gsap.killTweensOf(swatch);
93
+ });
94
+ scope.attr(root, 'data-mk-unparsed', null);
95
+ scope.attr(root, 'data-mk-ready', '');
96
+
97
+ const opaque = (color: Hsva) => (alpha ? color : { ...color, a: 1 });
98
+ let color = opaque(toHsva(options.value ?? (field.value || undefined), { h: 0, s: 0, v: 0, a: 1 }));
99
+ const text = () => formatColor(color, format);
100
+ const paintSwatch = (shown: Hsva) => root.style.setProperty('--mk-color-swatch', formatColor(shown, 'rgb'));
101
+ const pop = () => {
102
+ if (!reduced()) keep(gsap.fromTo(swatch, { scale: 1.18 }, { scale: 1, duration: 0.3, ease: EASE.pop, clearProps: 'scale,transform' }));
103
+ };
104
+ const emit = () => {
105
+ const value = toHex(color);
106
+ options.onChange?.(value, { ...color });
107
+ root.dispatchEvent(new CustomEvent('mk:change', { bubbles: true, detail: { value, color: { ...color } } }));
108
+ };
109
+
110
+ field.value = text();
111
+ paintSwatch(color);
112
+
113
+ scope.on(field, 'input', () => {
114
+ const parsed = parseColor(field.value, color.h);
115
+ if (parsed) paintSwatch(opaque(parsed));
116
+ root.toggleAttribute('data-mk-unparsed', !parsed && field.value.trim() !== '');
117
+ });
118
+
119
+ const commit = () => {
120
+ const parsed = parseColor(field.value, color.h);
121
+ root.removeAttribute('data-mk-unparsed');
122
+ if (!parsed) {
123
+ keep(shake(root));
124
+ field.value = text();
125
+ paintSwatch(color);
126
+ status.textContent = 'Color no válido';
127
+ return;
128
+ }
129
+ const next = opaque(parsed);
130
+ const changed = !sameColor(next, color);
131
+ color = next;
132
+ field.value = text();
133
+ paintSwatch(color);
134
+ status.textContent = '';
135
+ if (!changed) return;
136
+ pop();
137
+ emit();
138
+ };
139
+ scope.on(field, 'blur', commit);
140
+ scope.on(field, 'keydown', (event) => {
141
+ const key = (event as KeyboardEvent).key;
142
+ if (key === 'Enter') {
143
+ event.preventDefault();
144
+ commit();
145
+ } else if (key === 'Escape' && field.value !== text()) {
146
+ event.preventDefault();
147
+ field.value = text();
148
+ paintSwatch(color);
149
+ root.removeAttribute('data-mk-unparsed');
150
+ }
151
+ });
152
+
153
+ return {
154
+ setColor(next, notify = true) {
155
+ if (scope.disposed) return;
156
+ const target = opaque(toHsva(next, color));
157
+ const changed = !sameColor(target, color);
158
+ color = target;
159
+ field.value = text();
160
+ paintSwatch(color);
161
+ root.removeAttribute('data-mk-unparsed');
162
+ if (!changed) return;
163
+ pop();
164
+ if (notify) emit();
165
+ },
166
+ get value() {
167
+ return toHex(color);
168
+ },
169
+ get color() {
170
+ return { ...color };
171
+ },
172
+ destroy: () => scope.dispose(),
173
+ };
174
+ }
@@ -0,0 +1,42 @@
1
+ 'use client';
2
+ import { useRef, type HTMLAttributes } from 'react';
3
+ import { useIsomorphicLayoutEffect, useLatest } from '../../react/use-recipe';
4
+ import { toHex, toHsva } from '../../core/color';
5
+ import { createColorField, type ColorFieldInstance, type ColorFieldOptions } from './engine';
6
+
7
+ export interface ColorFieldProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>, Omit<ColorFieldOptions, 'value'> {
8
+ /** Controlled colour; without it the field keeps its own (defaultValue). */
9
+ value?: string;
10
+ defaultValue?: string;
11
+ }
12
+
13
+ /** <ColorField value={color} onChange={setColor} format="rgb" />. The engine creates the input. */
14
+ export function ColorField({ value, defaultValue, format, alpha, label, name, disabled, readOnly, onChange, className, ...props }: ColorFieldProps) {
15
+ const ref = useRef<HTMLDivElement>(null);
16
+ const instance = useRef<ColorFieldInstance | null>(null);
17
+ const change = useLatest(onChange);
18
+ const start = useRef(value ?? defaultValue);
19
+ useIsomorphicLayoutEffect(() => {
20
+ const created = createColorField(ref.current, {
21
+ value: value ?? start.current,
22
+ format,
23
+ alpha,
24
+ label,
25
+ name,
26
+ disabled,
27
+ readOnly,
28
+ onChange: (hex, color) => change.current?.(hex, color),
29
+ });
30
+ instance.current = created;
31
+ return () => {
32
+ start.current = created.value;
33
+ created.destroy();
34
+ instance.current = null;
35
+ };
36
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37
+ }, [format, alpha, label, name, disabled, readOnly]);
38
+ useIsomorphicLayoutEffect(() => {
39
+ if (value !== undefined && instance.current && instance.current.value !== toHex(toHsva(value))) instance.current.setColor(value, false);
40
+ }, [value]);
41
+ return <div {...props} ref={ref} className={['mk-color-field', className].filter(Boolean).join(' ')} />;
42
+ }