microui-wc 0.1.0 โ†’ 0.1.2

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 (343) hide show
  1. package/AGENTS.md +71 -71
  2. package/CHANGELOG.md +1 -1
  3. package/README.md +14 -9
  4. package/dist/AGENTS.md +116 -116
  5. package/dist/README.md +21 -16
  6. package/dist/components.css +1 -1
  7. package/dist/microui.css +1 -1
  8. package/dist/microui.esm.js.map +1 -1
  9. package/dist/microui.min.js.map +1 -1
  10. package/dist/styles/components/switch.css +1 -1
  11. package/docs/getting-started.md +3 -3
  12. package/package.json +38 -10
  13. package/src/components/mu-schema-form.js +1 -1
  14. package/src/styles/components/switch.css +7 -8
  15. package/src/styles/components.css +6 -6
  16. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
  17. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -33
  18. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  19. package/.github/workflows/ci.yml +0 -42
  20. package/.github/workflows/deploy-pages.yml +0 -112
  21. package/CODE_OF_CONDUCT.md +0 -59
  22. package/CONTRIBUTING.md +0 -156
  23. package/SECURITY.md +0 -58
  24. package/app/.generated/routes/alerts.js +0 -8
  25. package/app/.generated/routes/avatars.js +0 -8
  26. package/app/.generated/routes/badges.js +0 -8
  27. package/app/.generated/routes/buttons.js +0 -10
  28. package/app/.generated/routes/cards.js +0 -10
  29. package/app/.generated/routes/checkboxes.js +0 -9
  30. package/app/.generated/routes/chips.js +0 -8
  31. package/app/.generated/routes/dropdowns.js +0 -9
  32. package/app/.generated/routes/home.js +0 -7
  33. package/app/.generated/routes/icons.js +0 -9
  34. package/app/.generated/routes/inputs.js +0 -10
  35. package/app/.generated/routes/installation.js +0 -7
  36. package/app/.generated/routes/layout.js +0 -9
  37. package/app/.generated/routes/modals.js +0 -9
  38. package/app/.generated/routes/navbar.js +0 -7
  39. package/app/.generated/routes/progress.js +0 -9
  40. package/app/.generated/routes/radios.js +0 -9
  41. package/app/.generated/routes/switches.js +0 -9
  42. package/app/.generated/routes/tabs.js +0 -8
  43. package/app/.generated/routes/toasts.js +0 -9
  44. package/app/index.html +0 -67
  45. package/app/pages/alerts.html +0 -23
  46. package/app/pages/avatars.html +0 -22
  47. package/app/pages/badges.html +0 -22
  48. package/app/pages/buttons.html +0 -71
  49. package/app/pages/cards.html +0 -54
  50. package/app/pages/checkboxes.html +0 -39
  51. package/app/pages/chips.html +0 -23
  52. package/app/pages/dropdowns.html +0 -41
  53. package/app/pages/home.html +0 -59
  54. package/app/pages/icons.html +0 -29
  55. package/app/pages/inputs.html +0 -66
  56. package/app/pages/installation.html +0 -34
  57. package/app/pages/layout.html +0 -30
  58. package/app/pages/modals.html +0 -21
  59. package/app/pages/navbar.html +0 -22
  60. package/app/pages/progress.html +0 -35
  61. package/app/pages/radios.html +0 -40
  62. package/app/pages/switches.html +0 -39
  63. package/app/pages/tabs.html +0 -30
  64. package/app/pages/toasts.html +0 -22
  65. package/app-dist/index.html +0 -67
  66. package/app-dist/pages/alerts.html +0 -23
  67. package/app-dist/pages/avatars.html +0 -22
  68. package/app-dist/pages/badges.html +0 -22
  69. package/app-dist/pages/buttons.html +0 -71
  70. package/app-dist/pages/cards.html +0 -54
  71. package/app-dist/pages/checkboxes.html +0 -39
  72. package/app-dist/pages/chips.html +0 -23
  73. package/app-dist/pages/dropdowns.html +0 -41
  74. package/app-dist/pages/home.html +0 -59
  75. package/app-dist/pages/icons.html +0 -29
  76. package/app-dist/pages/inputs.html +0 -66
  77. package/app-dist/pages/installation.html +0 -34
  78. package/app-dist/pages/layout.html +0 -30
  79. package/app-dist/pages/modals.html +0 -21
  80. package/app-dist/pages/navbar.html +0 -22
  81. package/app-dist/pages/progress.html +0 -35
  82. package/app-dist/pages/radios.html +0 -40
  83. package/app-dist/pages/switches.html +0 -39
  84. package/app-dist/pages/tabs.html +0 -30
  85. package/app-dist/pages/toasts.html +0 -22
  86. package/app-dist/pages.json +0 -217
  87. package/app-dist/routes/alerts.js +0 -5
  88. package/app-dist/routes/avatars.js +0 -1
  89. package/app-dist/routes/badges.js +0 -1
  90. package/app-dist/routes/buttons.js +0 -1
  91. package/app-dist/routes/cards.js +0 -1
  92. package/app-dist/routes/checkboxes.js +0 -9
  93. package/app-dist/routes/chips.js +0 -4
  94. package/app-dist/routes/chunk-019e5e2f.js +0 -5
  95. package/app-dist/routes/chunk-0m4j19yd.js +0 -2
  96. package/app-dist/routes/chunk-0tmmp5q0.js +0 -1
  97. package/app-dist/routes/chunk-10xn709r.js +0 -1
  98. package/app-dist/routes/chunk-15m2qcda.js +0 -2
  99. package/app-dist/routes/chunk-1bh8g23n.js +0 -1
  100. package/app-dist/routes/chunk-1vg0v937.js +0 -1
  101. package/app-dist/routes/chunk-1zvcgy3j.js +0 -1
  102. package/app-dist/routes/chunk-2afb0861.js +0 -1
  103. package/app-dist/routes/chunk-2c6ttpzt.js +0 -5
  104. package/app-dist/routes/chunk-3dy30fhs.js +0 -1
  105. package/app-dist/routes/chunk-426dnces.js +0 -13
  106. package/app-dist/routes/chunk-44kgxery.js +0 -1
  107. package/app-dist/routes/chunk-47fdnejd.js +0 -33
  108. package/app-dist/routes/chunk-49a6t2vq.js +0 -1
  109. package/app-dist/routes/chunk-4fe1rm5b.js +0 -1
  110. package/app-dist/routes/chunk-4ggmvkta.js +0 -33
  111. package/app-dist/routes/chunk-4vkz81q7.js +0 -33
  112. package/app-dist/routes/chunk-4w4tmj8f.js +0 -31
  113. package/app-dist/routes/chunk-532s62kr.js +0 -31
  114. package/app-dist/routes/chunk-5hm3bssy.js +0 -33
  115. package/app-dist/routes/chunk-5vrh24hc.js +0 -1
  116. package/app-dist/routes/chunk-61pcg25a.js +0 -1
  117. package/app-dist/routes/chunk-6nfhygvf.js +0 -1
  118. package/app-dist/routes/chunk-700e7je6.js +0 -33
  119. package/app-dist/routes/chunk-7fsn17kg.js +0 -1
  120. package/app-dist/routes/chunk-7k789b32.js +0 -1
  121. package/app-dist/routes/chunk-7r46q0ys.js +0 -36
  122. package/app-dist/routes/chunk-86fmc1fr.js +0 -5
  123. package/app-dist/routes/chunk-8qth37vw.js +0 -1
  124. package/app-dist/routes/chunk-924wv8n0.js +0 -1
  125. package/app-dist/routes/chunk-9mbhgxk9.js +0 -1
  126. package/app-dist/routes/chunk-a216hyd9.js +0 -1
  127. package/app-dist/routes/chunk-akzxykh9.js +0 -33
  128. package/app-dist/routes/chunk-b3dcvy8c.js +0 -1
  129. package/app-dist/routes/chunk-b74zahz5.js +0 -31
  130. package/app-dist/routes/chunk-bftj53p2.js +0 -5
  131. package/app-dist/routes/chunk-c01hnz3e.js +0 -1
  132. package/app-dist/routes/chunk-d8pvv5km.js +0 -1
  133. package/app-dist/routes/chunk-dev0aezr.js +0 -2
  134. package/app-dist/routes/chunk-dh6vnv0e.js +0 -1
  135. package/app-dist/routes/chunk-dn2cbpva.js +0 -36
  136. package/app-dist/routes/chunk-dvn0my90.js +0 -1
  137. package/app-dist/routes/chunk-dvq8mnve.js +0 -36
  138. package/app-dist/routes/chunk-e8c2gc4d.js +0 -5
  139. package/app-dist/routes/chunk-ejf9ak2x.js +0 -1
  140. package/app-dist/routes/chunk-f083m55s.js +0 -1
  141. package/app-dist/routes/chunk-fnrj28s1.js +0 -31
  142. package/app-dist/routes/chunk-fvg3yjdp.js +0 -31
  143. package/app-dist/routes/chunk-g7k381n1.js +0 -1
  144. package/app-dist/routes/chunk-h01kq2ae.js +0 -13
  145. package/app-dist/routes/chunk-h4dk761v.js +0 -5
  146. package/app-dist/routes/chunk-hmx91z2x.js +0 -5
  147. package/app-dist/routes/chunk-hxbg4m42.js +0 -36
  148. package/app-dist/routes/chunk-jbjnfp2b.js +0 -2
  149. package/app-dist/routes/chunk-jxtz5vv6.js +0 -36
  150. package/app-dist/routes/chunk-jxzcs0ey.js +0 -36
  151. package/app-dist/routes/chunk-kt7wwhcx.js +0 -1
  152. package/app-dist/routes/chunk-kzptszyc.js +0 -33
  153. package/app-dist/routes/chunk-mhgca4w4.js +0 -2
  154. package/app-dist/routes/chunk-mhswxa20.js +0 -1
  155. package/app-dist/routes/chunk-n8zfeex6.js +0 -1
  156. package/app-dist/routes/chunk-pee47b2r.js +0 -1
  157. package/app-dist/routes/chunk-pesmw829.js +0 -1
  158. package/app-dist/routes/chunk-pgc4c6f3.js +0 -36
  159. package/app-dist/routes/chunk-q8egegm1.js +0 -1
  160. package/app-dist/routes/chunk-q9mn2qyq.js +0 -36
  161. package/app-dist/routes/chunk-qh0rtaf3.js +0 -5
  162. package/app-dist/routes/chunk-qqhmk6ye.js +0 -2
  163. package/app-dist/routes/chunk-qrxygmf7.js +0 -33
  164. package/app-dist/routes/chunk-r46yzksx.js +0 -36
  165. package/app-dist/routes/chunk-rgpbw2w0.js +0 -5
  166. package/app-dist/routes/chunk-rnpzv3d8.js +0 -2
  167. package/app-dist/routes/chunk-s5v8cv05.js +0 -2
  168. package/app-dist/routes/chunk-sbwn5bpc.js +0 -1
  169. package/app-dist/routes/chunk-sqbg8jbt.js +0 -33
  170. package/app-dist/routes/chunk-sv8dqnf7.js +0 -1
  171. package/app-dist/routes/chunk-t67sw3za.js +0 -1
  172. package/app-dist/routes/chunk-tjdpqwdf.js +0 -31
  173. package/app-dist/routes/chunk-tq2mfghg.js +0 -1
  174. package/app-dist/routes/chunk-ttn10vt6.js +0 -1
  175. package/app-dist/routes/chunk-v2hzpjxr.js +0 -1
  176. package/app-dist/routes/chunk-wfjjkw9y.js +0 -1
  177. package/app-dist/routes/chunk-wt8cxzmf.js +0 -31
  178. package/app-dist/routes/chunk-x45d372k.js +0 -5
  179. package/app-dist/routes/chunk-y3wsazkt.js +0 -1
  180. package/app-dist/routes/chunk-y7pmgc7t.js +0 -33
  181. package/app-dist/routes/chunk-zefdt2q3.js +0 -31
  182. package/app-dist/routes/dropdowns.js +0 -6
  183. package/app-dist/routes/home.js +0 -1
  184. package/app-dist/routes/icons.js +0 -1
  185. package/app-dist/routes/inputs.js +0 -12
  186. package/app-dist/routes/installation.js +0 -1
  187. package/app-dist/routes/layout.js +0 -1
  188. package/app-dist/routes/modals.js +0 -7
  189. package/app-dist/routes/navbar.js +0 -1
  190. package/app-dist/routes/progress.js +0 -1
  191. package/app-dist/routes/radios.js +0 -6
  192. package/app-dist/routes/switches.js +0 -6
  193. package/app-dist/routes/tabs.js +0 -1
  194. package/app-dist/routes/toasts.js +0 -16
  195. package/assets/fonts/material-symbols-mini.woff2 +0 -0
  196. package/assets/fonts/material-symbols.woff2 +0 -0
  197. package/assets/fonts/roboto-400.woff2 +0 -0
  198. package/assets/fonts/roboto-500.woff2 +0 -0
  199. package/assets/fonts/roboto-700.woff2 +0 -0
  200. package/assets/logo-banner-400.jpg +0 -0
  201. package/assets/logo-banner-400.webp +0 -0
  202. package/assets/logo-banner-800.webp +0 -0
  203. package/assets/logo-banner.jpg +0 -0
  204. package/assets/logo-icon-64.jpg +0 -0
  205. package/assets/logo-icon-64.webp +0 -0
  206. package/assets/logo-icon.jpg +0 -0
  207. package/assets/logo-square.jpg +0 -0
  208. package/bun.lock +0 -312
  209. package/bunfig.toml +0 -4
  210. package/custom-elements.json +0 -1916
  211. package/demo/api/sample-data.json +0 -38
  212. package/demo/content/alerts.html +0 -115
  213. package/demo/content/avatars.html +0 -70
  214. package/demo/content/badges.html +0 -65
  215. package/demo/content/buttons.html +0 -188
  216. package/demo/content/callouts.html +0 -91
  217. package/demo/content/cards.html +0 -121
  218. package/demo/content/checkboxes.html +0 -178
  219. package/demo/content/chips.html +0 -67
  220. package/demo/content/codeblocks.html +0 -101
  221. package/demo/content/confirms.html +0 -115
  222. package/demo/content/datatables.html +0 -149
  223. package/demo/content/dividers.html +0 -119
  224. package/demo/content/dropdowns.html +0 -89
  225. package/demo/content/enterprise.html +0 -252
  226. package/demo/content/home.html +0 -149
  227. package/demo/content/icons.html +0 -89
  228. package/demo/content/inputs.html +0 -135
  229. package/demo/content/installation.html +0 -16
  230. package/demo/content/layout.html +0 -136
  231. package/demo/content/modals.html +0 -141
  232. package/demo/content/navbar.html +0 -70
  233. package/demo/content/progress.html +0 -119
  234. package/demo/content/radios.html +0 -88
  235. package/demo/content/skeletons.html +0 -109
  236. package/demo/content/spinners.html +0 -96
  237. package/demo/content/switches.html +0 -84
  238. package/demo/content/tables.html +0 -124
  239. package/demo/content/tabs.html +0 -85
  240. package/demo/content/toasts.html +0 -116
  241. package/demo/content/tooltips.html +0 -107
  242. package/demo/content/virtual-lists.html +0 -233
  243. package/demo/favicon.ico +0 -0
  244. package/demo/favicon.png +0 -0
  245. package/demo/full.html +0 -52
  246. package/demo/iife.html +0 -46
  247. package/demo/manifest.json +0 -34
  248. package/demo/pages/datatable-demo.html +0 -237
  249. package/demo/pages/prompt-ui-demo.html +0 -218
  250. package/demo/pages/responsive-demo.html +0 -122
  251. package/demo/pages/schema-form-demo.html +0 -270
  252. package/demo/robots.txt +0 -6
  253. package/demo/shell.html +0 -712
  254. package/demo/sw.js +0 -387
  255. package/lighthouse-audit.mjs +0 -113
  256. package/scripts/analyze-components.js +0 -105
  257. package/scripts/build-app.js +0 -193
  258. package/scripts/build-framework.js +0 -444
  259. package/scripts/build-utils.js +0 -101
  260. package/scripts/test-isolated.js +0 -151
  261. package/server.js +0 -256
  262. package/tests/agents/agent-integration.test.js +0 -76
  263. package/tests/benchmark.html +0 -296
  264. package/tests/build/scan-components.test.js +0 -173
  265. package/tests/components/all-components.test.js +0 -245
  266. package/tests/components/all-missing-components.test.js +0 -574
  267. package/tests/components/mu-alert.test.js +0 -113
  268. package/tests/components/mu-avatar.test.js +0 -148
  269. package/tests/components/mu-badge.test.js +0 -92
  270. package/tests/components/mu-button.test.js +0 -112
  271. package/tests/components/mu-card.test.js +0 -89
  272. package/tests/components/mu-checkbox.test.js +0 -158
  273. package/tests/components/mu-chip.test.js +0 -118
  274. package/tests/components/mu-container.test.js +0 -120
  275. package/tests/components/mu-divider.test.js +0 -98
  276. package/tests/components/mu-drawer-item.test.js +0 -199
  277. package/tests/components/mu-drawer.test.js +0 -96
  278. package/tests/components/mu-dropdown.test.js +0 -125
  279. package/tests/components/mu-form.test.js +0 -138
  280. package/tests/components/mu-grid.test.js +0 -135
  281. package/tests/components/mu-icon.test.js +0 -110
  282. package/tests/components/mu-input.test.js +0 -131
  283. package/tests/components/mu-lazy.test.js +0 -103
  284. package/tests/components/mu-modal.test.js +0 -275
  285. package/tests/components/mu-navbar.test.js +0 -101
  286. package/tests/components/mu-progress.test.js +0 -115
  287. package/tests/components/mu-radio.test.js +0 -114
  288. package/tests/components/mu-repeat.test.js +0 -106
  289. package/tests/components/mu-sidebar.test.js +0 -126
  290. package/tests/components/mu-skeleton.test.js +0 -162
  291. package/tests/components/mu-stack.test.js +0 -143
  292. package/tests/components/mu-switch.test.js +0 -292
  293. package/tests/components/mu-table.test.js +0 -124
  294. package/tests/components/mu-tabs.test.js +0 -104
  295. package/tests/components/mu-textarea.test.js +0 -115
  296. package/tests/components/mu-toast.test.js +0 -321
  297. package/tests/components/mu-tooltip.test.js +0 -133
  298. package/tests/components/mu-virtual-list.test.js +0 -109
  299. package/tests/core/MuElement.test.js +0 -120
  300. package/tests/core/agent-api.test.js +0 -125
  301. package/tests/core/all-core-modules.test.js +0 -442
  302. package/tests/core/bus.test.js +0 -364
  303. package/tests/core/component-schema.test.js +0 -160
  304. package/tests/core/feature-registry.test.js +0 -198
  305. package/tests/core/form-state.test.js +0 -167
  306. package/tests/core/http.test.js +0 -119
  307. package/tests/core/keyboard.test.js +0 -319
  308. package/tests/core/layers.test.js +0 -129
  309. package/tests/core/namespaced-stores.test.js +0 -114
  310. package/tests/core/render.test.js +0 -121
  311. package/tests/core/ripple.test.js +0 -131
  312. package/tests/core/router.test.js +0 -89
  313. package/tests/core/scheduler.test.js +0 -121
  314. package/tests/core/signals.test.js +0 -128
  315. package/tests/core/store.test.js +0 -171
  316. package/tests/core/transitions.test.js +0 -82
  317. package/tests/e2e/accessibility-harness.html +0 -58
  318. package/tests/e2e/accessibility.test.js +0 -401
  319. package/tests/e2e/agent-features.test.js +0 -372
  320. package/tests/e2e/card-spacing.test.js +0 -287
  321. package/tests/e2e/components.test.js +0 -439
  322. package/tests/e2e/demo-routes.test.js +0 -478
  323. package/tests/e2e/layout-css-fallback.test.js +0 -334
  324. package/tests/e2e/mu-alert.e2e.test.js +0 -111
  325. package/tests/e2e/mu-checkbox.test.js +0 -489
  326. package/tests/e2e/mu-chip.test.js +0 -347
  327. package/tests/e2e/mu-form.test.js +0 -499
  328. package/tests/e2e/mu-icon.test.js +0 -114
  329. package/tests/e2e/mu-radio.test.js +0 -113
  330. package/tests/e2e/mu-skeleton.test.js +0 -140
  331. package/tests/e2e/mu-switch.test.js +0 -415
  332. package/tests/e2e/mu-tabs.test.js +0 -494
  333. package/tests/e2e/mu-textarea.test.js +0 -242
  334. package/tests/e2e/mu-virtual-list.test.js +0 -427
  335. package/tests/e2e/perf-memory.test.js +0 -161
  336. package/tests/e2e/puppeteer-helper.js +0 -137
  337. package/tests/e2e/puppeteer.test.js +0 -226
  338. package/tests/e2e/pwa.test.js +0 -261
  339. package/tests/e2e/test-harness.html +0 -319
  340. package/tests/manual/test-components.html +0 -120
  341. package/tests/memory-test.html +0 -309
  342. package/tests/setup-dom.js +0 -93
  343. package/tests/visual-test.html +0 -301
