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,142 @@
1
+ /**
2
+ * @fileoverview mu-input - MD3 Text Field Component
3
+ *
4
+ * Usage: <mu-input type="text" placeholder="Enter text" variant="filled"></mu-input>
5
+ *
6
+ * Features:
7
+ * - Native focus handling via CSS :focus-within
8
+ * - Animated underline indicator
9
+ * - Supports all input types
10
+ */
11
+
12
+ import { MuElement, define } from '../core/MuElement.js';
13
+ import { escapeHTML } from '../core/utils.js';
14
+
15
+ export class MuInput extends MuElement {
16
+ static baseClass = 'mu-input';
17
+ static cssFile = 'input';
18
+ static observedAttributes = ['type', 'placeholder', 'value', 'disabled', 'variant', 'size', 'label'];
19
+
20
+ /** @type {HTMLInputElement|null} */
21
+ #input = null;
22
+
23
+ render() {
24
+ // Idempotent: skip if already rendered
25
+ if (this.querySelector('.mu-input__field')) {
26
+ this.#input = this.querySelector('input');
27
+ this.#updateClasses();
28
+ return;
29
+ }
30
+
31
+ const type = this.attr('type', 'text');
32
+ const placeholder = this.attr('placeholder', '');
33
+ const label = this.attr('label', '');
34
+ const value = this.attr('value', '');
35
+
36
+ // Use label for floating label, fallback to placeholder
37
+ const labelText = label || placeholder;
38
+
39
+ // Never show native placeholder when using floating label
40
+ // Only show if explicitly no label is provided AND no placeholder
41
+ const showNativePlaceholder = !labelText;
42
+
43
+ // AGENT VALIDATION: Input must have a label
44
+ if (!labelText && !this.getAttribute('aria-label')) {
45
+ this.logError('A11Y_MISSING_LABEL', 'Input must have a label or aria-label attribute.');
46
+ }
47
+
48
+ // Generate unique ID for label-input association (accessibility)
49
+ const inputId = this.id || `mu-input-${Math.random().toString(36).substring(2, 9)}`;
50
+
51
+ // Escape user-provided attributes to prevent XSS
52
+ const safeLabelText = escapeHTML(labelText);
53
+ const safePlaceholder = escapeHTML(placeholder);
54
+ const safeValue = escapeHTML(value);
55
+
56
+ this.innerHTML = `
57
+ ${safeLabelText ? `<label class="mu-input__label" for="${inputId}">${safeLabelText}</label>` : ''}
58
+ <input
59
+ class="mu-input__field"
60
+ id="${inputId}"
61
+ type="${type}"
62
+ ${showNativePlaceholder ? `placeholder="${safePlaceholder}"` : ''}
63
+ ${!safeLabelText ? `aria-label="${safePlaceholder || 'Text input'}"` : ''}
64
+ value="${safeValue}"
65
+ ${this.has('disabled') ? 'disabled' : ''}
66
+ />
67
+ `;
68
+
69
+ this.#input = this.querySelector('input');
70
+ this.#updateClasses();
71
+ this.#updateValueState();
72
+
73
+ // Forward events
74
+ this.listen(this.#input, 'input', (e) => {
75
+ this.#updateValueState();
76
+ this.emit('mu-input', { value: e.target.value });
77
+ });
78
+
79
+ this.listen(this.#input, 'focus', () => {
80
+ this.emit('mu-focus');
81
+ });
82
+
83
+ this.listen(this.#input, 'blur', () => {
84
+ this.emit('mu-blur');
85
+ });
86
+ }
87
+
88
+ #updateValueState() {
89
+ if (this.#input?.value) {
90
+ this.classList.add('has-value');
91
+ } else {
92
+ this.classList.remove('has-value');
93
+ }
94
+ }
95
+
96
+ update(attr, newValue, oldValue) {
97
+ if (!this.#input) return;
98
+
99
+ switch (attr) {
100
+ case 'value':
101
+ this.#input.value = newValue ?? '';
102
+ break;
103
+ case 'placeholder':
104
+ this.#input.placeholder = newValue ?? '';
105
+ break;
106
+ case 'type':
107
+ this.#input.type = newValue ?? 'text';
108
+ break;
109
+ case 'disabled':
110
+ this.#input.disabled = this.has('disabled');
111
+ break;
112
+ }
113
+
114
+ this.#updateClasses();
115
+ }
116
+
117
+ #updateClasses() {
118
+ const variant = this.attr('variant', 'outlined');
119
+ const size = this.attr('size', 'md');
120
+
121
+ this.className = `mu-input mu-input--${variant} mu-input--${size}`;
122
+
123
+ if (this.has('disabled')) {
124
+ this.classList.add('is-disabled');
125
+ }
126
+ }
127
+
128
+ // Expose input value
129
+ get value() {
130
+ return this.#input?.value ?? '';
131
+ }
132
+
133
+ set value(v) {
134
+ if (this.#input) this.#input.value = v;
135
+ }
136
+
137
+ focus() {
138
+ this.#input?.focus();
139
+ }
140
+ }
141
+
142
+ define('mu-input', MuInput);
@@ -0,0 +1,129 @@
1
+ /**
2
+ * mu-layout.js - Material Design 3 Responsive Layout Container
3
+ *
4
+ * Main layout container that orchestrates drawer, content, and bottom nav.
5
+ * Provides responsive layout structure with proper spacing.
6
+ *
7
+ * LIGHT DOM: Uses Light DOM for styling consistency.
8
+ * Uses slot="..." attributes on children to distribute content.
9
+ */
10
+
11
+ import { MuElement, define } from '../core/MuElement.js';
12
+
13
+ export class MuLayout extends MuElement {
14
+ static get observedAttributes() {
15
+ return ['has-drawer', 'has-bottom-nav'];
16
+ }
17
+
18
+ static baseClass = 'mu-layout';
19
+ static cssFile = 'layout';
20
+
21
+ constructor() {
22
+ super();
23
+ }
24
+
25
+ connectedCallback() {
26
+ // Capture slotted children before render
27
+ if (!this._slotsCaptured) {
28
+ this._slots = {
29
+ header: this.querySelector('[slot="header"]'),
30
+ drawer: this.querySelector('[slot="drawer"]'),
31
+ footer: this.querySelector('[slot="footer"]'),
32
+ bottom: this.querySelector('[slot="bottom"]'),
33
+ default: Array.from(this.children).filter(c => !c.hasAttribute('slot'))
34
+ };
35
+ this._slotsCaptured = true;
36
+ }
37
+ super.connectedCallback();
38
+ this._setupScrollReset();
39
+ this._updateLayout();
40
+ }
41
+
42
+ disconnectedCallback() {
43
+ super.disconnectedCallback();
44
+ // Listener cleanup handled by MuElement AbortController
45
+ }
46
+
47
+ _setupScrollReset() {
48
+ // Reset content scroll when navigating to a new section
49
+ this.listen(window, 'hashchange', () => {
50
+ const mainContainer = this.querySelector('.mu-layout-main');
51
+ if (mainContainer) {
52
+ mainContainer.scrollTop = 0;
53
+ }
54
+ });
55
+ }
56
+
57
+ _updateLayout() {
58
+ const hasDrawer = this._slots.drawer !== null;
59
+ const hasBottomNav = this._slots.bottom !== null;
60
+
61
+ this.toggleAttribute('has-drawer', hasDrawer);
62
+ this.toggleAttribute('has-bottom-nav', hasBottomNav);
63
+ }
64
+
65
+ render() {
66
+ // Build layout structure with DOM manipulation
67
+ this.innerHTML = '';
68
+
69
+ // Layout wrapper
70
+ const wrapper = document.createElement('div');
71
+ wrapper.className = 'mu-layout-wrapper';
72
+
73
+ // Header
74
+ const headerContainer = document.createElement('header');
75
+ headerContainer.className = 'mu-layout-header';
76
+ if (this._slots.header) {
77
+ headerContainer.appendChild(this._slots.header);
78
+ }
79
+ wrapper.appendChild(headerContainer);
80
+
81
+ // Layout body (drawer + main)
82
+ const body = document.createElement('div');
83
+ body.className = 'mu-layout-body';
84
+
85
+ // Drawer container
86
+ const drawerContainer = document.createElement('aside');
87
+ drawerContainer.className = 'mu-layout-drawer';
88
+ if (this._slots.drawer) {
89
+ drawerContainer.appendChild(this._slots.drawer);
90
+ }
91
+ body.appendChild(drawerContainer);
92
+
93
+ // Main container
94
+ const mainContainer = document.createElement('div');
95
+ mainContainer.className = 'mu-layout-main';
96
+
97
+ const content = document.createElement('main');
98
+ content.className = 'mu-layout-content';
99
+ if (this._slots.default) {
100
+ this._slots.default.forEach(child => content.appendChild(child));
101
+ }
102
+ mainContainer.appendChild(content);
103
+ body.appendChild(mainContainer);
104
+
105
+ wrapper.appendChild(body);
106
+
107
+ // Footer
108
+ const footerContainer = document.createElement('footer');
109
+ footerContainer.className = 'mu-layout-footer';
110
+ if (this._slots.footer) {
111
+ footerContainer.appendChild(this._slots.footer);
112
+ }
113
+ wrapper.appendChild(footerContainer);
114
+
115
+ this.appendChild(wrapper);
116
+
117
+ // Bottom nav container (outside wrapper, fixed)
118
+ const bottomContainer = document.createElement('div');
119
+ bottomContainer.className = 'mu-layout-bottom';
120
+ if (this._slots.bottom) {
121
+ bottomContainer.appendChild(this._slots.bottom);
122
+ }
123
+ this.appendChild(bottomContainer);
124
+ }
125
+ }
126
+
127
+ if (!customElements.get('mu-layout')) {
128
+ customElements.define('mu-layout', MuLayout);
129
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @fileoverview mu-lazy - Lazy Loading Component
3
+ *
4
+ * Defers rendering until element is visible in viewport.
5
+ * Uses IntersectionObserver for efficient detection.
6
+ *
7
+ * Usage:
8
+ * <mu-lazy>
9
+ * <template>
10
+ * <heavy-component></heavy-component>
11
+ * </template>
12
+ * <div slot="placeholder">Loading...</div>
13
+ * </mu-lazy>
14
+ */
15
+
16
+ import { MuElement, define } from '../core/MuElement.js';
17
+
18
+ export class MuLazy extends MuElement {
19
+ static baseClass = 'mu-lazy';
20
+ static observedAttributes = ['root-margin', 'threshold'];
21
+
22
+ #observer = null;
23
+ #loaded = false;
24
+
25
+ connectedCallback() {
26
+ super.connectedCallback();
27
+
28
+ const rootMargin = this.attr('root-margin', '200px');
29
+ const threshold = parseFloat(this.attr('threshold', '0'));
30
+
31
+ this.#observer = new IntersectionObserver((entries) => {
32
+ if (entries[0].isIntersecting && !this.#loaded) {
33
+ this.#load();
34
+ }
35
+ }, {
36
+ rootMargin,
37
+ threshold
38
+ });
39
+
40
+ this.#observer.observe(this);
41
+ }
42
+
43
+ disconnectedCallback() {
44
+ super.disconnectedCallback();
45
+ this.#observer?.disconnect();
46
+ }
47
+
48
+ render() {
49
+ // Show placeholder initially
50
+ const placeholder = this.querySelector('[slot="placeholder"]');
51
+ if (placeholder) {
52
+ placeholder.style.display = 'block';
53
+ }
54
+
55
+ // Hide template
56
+ const template = this.querySelector('template');
57
+ if (template) {
58
+ template.style.display = 'none';
59
+ }
60
+ }
61
+
62
+ #load() {
63
+ this.#loaded = true;
64
+ this.#observer?.disconnect();
65
+
66
+ const template = this.querySelector('template');
67
+ const placeholder = this.querySelector('[slot="placeholder"]');
68
+
69
+ if (template) {
70
+ // Clone and append template content
71
+ const content = template.content.cloneNode(true);
72
+ this.appendChild(content);
73
+ template.remove();
74
+ }
75
+
76
+ if (placeholder) {
77
+ placeholder.remove();
78
+ }
79
+
80
+ this.emit('mu-loaded');
81
+ this.classList.add('is-loaded');
82
+ }
83
+
84
+ /**
85
+ * Force load immediately
86
+ */
87
+ load() {
88
+ if (!this.#loaded) {
89
+ this.#load();
90
+ }
91
+ }
92
+ }
93
+
94
+ define('mu-lazy', MuLazy);
@@ -0,0 +1,160 @@
1
+ /**
2
+ * @fileoverview mu-modal - MD3 Dialog Component (SOTA Native Dialog)
3
+ * Uses native <dialog> element with showModal() for proper top-layer,
4
+ * focus trapping, ESC handling, and backdrop - all built-in.
5
+ *
6
+ * MD3 Reference: https://m3.material.io/components/dialogs
7
+ */
8
+
9
+ import { MuElement, define } from '../core/MuElement.js';
10
+ import { afterPaint } from '../core/scheduler.js';
11
+
12
+ export class MuModal extends MuElement {
13
+ static baseClass = 'mu-modal';
14
+ static cssFile = 'dialog';
15
+ static observedAttributes = ['open', 'size'];
16
+
17
+ /** @type {HTMLDialogElement|null} */
18
+ #dialog = null;
19
+
20
+ connectedCallback() {
21
+ // Store user content only once, before first render
22
+ if (!this.hasAttribute('data-rendered')) {
23
+ this._userContent = this.innerHTML;
24
+ this.setAttribute('data-rendered', 'true');
25
+ }
26
+
27
+ super.connectedCallback();
28
+
29
+ // CRITICAL: Always setup listeners after super.connectedCallback()
30
+ // because it resets the AbortController. The render() creates DOM,
31
+ // but listeners must be attached here to survive disconnect/reconnect.
32
+ this.#setupListeners();
33
+ }
34
+
35
+ render() {
36
+ // Idempotent: check if already rendered via DOM structure
37
+ if (this.querySelector('dialog')) return;
38
+
39
+ const size = this.attr('size', 'md');
40
+ const content = this._userContent || '';
41
+
42
+ this.innerHTML = `
43
+ <dialog class="mu-modal__dialog mu-modal--${size}">
44
+ <button class="mu-modal__close" aria-label="Close">✕</button>
45
+ <div class="mu-modal__body">${content}</div>
46
+ </dialog>
47
+ `;
48
+
49
+ this.#dialog = this.querySelector('dialog');
50
+ }
51
+
52
+ /**
53
+ * Setup all event listeners. Called after every connectedCallback
54
+ * to ensure listeners survive DOM disconnect/reconnect cycles.
55
+ */
56
+ #setupListeners() {
57
+ this.#dialog = this.querySelector('dialog');
58
+ if (!this.#dialog) return;
59
+
60
+ // Native dialog 'close' event (fires on ESC, form[method=dialog], or .close())
61
+ this.listen(this.#dialog, 'close', () => {
62
+ this.removeAttribute('open');
63
+ this.classList.remove('is-open', 'is-visible');
64
+ document.body.style.overflow = '';
65
+ this.emit('mu-close');
66
+ });
67
+
68
+ // ESC key triggers 'cancel' event on dialog
69
+ this.listen(this.#dialog, 'cancel', (e) => {
70
+ e.preventDefault(); // Prevent default close to control animation
71
+ this.close();
72
+ });
73
+
74
+ // Click on backdrop (::backdrop pseudo-element triggers click on dialog)
75
+ this.listen(this.#dialog, 'click', (e) => {
76
+ // Only close if clicking the dialog element itself (backdrop area)
77
+ // not its children
78
+ if (e.target === this.#dialog) {
79
+ this.close();
80
+ }
81
+ });
82
+
83
+ // Close button - MD3 standard X button in top-right
84
+ const closeBtn = this.querySelector('.mu-modal__close');
85
+ if (closeBtn) {
86
+ this.listen(closeBtn, 'click', () => {
87
+ this.close();
88
+ });
89
+ }
90
+ }
91
+
92
+ update(attr, newValue, oldValue) {
93
+ if (attr === 'open') {
94
+ if (newValue !== null) {
95
+ this.#showDialog();
96
+ }
97
+ }
98
+ }
99
+
100
+ #showDialog() {
101
+ if (!this.#dialog || this.#dialog.open) return;
102
+
103
+ this.classList.add('is-open');
104
+ this.#dialog.showModal(); // Native top-layer, focus trap, backdrop!
105
+ document.body.style.overflow = 'hidden';
106
+
107
+ // Trigger animation - MD3 requires emphasized-decelerate for enter
108
+ afterPaint().then(() => this.classList.add('is-visible'));
109
+ }
110
+
111
+ /**
112
+ * Open the modal dialog (public API)
113
+ */
114
+ open() {
115
+ this.setAttribute('open', '');
116
+ }
117
+
118
+ /**
119
+ * Close the modal dialog with animation (public API)
120
+ */
121
+ close() {
122
+ if (!this.#dialog) return;
123
+
124
+ // MD3: emphasized-accelerate for exit
125
+ this.classList.remove('is-visible');
126
+
127
+ // SOTA 2026: Use transitionend instead of setTimeout
128
+ // In test environments (JSDOM/linkedom), transitionend won't fire, so use a flag
129
+ let cleaned = false;
130
+ const cleanup = () => {
131
+ if (cleaned) return;
132
+ cleaned = true;
133
+ if (this.#dialog && this.#dialog.open) {
134
+ this.#dialog.close();
135
+ }
136
+ this.removeAttribute('open');
137
+ this.classList.remove('is-open');
138
+ document.body.style.overflow = '';
139
+ this.emit('mu-close');
140
+ };
141
+
142
+ // Listen for transition end
143
+ const dialog = this.#dialog;
144
+ const onTransitionEnd = (e) => {
145
+ if (e.target === dialog) {
146
+ dialog.removeEventListener('transitionend', onTransitionEnd);
147
+ cleanup();
148
+ }
149
+ };
150
+ dialog.addEventListener('transitionend', onTransitionEnd);
151
+
152
+ // Fallback: cleanup after expected transition time (200ms matches CSS)
153
+ this.setTimeout(() => {
154
+ dialog.removeEventListener('transitionend', onTransitionEnd);
155
+ cleanup();
156
+ }, 200);
157
+ }
158
+ }
159
+
160
+ define('mu-modal', MuModal);
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @fileoverview mu-navbar - Navigation Bar Component
3
+ *
4
+ * Usage:
5
+ * <mu-navbar>
6
+ * <mu-navbar-brand>Logo</mu-navbar-brand>
7
+ * <mu-navbar-links>
8
+ * <a href="/">Home</a>
9
+ * <a href="/about">About</a>
10
+ * </mu-navbar-links>
11
+ * <mu-navbar-actions>
12
+ * <mu-theme-toggle></mu-theme-toggle>
13
+ * </mu-navbar-actions>
14
+ * </mu-navbar>
15
+ */
16
+
17
+ import { MuElement, define } from '../core/MuElement.js';
18
+
19
+ export class MuNavbar extends MuElement {
20
+ static baseClass = 'mu-navbar';
21
+ static cssFile = 'navbar';
22
+ static observedAttributes = ['sticky', 'variant'];
23
+
24
+ render() {
25
+ this.style.display = 'flex';
26
+ this.style.alignItems = 'center';
27
+ this.style.justifyContent = 'space-between';
28
+ this.style.padding = '0 var(--md-sys-spacing-md, 16px)';
29
+ this.style.height = '64px';
30
+ this.style.background = 'var(--md-sys-color-surface-container)';
31
+ this.style.borderBottom = '1px solid var(--md-sys-color-outline-variant)';
32
+
33
+ if (this.has('sticky')) {
34
+ this.style.position = 'sticky';
35
+ this.style.top = '0';
36
+ this.style.zIndex = '100';
37
+ }
38
+ }
39
+ }
40
+
41
+ export class MuNavbarBrand extends MuElement {
42
+ static baseClass = 'mu-navbar__brand';
43
+
44
+ render() {
45
+ this.style.fontWeight = '600';
46
+ this.style.fontSize = '1.25rem';
47
+ }
48
+ }
49
+
50
+ export class MuNavbarLinks extends MuElement {
51
+ static baseClass = 'mu-navbar__links';
52
+
53
+ render() {
54
+ // All styles handled by CSS in components.css
55
+ }
56
+ }
57
+
58
+ export class MuNavbarActions extends MuElement {
59
+ static baseClass = 'mu-navbar__actions';
60
+
61
+ render() {
62
+ this.style.display = 'flex';
63
+ this.style.gap = 'var(--md-sys-spacing-sm, 8px)';
64
+ this.style.alignItems = 'center';
65
+ }
66
+ }
67
+
68
+ define('mu-navbar', MuNavbar);
69
+ define('mu-navbar-brand', MuNavbarBrand);
70
+ define('mu-navbar-links', MuNavbarLinks);
71
+ define('mu-navbar-actions', MuNavbarActions);
@@ -0,0 +1,77 @@
1
+ /**
2
+ * mu-page - Self-contained page component
3
+ *
4
+ * Features:
5
+ * - Declares route and title
6
+ * - Declares dependencies (for auto-bundling)
7
+ * - Contains template HTML
8
+ *
9
+ * Usage in pages/*.html:
10
+ *
11
+ * <mu-page route="buttons" title="Buttons">
12
+ * <script type="x-dependencies">
13
+ * mu-button
14
+ * mu-tabs
15
+ * </script>
16
+ *
17
+ * <template>
18
+ * <h1>Buttons</h1>
19
+ * ...
20
+ * </template>
21
+ * </mu-page>
22
+ *
23
+ * @agent-pattern
24
+ * When creating a new page, create a single file in app/pages/
25
+ * with this structure. The build system will auto-generate route bundles.
26
+ */
27
+
28
+ import { MuElement, define } from '../core/MuElement.js';
29
+
30
+ class MuPage extends MuElement {
31
+ static baseClass = 'mu-page';
32
+ static observedAttributes = ['route', 'title'];
33
+
34
+ get route() {
35
+ return this.attr('route', '');
36
+ }
37
+
38
+ get pageTitle() {
39
+ return this.attr('title', '');
40
+ }
41
+
42
+ get dependencies() {
43
+ const script = this.querySelector('script[type="x-dependencies"]');
44
+ if (!script) return [];
45
+
46
+ return script.textContent
47
+ .split(/[\n,]/)
48
+ .map(d => d.trim())
49
+ .filter(d => d && d.startsWith('mu-'));
50
+ }
51
+
52
+ connectedCallback() {
53
+ super.connectedCallback();
54
+
55
+ // If rendered directly (not via router), render template
56
+ if (this.querySelector('template')) {
57
+ this.render();
58
+ }
59
+ }
60
+
61
+ render() {
62
+ const template = this.querySelector('template');
63
+ if (template) {
64
+ // Clone template content
65
+ const content = template.content.cloneNode(true);
66
+
67
+ // Clear and append
68
+ const script = this.querySelector('script[type="x-dependencies"]');
69
+ this.innerHTML = '';
70
+ if (script) this.appendChild(script); // Keep deps for debugging
71
+ this.appendChild(content);
72
+ }
73
+ }
74
+ }
75
+
76
+ define('mu-page', MuPage);
77
+ export { MuPage };