@yewdiel21/motion-kit 0.10.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/README.md +155 -93
  2. package/dist/auto/index.d.ts +53 -3
  3. package/dist/auto/index.js +101 -3
  4. package/dist/auto/index.js.map +1 -1
  5. package/dist/{chunk-IKQ5FODN.js → chunk-6P4P7NU6.js} +2 -218
  6. package/dist/chunk-6P4P7NU6.js.map +1 -0
  7. package/dist/chunk-CU6SXW3E.js +20334 -0
  8. package/dist/chunk-CU6SXW3E.js.map +1 -0
  9. package/dist/{chunk-XAKC2QY7.js → chunk-EY4BJKC4.js} +3 -28
  10. package/dist/chunk-EY4BJKC4.js.map +1 -0
  11. package/dist/chunk-QP4QJOEN.js +72 -0
  12. package/dist/chunk-QP4QJOEN.js.map +1 -0
  13. package/dist/css/components/activity-feed.css +240 -0
  14. package/dist/css/components/attachment.css +266 -0
  15. package/dist/css/components/breadcrumb.css +110 -0
  16. package/dist/css/components/chart-tooltip.css +168 -0
  17. package/dist/css/components/chart.css +296 -0
  18. package/dist/css/components/code-block.css +264 -0
  19. package/dist/css/components/color-area.css +82 -0
  20. package/dist/css/components/color-field.css +67 -0
  21. package/dist/css/components/color-picker.css +131 -0
  22. package/dist/css/components/color-slider.css +113 -0
  23. package/dist/css/components/command-search.css +252 -0
  24. package/dist/css/components/context-menu.css +23 -0
  25. package/dist/css/components/credit-card.css +288 -0
  26. package/dist/css/components/data-table.css +591 -0
  27. package/dist/css/components/date-range-picker.css +168 -0
  28. package/dist/css/components/date-time-picker.css +178 -0
  29. package/dist/css/components/drawer.css +58 -0
  30. package/dist/css/components/editable-table.css +201 -0
  31. package/dist/css/components/empty-state.css +61 -0
  32. package/dist/css/components/file-explorer.css +633 -0
  33. package/dist/css/components/filter-builder.css +232 -0
  34. package/dist/css/components/hold-confirm.css +87 -0
  35. package/dist/css/components/hover-card.css +13 -7
  36. package/dist/css/components/image-preview.css +195 -0
  37. package/dist/css/components/json-viewer.css +272 -0
  38. package/dist/css/components/like-button.css +78 -0
  39. package/dist/css/components/link-preview.css +275 -0
  40. package/dist/css/components/loading-button.css +77 -0
  41. package/dist/css/components/multi-select.css +267 -0
  42. package/dist/css/components/notification-bell.css +127 -0
  43. package/dist/css/components/password-strength.css +183 -0
  44. package/dist/css/components/popover.css +25 -0
  45. package/dist/css/components/progress.css +140 -0
  46. package/dist/css/components/questionnaire.css +217 -0
  47. package/dist/css/components/range-calendar.css +186 -0
  48. package/dist/css/components/range-slider.css +192 -0
  49. package/dist/css/components/resizable-panel.css +243 -0
  50. package/dist/css/components/rich-text-editor.css +284 -0
  51. package/dist/css/components/scratch-card.css +75 -0
  52. package/dist/css/components/skeleton.css +108 -0
  53. package/dist/css/components/split-view.css +19 -0
  54. package/dist/css/components/star-rating.css +80 -0
  55. package/dist/css/components/stat-card.css +164 -0
  56. package/dist/css/components/swipe-actions.css +105 -0
  57. package/dist/css/components/tag-input.css +244 -0
  58. package/dist/css/components/time-field.css +88 -0
  59. package/dist/css/components/timeline.css +219 -0
  60. package/dist/css/components/tooltip.css +79 -0
  61. package/dist/css/components/tree-view.css +210 -0
  62. package/dist/css/components/virtual-list.css +195 -0
  63. package/dist/css/tokens.css +185 -181
  64. package/dist/elements/index.d.ts +674 -5
  65. package/dist/elements/index.js +1361 -8
  66. package/dist/elements/index.js.map +1 -1
  67. package/dist/{engine-GDGwQnJE.d.ts → engine-Cn6IhE3z.d.ts} +1 -1
  68. package/dist/engine-QECQnGz1.d.ts +33 -0
  69. package/dist/index.css +9104 -189
  70. package/dist/index.d.ts +89 -5
  71. package/dist/index.js +243 -9
  72. package/dist/index.js.map +1 -1
  73. package/dist/react/index.d.ts +579 -23
  74. package/dist/react/index.js +2042 -7
  75. package/dist/react/index.js.map +1 -1
  76. package/dist/{reduced-BmBzKH94.d.ts → reduced-BBUusld6.d.ts} +9 -2
  77. package/dist/reveal-DEvp6U6T.d.ts +2381 -0
  78. package/dist/{store-DYb3tTsZ.d.ts → store-DjkTBX7f.d.ts} +2 -2
  79. package/package.json +1 -1
  80. package/registry.json +406 -1
  81. package/src/auto/auto-init.ts +98 -0
  82. package/src/components/activity-feed/README.md +56 -0
  83. package/src/components/activity-feed/activity-feed.css +239 -0
  84. package/src/components/activity-feed/element.ts +36 -0
  85. package/src/components/activity-feed/engine.ts +351 -0
  86. package/src/components/activity-feed/react.tsx +32 -0
  87. package/src/components/attachment/README.md +27 -0
  88. package/src/components/attachment/attachment.css +265 -0
  89. package/src/components/attachment/element.ts +50 -0
  90. package/src/components/attachment/engine.ts +469 -0
  91. package/src/components/attachment/react.tsx +65 -0
  92. package/src/components/breadcrumb/README.md +38 -0
  93. package/src/components/breadcrumb/breadcrumb.css +109 -0
  94. package/src/components/breadcrumb/element.ts +27 -0
  95. package/src/components/breadcrumb/engine.ts +249 -0
  96. package/src/components/breadcrumb/react.tsx +30 -0
  97. package/src/components/chart/README.md +24 -0
  98. package/src/components/chart/chart.css +295 -0
  99. package/src/components/chart/element.ts +41 -0
  100. package/src/components/chart/engine.ts +811 -0
  101. package/src/components/chart/react.tsx +50 -0
  102. package/src/components/chart-tooltip/README.md +53 -0
  103. package/src/components/chart-tooltip/chart-tooltip.css +167 -0
  104. package/src/components/chart-tooltip/element.ts +37 -0
  105. package/src/components/chart-tooltip/engine.ts +442 -0
  106. package/src/components/chart-tooltip/react.tsx +47 -0
  107. package/src/components/code-block/README.md +19 -0
  108. package/src/components/code-block/code-block.css +263 -0
  109. package/src/components/code-block/element.ts +34 -0
  110. package/src/components/code-block/engine.ts +254 -0
  111. package/src/components/code-block/highlight.ts +244 -0
  112. package/src/components/code-block/react.tsx +94 -0
  113. package/src/components/color-area/README.md +50 -0
  114. package/src/components/color-area/color-area.css +81 -0
  115. package/src/components/color-area/element.ts +26 -0
  116. package/src/components/color-area/engine.ts +246 -0
  117. package/src/components/color-area/react.tsx +42 -0
  118. package/src/components/color-field/README.md +43 -0
  119. package/src/components/color-field/color-field.css +66 -0
  120. package/src/components/color-field/element.ts +26 -0
  121. package/src/components/color-field/engine.ts +174 -0
  122. package/src/components/color-field/react.tsx +42 -0
  123. package/src/components/color-picker/README.md +45 -0
  124. package/src/components/color-picker/color-picker.css +130 -0
  125. package/src/components/color-picker/element.ts +45 -0
  126. package/src/components/color-picker/engine.ts +314 -0
  127. package/src/components/color-picker/react.tsx +47 -0
  128. package/src/components/color-slider/README.md +55 -0
  129. package/src/components/color-slider/color-slider.css +112 -0
  130. package/src/components/color-slider/element.ts +26 -0
  131. package/src/components/color-slider/engine.ts +234 -0
  132. package/src/components/color-slider/react.tsx +45 -0
  133. package/src/components/command-search/README.md +15 -0
  134. package/src/components/command-search/command-search.css +251 -0
  135. package/src/components/command-search/element.ts +36 -0
  136. package/src/components/command-search/engine.ts +356 -0
  137. package/src/components/command-search/match.ts +53 -0
  138. package/src/components/command-search/react.tsx +66 -0
  139. package/src/components/context-menu/README.md +31 -0
  140. package/src/components/context-menu/context-menu.css +22 -0
  141. package/src/components/context-menu/element.ts +40 -0
  142. package/src/components/context-menu/engine.ts +153 -0
  143. package/src/components/context-menu/react.tsx +57 -0
  144. package/src/components/credit-card/README.md +20 -0
  145. package/src/components/credit-card/card.ts +77 -0
  146. package/src/components/credit-card/credit-card.css +287 -0
  147. package/src/components/credit-card/element.ts +33 -0
  148. package/src/components/credit-card/engine.ts +410 -0
  149. package/src/components/credit-card/react.tsx +36 -0
  150. package/src/components/data-table/README.md +83 -0
  151. package/src/components/data-table/data-table.css +590 -0
  152. package/src/components/data-table/element.ts +54 -0
  153. package/src/components/data-table/engine.ts +1059 -0
  154. package/src/components/data-table/react.tsx +94 -0
  155. package/src/components/date-range-picker/README.md +51 -0
  156. package/src/components/date-range-picker/date-range-picker.css +167 -0
  157. package/src/components/date-range-picker/element.ts +52 -0
  158. package/src/components/date-range-picker/engine.ts +352 -0
  159. package/src/components/date-range-picker/react.tsx +57 -0
  160. package/src/components/date-time-picker/README.md +48 -0
  161. package/src/components/date-time-picker/date-time-picker.css +177 -0
  162. package/src/components/date-time-picker/element.ts +47 -0
  163. package/src/components/date-time-picker/engine.ts +350 -0
  164. package/src/components/date-time-picker/react.tsx +54 -0
  165. package/src/components/dialog/README.md +103 -102
  166. package/src/components/dialog/element.ts +123 -118
  167. package/src/components/dialog/engine.ts +449 -432
  168. package/src/components/drawer/README.md +28 -0
  169. package/src/components/drawer/drawer.css +57 -0
  170. package/src/components/drawer/element.ts +21 -0
  171. package/src/components/drawer/engine.ts +56 -0
  172. package/src/components/drawer/react.tsx +85 -0
  173. package/src/components/editable-table/README.md +67 -0
  174. package/src/components/editable-table/editable-table.css +200 -0
  175. package/src/components/editable-table/element.ts +45 -0
  176. package/src/components/editable-table/engine.ts +775 -0
  177. package/src/components/editable-table/react.tsx +79 -0
  178. package/src/components/empty-state/README.md +41 -0
  179. package/src/components/empty-state/element.ts +23 -0
  180. package/src/components/empty-state/empty-state.css +60 -0
  181. package/src/components/empty-state/engine.ts +232 -0
  182. package/src/components/empty-state/react.tsx +34 -0
  183. package/src/components/file-explorer/README.md +67 -0
  184. package/src/components/file-explorer/element.ts +39 -0
  185. package/src/components/file-explorer/engine.ts +1307 -0
  186. package/src/components/file-explorer/file-explorer.css +632 -0
  187. package/src/components/file-explorer/react.tsx +77 -0
  188. package/src/components/filter-builder/README.md +47 -0
  189. package/src/components/filter-builder/element.ts +34 -0
  190. package/src/components/filter-builder/engine.ts +365 -0
  191. package/src/components/filter-builder/filter-builder.css +231 -0
  192. package/src/components/filter-builder/react.tsx +36 -0
  193. package/src/components/hold-confirm/README.md +13 -0
  194. package/src/components/hold-confirm/element.ts +24 -0
  195. package/src/components/hold-confirm/engine.ts +216 -0
  196. package/src/components/hold-confirm/hold-confirm.css +86 -0
  197. package/src/components/hold-confirm/react.tsx +28 -0
  198. package/src/components/hover-card/README.md +6 -2
  199. package/src/components/hover-card/engine.ts +68 -6
  200. package/src/components/hover-card/hover-card.css +13 -7
  201. package/src/components/image-preview/README.md +16 -0
  202. package/src/components/image-preview/element.ts +26 -0
  203. package/src/components/image-preview/engine.ts +325 -0
  204. package/src/components/image-preview/image-preview.css +194 -0
  205. package/src/components/image-preview/react.tsx +43 -0
  206. package/src/components/json-viewer/README.md +56 -0
  207. package/src/components/json-viewer/element.ts +37 -0
  208. package/src/components/json-viewer/engine.ts +440 -0
  209. package/src/components/json-viewer/json-viewer.css +271 -0
  210. package/src/components/json-viewer/react.tsx +56 -0
  211. package/src/components/like-button/README.md +13 -0
  212. package/src/components/like-button/element.ts +47 -0
  213. package/src/components/like-button/engine.ts +145 -0
  214. package/src/components/like-button/like-button.css +77 -0
  215. package/src/components/like-button/react.tsx +39 -0
  216. package/src/components/link-preview/README.md +19 -0
  217. package/src/components/link-preview/element.ts +29 -0
  218. package/src/components/link-preview/engine.ts +192 -0
  219. package/src/components/link-preview/link-preview.css +274 -0
  220. package/src/components/link-preview/react.tsx +101 -0
  221. package/src/components/loading-button/README.md +45 -0
  222. package/src/components/loading-button/element.ts +34 -0
  223. package/src/components/loading-button/engine.ts +201 -0
  224. package/src/components/loading-button/loading-button.css +76 -0
  225. package/src/components/loading-button/react.tsx +43 -0
  226. package/src/components/multi-select/README.md +48 -0
  227. package/src/components/multi-select/element.ts +28 -0
  228. package/src/components/multi-select/engine.ts +294 -0
  229. package/src/components/multi-select/multi-select.css +266 -0
  230. package/src/components/multi-select/react.tsx +39 -0
  231. package/src/components/notification-bell/README.md +14 -0
  232. package/src/components/notification-bell/element.ts +48 -0
  233. package/src/components/notification-bell/engine.ts +202 -0
  234. package/src/components/notification-bell/notification-bell.css +126 -0
  235. package/src/components/notification-bell/react.tsx +57 -0
  236. package/src/components/password-strength/README.md +17 -0
  237. package/src/components/password-strength/element.ts +22 -0
  238. package/src/components/password-strength/engine.ts +212 -0
  239. package/src/components/password-strength/password-strength.css +182 -0
  240. package/src/components/password-strength/react.tsx +36 -0
  241. package/src/components/password-strength/score.ts +62 -0
  242. package/src/components/popover/README.md +44 -0
  243. package/src/components/popover/element.ts +31 -0
  244. package/src/components/popover/engine.ts +114 -0
  245. package/src/components/popover/popover.css +24 -0
  246. package/src/components/popover/react.tsx +50 -0
  247. package/src/components/progress/README.md +17 -0
  248. package/src/components/progress/element.ts +30 -0
  249. package/src/components/progress/engine.ts +173 -0
  250. package/src/components/progress/progress.css +139 -0
  251. package/src/components/progress/react.tsx +35 -0
  252. package/src/components/questionnaire/README.md +32 -0
  253. package/src/components/questionnaire/element.ts +118 -0
  254. package/src/components/questionnaire/engine.ts +255 -0
  255. package/src/components/questionnaire/questionnaire.css +216 -0
  256. package/src/components/questionnaire/react.tsx +140 -0
  257. package/src/components/range-calendar/README.md +58 -0
  258. package/src/components/range-calendar/element.ts +42 -0
  259. package/src/components/range-calendar/engine.ts +390 -0
  260. package/src/components/range-calendar/range-calendar.css +185 -0
  261. package/src/components/range-calendar/react.tsx +56 -0
  262. package/src/components/range-slider/README.md +23 -0
  263. package/src/components/range-slider/element.ts +53 -0
  264. package/src/components/range-slider/engine.ts +316 -0
  265. package/src/components/range-slider/range-slider.css +191 -0
  266. package/src/components/range-slider/react.tsx +66 -0
  267. package/src/components/resizable-panel/README.md +61 -0
  268. package/src/components/resizable-panel/element.ts +36 -0
  269. package/src/components/resizable-panel/engine.ts +551 -0
  270. package/src/components/resizable-panel/react.tsx +74 -0
  271. package/src/components/resizable-panel/resizable-panel.css +242 -0
  272. package/src/components/rich-text-editor/README.md +57 -0
  273. package/src/components/rich-text-editor/element.ts +34 -0
  274. package/src/components/rich-text-editor/engine.ts +673 -0
  275. package/src/components/rich-text-editor/react.tsx +60 -0
  276. package/src/components/rich-text-editor/rich-text-editor.css +283 -0
  277. package/src/components/scratch-card/README.md +15 -0
  278. package/src/components/scratch-card/element.ts +30 -0
  279. package/src/components/scratch-card/engine.ts +257 -0
  280. package/src/components/scratch-card/react.tsx +40 -0
  281. package/src/components/scratch-card/scratch-card.css +74 -0
  282. package/src/components/skeleton/README.md +15 -0
  283. package/src/components/skeleton/element.ts +32 -0
  284. package/src/components/skeleton/engine.ts +104 -0
  285. package/src/components/skeleton/react.tsx +41 -0
  286. package/src/components/skeleton/skeleton.css +107 -0
  287. package/src/components/split-view/README.md +50 -0
  288. package/src/components/split-view/element.ts +34 -0
  289. package/src/components/split-view/engine.ts +114 -0
  290. package/src/components/split-view/react.tsx +63 -0
  291. package/src/components/split-view/split-view.css +18 -0
  292. package/src/components/star-rating/README.md +14 -0
  293. package/src/components/star-rating/element.ts +26 -0
  294. package/src/components/star-rating/engine.ts +217 -0
  295. package/src/components/star-rating/react.tsx +33 -0
  296. package/src/components/star-rating/star-rating.css +79 -0
  297. package/src/components/stat-card/README.md +42 -0
  298. package/src/components/stat-card/element.ts +40 -0
  299. package/src/components/stat-card/engine.ts +283 -0
  300. package/src/components/stat-card/react.tsx +36 -0
  301. package/src/components/stat-card/stat-card.css +163 -0
  302. package/src/components/swipe-actions/README.md +19 -0
  303. package/src/components/swipe-actions/element.ts +26 -0
  304. package/src/components/swipe-actions/engine.ts +260 -0
  305. package/src/components/swipe-actions/react.tsx +80 -0
  306. package/src/components/swipe-actions/swipe-actions.css +104 -0
  307. package/src/components/tag-input/README.md +42 -0
  308. package/src/components/tag-input/element.ts +39 -0
  309. package/src/components/tag-input/engine.ts +313 -0
  310. package/src/components/tag-input/react.tsx +54 -0
  311. package/src/components/tag-input/tag-input.css +243 -0
  312. package/src/components/time-field/README.md +54 -0
  313. package/src/components/time-field/element.ts +38 -0
  314. package/src/components/time-field/engine.ts +110 -0
  315. package/src/components/time-field/react.tsx +45 -0
  316. package/src/components/time-field/time-field.css +87 -0
  317. package/src/components/timeline/README.md +57 -0
  318. package/src/components/timeline/element.ts +31 -0
  319. package/src/components/timeline/engine.ts +300 -0
  320. package/src/components/timeline/react.tsx +59 -0
  321. package/src/components/timeline/timeline.css +218 -0
  322. package/src/components/tooltip/README.md +46 -0
  323. package/src/components/tooltip/element.ts +22 -0
  324. package/src/components/tooltip/engine.ts +288 -0
  325. package/src/components/tooltip/react.tsx +30 -0
  326. package/src/components/tooltip/tooltip.css +78 -0
  327. package/src/components/tree-view/README.md +61 -0
  328. package/src/components/tree-view/element.ts +32 -0
  329. package/src/components/tree-view/engine.ts +569 -0
  330. package/src/components/tree-view/react.tsx +78 -0
  331. package/src/components/tree-view/tree-view.css +209 -0
  332. package/src/components/virtual-list/README.md +81 -0
  333. package/src/components/virtual-list/element.ts +42 -0
  334. package/src/components/virtual-list/engine.ts +678 -0
  335. package/src/components/virtual-list/react.tsx +101 -0
  336. package/src/components/virtual-list/virtual-list.css +194 -0
  337. package/src/core/chips.ts +196 -0
  338. package/src/core/color.ts +304 -0
  339. package/src/core/date-range.ts +67 -0
  340. package/src/core/dates.ts +11 -1
  341. package/src/core/files.ts +107 -0
  342. package/src/core/filter.ts +229 -0
  343. package/src/core/gsap.ts +80 -65
  344. package/src/core/listbox.ts +332 -0
  345. package/src/core/mark.ts +29 -0
  346. package/src/core/position.ts +89 -0
  347. package/src/core/relative-time.ts +77 -0
  348. package/src/core/segment-field.ts +373 -0
  349. package/src/core/segments.ts +153 -0
  350. package/src/core/tree.ts +116 -0
  351. package/src/core/virtual.ts +79 -0
  352. package/src/css/tokens.css +186 -182
  353. package/src/elements/index.ts +147 -0
  354. package/src/index.ts +72 -0
  355. package/src/motion/micro.ts +248 -0
  356. package/src/motion/sheet.ts +88 -65
  357. package/src/motion/surface.ts +9 -0
  358. package/src/react/index.ts +57 -0
  359. package/dist/chunk-IKQ5FODN.js.map +0 -1
  360. package/dist/chunk-J6OCFNGU.js +0 -177
  361. package/dist/chunk-J6OCFNGU.js.map +0 -1
  362. package/dist/chunk-TFNRIZHU.js +0 -3977
  363. package/dist/chunk-TFNRIZHU.js.map +0 -1
  364. package/dist/chunk-XAKC2QY7.js.map +0 -1
  365. package/dist/reveal-jsX-uwUz.d.ts +0 -625