@@ -1,101 +0,0 @@
1
- /**
2
- * @fileoverview Build utilities for microUI
3
- *
4
- * Contains reusable functions for the build process,
5
- * particularly for automatic component detection.
6
- */
7
-
8
- /**
9
- * Scan HTML content for mu-* components within page divs.
10
- * Extracts component names from each page section.
11
- *
12
- * @param {string} htmlContent - Full HTML content to scan
13
- * @returns {Object<string, string[]>} Map of pageId -> component names
14
- *
15
- * @example
16
- * const html = '<div id="page-home"><mu-button>Click</mu-button></div>';
17
- * const result = scanPageComponents(html);
18
- * // { home: ['mu-button'] }
19
- */
20
- export function scanPageComponents(htmlContent) {
21
- const pages = {};
22
-
23
- // Match page divs: <div id="page-xxx">...</div>
24
- // Use non-greedy matching and look ahead for next page or end
25
- const pageRegex = /<div\s+id="page-(\w+)"[^>]*>([\s\S]*?)(?=<div\s+id="page-|\s*<\/mu-layout|\s*<footer|\s*$)/gi;
26
-
27
- let match;
28
- while ((match = pageRegex.exec(htmlContent)) !== null) {
29
- const pageId = match[1];
30
- const pageContent = match[2];
31
-
32
- // Extract all mu-* tags (opening tags only)
33
- const components = new Set();
34
- const tagRegex = /<(mu-[\w-]+)/gi;
35
- let tagMatch;
36
- while ((tagMatch = tagRegex.exec(pageContent)) !== null) {
37
- // Normalize to lowercase
38
- components.add(tagMatch[1].toLowerCase());
39
- }
40
-
41
- if (components.size > 0) {
42
- pages[pageId] = [...components].sort();
43
- }
44
- }
45
-
46
- return pages;
47
- }
48
-
49
- /**
50
- * Map component names to their route file names.
51
- * Some components share routes (e.g., mu-tab is in tabs route).
52
- *
53
- * @param {string[]} components - Array of component names
54
- * @returns {string[]} Array of route names to load
55
- */
56
- export function componentsToRoutes(components) {
57
- // Component -> route mapping (most are 1:1 with pluralization)
58
- const componentRouteMap = {
59
- 'mu-tab': 'tabs',
60
- 'mu-tabs': 'tabs',
61
- 'mu-button': 'buttons',
62
- 'mu-input': 'inputs',
63
- 'mu-textarea': 'inputs',
64
- 'mu-checkbox': 'checkboxes',
65
- 'mu-switch': 'switches',
66
- 'mu-radio': 'radios',
67
- 'mu-dropdown': 'dropdowns',
68
- 'mu-card': 'cards',
69
- 'mu-stack': 'layout',
70
- 'mu-grid': 'layout',
71
- 'mu-alert': 'alerts',
72
- 'mu-toast': 'toasts',
73
- 'mu-modal': 'modals',
74
- 'mu-progress': 'progress',
75
- 'mu-spinner': 'progress',
76
- 'mu-avatar': 'avatars',
77
- 'mu-badge': 'badges',
78
- 'mu-chip': 'chips',
79
- 'mu-icon': 'icons',
80
- 'mu-navbar': 'navbar',
81
- 'mu-example': 'tabs', // part of tabs route
82
- 'mu-code': 'tabs', // part of tabs route
83
- 'mu-api-table': 'tabs', // part of tabs route
84
- // Shell components (always loaded)
85
- 'mu-layout': 'shell-critical',
86
- 'mu-drawer': 'shell-critical',
87
- 'mu-drawer-item': 'shell-critical',
88
- 'mu-theme-toggle': 'shell-deferred',
89
- 'mu-bottom-nav': 'shell-deferred',
90
- };
91
-
92
- const routes = new Set();
93
- for (const comp of components) {
94
- const route = componentRouteMap[comp];
95
- if (route) {
96
- routes.add(route);
97
- }
98
- }
99
-
100
- return [...routes].sort();
101
- }
@@ -1,151 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * @fileoverview Isolated Test Runner
4
- *
5
- * Runs each test file in a separate Bun process to ensure complete isolation
6
- * of globalThis, module cache, and custom element registries.
7
- *
8
- * This solves the linkedom globalThis pollution issue where tests pass
9
- * individually but fail when run together.
10
- *
11
- * Usage: bun run scripts/test-isolated.js [pattern]
12
- */
13
-
14
- import { spawn } from 'bun';
15
- import { readdirSync, statSync } from 'fs';
16
- import { join, relative } from 'path';
17
-
18
- const args = process.argv.slice(2);
19
- const filterPattern = args[0] || '';
20
-
21
- // Colors for output
22
- const colors = {
23
- reset: '\x1b[0m',
24
- green: '\x1b[32m',
25
- red: '\x1b[31m',
26
- yellow: '\x1b[33m',
27
- cyan: '\x1b[36m',
28
- dim: '\x1b[2m'
29
- };
30
-
31
- // Find all test files
32
- function findTestFiles(dir, files = []) {
33
- const entries = readdirSync(dir);
34
- for (const entry of entries) {
35
- const fullPath = join(dir, entry);
36
- const stat = statSync(fullPath);
37
- if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') {
38
- findTestFiles(fullPath, files);
39
- } else if (entry.endsWith('.test.js')) {
40
- files.push(fullPath);
41
- }
42
- }
43
- return files;
44
- }
45
-
46
- // Run a single test file in isolation
47
- async function runTestFile(testFile) {
48
- const relativePath = relative(process.cwd(), testFile);
49
-
50
- const proc = spawn({
51
- cmd: ['bun', 'test', testFile],
52
- cwd: process.cwd(),
53
- stdout: 'pipe',
54
- stderr: 'pipe',
55
- env: {
56
- ...process.env,
57
- FORCE_COLOR: '1'
58
- }
59
- });
60
-
61
- const stdout = await new Response(proc.stdout).text();
62
- const stderr = await new Response(proc.stderr).text();
63
- const exitCode = await proc.exited;
64
-
65
- // Combine output (bun test writes summary to stderr)
66
- const output = stdout + stderr;
67
-
68
- // Parse results from output
69
- const passMatch = output.match(/\s*(\d+)\s+pass/);
70
- const failMatch = output.match(/\s*(\d+)\s+fail/);
71
- const skipMatch = output.match(/\s*(\d+)\s+skip/);
72
-
73
- const pass = passMatch ? parseInt(passMatch[1]) : 0;
74
- const fail = failMatch ? parseInt(failMatch[1]) : 0;
75
- const skip = skipMatch ? parseInt(skipMatch[1]) : 0;
76
-
77
- return {
78
- file: relativePath,
79
- pass,
80
- fail,
81
- skip,
82
- exitCode,
83
- stdout,
84
- stderr
85
- };
86
- }
87
-
88
- // Main execution
89
- async function main() {
90
- const testsDir = join(process.cwd(), 'tests');
91
- let testFiles = findTestFiles(testsDir);
92
-
93
- // Filter by pattern if provided
94
- if (filterPattern) {
95
- testFiles = testFiles.filter(f => f.includes(filterPattern));
96
- }
97
-
98
- // Filter out e2e tests (they have their own runner)
99
- testFiles = testFiles.filter(f => !f.includes('/e2e/'));
100
-
101
- console.log(`${colors.cyan}๐Ÿงช Isolated Test Runner${colors.reset}`);
102
- console.log(`${colors.dim}Running ${testFiles.length} test files in separate processes...${colors.reset}\n`);
103
-
104
- const startTime = Date.now();
105
- const results = [];
106
-
107
- for (const testFile of testFiles) {
108
- const result = await runTestFile(testFile);
109
- results.push(result);
110
-
111
- // Print inline status
112
- const status = result.fail === 0
113
- ? `${colors.green}โœ“${colors.reset}`
114
- : `${colors.red}โœ—${colors.reset}`;
115
- const counts = `${colors.green}${result.pass}${colors.reset}/${colors.red}${result.fail}${colors.reset}/${colors.yellow}${result.skip}${colors.reset}`;
116
- console.log(`${status} ${result.file} [${counts}]`);
117
-
118
- // Show errors for failed files
119
- if (result.fail > 0 && process.env.VERBOSE) {
120
- console.log(result.stdout);
121
- }
122
- }
123
-
124
- const duration = Date.now() - startTime;
125
-
126
- // Summary
127
- const totalPass = results.reduce((sum, r) => sum + r.pass, 0);
128
- const totalFail = results.reduce((sum, r) => sum + r.fail, 0);
129
- const totalSkip = results.reduce((sum, r) => sum + r.skip, 0);
130
- const failedFiles = results.filter(r => r.fail > 0);
131
-
132
- console.log(`\n${colors.cyan}โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”${colors.reset}`);
133
- console.log(`${colors.green}${totalPass} pass${colors.reset} | ${colors.red}${totalFail} fail${colors.reset} | ${colors.yellow}${totalSkip} skip${colors.reset}`);
134
- console.log(`${colors.dim}Ran ${results.length} test files in ${(duration / 1000).toFixed(2)}s${colors.reset}`);
135
-
136
- if (failedFiles.length > 0) {
137
- console.log(`\n${colors.red}Failed files:${colors.reset}`);
138
- for (const f of failedFiles) {
139
- console.log(` ${colors.red}โœ—${colors.reset} ${f.file} (${f.fail} failures)`);
140
- }
141
- process.exit(1);
142
- }
143
-
144
- console.log(`\n${colors.green}โœ“ All tests passed!${colors.reset}`);
145
- process.exit(0);
146
- }
147
-
148
- main().catch(err => {
149
- console.error('Error:', err);
150
- process.exit(1);
151
- });
package/server.js DELETED
@@ -1,256 +0,0 @@
1
- /**
2
- * microUI Dev Server with caching + Brotli/gzip compression
3
- * Optimized for Lighthouse 100 - SOTA 2026
4
- * Run: bun run server.js
5
- */
6
-
7
- import { brotliCompressSync, constants as zlibConstants } from 'zlib';
8
-
9
- const PORT = 5001;
10
-
11
- // Cache durations
12
- const CACHE_LONG = 'public, max-age=31536000, immutable'; // 1 year for versioned assets
13
- const CACHE_SHORT = 'public, max-age=3600'; // 1 hour for HTML
14
- const CACHE_REVALIDATE = 'public, max-age=0, must-revalidate'; // Always revalidate but allow bf-cache
15
-
16
- // MIME types
17
- const MIME_TYPES = {
18
- '.html': 'text/html; charset=utf-8',
19
- '.css': 'text/css; charset=utf-8',
20
- '.js': 'text/javascript; charset=utf-8',
21
- '.mjs': 'text/javascript; charset=utf-8',
22
- '.json': 'application/json',
23
- '.txt': 'text/plain; charset=utf-8',
24
- '.png': 'image/png',
25
- '.jpg': 'image/jpeg',
26
- '.jpeg': 'image/jpeg',
27
- '.webp': 'image/webp',
28
- '.svg': 'image/svg+xml',
29
- '.ico': 'image/x-icon',
30
- '.woff': 'font/woff',
31
- '.woff2': 'font/woff2',
32
- '.webmanifest': 'application/manifest+json',
33
- };
34
-
35
- // Types that benefit from gzip
36
- const COMPRESSIBLE_TYPES = ['.html', '.css', '.js', '.mjs', '.json', '.svg'];
37
-
38
- // Preload hints for critical resources (Link headers)
39
- const PRELOAD_HINTS = {
40
- '/demo/shell.html': [
41
- '</dist/microui.css>; rel=preload; as=style',
42
- '</assets/fonts/roboto-400.woff2>; rel=preload; as=font; type="font/woff2"; crossorigin',
43
- '</assets/logo-banner-400.webp>; rel=preload; as=image; type="image/webp"',
44
- ],
45
- };
46
-
47
- function getContentType(path) {
48
- const ext = path.match(/\.[^.]+$/)?.[0] || '';
49
- return MIME_TYPES[ext] || 'application/octet-stream';
50
- }
51
-
52
- function getCacheControl(path) {
53
- const cleanPath = path.split('?')[0];
54
-
55
- // Immutable assets: versioned bundles, fonts, images
56
- if (cleanPath.startsWith('/dist/') ||
57
- cleanPath.startsWith('/assets/') ||
58
- cleanPath.endsWith('.woff2') ||
59
- cleanPath.endsWith('.woff') ||
60
- cleanPath.endsWith('.png') ||
61
- cleanPath.endsWith('.webp') ||
62
- cleanPath.endsWith('.jpg') ||
63
- cleanPath.endsWith('.ico')) {
64
- return CACHE_LONG;
65
- }
66
-
67
- // HTML: allow bf-cache but revalidate
68
- if (cleanPath.endsWith('.html') || cleanPath === '/' || cleanPath === '/index.html') {
69
- return CACHE_REVALIDATE;
70
- }
71
-
72
- // SW and manifest need revalidate
73
- if (cleanPath.endsWith('sw.js') || cleanPath.endsWith('manifest.json')) {
74
- return CACHE_REVALIDATE;
75
- }
76
-
77
- return CACHE_SHORT;
78
- }
79
-
80
- function shouldCompress(path) {
81
- const cleanPath = path.split('?')[0];
82
- const ext = cleanPath.match(/\.[^.]+$/)?.[0] || '';
83
- return COMPRESSIBLE_TYPES.includes(ext);
84
- }
85
-
86
- function getPreloadLinks(path) {
87
- return PRELOAD_HINTS[path] || [];
88
- }
89
-
90
- const MAX_PORT_RETRIES = 10;
91
-
92
- function startServer(initialPort) {
93
- let port = initialPort;
94
-
95
- for (let i = 0; i < MAX_PORT_RETRIES; i++) {
96
- try {
97
- const server = Bun.serve({
98
- port: port,
99
- async fetch(req) {
100
- const url = new URL(req.url);
101
- let path = url.pathname;
102
-
103
- // ===== CACHE MANAGEMENT ENDPOINTS =====
104
-
105
- // Clear cache endpoint - sends headers to invalidate browser cache
106
- if (path === '/-/clear-cache') {
107
- return new Response(JSON.stringify({
108
- status: 'ok',
109
- message: 'Cache cleared. Reload the page with Ctrl+Shift+R',
110
- timestamp: new Date().toISOString()
111
- }), {
112
- headers: {
113
- 'Content-Type': 'application/json',
114
- 'Cache-Control': 'no-store, no-cache, must-revalidate',
115
- 'Clear-Site-Data': '"cache", "storage"',
116
- },
117
- });
118
- }
119
-
120
- // Health check
121
- if (path === '/-/health') {
122
- return new Response(JSON.stringify({ status: 'ok', port: server.port }), {
123
- headers: { 'Content-Type': 'application/json' },
124
- });
125
- }
126
-
127
- // Serve robots.txt inline (Lighthouse has issues with redirects)
128
- if (path === '/robots.txt') {
129
- const robotsTxt = `# robots.txt for microUI
130
- User-agent: *
131
- Allow: /
132
-
133
- # Sitemap
134
- Sitemap: https://microui.dev/sitemap.xml
135
- `;
136
- return new Response(robotsTxt, {
137
- headers: {
138
- 'Content-Type': 'text/plain; charset=utf-8',
139
- 'Cache-Control': 'public, max-age=86400',
140
- 'X-Robots-Tag': 'all',
141
- },
142
- });
143
- }
144
-
145
- // Default to demo/shell.html for root
146
- if (path === '/' || path === '/index.html') {
147
- path = '/demo/shell.html';
148
- }
149
-
150
- // Serve shell.html for App Shell pattern
151
- if (path === '/shell.html') {
152
- path = '/demo/shell.html';
153
- }
154
-
155
- // Serve content fragments for dynamic loading
156
- if (path.startsWith('/content/')) {
157
- path = '/demo' + path;
158
- }
159
-
160
- // Serve PWA assets from demo/
161
- if (path === '/sw.js' || path === '/manifest.json' ||
162
- path === '/favicon.ico' || path === '/favicon.png') {
163
- path = '/demo' + path;
164
- }
165
-
166
- // Security: prevent directory traversal
167
- if (path.includes('..')) {
168
- return new Response('Forbidden', { status: 403 });
169
- }
170
-
171
- const filePath = '.' + path;
172
- const file = Bun.file(filePath);
173
-
174
- if (await file.exists()) {
175
- const contentType = getContentType(path);
176
- const cacheControl = getCacheControl(path);
177
- const acceptEncoding = req.headers.get('accept-encoding') || '';
178
- const preloadLinks = getPreloadLinks(path);
179
-
180
- // Build headers
181
- const headers = {
182
- 'Content-Type': contentType,
183
- 'Cache-Control': cacheControl,
184
- 'X-Content-Type-Options': 'nosniff',
185
- // Enable bf-cache
186
- 'Vary': 'Accept-Encoding',
187
- };
188
-
189
- // Add Link preload headers for HTML
190
- if (preloadLinks.length > 0) {
191
- headers['Link'] = preloadLinks.join(', ');
192
- }
193
-
194
- // Brotli (priority) or Gzip compression for text assets
195
- if (shouldCompress(path)) {
196
- const content = await file.arrayBuffer();
197
- const rawData = Buffer.from(content);
198
-
199
- // Prefer Brotli (20-30% better compression than gzip)
200
- if (acceptEncoding.includes('br')) {
201
- try {
202
- const brotliCompressed = brotliCompressSync(rawData, {
203
- params: {
204
- [zlibConstants.BROTLI_PARAM_QUALITY]: 6, // Balance speed/compression
205
- }
206
- });
207
-
208
- return new Response(brotliCompressed, {
209
- headers: {
210
- ...headers,
211
- 'Content-Encoding': 'br',
212
- },
213
- });
214
- } catch {
215
- // Fallback to gzip if Brotli fails
216
- }
217
- }
218
-
219
- // Fallback to gzip
220
- if (acceptEncoding.includes('gzip')) {
221
- const compressed = Bun.gzipSync(new Uint8Array(content));
222
- return new Response(compressed, {
223
- headers: {
224
- ...headers,
225
- 'Content-Encoding': 'gzip',
226
- },
227
- });
228
- }
229
- }
230
-
231
- return new Response(file, { headers });
232
- }
233
-
234
- return new Response('Not Found', { status: 404 });
235
- },
236
- });
237
-
238
- console.log(`๐Ÿš€ microUI Dev Server running at http://localhost:${server.port}`);
239
- console.log(`๐Ÿ“ฆ Lighthouse-optimized: Cache-Control, Gzip, Link preload`);
240
- console.log(`๐Ÿงน Clear cache: http://localhost:${server.port}/-/clear-cache`);
241
- return server;
242
- } catch (e) {
243
- if (e.code === 'EADDRINUSE') {
244
- console.warn(`โš ๏ธ Port ${port} is busy, trying ${port + 1}...`);
245
- port++;
246
- } else {
247
- throw e;
248
- }
249
- }
250
- }
251
-
252
- console.error(`โŒ Failed to start server after ${MAX_PORT_RETRIES} attempts. Last port tried: ${port}`);
253
- process.exit(1);
254
- }
255
-
256
- startServer(PORT);
@@ -1,76 +0,0 @@
1
- import { describe, test, expect, beforeAll } from 'bun:test';
2
- import { parseHTML } from 'linkedom';
3
-
4
- // Mock Browser Environment
5
- const { document, customElements, HTMLElement, window } = parseHTML('<!DOCTYPE html><html><body></body></html>');
6
- globalThis.document = document;
7
- globalThis.customElements = customElements;
8
- globalThis.HTMLElement = HTMLElement;
9
- globalThis.window = window;
10
- globalThis.requestAnimationFrame = (cb) => cb();
11
-
12
- describe('Agent Integration Features', () => {
13
- let MuElement, MuInput, MuButton;
14
-
15
- beforeAll(async () => {
16
- // Load Core
17
- const core = await import('../../src/core/MuElement.js');
18
- MuElement = core.MuElement;
19
-
20
- // Load Components
21
- const inputModule = await import('../../src/components/mu-input.js');
22
- MuInput = inputModule.MuInput;
23
-
24
- const buttonModule = await import('../../src/components/mu-button.js');
25
- MuButton = buttonModule.MuButton;
26
- });
27
-
28
- test('should expose window.__MICROUI_ERRORS__', () => {
29
- // Create an element to trigger init
30
- const el = new MuInput();
31
- expect(Array.isArray(window.__MICROUI_ERRORS__)).toBe(true);
32
- });
33
-
34
- test('should expose window.microUIAgent helper', () => {
35
- expect(window.microUIAgent).toBeDefined();
36
- expect(typeof window.microUIAgent.reset).toBe('function');
37
- expect(typeof window.microUIAgent.getErrors).toBe('function');
38
- });
39
-
40
- test('should log error for invalid button variant', () => {
41
- window.microUIAgent.reset();
42
-
43
- const btn = document.createElement('mu-button');
44
- btn.setAttribute('variant', 'invalid-variant');
45
- document.body.appendChild(btn); // Render triggers updateClasses -> validation
46
-
47
- const errors = window.microUIAgent.getErrors();
48
- expect(errors.length).toBe(1);
49
- expect(errors[0].code).toBe('INVALID_VARIANT');
50
- expect(errors[0].component).toBe('mu-button');
51
- });
52
-
53
- test('should log error for missing input label', () => {
54
- window.microUIAgent.reset();
55
-
56
- const input = document.createElement('mu-input');
57
- // No label, no aria-label, no placeholder validation logic check?
58
- // Logic: if (!labelText && !ariaLabel) -> Error
59
- document.body.appendChild(input);
60
-
61
- const errors = window.microUIAgent.getErrors();
62
- expect(errors.length).toBe(1);
63
- expect(errors[0].code).toBe('A11Y_MISSING_LABEL');
64
- });
65
-
66
- test('should NOT log error if label is present', () => {
67
- window.microUIAgent.reset();
68
-
69
- const input = document.createElement('mu-input');
70
- input.setAttribute('label', 'Valid Label');
71
- document.body.appendChild(input);
72
-
73
- const errors = window.microUIAgent.getErrors();
74
- expect(errors.length).toBe(0);
75
- });
76
- });