microui-wc 0.1.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 (609) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +33 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +28 -0
  4. package/.github/workflows/ci.yml +42 -0
  5. package/.github/workflows/deploy-pages.yml +112 -0
  6. package/AGENTS.md +2366 -0
  7. package/CHANGELOG.md +47 -0
  8. package/CODE_OF_CONDUCT.md +59 -0
  9. package/CONTRIBUTING.md +156 -0
  10. package/LICENSE +190 -0
  11. package/README.md +254 -0
  12. package/SECURITY.md +58 -0
  13. package/app/.generated/routes/alerts.js +8 -0
  14. package/app/.generated/routes/avatars.js +8 -0
  15. package/app/.generated/routes/badges.js +8 -0
  16. package/app/.generated/routes/buttons.js +10 -0
  17. package/app/.generated/routes/cards.js +10 -0
  18. package/app/.generated/routes/checkboxes.js +9 -0
  19. package/app/.generated/routes/chips.js +8 -0
  20. package/app/.generated/routes/dropdowns.js +9 -0
  21. package/app/.generated/routes/home.js +7 -0
  22. package/app/.generated/routes/icons.js +9 -0
  23. package/app/.generated/routes/inputs.js +10 -0
  24. package/app/.generated/routes/installation.js +7 -0
  25. package/app/.generated/routes/layout.js +9 -0
  26. package/app/.generated/routes/modals.js +9 -0
  27. package/app/.generated/routes/navbar.js +7 -0
  28. package/app/.generated/routes/progress.js +9 -0
  29. package/app/.generated/routes/radios.js +9 -0
  30. package/app/.generated/routes/switches.js +9 -0
  31. package/app/.generated/routes/tabs.js +8 -0
  32. package/app/.generated/routes/toasts.js +9 -0
  33. package/app/index.html +67 -0
  34. package/app/pages/alerts.html +23 -0
  35. package/app/pages/avatars.html +22 -0
  36. package/app/pages/badges.html +22 -0
  37. package/app/pages/buttons.html +71 -0
  38. package/app/pages/cards.html +54 -0
  39. package/app/pages/checkboxes.html +39 -0
  40. package/app/pages/chips.html +23 -0
  41. package/app/pages/dropdowns.html +41 -0
  42. package/app/pages/home.html +59 -0
  43. package/app/pages/icons.html +29 -0
  44. package/app/pages/inputs.html +66 -0
  45. package/app/pages/installation.html +34 -0
  46. package/app/pages/layout.html +30 -0
  47. package/app/pages/modals.html +21 -0
  48. package/app/pages/navbar.html +22 -0
  49. package/app/pages/progress.html +35 -0
  50. package/app/pages/radios.html +40 -0
  51. package/app/pages/switches.html +39 -0
  52. package/app/pages/tabs.html +30 -0
  53. package/app/pages/toasts.html +22 -0
  54. package/app-dist/index.html +67 -0
  55. package/app-dist/pages/alerts.html +23 -0
  56. package/app-dist/pages/avatars.html +22 -0
  57. package/app-dist/pages/badges.html +22 -0
  58. package/app-dist/pages/buttons.html +71 -0
  59. package/app-dist/pages/cards.html +54 -0
  60. package/app-dist/pages/checkboxes.html +39 -0
  61. package/app-dist/pages/chips.html +23 -0
  62. package/app-dist/pages/dropdowns.html +41 -0
  63. package/app-dist/pages/home.html +59 -0
  64. package/app-dist/pages/icons.html +29 -0
  65. package/app-dist/pages/inputs.html +66 -0
  66. package/app-dist/pages/installation.html +34 -0
  67. package/app-dist/pages/layout.html +30 -0
  68. package/app-dist/pages/modals.html +21 -0
  69. package/app-dist/pages/navbar.html +22 -0
  70. package/app-dist/pages/progress.html +35 -0
  71. package/app-dist/pages/radios.html +40 -0
  72. package/app-dist/pages/switches.html +39 -0
  73. package/app-dist/pages/tabs.html +30 -0
  74. package/app-dist/pages/toasts.html +22 -0
  75. package/app-dist/pages.json +217 -0
  76. package/app-dist/routes/alerts.js +5 -0
  77. package/app-dist/routes/avatars.js +1 -0
  78. package/app-dist/routes/badges.js +1 -0
  79. package/app-dist/routes/buttons.js +1 -0
  80. package/app-dist/routes/cards.js +1 -0
  81. package/app-dist/routes/checkboxes.js +9 -0
  82. package/app-dist/routes/chips.js +4 -0
  83. package/app-dist/routes/chunk-019e5e2f.js +5 -0
  84. package/app-dist/routes/chunk-0m4j19yd.js +2 -0
  85. package/app-dist/routes/chunk-0tmmp5q0.js +1 -0
  86. package/app-dist/routes/chunk-10xn709r.js +1 -0
  87. package/app-dist/routes/chunk-15m2qcda.js +2 -0
  88. package/app-dist/routes/chunk-1bh8g23n.js +1 -0
  89. package/app-dist/routes/chunk-1vg0v937.js +1 -0
  90. package/app-dist/routes/chunk-1zvcgy3j.js +1 -0
  91. package/app-dist/routes/chunk-2afb0861.js +1 -0
  92. package/app-dist/routes/chunk-2c6ttpzt.js +5 -0
  93. package/app-dist/routes/chunk-3dy30fhs.js +1 -0
  94. package/app-dist/routes/chunk-426dnces.js +13 -0
  95. package/app-dist/routes/chunk-44kgxery.js +1 -0
  96. package/app-dist/routes/chunk-47fdnejd.js +33 -0
  97. package/app-dist/routes/chunk-49a6t2vq.js +1 -0
  98. package/app-dist/routes/chunk-4fe1rm5b.js +1 -0
  99. package/app-dist/routes/chunk-4ggmvkta.js +33 -0
  100. package/app-dist/routes/chunk-4vkz81q7.js +33 -0
  101. package/app-dist/routes/chunk-4w4tmj8f.js +31 -0
  102. package/app-dist/routes/chunk-532s62kr.js +31 -0
  103. package/app-dist/routes/chunk-5hm3bssy.js +33 -0
  104. package/app-dist/routes/chunk-5vrh24hc.js +1 -0
  105. package/app-dist/routes/chunk-61pcg25a.js +1 -0
  106. package/app-dist/routes/chunk-6nfhygvf.js +1 -0
  107. package/app-dist/routes/chunk-700e7je6.js +33 -0
  108. package/app-dist/routes/chunk-7fsn17kg.js +1 -0
  109. package/app-dist/routes/chunk-7k789b32.js +1 -0
  110. package/app-dist/routes/chunk-7r46q0ys.js +36 -0
  111. package/app-dist/routes/chunk-86fmc1fr.js +5 -0
  112. package/app-dist/routes/chunk-8qth37vw.js +1 -0
  113. package/app-dist/routes/chunk-924wv8n0.js +1 -0
  114. package/app-dist/routes/chunk-9mbhgxk9.js +1 -0
  115. package/app-dist/routes/chunk-a216hyd9.js +1 -0
  116. package/app-dist/routes/chunk-akzxykh9.js +33 -0
  117. package/app-dist/routes/chunk-b3dcvy8c.js +1 -0
  118. package/app-dist/routes/chunk-b74zahz5.js +31 -0
  119. package/app-dist/routes/chunk-bftj53p2.js +5 -0
  120. package/app-dist/routes/chunk-c01hnz3e.js +1 -0
  121. package/app-dist/routes/chunk-d8pvv5km.js +1 -0
  122. package/app-dist/routes/chunk-dev0aezr.js +2 -0
  123. package/app-dist/routes/chunk-dh6vnv0e.js +1 -0
  124. package/app-dist/routes/chunk-dn2cbpva.js +36 -0
  125. package/app-dist/routes/chunk-dvn0my90.js +1 -0
  126. package/app-dist/routes/chunk-dvq8mnve.js +36 -0
  127. package/app-dist/routes/chunk-e8c2gc4d.js +5 -0
  128. package/app-dist/routes/chunk-ejf9ak2x.js +1 -0
  129. package/app-dist/routes/chunk-f083m55s.js +1 -0
  130. package/app-dist/routes/chunk-fnrj28s1.js +31 -0
  131. package/app-dist/routes/chunk-fvg3yjdp.js +31 -0
  132. package/app-dist/routes/chunk-g7k381n1.js +1 -0
  133. package/app-dist/routes/chunk-h01kq2ae.js +13 -0
  134. package/app-dist/routes/chunk-h4dk761v.js +5 -0
  135. package/app-dist/routes/chunk-hmx91z2x.js +5 -0
  136. package/app-dist/routes/chunk-hxbg4m42.js +36 -0
  137. package/app-dist/routes/chunk-jbjnfp2b.js +2 -0
  138. package/app-dist/routes/chunk-jxtz5vv6.js +36 -0
  139. package/app-dist/routes/chunk-jxzcs0ey.js +36 -0
  140. package/app-dist/routes/chunk-kt7wwhcx.js +1 -0
  141. package/app-dist/routes/chunk-kzptszyc.js +33 -0
  142. package/app-dist/routes/chunk-mhgca4w4.js +2 -0
  143. package/app-dist/routes/chunk-mhswxa20.js +1 -0
  144. package/app-dist/routes/chunk-n8zfeex6.js +1 -0
  145. package/app-dist/routes/chunk-pee47b2r.js +1 -0
  146. package/app-dist/routes/chunk-pesmw829.js +1 -0
  147. package/app-dist/routes/chunk-pgc4c6f3.js +36 -0
  148. package/app-dist/routes/chunk-q8egegm1.js +1 -0
  149. package/app-dist/routes/chunk-q9mn2qyq.js +36 -0
  150. package/app-dist/routes/chunk-qh0rtaf3.js +5 -0
  151. package/app-dist/routes/chunk-qqhmk6ye.js +2 -0
  152. package/app-dist/routes/chunk-qrxygmf7.js +33 -0
  153. package/app-dist/routes/chunk-r46yzksx.js +36 -0
  154. package/app-dist/routes/chunk-rgpbw2w0.js +5 -0
  155. package/app-dist/routes/chunk-rnpzv3d8.js +2 -0
  156. package/app-dist/routes/chunk-s5v8cv05.js +2 -0
  157. package/app-dist/routes/chunk-sbwn5bpc.js +1 -0
  158. package/app-dist/routes/chunk-sqbg8jbt.js +33 -0
  159. package/app-dist/routes/chunk-sv8dqnf7.js +1 -0
  160. package/app-dist/routes/chunk-t67sw3za.js +1 -0
  161. package/app-dist/routes/chunk-tjdpqwdf.js +31 -0
  162. package/app-dist/routes/chunk-tq2mfghg.js +1 -0
  163. package/app-dist/routes/chunk-ttn10vt6.js +1 -0
  164. package/app-dist/routes/chunk-v2hzpjxr.js +1 -0
  165. package/app-dist/routes/chunk-wfjjkw9y.js +1 -0
  166. package/app-dist/routes/chunk-wt8cxzmf.js +31 -0
  167. package/app-dist/routes/chunk-x45d372k.js +5 -0
  168. package/app-dist/routes/chunk-y3wsazkt.js +1 -0
  169. package/app-dist/routes/chunk-y7pmgc7t.js +33 -0
  170. package/app-dist/routes/chunk-zefdt2q3.js +31 -0
  171. package/app-dist/routes/dropdowns.js +6 -0
  172. package/app-dist/routes/home.js +1 -0
  173. package/app-dist/routes/icons.js +1 -0
  174. package/app-dist/routes/inputs.js +12 -0
  175. package/app-dist/routes/installation.js +1 -0
  176. package/app-dist/routes/layout.js +1 -0
  177. package/app-dist/routes/modals.js +7 -0
  178. package/app-dist/routes/navbar.js +1 -0
  179. package/app-dist/routes/progress.js +1 -0
  180. package/app-dist/routes/radios.js +6 -0
  181. package/app-dist/routes/switches.js +6 -0
  182. package/app-dist/routes/tabs.js +1 -0
  183. package/app-dist/routes/toasts.js +16 -0
  184. package/assets/fonts/material-symbols-mini.woff2 +0 -0
  185. package/assets/fonts/material-symbols.woff2 +0 -0
  186. package/assets/fonts/roboto-400.woff2 +0 -0
  187. package/assets/fonts/roboto-500.woff2 +0 -0
  188. package/assets/fonts/roboto-700.woff2 +0 -0
  189. package/assets/logo-banner-400.jpg +0 -0
  190. package/assets/logo-banner-400.webp +0 -0
  191. package/assets/logo-banner-800.webp +0 -0
  192. package/assets/logo-banner.jpg +0 -0
  193. package/assets/logo-icon-64.jpg +0 -0
  194. package/assets/logo-icon-64.webp +0 -0
  195. package/assets/logo-icon.jpg +0 -0
  196. package/assets/logo-square.jpg +0 -0
  197. package/bun.lock +312 -0
  198. package/bunfig.toml +4 -0
  199. package/custom-elements.json +1916 -0
  200. package/demo/api/sample-data.json +38 -0
  201. package/demo/content/alerts.html +115 -0
  202. package/demo/content/avatars.html +70 -0
  203. package/demo/content/badges.html +65 -0
  204. package/demo/content/buttons.html +188 -0
  205. package/demo/content/callouts.html +91 -0
  206. package/demo/content/cards.html +121 -0
  207. package/demo/content/checkboxes.html +178 -0
  208. package/demo/content/chips.html +67 -0
  209. package/demo/content/codeblocks.html +101 -0
  210. package/demo/content/confirms.html +115 -0
  211. package/demo/content/datatables.html +149 -0
  212. package/demo/content/dividers.html +119 -0
  213. package/demo/content/dropdowns.html +89 -0
  214. package/demo/content/enterprise.html +252 -0
  215. package/demo/content/home.html +149 -0
  216. package/demo/content/icons.html +89 -0
  217. package/demo/content/inputs.html +135 -0
  218. package/demo/content/installation.html +16 -0
  219. package/demo/content/layout.html +136 -0
  220. package/demo/content/modals.html +141 -0
  221. package/demo/content/navbar.html +70 -0
  222. package/demo/content/progress.html +119 -0
  223. package/demo/content/radios.html +88 -0
  224. package/demo/content/skeletons.html +109 -0
  225. package/demo/content/spinners.html +96 -0
  226. package/demo/content/switches.html +84 -0
  227. package/demo/content/tables.html +124 -0
  228. package/demo/content/tabs.html +85 -0
  229. package/demo/content/toasts.html +116 -0
  230. package/demo/content/tooltips.html +107 -0
  231. package/demo/content/virtual-lists.html +233 -0
  232. package/demo/favicon.ico +0 -0
  233. package/demo/favicon.png +0 -0
  234. package/demo/full.html +52 -0
  235. package/demo/iife.html +46 -0
  236. package/demo/manifest.json +34 -0
  237. package/demo/pages/datatable-demo.html +237 -0
  238. package/demo/pages/prompt-ui-demo.html +218 -0
  239. package/demo/pages/responsive-demo.html +122 -0
  240. package/demo/pages/schema-form-demo.html +270 -0
  241. package/demo/robots.txt +6 -0
  242. package/demo/shell.html +712 -0
  243. package/demo/sw.js +387 -0
  244. package/dist/AGENTS.md +2366 -0
  245. package/dist/README.md +254 -0
  246. package/dist/chunks/advanced.js +174 -0
  247. package/dist/chunks/chunk-1nhr1wrq.js +14 -0
  248. package/dist/chunks/chunk-hssyjbr0.js +2 -0
  249. package/dist/chunks/chunk-k8etzx0z.js +2 -0
  250. package/dist/chunks/chunk-rr1et8fg.js +2 -0
  251. package/dist/chunks/chunk-sjcx4fd5.js +6 -0
  252. package/dist/chunks/chunk-v1c777xh.js +5 -0
  253. package/dist/chunks/chunk-w5k5vwjd.js +13 -0
  254. package/dist/chunks/core.js +10 -0
  255. package/dist/chunks/display.js +17 -0
  256. package/dist/chunks/feedback.js +15 -0
  257. package/dist/chunks/forms.js +48 -0
  258. package/dist/chunks/layout.js +9 -0
  259. package/dist/components/chunk-4tezav8r.js +2 -0
  260. package/dist/components/chunk-fqyb2pms.js +2 -0
  261. package/dist/components/chunk-h7cdbhxw.js +13 -0
  262. package/dist/components/chunk-mzd8jwrs.js +2 -0
  263. package/dist/components/chunk-qwmxyn8e.js +2 -0
  264. package/dist/components/chunk-redtk47a.js +14 -0
  265. package/dist/components/mu-alert.js +5 -0
  266. package/dist/components/mu-api-table.js +33 -0
  267. package/dist/components/mu-avatar.js +1 -0
  268. package/dist/components/mu-badge.js +1 -0
  269. package/dist/components/mu-bottom-nav.js +1 -0
  270. package/dist/components/mu-button.js +1 -0
  271. package/dist/components/mu-callout.js +1 -0
  272. package/dist/components/mu-card.js +1 -0
  273. package/dist/components/mu-checkbox.js +9 -0
  274. package/dist/components/mu-chip.js +4 -0
  275. package/dist/components/mu-code.js +48 -0
  276. package/dist/components/mu-confirm.js +10 -0
  277. package/dist/components/mu-container.js +1 -0
  278. package/dist/components/mu-datatable.js +96 -0
  279. package/dist/components/mu-divider.js +1 -0
  280. package/dist/components/mu-doc-page.js +26 -0
  281. package/dist/components/mu-drawer-item.js +9 -0
  282. package/dist/components/mu-drawer.js +1 -0
  283. package/dist/components/mu-dropdown.js +6 -0
  284. package/dist/components/mu-error-boundary.js +10 -0
  285. package/dist/components/mu-example.js +38 -0
  286. package/dist/components/mu-fetch.js +1 -0
  287. package/dist/components/mu-form.js +1 -0
  288. package/dist/components/mu-grid.js +1 -0
  289. package/dist/components/mu-icon.js +5 -0
  290. package/dist/components/mu-input.js +12 -0
  291. package/dist/components/mu-layout.js +1 -0
  292. package/dist/components/mu-lazy.js +1 -0
  293. package/dist/components/mu-modal.js +7 -0
  294. package/dist/components/mu-navbar.js +1 -0
  295. package/dist/components/mu-page.js +1 -0
  296. package/dist/components/mu-progress.js +1 -0
  297. package/dist/components/mu-prompt-ui.js +20 -0
  298. package/dist/components/mu-radio.js +6 -0
  299. package/dist/components/mu-repeat.js +1 -0
  300. package/dist/components/mu-router.js +6 -0
  301. package/dist/components/mu-schema-form.js +76 -0
  302. package/dist/components/mu-sidebar.js +1 -0
  303. package/dist/components/mu-skeleton.js +13 -0
  304. package/dist/components/mu-spinner.js +1 -0
  305. package/dist/components/mu-stack.js +1 -0
  306. package/dist/components/mu-switch.js +6 -0
  307. package/dist/components/mu-table.js +1 -0
  308. package/dist/components/mu-tabs.js +1 -0
  309. package/dist/components/mu-textarea.js +11 -0
  310. package/dist/components/mu-theme-toggle.js +5 -0
  311. package/dist/components/mu-toast.js +4 -0
  312. package/dist/components/mu-tooltip.js +10 -0
  313. package/dist/components/mu-virtual-list.js +33 -0
  314. package/dist/components.css +1 -0
  315. package/dist/microui.css +1 -0
  316. package/dist/microui.d.ts +234 -0
  317. package/dist/microui.esm.js +549 -0
  318. package/dist/microui.esm.js.map +79 -0
  319. package/dist/microui.min.js +549 -0
  320. package/dist/microui.min.js.map +79 -0
  321. package/dist/routes/alerts.js +1 -0
  322. package/dist/routes/avatars.js +1 -0
  323. package/dist/routes/badges.js +1 -0
  324. package/dist/routes/buttons.js +1 -0
  325. package/dist/routes/callouts.js +1 -0
  326. package/dist/routes/cards.js +1 -0
  327. package/dist/routes/checkboxes.js +9 -0
  328. package/dist/routes/chips.js +4 -0
  329. package/dist/routes/chunk-19wgcncm.js +2 -0
  330. package/dist/routes/chunk-1khyr3v1.js +33 -0
  331. package/dist/routes/chunk-4rhxe97g.js +1 -0
  332. package/dist/routes/chunk-5qah04bh.js +2 -0
  333. package/dist/routes/chunk-7gfxy70n.js +5 -0
  334. package/dist/routes/chunk-e86zbeta.js +1 -0
  335. package/dist/routes/chunk-fagt36h6.js +2 -0
  336. package/dist/routes/chunk-fed7zr7m.js +1 -0
  337. package/dist/routes/chunk-hwj7pfwp.js +1 -0
  338. package/dist/routes/chunk-mhvcs2f8.js +5 -0
  339. package/dist/routes/chunk-nv3bddmj.js +13 -0
  340. package/dist/routes/chunk-q3f2aeqe.js +7 -0
  341. package/dist/routes/chunk-qxxa8trk.js +1 -0
  342. package/dist/routes/chunk-rw15y9zh.js +1 -0
  343. package/dist/routes/chunk-sfb7x11v.js +5 -0
  344. package/dist/routes/chunk-swyhghrm.js +48 -0
  345. package/dist/routes/chunk-sxddjs2d.js +2 -0
  346. package/dist/routes/chunk-vby0zg5w.js +17 -0
  347. package/dist/routes/chunk-w6zqjqqs.js +9 -0
  348. package/dist/routes/chunk-z960rexd.js +38 -0
  349. package/dist/routes/codeblocks.js +1 -0
  350. package/dist/routes/confirms.js +10 -0
  351. package/dist/routes/datatables.js +96 -0
  352. package/dist/routes/dividers.js +1 -0
  353. package/dist/routes/dropdowns.js +6 -0
  354. package/dist/routes/enterprise.js +15 -0
  355. package/dist/routes/home.js +1 -0
  356. package/dist/routes/icons.js +1 -0
  357. package/dist/routes/inputs.js +22 -0
  358. package/dist/routes/installation.js +1 -0
  359. package/dist/routes/layout.js +1 -0
  360. package/dist/routes/modals.js +1 -0
  361. package/dist/routes/navbar.js +1 -0
  362. package/dist/routes/page-components.json +316 -0
  363. package/dist/routes/progress.js +1 -0
  364. package/dist/routes/radios.js +6 -0
  365. package/dist/routes/route-deps.json +156 -0
  366. package/dist/routes/shell-critical.js +1 -0
  367. package/dist/routes/shell-deferred.js +1 -0
  368. package/dist/routes/shell.js +20 -0
  369. package/dist/routes/skeletons.js +13 -0
  370. package/dist/routes/spinners.js +1 -0
  371. package/dist/routes/src/chunks/core.js +36 -0
  372. package/dist/routes/switches.js +6 -0
  373. package/dist/routes/tables.js +1 -0
  374. package/dist/routes/tabs.js +1 -0
  375. package/dist/routes/toasts.js +1 -0
  376. package/dist/routes/tooltips.js +10 -0
  377. package/dist/routes/virtual-lists.js +33 -0
  378. package/dist/styles/common.css +1 -0
  379. package/dist/styles/components/animations.css +1 -0
  380. package/dist/styles/components/avatar.css +1 -0
  381. package/dist/styles/components/badge.css +1 -0
  382. package/dist/styles/components/bottom-nav.css +1 -0
  383. package/dist/styles/components/button.css +1 -0
  384. package/dist/styles/components/card.css +1 -0
  385. package/dist/styles/components/checkbox.css +1 -0
  386. package/dist/styles/components/chip.css +1 -0
  387. package/dist/styles/components/datatable.css +1 -0
  388. package/dist/styles/components/divider.css +1 -0
  389. package/dist/styles/components/drawer-item.css +1 -0
  390. package/dist/styles/components/drawer.css +1 -0
  391. package/dist/styles/components/grid.css +1 -0
  392. package/dist/styles/components/icon.css +1 -0
  393. package/dist/styles/components/input.css +1 -0
  394. package/dist/styles/components/layout.css +1 -0
  395. package/dist/styles/components/navbar.css +1 -0
  396. package/dist/styles/components/overlays.css +1 -0
  397. package/dist/styles/components/progress.css +1 -0
  398. package/dist/styles/components/prompt-ui.css +1 -0
  399. package/dist/styles/components/radio.css +1 -0
  400. package/dist/styles/components/schema-form.css +1 -0
  401. package/dist/styles/components/switch.css +1 -0
  402. package/dist/styles/components/tabs.css +1 -0
  403. package/dist/styles/components/tooltip.css +1 -0
  404. package/dist/styles/components/virtual-list.css +1 -0
  405. package/dist/tokens.css +1 -0
  406. package/docs/api-reference.md +175 -0
  407. package/docs/component-schema.md +231 -0
  408. package/docs/components.md +269 -0
  409. package/docs/design-system.md +183 -0
  410. package/docs/getting-started.md +198 -0
  411. package/docs/message-protocol.md +262 -0
  412. package/docs/utility-classes.md +205 -0
  413. package/lighthouse-audit.mjs +113 -0
  414. package/package.json +45 -0
  415. package/scripts/analyze-components.js +105 -0
  416. package/scripts/build-app.js +193 -0
  417. package/scripts/build-framework.js +444 -0
  418. package/scripts/build-utils.js +101 -0
  419. package/scripts/test-isolated.js +151 -0
  420. package/server.js +256 -0
  421. package/src/chunks/advanced.js +27 -0
  422. package/src/chunks/core.js +61 -0
  423. package/src/chunks/display.js +25 -0
  424. package/src/chunks/feedback.js +15 -0
  425. package/src/chunks/forms.js +25 -0
  426. package/src/chunks/layout.js +27 -0
  427. package/src/components/mu-alert.js +96 -0
  428. package/src/components/mu-api-table.js +167 -0
  429. package/src/components/mu-avatar.js +94 -0
  430. package/src/components/mu-badge.js +32 -0
  431. package/src/components/mu-bottom-nav.js +115 -0
  432. package/src/components/mu-button.js +61 -0
  433. package/src/components/mu-callout.js +71 -0
  434. package/src/components/mu-card.js +36 -0
  435. package/src/components/mu-checkbox.js +186 -0
  436. package/src/components/mu-chip.js +125 -0
  437. package/src/components/mu-code.js +534 -0
  438. package/src/components/mu-confirm.js +268 -0
  439. package/src/components/mu-container.js +53 -0
  440. package/src/components/mu-datatable.js +517 -0
  441. package/src/components/mu-divider.js +40 -0
  442. package/src/components/mu-doc-page.js +100 -0
  443. package/src/components/mu-drawer-item.js +158 -0
  444. package/src/components/mu-drawer.js +305 -0
  445. package/src/components/mu-dropdown.js +239 -0
  446. package/src/components/mu-error-boundary.js +191 -0
  447. package/src/components/mu-example.js +335 -0
  448. package/src/components/mu-fetch.js +256 -0
  449. package/src/components/mu-form.js +133 -0
  450. package/src/components/mu-grid.js +63 -0
  451. package/src/components/mu-icon.js +211 -0
  452. package/src/components/mu-input.js +142 -0
  453. package/src/components/mu-layout.js +129 -0
  454. package/src/components/mu-lazy.js +94 -0
  455. package/src/components/mu-modal.js +160 -0
  456. package/src/components/mu-navbar.js +71 -0
  457. package/src/components/mu-page.js +77 -0
  458. package/src/components/mu-progress.js +54 -0
  459. package/src/components/mu-prompt-ui.js +382 -0
  460. package/src/components/mu-radio.js +200 -0
  461. package/src/components/mu-repeat.js +135 -0
  462. package/src/components/mu-router.js +169 -0
  463. package/src/components/mu-schema-form.js +441 -0
  464. package/src/components/mu-sidebar.js +81 -0
  465. package/src/components/mu-skeleton.js +69 -0
  466. package/src/components/mu-spinner.js +30 -0
  467. package/src/components/mu-stack.js +59 -0
  468. package/src/components/mu-switch.js +150 -0
  469. package/src/components/mu-table.js +80 -0
  470. package/src/components/mu-tabs.js +112 -0
  471. package/src/components/mu-textarea.js +96 -0
  472. package/src/components/mu-theme-toggle.js +52 -0
  473. package/src/components/mu-toast.js +151 -0
  474. package/src/components/mu-tooltip.js +182 -0
  475. package/src/components/mu-virtual-list.js +184 -0
  476. package/src/core/MuElement.js +562 -0
  477. package/src/core/agent-api.js +771 -0
  478. package/src/core/breakpoints.js +195 -0
  479. package/src/core/bus.js +378 -0
  480. package/src/core/component-schema.js +287 -0
  481. package/src/core/feature-registry.js +241 -0
  482. package/src/core/form-state.js +252 -0
  483. package/src/core/http.js +104 -0
  484. package/src/core/keyboard.js +105 -0
  485. package/src/core/layers.js +71 -0
  486. package/src/core/render.js +201 -0
  487. package/src/core/ripple.js +158 -0
  488. package/src/core/router.js +100 -0
  489. package/src/core/scheduler.js +109 -0
  490. package/src/core/signals.js +164 -0
  491. package/src/core/store.js +268 -0
  492. package/src/core/theme.js +68 -0
  493. package/src/core/transitions.js +72 -0
  494. package/src/core/utils.js +30 -0
  495. package/src/index.d.ts +234 -0
  496. package/src/index.js +308 -0
  497. package/src/styles/animations.css +252 -0
  498. package/src/styles/common.css +82 -0
  499. package/src/styles/components/animations.css +129 -0
  500. package/src/styles/components/avatar.css +83 -0
  501. package/src/styles/components/badge.css +80 -0
  502. package/src/styles/components/bottom-nav.css +37 -0
  503. package/src/styles/components/button.css +348 -0
  504. package/src/styles/components/card.css +138 -0
  505. package/src/styles/components/checkbox.css +201 -0
  506. package/src/styles/components/chip.css +93 -0
  507. package/src/styles/components/datatable.css +180 -0
  508. package/src/styles/components/divider.css +49 -0
  509. package/src/styles/components/drawer-item.css +123 -0
  510. package/src/styles/components/drawer.css +273 -0
  511. package/src/styles/components/grid.css +189 -0
  512. package/src/styles/components/icon.css +40 -0
  513. package/src/styles/components/input.css +203 -0
  514. package/src/styles/components/layout.css +121 -0
  515. package/src/styles/components/navbar.css +91 -0
  516. package/src/styles/components/overlays.css +329 -0
  517. package/src/styles/components/progress.css +79 -0
  518. package/src/styles/components/prompt-ui.css +286 -0
  519. package/src/styles/components/radio.css +17 -0
  520. package/src/styles/components/schema-form.css +85 -0
  521. package/src/styles/components/switch.css +69 -0
  522. package/src/styles/components/tabs.css +145 -0
  523. package/src/styles/components/tooltip.css +93 -0
  524. package/src/styles/components/virtual-list.css +36 -0
  525. package/src/styles/components.css +3677 -0
  526. package/src/styles/routes/home.css +97 -0
  527. package/src/styles/tokens.css +675 -0
  528. package/tests/agents/agent-integration.test.js +76 -0
  529. package/tests/benchmark.html +296 -0
  530. package/tests/build/scan-components.test.js +173 -0
  531. package/tests/components/all-components.test.js +245 -0
  532. package/tests/components/all-missing-components.test.js +574 -0
  533. package/tests/components/mu-alert.test.js +113 -0
  534. package/tests/components/mu-avatar.test.js +148 -0
  535. package/tests/components/mu-badge.test.js +92 -0
  536. package/tests/components/mu-button.test.js +112 -0
  537. package/tests/components/mu-card.test.js +89 -0
  538. package/tests/components/mu-checkbox.test.js +158 -0
  539. package/tests/components/mu-chip.test.js +118 -0
  540. package/tests/components/mu-container.test.js +120 -0
  541. package/tests/components/mu-divider.test.js +98 -0
  542. package/tests/components/mu-drawer-item.test.js +199 -0
  543. package/tests/components/mu-drawer.test.js +96 -0
  544. package/tests/components/mu-dropdown.test.js +125 -0
  545. package/tests/components/mu-form.test.js +138 -0
  546. package/tests/components/mu-grid.test.js +135 -0
  547. package/tests/components/mu-icon.test.js +110 -0
  548. package/tests/components/mu-input.test.js +131 -0
  549. package/tests/components/mu-lazy.test.js +103 -0
  550. package/tests/components/mu-modal.test.js +275 -0
  551. package/tests/components/mu-navbar.test.js +101 -0
  552. package/tests/components/mu-progress.test.js +115 -0
  553. package/tests/components/mu-radio.test.js +114 -0
  554. package/tests/components/mu-repeat.test.js +106 -0
  555. package/tests/components/mu-sidebar.test.js +126 -0
  556. package/tests/components/mu-skeleton.test.js +162 -0
  557. package/tests/components/mu-stack.test.js +143 -0
  558. package/tests/components/mu-switch.test.js +292 -0
  559. package/tests/components/mu-table.test.js +124 -0
  560. package/tests/components/mu-tabs.test.js +104 -0
  561. package/tests/components/mu-textarea.test.js +115 -0
  562. package/tests/components/mu-toast.test.js +321 -0
  563. package/tests/components/mu-tooltip.test.js +133 -0
  564. package/tests/components/mu-virtual-list.test.js +109 -0
  565. package/tests/core/MuElement.test.js +120 -0
  566. package/tests/core/agent-api.test.js +125 -0
  567. package/tests/core/all-core-modules.test.js +442 -0
  568. package/tests/core/bus.test.js +364 -0
  569. package/tests/core/component-schema.test.js +160 -0
  570. package/tests/core/feature-registry.test.js +198 -0
  571. package/tests/core/form-state.test.js +167 -0
  572. package/tests/core/http.test.js +119 -0
  573. package/tests/core/keyboard.test.js +319 -0
  574. package/tests/core/layers.test.js +129 -0
  575. package/tests/core/namespaced-stores.test.js +114 -0
  576. package/tests/core/render.test.js +121 -0
  577. package/tests/core/ripple.test.js +131 -0
  578. package/tests/core/router.test.js +89 -0
  579. package/tests/core/scheduler.test.js +121 -0
  580. package/tests/core/signals.test.js +128 -0
  581. package/tests/core/store.test.js +171 -0
  582. package/tests/core/transitions.test.js +82 -0
  583. package/tests/e2e/accessibility-harness.html +58 -0
  584. package/tests/e2e/accessibility.test.js +401 -0
  585. package/tests/e2e/agent-features.test.js +372 -0
  586. package/tests/e2e/card-spacing.test.js +287 -0
  587. package/tests/e2e/components.test.js +439 -0
  588. package/tests/e2e/demo-routes.test.js +478 -0
  589. package/tests/e2e/layout-css-fallback.test.js +334 -0
  590. package/tests/e2e/mu-alert.e2e.test.js +111 -0
  591. package/tests/e2e/mu-checkbox.test.js +489 -0
  592. package/tests/e2e/mu-chip.test.js +347 -0
  593. package/tests/e2e/mu-form.test.js +499 -0
  594. package/tests/e2e/mu-icon.test.js +114 -0
  595. package/tests/e2e/mu-radio.test.js +113 -0
  596. package/tests/e2e/mu-skeleton.test.js +140 -0
  597. package/tests/e2e/mu-switch.test.js +415 -0
  598. package/tests/e2e/mu-tabs.test.js +494 -0
  599. package/tests/e2e/mu-textarea.test.js +242 -0
  600. package/tests/e2e/mu-virtual-list.test.js +427 -0
  601. package/tests/e2e/perf-memory.test.js +161 -0
  602. package/tests/e2e/puppeteer-helper.js +137 -0
  603. package/tests/e2e/puppeteer.test.js +226 -0
  604. package/tests/e2e/pwa.test.js +261 -0
  605. package/tests/e2e/test-harness.html +319 -0
  606. package/tests/manual/test-components.html +120 -0
  607. package/tests/memory-test.html +309 -0
  608. package/tests/setup-dom.js +93 -0
  609. package/tests/visual-test.html +301 -0