@@ -0,0 +1,182 @@
1
+ /* password-strength — a Melonmind field (16 px radius, surface-container-high, 3 px focus ring) with an eye toggle,
2
+ four rounded segments that light up by level and a checklist whose checks draw themselves. */
3
+ .mk-password-strength,
4
+ mk-password-strength {
5
+ --mk-password-weak: var(--mk-error);
6
+ --mk-password-fair: #e8a317;
7
+ --mk-password-good: #3c9a5f;
8
+ --mk-password-strong: var(--mk-accent);
9
+ --mk-password-tone: var(--mk-outline);
10
+ display: grid;
11
+ gap: 0.75rem;
12
+ color: var(--mk-text);
13
+ font-family: var(--mk-font);
14
+ }
15
+
16
+ :is(.mk-password-strength, mk-password-strength):is([data-mk-score='0'], [data-mk-score='1']) {
17
+ --mk-password-tone: var(--mk-password-weak);
18
+ }
19
+
20
+ :is(.mk-password-strength, mk-password-strength)[data-mk-score='2'] {
21
+ --mk-password-tone: var(--mk-password-fair);
22
+ }
23
+
24
+ :is(.mk-password-strength, mk-password-strength)[data-mk-score='3'] {
25
+ --mk-password-tone: var(--mk-password-good);
26
+ }
27
+
28
+ :is(.mk-password-strength, mk-password-strength)[data-mk-score='4'] {
29
+ --mk-password-tone: var(--mk-password-strong);
30
+ }
31
+
32
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password-field] {
33
+ position: relative;
34
+ display: flex;
35
+ align-items: center;
36
+ }
37
+
38
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password] {
39
+ width: 100%;
40
+ min-height: 3.25rem;
41
+ padding: 0 3.5rem 0 1.1rem;
42
+ border: 0;
43
+ border-radius: 16px;
44
+ outline: none;
45
+ background: var(--mk-surface-4);
46
+ color: var(--mk-text);
47
+ font: inherit;
48
+ font-size: 1rem;
49
+ letter-spacing: 0.02em;
50
+ transition:
51
+ box-shadow 0.5s,
52
+ background-color 0.5s;
53
+ }
54
+
55
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password]:hover {
56
+ background: var(--mk-surface-5);
57
+ }
58
+
59
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password]:focus {
60
+ background: var(--mk-surface-2);
61
+ box-shadow:
62
+ 0 0 0 3px var(--mk-outline-soft),
63
+ 0 0.5px 2.5px rgb(0 0 0 / 0.3);
64
+ }
65
+
66
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password-toggle] {
67
+ position: absolute;
68
+ right: 0.4rem;
69
+ display: grid;
70
+ place-items: center;
71
+ width: 2.5rem;
72
+ height: 2.5rem;
73
+ padding: 0;
74
+ border: 0;
75
+ border-radius: 50%;
76
+ background: transparent;
77
+ color: var(--mk-muted);
78
+ cursor: pointer;
79
+ transition:
80
+ background-color 0.2s ease,
81
+ color 0.2s ease;
82
+ }
83
+
84
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password-toggle]:hover {
85
+ background: var(--mk-surface-3);
86
+ color: var(--mk-text);
87
+ }
88
+
89
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password-toggle]:focus-visible {
90
+ outline: 2px solid var(--mk-accent);
91
+ outline-offset: 2px;
92
+ }
93
+
94
+ :is(.mk-password-strength, mk-password-strength) svg {
95
+ width: 1.25rem;
96
+ height: 1.25rem;
97
+ fill: none;
98
+ stroke: currentColor;
99
+ stroke-width: 1.8;
100
+ stroke-linecap: round;
101
+ stroke-linejoin: round;
102
+ }
103
+
104
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password-meter] {
105
+ display: grid;
106
+ grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
107
+ align-items: center;
108
+ gap: 0.35rem;
109
+ }
110
+
111
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password-meter] > span:not([data-mk-password-label]) {
112
+ height: 6px;
113
+ overflow: hidden;
114
+ border-radius: 64px;
115
+ background: var(--mk-surface-4);
116
+ }
117
+
118
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password-meter] i {
119
+ display: block;
120
+ height: 100%;
121
+ border-radius: inherit;
122
+ background: var(--mk-password-tone);
123
+ transform: scaleX(0);
124
+ transform-origin: left center;
125
+ transition: background-color 0.3s ease;
126
+ }
127
+
128
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password-label] {
129
+ min-width: 6.5rem;
130
+ margin-left: 0.4rem;
131
+ color: var(--mk-password-tone);
132
+ font-size: 0.8125rem;
133
+ font-weight: 500;
134
+ text-align: right;
135
+ }
136
+
137
+ :is(.mk-password-strength, mk-password-strength) [data-mk-password-checks] {
138
+ display: grid;
139
+ grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
140
+ gap: 0.3rem 1rem;
141
+ margin: 0;
142
+ padding: 0;
143
+ color: var(--mk-muted);
144
+ font-size: 0.8125rem;
145
+ list-style: none;
146
+ }
147
+
148
+ :is(.mk-password-strength, mk-password-strength) [data-mk-check] {
149
+ display: flex;
150
+ align-items: center;
151
+ gap: 0.4rem;
152
+ transition: color 0.2s ease;
153
+ }
154
+
155
+ :is(.mk-password-strength, mk-password-strength) [data-mk-check] svg {
156
+ flex: none;
157
+ width: 1rem;
158
+ height: 1rem;
159
+ padding: 2px;
160
+ border-radius: 50%;
161
+ background: var(--mk-surface-3);
162
+ stroke: transparent;
163
+ stroke-width: 3;
164
+ transition:
165
+ background-color 0.2s ease,
166
+ stroke 0.2s ease;
167
+ }
168
+
169
+ :is(.mk-password-strength, mk-password-strength) [data-mk-check][data-mk-met] {
170
+ color: var(--mk-text);
171
+ }
172
+
173
+ :is(.mk-password-strength, mk-password-strength) [data-mk-check][data-mk-met] svg {
174
+ background: var(--mk-password-good);
175
+ stroke: #fff;
176
+ }
177
+
178
+ @media (prefers-reduced-motion: reduce) {
179
+ :is(.mk-password-strength, mk-password-strength) :is([data-mk-password], [data-mk-check], [data-mk-check] svg, [data-mk-password-meter] i) {
180
+ transition: none;
181
+ }
182
+ }
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+ import { useRef, type InputHTMLAttributes } from 'react';
3
+ import { useIsomorphicLayoutEffect, useLatest } from '../../react/use-recipe';
4
+ import { createPasswordStrength, type PasswordStrengthOptions } from './engine';
5
+
6
+ export interface PasswordStrengthProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'onChange'>, Omit<PasswordStrengthOptions, 'onChange'> {
7
+ onStrength?: PasswordStrengthOptions['onChange'];
8
+ /** The text of the field as it changes. */
9
+ onValueChange?: (value: string) => void;
10
+ }
11
+
12
+ /** <PasswordStrength name="password" aria-label="Contraseña" requireScore={3} onStrength={setResult} />. The field stays uncontrolled. */
13
+ export function PasswordStrength({ minLength, score, requireScore, labels, onStrength, onValueChange, className, ...props }: PasswordStrengthProps) {
14
+ const ref = useRef<HTMLDivElement>(null);
15
+ const strength = useLatest(onStrength);
16
+ const value = useLatest(onValueChange);
17
+ const scorer = useLatest(score);
18
+ const custom = score !== undefined;
19
+ const key = JSON.stringify(labels ?? {});
20
+ useIsomorphicLayoutEffect(() => {
21
+ const instance = createPasswordStrength(ref.current, {
22
+ minLength,
23
+ requireScore,
24
+ labels,
25
+ score: custom ? (text) => scorer.current!(text) : undefined,
26
+ onChange: (result) => strength.current?.(result),
27
+ });
28
+ return () => instance.destroy();
29
+ // eslint-disable-next-line react-hooks/exhaustive-deps
30
+ }, [minLength, requireScore, key, custom]);
31
+ return (
32
+ <div ref={ref} className={['mk-password-strength', className].filter(Boolean).join(' ')}>
33
+ <input autoComplete="new-password" aria-label="Contraseña" {...props} type="password" onInput={(event) => value.current?.(event.currentTarget.value)} />
34
+ </div>
35
+ );
36
+ }
@@ -0,0 +1,62 @@
1
+ /*
2
+ * Password strength (pure): length and variety raise the score, common
3
+ * passwords, runs (abc, 123) and repeats (aaa) lower it. 0–4, a label and the
4
+ * checks met. A heuristic for feedback, not a security guarantee: the server
5
+ * decides what it accepts.
6
+ */
7
+
8
+ export interface PasswordChecks {
9
+ length: boolean;
10
+ lower: boolean;
11
+ upper: boolean;
12
+ number: boolean;
13
+ symbol: boolean;
14
+ }
15
+
16
+ export interface PasswordScore {
17
+ score: 0 | 1 | 2 | 3 | 4;
18
+ label: string;
19
+ checks: PasswordChecks;
20
+ }
21
+
22
+ export const STRENGTH_LABELS = ['Muy débil', 'Débil', 'Aceptable', 'Fuerte', 'Muy fuerte'] as const;
23
+
24
+ const COMMON = new Set(
25
+ 'password password1 123456 1234567 12345678 123456789 1234567890 qwerty qwerty123 abc123 111111 000000 iloveyou admin welcome letmein monkey dragon contraseña contrasena secreto hola123 football baseball sunshine princess'.split(' '),
26
+ );
27
+
28
+ const runs = (value: string) => {
29
+ const text = value.toLowerCase();
30
+ for (let i = 0; i + 2 < text.length; i++) {
31
+ const [a, b, c] = [text.charCodeAt(i), text.charCodeAt(i + 1), text.charCodeAt(i + 2)];
32
+ if ((b - a === 1 && c - b === 1) || (a - b === 1 && b - c === 1)) return true;
33
+ }
34
+ return false;
35
+ };
36
+
37
+ export function scorePassword(value: string, minLength = 8): PasswordScore {
38
+ const text = String(value ?? '');
39
+ const checks: PasswordChecks = {
40
+ length: text.length >= minLength,
41
+ lower: /[a-zà-ÿ]/.test(text),
42
+ upper: /[A-ZÀ-Þ]/.test(text),
43
+ number: /\d/.test(text),
44
+ symbol: /[^\p{L}\p{N}\s]/u.test(text),
45
+ };
46
+ if (!text) return { score: 0, label: '', checks };
47
+ const variety = [checks.lower, checks.upper, checks.number, checks.symbol].filter(Boolean).length;
48
+ let points = 0;
49
+ if (text.length >= minLength) points += 1;
50
+ if (text.length >= minLength + 4) points += 1;
51
+ if (text.length >= minLength + 8) points += 1;
52
+ if (variety >= 3) points += 1;
53
+ if (variety === 4) points += 1;
54
+ // Penalties count after the cap: a long, varied password with a pattern is not the best.
55
+ points = Math.min(4, points);
56
+ if (/(.)\1\1/.test(text)) points -= 1;
57
+ if (runs(text)) points -= 1;
58
+ if (text.length < minLength) points = Math.min(points, 1);
59
+ if (COMMON.has(text.toLowerCase())) points = 0;
60
+ const score = Math.max(0, Math.min(4, points)) as PasswordScore['score'];
61
+ return { score, label: STRENGTH_LABELS[score], checks };
62
+ }
@@ -0,0 +1,44 @@
1
+ # popover
2
+
3
+ Panel flotante interactivo anclado a su botón, sobre la misma superficie que `menu` y `color-picker`: crece desde el botón (transformación de contenedor de `motion/morph.ts`) mientras su contenido entra en cascada como las opciones de un menú (desde 90 % y un blur de 4 px, 40 ms entre piezas), y al cerrar se pliega de vuelta en él. Se cierra con Escape, con un clic fuera o con cualquier `[data-mk-close]` de dentro, y el foco vuelve al botón.
4
+
5
+ Importa también `css/components/dialog.css` (o el CSS completo). La CLI lo copia: la entrada `requires` dialog.
6
+
7
+ ## HTML / Astro
8
+
9
+ ```html
10
+ <mk-popover class="mk-popover">
11
+ <button class="mk-button" data-mk-popover-trigger>Filtros</button>
12
+ <div data-mk-popover-content>
13
+ <label class="mk-field">Estado <select>…</select></label>
14
+ <button class="mk-button mk-button--primary" data-mk-close>Aplicar</button>
15
+ </div>
16
+ </mk-popover>
17
+ ```
18
+
19
+ `[data-mk-popover-content]` pasa a un `<dialog>` que crea el motor y vuelve a su sitio al destruirlo. También puedes escribir directamente `<dialog data-mk-popover-panel>`.
20
+
21
+ ## React
22
+
23
+ ```tsx
24
+ <Popover trigger={<button className="mk-button">Filtros</button>} onOpenChange={setOpen}>
25
+ <FiltersForm />
26
+ </Popover>
27
+ ```
28
+
29
+ Con `open` es controlado. `ref` da `open()` y `close()`.
30
+
31
+ ## Opciones
32
+
33
+ | Opción | Atributo | Por defecto | Qué hace |
34
+ |---|---|---|---|
35
+ | `label` | `label` | el texto del botón | Nombre accesible del panel. |
36
+ | `onOpenChange(open)` | — | — | Al abrirse o cerrarse. |
37
+
38
+ ## API y eventos
39
+
40
+ `open()`, `close()`, `toggle()`, `isOpen`, `panel` (el `<dialog>`), `destroy()`. Evento `mk:open-change` con `{ open }`.
41
+
42
+ ## Estilo
43
+
44
+ Esquinas de 20 px sobre `--mk-surface-1`, tan ancho como su contenido hasta 22rem, con 1rem de relleno. Se estiliza por clase (`.mk-popover-panel`), así la copia que se pliega al cerrar conserva su aspecto. En teléfonos el diálogo anclado se centra. Con movimiento reducido aparece sin crecer.
@@ -0,0 +1,31 @@
1
+ import { MkElement, defineElement, type OptionType } from '../../elements/base';
2
+ import { createPopover, type PopoverInstance } from './engine';
3
+
4
+ /**
5
+ * <mk-popover class="mk-popover">
6
+ * <button data-mk-popover-trigger>Filtros</button>
7
+ * <div data-mk-popover-content>…</div>
8
+ * </mk-popover>
9
+ * Emits mk:open-change ({open}).
10
+ */
11
+ export class MkPopoverElement extends MkElement<PopoverInstance> {
12
+ static options: Record<string, OptionType> = { label: 'string' };
13
+
14
+ protected create(options: Record<string, unknown>) {
15
+ return createPopover(this, options);
16
+ }
17
+
18
+ open() {
19
+ this.instance?.open();
20
+ }
21
+
22
+ close() {
23
+ this.instance?.close();
24
+ }
25
+
26
+ get isOpen() {
27
+ return this.instance?.isOpen ?? false;
28
+ }
29
+ }
30
+
31
+ export const definePopover = () => defineElement('mk-popover', MkPopoverElement);
@@ -0,0 +1,114 @@
1
+ import { createScope } from '../../core/scope';
2
+ import { inert, type Instance } from '../../core/types';
3
+ import { flowInMenu } from '../../motion/entrances';
4
+ import { createDialog } from '../dialog/engine';
5
+
6
+ /*
7
+ * Popover: an interactive panel anchored to its trigger, on the same anchored
8
+ * dialog surface as menu and color-picker. It grows out of the trigger
9
+ * (motion/morph.ts container transform) while its content flows in like a
10
+ * menu's options (from 90 % out of a 4 px blur, 40 ms apart), folds back into
11
+ * the trigger on close, closes with Escape, a click outside or any
12
+ * [data-mk-close] inside, and gives the focus back to the trigger. A
13
+ * dialog[data-mk-popover-panel] is used as it is; [data-mk-popover-content] is
14
+ * moved into a dialog the engine creates and put back on destroy.
15
+ */
16
+
17
+ export interface PopoverOptions {
18
+ /** Accessible name of the panel (default: the trigger's text). */
19
+ label?: string;
20
+ onOpenChange?: (open: boolean) => void;
21
+ }
22
+
23
+ export interface PopoverInstance extends Instance {
24
+ open(): void;
25
+ close(): void;
26
+ toggle(): void;
27
+ readonly isOpen: boolean;
28
+ /** The panel (a <dialog>). */
29
+ readonly panel: HTMLElement | null;
30
+ }
31
+
32
+ let sequence = 0;
33
+
34
+ export function createPopover(root: HTMLElement | null, options: PopoverOptions = {}): PopoverInstance {
35
+ const inertInstance = inert<PopoverInstance>({ open() {}, close() {}, toggle() {}, isOpen: false, panel: null });
36
+ if (!root) return inertInstance;
37
+ let dialog = root.querySelector<HTMLDialogElement>('dialog[data-mk-popover-panel]');
38
+ const content = dialog ? null : root.querySelector<HTMLElement>('[data-mk-popover-content]');
39
+ const trigger =
40
+ root.querySelector<HTMLElement>('[data-mk-popover-trigger]') ??
41
+ [...root.querySelectorAll<HTMLElement>('button, a[href], [role="button"]')].find((element) => !dialog?.contains(element) && !content?.contains(element)) ??
42
+ null;
43
+ if (!trigger || (!dialog && !content)) return inertInstance;
44
+ const scope = createScope();
45
+
46
+ if (!dialog) {
47
+ // The authored content moves into a dialog in its place, and back on destroy.
48
+ const created = document.createElement('dialog');
49
+ const anchor = content!.nextSibling;
50
+ const parent = content!.parentNode!;
51
+ parent.insertBefore(created, content);
52
+ created.append(content!);
53
+ dialog = created;
54
+ scope.add(() => {
55
+ if (content!.isConnected || created.isConnected) parent.insertBefore(content!, created.isConnected ? created : anchor);
56
+ created.remove();
57
+ });
58
+ }
59
+ const panel = dialog;
60
+ // Classes, not only attributes: the copy that folds back into the trigger on close keeps classes only.
61
+ scope.attr(panel, 'class', [panel.getAttribute('class'), 'mk-dialog', 'mk-popover-panel'].filter(Boolean).join(' '));
62
+ if (!panel.id) scope.attr(panel, 'id', `mk-popover-${++sequence}`);
63
+ if (!panel.hasAttribute('aria-label') && !panel.hasAttribute('aria-labelledby')) scope.attr(panel, 'aria-label', options.label ?? trigger.textContent?.trim() ?? 'Panel');
64
+ scope.attr(trigger, 'aria-haspopup', 'dialog');
65
+ scope.attr(trigger, 'aria-expanded', 'false');
66
+ scope.attr(trigger, 'aria-controls', panel.id);
67
+ scope.attr(root, 'data-mk-ready', '');
68
+
69
+ const announce = (open: boolean) => {
70
+ trigger.setAttribute('aria-expanded', String(open));
71
+ options.onOpenChange?.(open);
72
+ root.dispatchEvent(new CustomEvent('mk:open-change', { bubbles: true, detail: { open } }));
73
+ };
74
+ let flow: ReturnType<typeof flowInMenu> = null;
75
+ const surface = createDialog(panel, {
76
+ placement: 'anchor',
77
+ backdrop: false,
78
+ drag: false,
79
+ autoResize: false,
80
+ triggers: false,
81
+ animateContent: false,
82
+ // Like a menu's options: the content flows in while the surface grows out of the trigger.
83
+ onOpen: () => {
84
+ flow?.kill();
85
+ flow = flowInMenu([...panel.children].filter((child) => !child.classList.contains('mk-morph-face')));
86
+ announce(true);
87
+ },
88
+ onClose: () => announce(false),
89
+ });
90
+ scope.add(() => {
91
+ flow?.kill();
92
+ surface.destroy();
93
+ });
94
+
95
+ const open = () => {
96
+ if (!surface.isOpen) surface.open(trigger);
97
+ };
98
+ scope.on(trigger, 'click', (event) => {
99
+ event.preventDefault();
100
+ if (surface.isOpen) surface.close();
101
+ else open();
102
+ });
103
+
104
+ return {
105
+ open,
106
+ close: () => surface.close(),
107
+ toggle: () => (surface.isOpen ? surface.close() : open()),
108
+ get isOpen() {
109
+ return surface.isOpen;
110
+ },
111
+ panel,
112
+ destroy: () => scope.dispose(),
113
+ };
114
+ }
@@ -0,0 +1,24 @@
1
+ /* popover — an anchored .mk-dialog (needs dialog.css): 20 px corners on surface-1, as wide as its content up to
2
+ 22rem, 1rem padding. Styled by class: the copy that folds back into the trigger keeps classes only. */
3
+ .mk-popover,
4
+ mk-popover {
5
+ display: inline-block;
6
+ }
7
+
8
+ .mk-dialog.mk-popover-panel {
9
+ --mk-dialog-radius: 20px;
10
+ --mk-dialog-bg: var(--mk-surface-1);
11
+ --mk-dialog-shadow: 0 16px 48px -12px color-mix(in srgb, var(--mk-shadow-color, #000) 35%, transparent);
12
+ gap: 0.75rem;
13
+ width: max-content;
14
+ min-width: min(14rem, calc(100vw - 32px));
15
+ max-width: min(22rem, calc(100vw - 32px));
16
+ padding: 1rem;
17
+ }
18
+
19
+ /* Phones: the anchored dialog is centred by dialog.css; keep it a panel, not a sheet. */
20
+ @media (max-width: 679px) {
21
+ .mk-dialog.mk-popover-panel {
22
+ max-width: calc(100vw - 32px);
23
+ }
24
+ }
@@ -0,0 +1,50 @@
1
+ 'use client';
2
+ import { forwardRef, useImperativeHandle, useRef, type HTMLAttributes, type ReactNode } from 'react';
3
+ import { useIsomorphicLayoutEffect, useLatest } from '../../react/use-recipe';
4
+ import { createPopover, type PopoverInstance, type PopoverOptions } from './engine';
5
+
6
+ export interface PopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'content'>, PopoverOptions {
7
+ /** The control that opens it (a button). */
8
+ trigger: ReactNode;
9
+ /** Controlled open state (optional). */
10
+ open?: boolean;
11
+ /** Extra class for the panel. */
12
+ panelClassName?: string;
13
+ }
14
+
15
+ export interface PopoverHandle {
16
+ open(): void;
17
+ close(): void;
18
+ }
19
+
20
+ /** <Popover trigger={<button>Filtros</button>}>…</Popover>: the panel grows out of the trigger. */
21
+ export const Popover = forwardRef<PopoverHandle, PopoverProps>(function Popover({ trigger, open, label, onOpenChange, panelClassName, className, children, ...props }, handle) {
22
+ const ref = useRef<HTMLDivElement>(null);
23
+ const instance = useRef<PopoverInstance | null>(null);
24
+ const change = useLatest(onOpenChange);
25
+ useImperativeHandle(handle, () => ({ open: () => instance.current?.open(), close: () => instance.current?.close() }), []);
26
+ useIsomorphicLayoutEffect(() => {
27
+ const created = createPopover(ref.current, { label, onOpenChange: (value) => change.current?.(value) });
28
+ instance.current = created;
29
+ return () => {
30
+ created.destroy();
31
+ instance.current = null;
32
+ };
33
+ // eslint-disable-next-line react-hooks/exhaustive-deps
34
+ }, [label]);
35
+ useIsomorphicLayoutEffect(() => {
36
+ if (open === undefined || !instance.current || instance.current.isOpen === open) return;
37
+ if (open) instance.current.open();
38
+ else instance.current.close();
39
+ }, [open]);
40
+ return (
41
+ <div {...props} ref={ref} className={['mk-popover', className].filter(Boolean).join(' ')}>
42
+ <span data-mk-popover-trigger-slot="" style={{ display: 'contents' }}>
43
+ {trigger}
44
+ </span>
45
+ <dialog data-mk-popover-panel="" className={panelClassName}>
46
+ {children}
47
+ </dialog>
48
+ </div>
49
+ );
50
+ });
@@ -0,0 +1,17 @@
1
+ # progress
2
+
3
+ Barra o anillo de progreso con valor determinado o indeterminado. El anillo sigue el `MetricsRing` de Melon Mind: radio `(tamaño − trazo) / 2`, `stroke-dasharray` derivado del ratio y arranque a las 12.
4
+
5
+ ```html
6
+ <mk-progress class="mk-progress" value="40" label="Subiendo informe" show-value></mk-progress>
7
+ <mk-progress class="mk-progress" variant="ring" value="72" label="Meta mensual" show-value></mk-progress>
8
+ <mk-progress class="mk-progress" label="Procesando"></mk-progress> <!-- indeterminado -->
9
+ ```
10
+
11
+ `defineElements()` desde `/elements`, `createProgress(root, options)` o `<Progress value={42} label="Subida" showValue />` desde `/react`.
12
+
13
+ Opciones: `value` (número o `null` = indeterminado; por defecto `min`), `min=0`, `max=100`, `label` (aria-label), `variant='linear'|'ring'`, `showValue`, `formatValue(value, ratio)` (texto visible y `aria-valuetext`), `duration=.7` (segundos del deslizamiento). API: `setValue(number | null)`, `value`, `destroy()`.
14
+
15
+ El root recibe `role="progressbar"`, `aria-valuemin/max/now` (sin `aria-valuenow` cuando es indeterminado). Valores no finitos se ignoran y los demás se acotan a los límites. No hay región viva: el valor se lee al llegar a la barra, sin anunciar cada cambio.
16
+
17
+ El dibujo es un único hijo decorativo `[data-mk-progress-visual]`; el contenido que ya tenga el root se conserva y `destroy()` restaura atributos y estilos. Al subir o bajar, el relleno (o el arco) se desliza con GSAP, las cifras ruedan, la punta brilla al avanzar, el anillo respira y llegar al máximo lanza un estallido. Variables: `--mk-progress-height` (10px), `--mk-progress-size` (anillo, 4.5rem), `--mk-progress-track`, `--mk-progress-fill`. Movimiento reducido: el valor cambia sin transición y el indeterminado queda como relleno parcial estático.
@@ -0,0 +1,30 @@
1
+ import { MkElement, defineElement, type OptionType } from '../../elements/base';
2
+ import { createProgress, type ProgressInstance } from './engine';
3
+
4
+ /**
5
+ * <mk-progress class="mk-progress" value="40" label="Subida" show-value></mk-progress>
6
+ * Without `value` (or value="indeterminate") it is indeterminate. A new value moves the fill.
7
+ */
8
+ export class MkProgressElement extends MkElement<ProgressInstance> {
9
+ static options: Record<string, OptionType> = { value: 'number', min: 'number', max: 'number', label: 'string', variant: 'string', showValue: 'boolean' };
10
+
11
+ protected create(options: Record<string, unknown>) {
12
+ return createProgress(this, { ...options, value: typeof options.value === 'number' ? options.value : null });
13
+ }
14
+
15
+ attributeChangedCallback(name: string, previous: string | null, next: string | null) {
16
+ if (previous === next || !this.instance) return;
17
+ if (name === 'value') this.instance.setValue(next === null || !Number.isFinite(Number(next)) ? null : Number(next));
18
+ else super.attributeChangedCallback(name, previous, next);
19
+ }
20
+
21
+ setValue(value: number | null) {
22
+ this.instance?.setValue(value);
23
+ }
24
+
25
+ get value() {
26
+ return this.instance?.value ?? null;
27
+ }
28
+ }
29
+
30
+ export const defineProgress = () => defineElement('mk-progress', MkProgressElement);