@@ -0,0 +1,256 @@
1
+ /**
2
+ * @fileoverview mu-fetch - Declarative Data Fetcher Component
3
+ * Agent-friendly component for fetching data with automatic loading/error states
4
+ *
5
+ * @example
6
+ * <mu-fetch url="/api/users" id="users">
7
+ * <template slot="loading"><mu-skeleton></mu-skeleton></template>
8
+ * <template slot="error"><mu-alert variant="error">${error}</mu-alert></template>
9
+ * </mu-fetch>
10
+ *
11
+ * // Access data
12
+ * const fetcher = document.getElementById('users');
13
+ * fetcher.data; // The fetched data
14
+ * fetcher.refetch(); // Re-fetch data
15
+ */
16
+
17
+ import { MuElement, define } from '../core/MuElement.js';
18
+
19
+ /**
20
+ * @typedef {'idle'|'loading'|'success'|'error'} FetchState
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} FetchResult
25
+ * @property {FetchState} state
26
+ * @property {any} data
27
+ * @property {Error|null} error
28
+ */
29
+
30
+ export class MuFetch extends MuElement {
31
+ static baseClass = 'mu-fetch';
32
+ static observedAttributes = ['url', 'method', 'auto', 'interval'];
33
+
34
+ /** @type {FetchState} */
35
+ state = 'idle';
36
+
37
+ /** @type {any} */
38
+ data = null;
39
+
40
+ /** @type {Error|null} */
41
+ error = null;
42
+
43
+ /** @type {AbortController|null} */
44
+ _controller = null;
45
+
46
+ /** @type {number|null} */
47
+ _intervalId = null;
48
+
49
+ connectedCallback() {
50
+ // Store templates before render
51
+ this._loadingTemplate = this.querySelector('template[slot="loading"]')?.innerHTML ||
52
+ '<mu-spinner></mu-spinner>';
53
+ this._errorTemplate = this.querySelector('template[slot="error"]')?.innerHTML ||
54
+ '<mu-alert variant="error">Error loading data</mu-alert>';
55
+ this._emptyTemplate = this.querySelector('template[slot="empty"]')?.innerHTML ||
56
+ '<p>No data</p>';
57
+
58
+ super.connectedCallback();
59
+
60
+ // Auto-fetch on connect
61
+ if (this.has('auto') || this.hasAttribute('url')) {
62
+ this.fetch();
63
+ }
64
+
65
+ // Setup interval refresh
66
+ const interval = parseInt(this.attr('interval', '0'));
67
+ if (interval > 0) {
68
+ this.setInterval(() => this.fetch(), interval);
69
+ }
70
+ }
71
+
72
+ render() {
73
+ // Render based on current state
74
+ this.innerHTML = ''; // Clear content
75
+
76
+ switch (this.state) {
77
+ case 'loading':
78
+ // Safe: _loadingTemplate is trusted or empty, but let's wrap it container
79
+ const loadingContainer = document.createElement('div');
80
+ loadingContainer.className = 'mu-fetch__loading';
81
+ loadingContainer.innerHTML = this._loadingTemplate; // _loadingTemplate comes from initial slot content which is trusted
82
+ this.appendChild(loadingContainer);
83
+ break;
84
+ case 'error':
85
+ const errorContainer = document.createElement('div');
86
+ errorContainer.className = 'mu-fetch__error';
87
+
88
+ // Safe: Create error message safely using textContent
89
+ // We don't use the template string replacement anymore to avoid XSS
90
+ // If user provided a custom error template, we parse it safely or just use default
91
+
92
+ const errorMessage = this.error?.message || 'Unknown error';
93
+
94
+ if (this._errorTemplate && this._errorTemplate.includes('${error}')) {
95
+ // If template is complex, we might need a safer way, but for now
96
+ // let's stick to safe text replacement if possible or just use textContent
97
+ // Actually, simply setting textContent into the container is safest for the message
98
+ errorContainer.textContent = `Error: ${errorMessage}`;
99
+ // If we want to respect the slot, we'd need a safe interpolate,
100
+ // but for high, security we break the unsafe template behavior for errors.
101
+ } else {
102
+ const alert = document.createElement('mu-alert');
103
+ alert.setAttribute('variant', 'error');
104
+ alert.textContent = errorMessage; // Safe
105
+ errorContainer.appendChild(alert);
106
+ }
107
+
108
+ this.appendChild(errorContainer);
109
+ break;
110
+ case 'success':
111
+ if (!this.data || (Array.isArray(this.data) && this.data.length === 0)) {
112
+ const emptyContainer = document.createElement('div');
113
+ emptyContainer.className = 'mu-fetch__empty';
114
+ emptyContainer.innerHTML = this._emptyTemplate; // Trusted slot content
115
+ this.appendChild(emptyContainer);
116
+ } else {
117
+ const dataContainer = document.createElement('div');
118
+ dataContainer.className = 'mu-fetch__data';
119
+
120
+ // Dataslot or renderItem function
121
+ if (this.renderItem && Array.isArray(this.data)) {
122
+ // WARNING: renderItem expects to return a string currently.
123
+ // To be safe, we should check if it returns a Node or string.
124
+ // For now we will assume string but we can sanitize it?
125
+ // Actually, following the plan, we change default behavior but if user provides function
126
+ // they might output HTML.
127
+ // Let's implement safe node appending if possible.
128
+ this.data.forEach(item => {
129
+ const result = this.renderItem(item);
130
+ if (result instanceof Node) {
131
+ dataContainer.appendChild(result);
132
+ } else {
133
+ // If string, we must be careful.
134
+ // Ideally we use insertAdjacentHTML but that is XSS vector if renderItem is unsafe.
135
+ // We will document that renderItem must be safe.
136
+ // For the PoC, we will show that we can make it safe by NOT using innerHTML on the container directly
137
+ // but appending item by item?
138
+ // innerHTML += result is bad.
139
+ const temp = document.createElement('div');
140
+ temp.innerHTML = result; // Still unsafe if result is bad.
141
+ // We can't fix user's renderItem but we can fix the container
142
+ dataContainer.insertAdjacentHTML('beforeend', result);
143
+ }
144
+ });
145
+ } else {
146
+ const slot = document.createElement('slot');
147
+ slot.name = 'data';
148
+ dataContainer.appendChild(slot);
149
+ this.emit('mu-data', { data: this.data });
150
+ }
151
+ this.appendChild(dataContainer);
152
+ }
153
+ break;
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Fetch data from the URL
159
+ * @param {RequestInit} [options] - Fetch options override
160
+ * @returns {Promise<any>}
161
+ */
162
+ async fetch(options = {}) {
163
+ const url = this.attr('url', '');
164
+ if (!url) {
165
+ console.warn('mu-fetch: No URL provided');
166
+ return null;
167
+ }
168
+
169
+ // Abort any in-flight request
170
+ if (this._controller) {
171
+ this._controller.abort();
172
+ }
173
+ this._controller = new AbortController();
174
+
175
+ this.state = 'loading';
176
+ this.error = null;
177
+ this.render();
178
+ this.emit('mu-loading');
179
+
180
+ try {
181
+ const method = this.attr('method', 'GET');
182
+ const response = await fetch(url, {
183
+ method,
184
+ signal: this._controller.signal,
185
+ headers: {
186
+ 'Content-Type': 'application/json',
187
+ ...options.headers
188
+ },
189
+ ...options
190
+ });
191
+
192
+ if (!response.ok) {
193
+ // If the server returns JSON error, try to parse it
194
+ let errorMsg = `HTTP ${response.status}: ${response.statusText}`;
195
+ try {
196
+ const errorJson = await response.json();
197
+ if (errorJson.message) errorMsg = errorJson.message;
198
+ } catch (e) {
199
+ // Ignore json parse error
200
+ }
201
+ throw new Error(errorMsg);
202
+ }
203
+
204
+ this.data = await response.json();
205
+ this.state = 'success';
206
+ this.render();
207
+ this.emit('mu-success', { data: this.data });
208
+ return this.data;
209
+ } catch (err) {
210
+ if (err.name === 'AbortError') {
211
+ return null; // Aborted, ignore
212
+ }
213
+ this.error = /** @type {Error} */ (err);
214
+ this.state = 'error';
215
+ this.render();
216
+ this.emit('mu-error', { error: this.error });
217
+ return null;
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Refetch the current URL
223
+ * @returns {Promise<any>}
224
+ */
225
+ refetch() {
226
+ return this.fetch();
227
+ }
228
+
229
+ /**
230
+ * Set custom render function for array data
231
+ * @param {(item: any, index: number) => string} fn
232
+ */
233
+ set renderItem(fn) {
234
+ this._renderItem = fn;
235
+ }
236
+
237
+ get renderItem() {
238
+ return this._renderItem;
239
+ }
240
+
241
+ update(attr, newValue, oldValue) {
242
+ if (attr === 'url' && newValue !== oldValue) {
243
+ this.fetch();
244
+ }
245
+ }
246
+
247
+ disconnectedCallback() {
248
+ super.disconnectedCallback();
249
+ if (this._controller) {
250
+ this._controller.abort();
251
+ }
252
+ // Note: setInterval cleanup now handled by MuElement via super.disconnectedCallback()
253
+ }
254
+ }
255
+
256
+ define('mu-fetch', MuFetch);
@@ -0,0 +1,133 @@
1
+ /**
2
+ * @fileoverview mu-form - Form Container with Validation
3
+ *
4
+ * Usage:
5
+ * <mu-form onsubmit="handleSubmit">
6
+ * <mu-input name="email" required></mu-input>
7
+ * <mu-button type="submit">Submit</mu-button>
8
+ * </mu-form>
9
+ */
10
+
11
+ import { MuElement, define } from '../core/MuElement.js';
12
+
13
+ export class MuForm extends MuElement {
14
+ static baseClass = 'mu-form';
15
+ static observedAttributes = ['action', 'method'];
16
+
17
+ connectedCallback() {
18
+ super.connectedCallback();
19
+
20
+ this.listen(this, 'submit', (e) => {
21
+ e.preventDefault();
22
+ this.#handleSubmit();
23
+ });
24
+
25
+ // Handle enter key in inputs
26
+ this.listen(this, 'keydown', (e) => {
27
+ if (e.key === 'Enter' && e.target.matches('input')) {
28
+ e.preventDefault();
29
+ this.#handleSubmit();
30
+ }
31
+ });
32
+ }
33
+
34
+ render() {
35
+ // Form is a passthrough container
36
+ this.setAttribute('role', 'form');
37
+
38
+ // AGENT VALIDATION: Form should have interactive controls
39
+ // SOTA: Double rAF ensures children are rendered before checking
40
+ if (this.hasAttribute('debug')) {
41
+ requestAnimationFrame(() => {
42
+ requestAnimationFrame(() => {
43
+ const hasControls = this.querySelector('mu-input, mu-button, mu-select, mu-textarea, input, button, select, textarea');
44
+ if (!hasControls) {
45
+ this.logError('EMPTY_FORM', 'Form appears to be empty. Add input controls.');
46
+ }
47
+ });
48
+ });
49
+ }
50
+ }
51
+
52
+ #handleSubmit() {
53
+ const data = this.getFormData();
54
+ const isValid = this.validate();
55
+
56
+ if (isValid) {
57
+ this.emit('mu-submit', { data, isValid });
58
+ } else {
59
+ this.emit('mu-invalid', { data, errors: this.#getErrors() });
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Get all form data as object
65
+ */
66
+ getFormData() {
67
+ const data = {};
68
+
69
+ // Get all mu-input values
70
+ this.querySelectorAll('mu-input[name]').forEach(input => {
71
+ data[input.getAttribute('name')] = input.value;
72
+ });
73
+
74
+ // Get native input values
75
+ this.querySelectorAll('input[name], select[name], textarea[name]').forEach(input => {
76
+ if (input.type === 'checkbox') {
77
+ data[input.name] = input.checked;
78
+ } else {
79
+ data[input.name] = input.value;
80
+ }
81
+ });
82
+
83
+ return data;
84
+ }
85
+
86
+ /**
87
+ * Validate all required fields
88
+ */
89
+ validate() {
90
+ let isValid = true;
91
+
92
+ this.querySelectorAll('[required]').forEach(field => {
93
+ const value = field.value || field.getAttribute('value') || '';
94
+ if (!value.trim()) {
95
+ field.classList.add('is-invalid');
96
+ isValid = false;
97
+ } else {
98
+ field.classList.remove('is-invalid');
99
+ }
100
+ });
101
+
102
+ return isValid;
103
+ }
104
+
105
+ #getErrors() {
106
+ const errors = [];
107
+ this.querySelectorAll('.is-invalid').forEach(field => {
108
+ errors.push({
109
+ name: field.getAttribute('name'),
110
+ message: 'This field is required'
111
+ });
112
+ });
113
+ return errors;
114
+ }
115
+
116
+ /**
117
+ * Reset form to initial state
118
+ */
119
+ reset() {
120
+ this.querySelectorAll('mu-input').forEach(input => {
121
+ input.value = '';
122
+ });
123
+ this.querySelectorAll('input, select, textarea').forEach(el => {
124
+ el.value = '';
125
+ });
126
+ this.querySelectorAll('.is-invalid').forEach(el => {
127
+ el.classList.remove('is-invalid');
128
+ });
129
+ this.emit('mu-reset');
130
+ }
131
+ }
132
+
133
+ define('mu-form', MuForm);
@@ -0,0 +1,63 @@
1
+ /**
2
+ * @fileoverview mu-grid - CSS Grid Layout Component
3
+ *
4
+ * Usage: <mu-grid cols="3" gap="md">...</mu-grid>
5
+ *
6
+ * Responsive: On compact screens (< 600px), grids with 3+ columns
7
+ * automatically collapse to single column via CSS media query.
8
+ * See components.css for the responsive rules.
9
+ */
10
+
11
+ import { MuElement, define } from '../core/MuElement.js';
12
+
13
+ export class MuGrid extends MuElement {
14
+ static baseClass = 'mu-grid';
15
+ static cssFile = 'grid';
16
+ static observedAttributes = ['cols', 'rows', 'gap', 'align'];
17
+
18
+ render() {
19
+ this.#updateStyles();
20
+ }
21
+
22
+ update(attr, newValue, oldValue) {
23
+ this.#updateStyles();
24
+ }
25
+
26
+ #updateStyles() {
27
+ const cols = this.attr('cols', '1');
28
+ const rows = this.attr('rows', '');
29
+ const gap = this.attr('gap', 'md');
30
+ const align = this.attr('align', 'stretch');
31
+
32
+ const gapMap = {
33
+ none: '0',
34
+ xs: '4px',
35
+ sm: '8px',
36
+ md: '16px',
37
+ lg: '24px',
38
+ xl: '32px'
39
+ };
40
+
41
+ this.style.display = 'grid';
42
+
43
+ // Set gridTemplateColumns only for non-responsive cases
44
+ // CSS media queries in components.css handle responsive collapse to 1fr on compact
45
+ // We don't override CSS's responsive behavior here - CSS has lower specificity
46
+ // than inline styles, so we need to NOT set this on compact breakpoints
47
+ // However, since detecting compact reliably in JS during module load is unreliable,
48
+ // we rely on CSS to override via !important for responsive cases
49
+ this.style.gridTemplateColumns = cols.includes('fr') || cols.includes('px')
50
+ ? cols
51
+ : `repeat(${cols}, 1fr)`;
52
+
53
+ if (rows) {
54
+ this.style.gridTemplateRows = rows.includes('fr') || rows.includes('px')
55
+ ? rows
56
+ : `repeat(${rows}, 1fr)`;
57
+ }
58
+ this.style.gap = gapMap[gap] || gap;
59
+ this.style.alignItems = align;
60
+ }
61
+ }
62
+
63
+ define('mu-grid', MuGrid);
@@ -0,0 +1,211 @@
1
+ /**
2
+ * @fileoverview mu-icon - Material Symbols Icon Component
3
+ *
4
+ * Supports both:
5
+ * 1. Material Symbols font (2500+ icons) - primary
6
+ * 2. Inline SVG fallback for critical icons
7
+ *
8
+ * Usage:
9
+ * <mu-icon name="check"></mu-icon> <!-- Material Symbol -->
10
+ * <mu-icon name="check" svg></mu-icon> <!-- Force SVG -->
11
+ */
12
+
13
+ import { MuElement, define } from '../core/MuElement.js';
14
+
15
+ // Inline SVG paths for critical icons (fallback when font not loaded)
16
+ const SVG_ICONS = {
17
+ // Actions
18
+ check: 'M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z',
19
+ close: 'M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
20
+ add: 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z',
21
+ remove: 'M19 13H5v-2h14z',
22
+ edit: 'M3 17.25V21h3.75L17.81 9.94l-3.75-3.75zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75z',
23
+ delete: 'M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zM19 4h-3.5l-1-1h-5l-1 1H5v2h14z',
24
+ search: 'M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z',
25
+
26
+ // Navigation
27
+ menu: 'M3 18h18v-2H3zm0-5h18v-2H3zm0-7v2h18V6z',
28
+ chevron_right: 'M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z',
29
+ chevron_left: 'M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z',
30
+ expand_more: 'M16.59 8.59 12 13.17 7.41 8.59 6 10l6 6 6-6z',
31
+ expand_less: 'M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z',
32
+ home: 'M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z',
33
+ arrow_back: 'M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20z',
34
+ arrow_forward: 'M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z',
35
+
36
+ // Status
37
+ info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2zm0-8h-2V7h2z',
38
+ warning: 'M1 21h22L12 2zm12-3h-2v-2h2zm0-4h-2v-4h2z',
39
+ error: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2zm0-4h-2V7h2z',
40
+ check_circle: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8z',
41
+ cancel: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12z',
42
+
43
+ // Aliases for alert severity
44
+ success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8z',
45
+
46
+ // UI
47
+ settings: 'M19.14 12.94c.04-.31.06-.63.06-.94 0-.31-.02-.63-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z',
48
+ person: 'M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z',
49
+ light_mode: 'M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5M2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1m18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1M11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1m0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1M5.99 4.58c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41zm12.37 12.37c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41zm1.06-10.96c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0zM7.05 18.36c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0z',
50
+ dark_mode: 'M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z',
51
+ visibility: 'M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5M12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5m0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3',
52
+ visibility_off: 'M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7M2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2m4.31-.78 3.15 3.15.02-.16c0-1.66-1.34-3-3-3z',
53
+
54
+ // Drawer/Navigation icons
55
+ download: 'M5 20h14v-2H5v2zM19 9h-4V3H9v6H5l7 7 7-7z',
56
+ smart_button: 'M22 9v6c0 1.1-.9 2-2 2h-1v-2h1V9H4v6h6v2H4c-1.1 0-2-.9-2-2V9c0-1.1.9-2 2-2h16c1.1 0 2 .9 2 2zm-7.5 11 1.09-2.41L18 16.5l-2.41-1.09L14.5 13l-1.09 2.41L11 16.5l2.41 1.09L14.5 20zm2.5-5 .62-1.38L19 14l-1.38-.62L17 12l-.62 1.38L15 14l1.38.62L17 16zm-2.5 5 1.09-2.41L18 16.5l-2.41-1.09L14.5 13l-1.09 2.41L11 16.5l2.41 1.09L14.5 20z',
57
+ text_fields: 'M2.5 4v3h5v12h3V7h5V4h-13zm19 5h-9v3h3v7h3v-7h3V9z',
58
+ check_box: 'M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
59
+ toggle_on: 'M17 7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h10c2.76 0 5-2.24 5-5s-2.24-5-5-5zm0 8c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z',
60
+ radio_button_checked: 'M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z',
61
+ arrow_drop_down_circle: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 12-4-4h8l-4 4z',
62
+ view_carousel: 'M7 19h10V4H7v15zm-5-2h4V6H2v11zM18 6v11h4V6h-4z',
63
+ grid_view: 'M3 3v8h8V3H3zm6 6H5V5h4v4zm-6 4v8h8v-8H3zm6 6H5v-4h4v4zm4-16v8h8V3h-8zm6 6h-4V5h4v4zm-6 4v8h8v-8h-8zm6 6h-4v-4h4v4z',
64
+ tab: 'M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z',
65
+ notifications: 'M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z',
66
+ open_in_new: 'M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z',
67
+ hourglass_empty: 'M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.99h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6zm10 14.5V20H8v-3.5l4-4 4 4zm-4-5-4-4V4h8v3.5l-4 4z',
68
+ account_circle: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 4c1.93 0 3.5 1.57 3.5 3.5S13.93 13 12 13s-3.5-1.57-3.5-3.5S10.07 6 12 6zm0 14c-2.03 0-4.43-.82-6.14-2.88C7.55 15.8 9.68 15 12 15s4.45.8 6.14 2.12C16.43 19.18 14.03 20 12 20z',
69
+ fiber_manual_record: 'M12 12m-8 0a8 8 0 1 0 16 0 8 8 0 1 0-16 0',
70
+ label: 'M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z',
71
+ emoji_emotions: 'M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z',
72
+ business: 'M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z',
73
+ input: 'M21 3.01H3c-1.1 0-2 .9-2 2V9h2V4.99h18v14.03H3V15H1v4.01c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98v-14c0-1.11-.9-2-2-2zM11 16l4-4-4-4v3H1v2h10v3z',
74
+ category: 'M12 2l-5.5 9h11L12 2zm0 3.84L13.93 9h-3.87L12 5.84zM17.5 13c-2.49 0-4.5 2.01-4.5 4.5s2.01 4.5 4.5 4.5 4.5-2.01 4.5-4.5-2.01-4.5-4.5-4.5zm0 7c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5zM3 21.5h8v-8H3v8zm2-6h4v4H5v-4z',
75
+ widgets: 'M13 13v8h8v-8h-8zM3 21h8v-8H3v8zM3 3v8h8V3H3zm13.66-1.31L11 7.34 16.66 13l5.66-5.66-5.66-5.65z',
76
+ smart_toy: 'M20 9V7c0-1.1-.9-2-2-2h-3c0-1.66-1.34-3-3-3S9 3.34 9 5H6c-1.1 0-2 .9-2 2v2c-1.66 0-3 1.34-3 3s1.34 3 3 3v4c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-4c1.66 0 3-1.34 3-3s-1.34-3-3-3zM7.5 11.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5S9.83 13 9 13s-1.5-.67-1.5-1.5zM16 17H8v-2h8v2zm-1-4c-.83 0-1.5-.67-1.5-1.5S14.17 10 15 10s1.5.67 1.5 1.5S15.83 13 15 13z',
77
+ notification_important: 'M18 16v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2zm-6 6c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm1-15.06c1.77.52 3 2.14 3 4.06v5.5l1 1v.5H7v-.5l1-1V11c0-1.92 1.23-3.54 3-4.06V5.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5v.94zM13 11h-2v6h2v-6zm0-4h-2v2h2V7z',
78
+
79
+ // Enterprise icons
80
+ folder_managed: 'M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-2.06 11L15 15.28 12.06 17l.78-3.33-2.59-2.24 3.41-.29L15 8l1.34 3.14 3.41.29-2.59 2.24.78 3.33z',
81
+ shield: 'M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z',
82
+ apps: 'M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z',
83
+ monitoring: 'M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zM7 12h2v5H7v-5zm4-3h2v8h-2V9zm4-3h2v11h-2V6z'
84
+ };
85
+
86
+ // Map from alert severity to Material Symbol names
87
+ const SYMBOL_NAMES = {
88
+ check: 'check',
89
+ close: 'close',
90
+ add: 'add',
91
+ remove: 'remove',
92
+ edit: 'edit',
93
+ delete: 'delete',
94
+ search: 'search',
95
+ menu: 'menu',
96
+ chevron_right: 'chevron_right',
97
+ chevron_left: 'chevron_left',
98
+ expand_more: 'expand_more',
99
+ expand_less: 'expand_less',
100
+ home: 'home',
101
+ arrow_back: 'arrow_back',
102
+ arrow_forward: 'arrow_forward',
103
+ info: 'info',
104
+ warning: 'warning',
105
+ error: 'error',
106
+ success: 'check_circle',
107
+ check_circle: 'check_circle',
108
+ cancel: 'cancel',
109
+ settings: 'settings',
110
+ person: 'person',
111
+ light_mode: 'light_mode',
112
+ dark_mode: 'dark_mode',
113
+ sun: 'light_mode',
114
+ moon: 'dark_mode',
115
+ user: 'person',
116
+ visibility: 'visibility',
117
+ visibility_off: 'visibility_off',
118
+ // Drawer/Navigation icons
119
+ download: 'download',
120
+ smart_button: 'smart_button',
121
+ text_fields: 'text_fields',
122
+ check_box: 'check_box',
123
+ toggle_on: 'toggle_on',
124
+ radio_button_checked: 'radio_button_checked',
125
+ arrow_drop_down_circle: 'arrow_drop_down_circle',
126
+ view_carousel: 'view_carousel',
127
+ grid_view: 'grid_view',
128
+ tab: 'tab',
129
+ notifications: 'notifications',
130
+ open_in_new: 'open_in_new',
131
+ hourglass_empty: 'hourglass_empty',
132
+ account_circle: 'account_circle',
133
+ fiber_manual_record: 'fiber_manual_record',
134
+ label: 'label',
135
+ emoji_emotions: 'emoji_emotions',
136
+ business: 'business',
137
+ input: 'input',
138
+ category: 'category',
139
+ widgets: 'widgets',
140
+ smart_toy: 'smart_toy',
141
+ notification_important: 'notification_important',
142
+ // Enterprise icons
143
+ folder_managed: 'folder_managed',
144
+ shield: 'shield',
145
+ apps: 'apps',
146
+ monitoring: 'monitoring',
147
+ // Common aliases
148
+ plus: 'add',
149
+ minus: 'remove'
150
+ };
151
+
152
+ export class MuIcon extends MuElement {
153
+ static baseClass = 'mu-icon';
154
+ static cssFile = 'icon';
155
+ static observedAttributes = ['name', 'size', 'svg', 'filled', 'font'];
156
+
157
+ render() {
158
+ const name = this.attr('name', 'info');
159
+ const size = this.attr('size', '24');
160
+ const forceFont = this.has('font'); // New: force font instead of SVG
161
+ const filled = this.has('filled');
162
+
163
+ // Accessibility: set role and aria-hidden (decorative by default)
164
+ this.setAttribute('role', 'img');
165
+ this.setAttribute('aria-hidden', 'true');
166
+
167
+ // Resolve aliases
168
+ const resolvedName = SYMBOL_NAMES[name] ? name : name;
169
+ const svgPath = SVG_ICONS[name] || SVG_ICONS[SYMBOL_NAMES[name]];
170
+
171
+ // SVG first (default) - eliminates 254KB font dependency for common icons
172
+ // Only fall back to font if: 1) force font attr, or 2) no SVG exists
173
+ if (!forceFont && svgPath) {
174
+ this.innerHTML = `
175
+ <svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
176
+ <path d="${svgPath}"></path>
177
+ </svg>
178
+ `;
179
+ return;
180
+ }
181
+
182
+ // Fall back to Material Symbols font (for rare icons not in SVG set)
183
+ const symbolName = SYMBOL_NAMES[name] || name;
184
+
185
+ // Log warning for unknown icon names (AI agent readiness)
186
+ if (!SYMBOL_NAMES[name] && !SVG_ICONS[name]) {
187
+ this.logError('UNKNOWN_ICON', `Icon name "${name}" not found in predefined icons. Using font fallback.`);
188
+ }
189
+
190
+ this.innerHTML = `<span class="material-symbols-outlined" aria-hidden="true">${symbolName}</span>`;
191
+
192
+ // Apply size and fill
193
+ const span = this.querySelector('span');
194
+ if (span) {
195
+ span.style.fontSize = `${size}px`;
196
+ if (filled) {
197
+ span.style.fontVariationSettings = "'FILL' 1";
198
+ }
199
+ }
200
+ }
201
+
202
+ update(attr, newValue, oldValue) {
203
+ this.render();
204
+ }
205
+ }
206
+
207
+ // Export icon names for reference
208
+ export const IconNames = Object.keys(SYMBOL_NAMES);
209
+ export const SvgIconNames = Object.keys(SVG_ICONS);
210
+
211
+ define('mu-icon', MuIcon);