microui-wc 0.1.1 → 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 (339) 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 +71 -71
  5. package/dist/README.md +14 -9
  6. package/dist/microui.css +1 -1
  7. package/dist/microui.esm.js.map +1 -1
  8. package/dist/microui.min.js.map +1 -1
  9. package/docs/getting-started.md +3 -3
  10. package/package.json +39 -11
  11. package/src/components/mu-schema-form.js +1 -1
  12. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
  13. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -33
  14. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  15. package/.github/workflows/ci.yml +0 -42
  16. package/.github/workflows/deploy-pages.yml +0 -112
  17. package/CODE_OF_CONDUCT.md +0 -59
  18. package/CONTRIBUTING.md +0 -156
  19. package/SECURITY.md +0 -58
  20. package/app/.generated/routes/alerts.js +0 -8
  21. package/app/.generated/routes/avatars.js +0 -8
  22. package/app/.generated/routes/badges.js +0 -8
  23. package/app/.generated/routes/buttons.js +0 -10
  24. package/app/.generated/routes/cards.js +0 -10
  25. package/app/.generated/routes/checkboxes.js +0 -9
  26. package/app/.generated/routes/chips.js +0 -8
  27. package/app/.generated/routes/dropdowns.js +0 -9
  28. package/app/.generated/routes/home.js +0 -7
  29. package/app/.generated/routes/icons.js +0 -9
  30. package/app/.generated/routes/inputs.js +0 -10
  31. package/app/.generated/routes/installation.js +0 -7
  32. package/app/.generated/routes/layout.js +0 -9
  33. package/app/.generated/routes/modals.js +0 -9
  34. package/app/.generated/routes/navbar.js +0 -7
  35. package/app/.generated/routes/progress.js +0 -9
  36. package/app/.generated/routes/radios.js +0 -9
  37. package/app/.generated/routes/switches.js +0 -9
  38. package/app/.generated/routes/tabs.js +0 -8
  39. package/app/.generated/routes/toasts.js +0 -9
  40. package/app/index.html +0 -67
  41. package/app/pages/alerts.html +0 -23
  42. package/app/pages/avatars.html +0 -22
  43. package/app/pages/badges.html +0 -22
  44. package/app/pages/buttons.html +0 -71
  45. package/app/pages/cards.html +0 -54
  46. package/app/pages/checkboxes.html +0 -39
  47. package/app/pages/chips.html +0 -23
  48. package/app/pages/dropdowns.html +0 -41
  49. package/app/pages/home.html +0 -59
  50. package/app/pages/icons.html +0 -29
  51. package/app/pages/inputs.html +0 -66
  52. package/app/pages/installation.html +0 -34
  53. package/app/pages/layout.html +0 -30
  54. package/app/pages/modals.html +0 -21
  55. package/app/pages/navbar.html +0 -22
  56. package/app/pages/progress.html +0 -35
  57. package/app/pages/radios.html +0 -40
  58. package/app/pages/switches.html +0 -39
  59. package/app/pages/tabs.html +0 -30
  60. package/app/pages/toasts.html +0 -22
  61. package/app-dist/index.html +0 -67
  62. package/app-dist/pages/alerts.html +0 -23
  63. package/app-dist/pages/avatars.html +0 -22
  64. package/app-dist/pages/badges.html +0 -22
  65. package/app-dist/pages/buttons.html +0 -71
  66. package/app-dist/pages/cards.html +0 -54
  67. package/app-dist/pages/checkboxes.html +0 -39
  68. package/app-dist/pages/chips.html +0 -23
  69. package/app-dist/pages/dropdowns.html +0 -41
  70. package/app-dist/pages/home.html +0 -59
  71. package/app-dist/pages/icons.html +0 -29
  72. package/app-dist/pages/inputs.html +0 -66
  73. package/app-dist/pages/installation.html +0 -34
  74. package/app-dist/pages/layout.html +0 -30
  75. package/app-dist/pages/modals.html +0 -21
  76. package/app-dist/pages/navbar.html +0 -22
  77. package/app-dist/pages/progress.html +0 -35
  78. package/app-dist/pages/radios.html +0 -40
  79. package/app-dist/pages/switches.html +0 -39
  80. package/app-dist/pages/tabs.html +0 -30
  81. package/app-dist/pages/toasts.html +0 -22
  82. package/app-dist/pages.json +0 -217
  83. package/app-dist/routes/alerts.js +0 -5
  84. package/app-dist/routes/avatars.js +0 -1
  85. package/app-dist/routes/badges.js +0 -1
  86. package/app-dist/routes/buttons.js +0 -1
  87. package/app-dist/routes/cards.js +0 -1
  88. package/app-dist/routes/checkboxes.js +0 -9
  89. package/app-dist/routes/chips.js +0 -4
  90. package/app-dist/routes/chunk-019e5e2f.js +0 -5
  91. package/app-dist/routes/chunk-0m4j19yd.js +0 -2
  92. package/app-dist/routes/chunk-0tmmp5q0.js +0 -1
  93. package/app-dist/routes/chunk-10xn709r.js +0 -1
  94. package/app-dist/routes/chunk-15m2qcda.js +0 -2
  95. package/app-dist/routes/chunk-1bh8g23n.js +0 -1
  96. package/app-dist/routes/chunk-1vg0v937.js +0 -1
  97. package/app-dist/routes/chunk-1zvcgy3j.js +0 -1
  98. package/app-dist/routes/chunk-2afb0861.js +0 -1
  99. package/app-dist/routes/chunk-2c6ttpzt.js +0 -5
  100. package/app-dist/routes/chunk-3dy30fhs.js +0 -1
  101. package/app-dist/routes/chunk-426dnces.js +0 -13
  102. package/app-dist/routes/chunk-44kgxery.js +0 -1
  103. package/app-dist/routes/chunk-47fdnejd.js +0 -33
  104. package/app-dist/routes/chunk-49a6t2vq.js +0 -1
  105. package/app-dist/routes/chunk-4fe1rm5b.js +0 -1
  106. package/app-dist/routes/chunk-4ggmvkta.js +0 -33
  107. package/app-dist/routes/chunk-4vkz81q7.js +0 -33
  108. package/app-dist/routes/chunk-4w4tmj8f.js +0 -31
  109. package/app-dist/routes/chunk-532s62kr.js +0 -31
  110. package/app-dist/routes/chunk-5hm3bssy.js +0 -33
  111. package/app-dist/routes/chunk-5vrh24hc.js +0 -1
  112. package/app-dist/routes/chunk-61pcg25a.js +0 -1
  113. package/app-dist/routes/chunk-6nfhygvf.js +0 -1
  114. package/app-dist/routes/chunk-700e7je6.js +0 -33
  115. package/app-dist/routes/chunk-7fsn17kg.js +0 -1
  116. package/app-dist/routes/chunk-7k789b32.js +0 -1
  117. package/app-dist/routes/chunk-7r46q0ys.js +0 -36
  118. package/app-dist/routes/chunk-86fmc1fr.js +0 -5
  119. package/app-dist/routes/chunk-8qth37vw.js +0 -1
  120. package/app-dist/routes/chunk-924wv8n0.js +0 -1
  121. package/app-dist/routes/chunk-9mbhgxk9.js +0 -1
  122. package/app-dist/routes/chunk-a216hyd9.js +0 -1
  123. package/app-dist/routes/chunk-akzxykh9.js +0 -33
  124. package/app-dist/routes/chunk-b3dcvy8c.js +0 -1
  125. package/app-dist/routes/chunk-b74zahz5.js +0 -31
  126. package/app-dist/routes/chunk-bftj53p2.js +0 -5
  127. package/app-dist/routes/chunk-c01hnz3e.js +0 -1
  128. package/app-dist/routes/chunk-d8pvv5km.js +0 -1
  129. package/app-dist/routes/chunk-dev0aezr.js +0 -2
  130. package/app-dist/routes/chunk-dh6vnv0e.js +0 -1
  131. package/app-dist/routes/chunk-dn2cbpva.js +0 -36
  132. package/app-dist/routes/chunk-dvn0my90.js +0 -1
  133. package/app-dist/routes/chunk-dvq8mnve.js +0 -36
  134. package/app-dist/routes/chunk-e8c2gc4d.js +0 -5
  135. package/app-dist/routes/chunk-ejf9ak2x.js +0 -1
  136. package/app-dist/routes/chunk-f083m55s.js +0 -1
  137. package/app-dist/routes/chunk-fnrj28s1.js +0 -31
  138. package/app-dist/routes/chunk-fvg3yjdp.js +0 -31
  139. package/app-dist/routes/chunk-g7k381n1.js +0 -1
  140. package/app-dist/routes/chunk-h01kq2ae.js +0 -13
  141. package/app-dist/routes/chunk-h4dk761v.js +0 -5
  142. package/app-dist/routes/chunk-hmx91z2x.js +0 -5
  143. package/app-dist/routes/chunk-hxbg4m42.js +0 -36
  144. package/app-dist/routes/chunk-jbjnfp2b.js +0 -2
  145. package/app-dist/routes/chunk-jxtz5vv6.js +0 -36
  146. package/app-dist/routes/chunk-jxzcs0ey.js +0 -36
  147. package/app-dist/routes/chunk-kt7wwhcx.js +0 -1
  148. package/app-dist/routes/chunk-kzptszyc.js +0 -33
  149. package/app-dist/routes/chunk-mhgca4w4.js +0 -2
  150. package/app-dist/routes/chunk-mhswxa20.js +0 -1
  151. package/app-dist/routes/chunk-n8zfeex6.js +0 -1
  152. package/app-dist/routes/chunk-pee47b2r.js +0 -1
  153. package/app-dist/routes/chunk-pesmw829.js +0 -1
  154. package/app-dist/routes/chunk-pgc4c6f3.js +0 -36
  155. package/app-dist/routes/chunk-q8egegm1.js +0 -1
  156. package/app-dist/routes/chunk-q9mn2qyq.js +0 -36
  157. package/app-dist/routes/chunk-qh0rtaf3.js +0 -5
  158. package/app-dist/routes/chunk-qqhmk6ye.js +0 -2
  159. package/app-dist/routes/chunk-qrxygmf7.js +0 -33
  160. package/app-dist/routes/chunk-r46yzksx.js +0 -36
  161. package/app-dist/routes/chunk-rgpbw2w0.js +0 -5
  162. package/app-dist/routes/chunk-rnpzv3d8.js +0 -2
  163. package/app-dist/routes/chunk-s5v8cv05.js +0 -2
  164. package/app-dist/routes/chunk-sbwn5bpc.js +0 -1
  165. package/app-dist/routes/chunk-sqbg8jbt.js +0 -33
  166. package/app-dist/routes/chunk-sv8dqnf7.js +0 -1
  167. package/app-dist/routes/chunk-t67sw3za.js +0 -1
  168. package/app-dist/routes/chunk-tjdpqwdf.js +0 -31
  169. package/app-dist/routes/chunk-tq2mfghg.js +0 -1
  170. package/app-dist/routes/chunk-ttn10vt6.js +0 -1
  171. package/app-dist/routes/chunk-v2hzpjxr.js +0 -1
  172. package/app-dist/routes/chunk-wfjjkw9y.js +0 -1
  173. package/app-dist/routes/chunk-wt8cxzmf.js +0 -31
  174. package/app-dist/routes/chunk-x45d372k.js +0 -5
  175. package/app-dist/routes/chunk-y3wsazkt.js +0 -1
  176. package/app-dist/routes/chunk-y7pmgc7t.js +0 -33
  177. package/app-dist/routes/chunk-zefdt2q3.js +0 -31
  178. package/app-dist/routes/dropdowns.js +0 -6
  179. package/app-dist/routes/home.js +0 -1
  180. package/app-dist/routes/icons.js +0 -1
  181. package/app-dist/routes/inputs.js +0 -12
  182. package/app-dist/routes/installation.js +0 -1
  183. package/app-dist/routes/layout.js +0 -1
  184. package/app-dist/routes/modals.js +0 -7
  185. package/app-dist/routes/navbar.js +0 -1
  186. package/app-dist/routes/progress.js +0 -1
  187. package/app-dist/routes/radios.js +0 -6
  188. package/app-dist/routes/switches.js +0 -6
  189. package/app-dist/routes/tabs.js +0 -1
  190. package/app-dist/routes/toasts.js +0 -16
  191. package/assets/fonts/material-symbols-mini.woff2 +0 -0
  192. package/assets/fonts/material-symbols.woff2 +0 -0
  193. package/assets/fonts/roboto-400.woff2 +0 -0
  194. package/assets/fonts/roboto-500.woff2 +0 -0
  195. package/assets/fonts/roboto-700.woff2 +0 -0
  196. package/assets/logo-banner-400.jpg +0 -0
  197. package/assets/logo-banner-400.webp +0 -0
  198. package/assets/logo-banner-800.webp +0 -0
  199. package/assets/logo-banner.jpg +0 -0
  200. package/assets/logo-icon-64.jpg +0 -0
  201. package/assets/logo-icon-64.webp +0 -0
  202. package/assets/logo-icon.jpg +0 -0
  203. package/assets/logo-square.jpg +0 -0
  204. package/bun.lock +0 -312
  205. package/bunfig.toml +0 -4
  206. package/custom-elements.json +0 -1916
  207. package/demo/api/sample-data.json +0 -38
  208. package/demo/content/alerts.html +0 -115
  209. package/demo/content/avatars.html +0 -70
  210. package/demo/content/badges.html +0 -65
  211. package/demo/content/buttons.html +0 -188
  212. package/demo/content/callouts.html +0 -91
  213. package/demo/content/cards.html +0 -121
  214. package/demo/content/checkboxes.html +0 -178
  215. package/demo/content/chips.html +0 -67
  216. package/demo/content/codeblocks.html +0 -101
  217. package/demo/content/confirms.html +0 -115
  218. package/demo/content/datatables.html +0 -149
  219. package/demo/content/dividers.html +0 -119
  220. package/demo/content/dropdowns.html +0 -89
  221. package/demo/content/enterprise.html +0 -252
  222. package/demo/content/home.html +0 -149
  223. package/demo/content/icons.html +0 -89
  224. package/demo/content/inputs.html +0 -135
  225. package/demo/content/installation.html +0 -16
  226. package/demo/content/layout.html +0 -136
  227. package/demo/content/modals.html +0 -141
  228. package/demo/content/navbar.html +0 -70
  229. package/demo/content/progress.html +0 -119
  230. package/demo/content/radios.html +0 -88
  231. package/demo/content/skeletons.html +0 -109
  232. package/demo/content/spinners.html +0 -96
  233. package/demo/content/switches.html +0 -84
  234. package/demo/content/tables.html +0 -124
  235. package/demo/content/tabs.html +0 -85
  236. package/demo/content/toasts.html +0 -116
  237. package/demo/content/tooltips.html +0 -107
  238. package/demo/content/virtual-lists.html +0 -233
  239. package/demo/favicon.ico +0 -0
  240. package/demo/favicon.png +0 -0
  241. package/demo/full.html +0 -52
  242. package/demo/iife.html +0 -46
  243. package/demo/manifest.json +0 -34
  244. package/demo/pages/datatable-demo.html +0 -237
  245. package/demo/pages/prompt-ui-demo.html +0 -218
  246. package/demo/pages/responsive-demo.html +0 -122
  247. package/demo/pages/schema-form-demo.html +0 -270
  248. package/demo/robots.txt +0 -6
  249. package/demo/shell.html +0 -712
  250. package/demo/sw.js +0 -387
  251. package/lighthouse-audit.mjs +0 -113
  252. package/scripts/analyze-components.js +0 -105
  253. package/scripts/build-app.js +0 -193
  254. package/scripts/build-framework.js +0 -444
  255. package/scripts/build-utils.js +0 -101
  256. package/scripts/test-isolated.js +0 -151
  257. package/server.js +0 -256
  258. package/tests/agents/agent-integration.test.js +0 -76
  259. package/tests/benchmark.html +0 -296
  260. package/tests/build/scan-components.test.js +0 -173
  261. package/tests/components/all-components.test.js +0 -245
  262. package/tests/components/all-missing-components.test.js +0 -574
  263. package/tests/components/mu-alert.test.js +0 -113
  264. package/tests/components/mu-avatar.test.js +0 -148
  265. package/tests/components/mu-badge.test.js +0 -92
  266. package/tests/components/mu-button.test.js +0 -112
  267. package/tests/components/mu-card.test.js +0 -89
  268. package/tests/components/mu-checkbox.test.js +0 -158
  269. package/tests/components/mu-chip.test.js +0 -118
  270. package/tests/components/mu-container.test.js +0 -120
  271. package/tests/components/mu-divider.test.js +0 -98
  272. package/tests/components/mu-drawer-item.test.js +0 -199
  273. package/tests/components/mu-drawer.test.js +0 -96
  274. package/tests/components/mu-dropdown.test.js +0 -125
  275. package/tests/components/mu-form.test.js +0 -138
  276. package/tests/components/mu-grid.test.js +0 -135
  277. package/tests/components/mu-icon.test.js +0 -110
  278. package/tests/components/mu-input.test.js +0 -131
  279. package/tests/components/mu-lazy.test.js +0 -103
  280. package/tests/components/mu-modal.test.js +0 -275
  281. package/tests/components/mu-navbar.test.js +0 -101
  282. package/tests/components/mu-progress.test.js +0 -115
  283. package/tests/components/mu-radio.test.js +0 -114
  284. package/tests/components/mu-repeat.test.js +0 -106
  285. package/tests/components/mu-sidebar.test.js +0 -126
  286. package/tests/components/mu-skeleton.test.js +0 -162
  287. package/tests/components/mu-stack.test.js +0 -143
  288. package/tests/components/mu-switch.test.js +0 -292
  289. package/tests/components/mu-table.test.js +0 -124
  290. package/tests/components/mu-tabs.test.js +0 -104
  291. package/tests/components/mu-textarea.test.js +0 -115
  292. package/tests/components/mu-toast.test.js +0 -321
  293. package/tests/components/mu-tooltip.test.js +0 -133
  294. package/tests/components/mu-virtual-list.test.js +0 -109
  295. package/tests/core/MuElement.test.js +0 -120
  296. package/tests/core/agent-api.test.js +0 -125
  297. package/tests/core/all-core-modules.test.js +0 -442
  298. package/tests/core/bus.test.js +0 -364
  299. package/tests/core/component-schema.test.js +0 -160
  300. package/tests/core/feature-registry.test.js +0 -198
  301. package/tests/core/form-state.test.js +0 -167
  302. package/tests/core/http.test.js +0 -119
  303. package/tests/core/keyboard.test.js +0 -319
  304. package/tests/core/layers.test.js +0 -129
  305. package/tests/core/namespaced-stores.test.js +0 -114
  306. package/tests/core/render.test.js +0 -121
  307. package/tests/core/ripple.test.js +0 -131
  308. package/tests/core/router.test.js +0 -89
  309. package/tests/core/scheduler.test.js +0 -121
  310. package/tests/core/signals.test.js +0 -128
  311. package/tests/core/store.test.js +0 -171
  312. package/tests/core/transitions.test.js +0 -82
  313. package/tests/e2e/accessibility-harness.html +0 -58
  314. package/tests/e2e/accessibility.test.js +0 -401
  315. package/tests/e2e/agent-features.test.js +0 -372
  316. package/tests/e2e/card-spacing.test.js +0 -287
  317. package/tests/e2e/components.test.js +0 -439
  318. package/tests/e2e/demo-routes.test.js +0 -478
  319. package/tests/e2e/layout-css-fallback.test.js +0 -334
  320. package/tests/e2e/mu-alert.e2e.test.js +0 -111
  321. package/tests/e2e/mu-checkbox.test.js +0 -489
  322. package/tests/e2e/mu-chip.test.js +0 -347
  323. package/tests/e2e/mu-form.test.js +0 -499
  324. package/tests/e2e/mu-icon.test.js +0 -114
  325. package/tests/e2e/mu-radio.test.js +0 -113
  326. package/tests/e2e/mu-skeleton.test.js +0 -140
  327. package/tests/e2e/mu-switch.test.js +0 -415
  328. package/tests/e2e/mu-tabs.test.js +0 -494
  329. package/tests/e2e/mu-textarea.test.js +0 -242
  330. package/tests/e2e/mu-virtual-list.test.js +0 -427
  331. package/tests/e2e/perf-memory.test.js +0 -161
  332. package/tests/e2e/puppeteer-helper.js +0 -137
  333. package/tests/e2e/puppeteer.test.js +0 -226
  334. package/tests/e2e/pwa.test.js +0 -261
  335. package/tests/e2e/test-harness.html +0 -319
  336. package/tests/manual/test-components.html +0 -120
  337. package/tests/memory-test.html +0 -309
  338. package/tests/setup-dom.js +0 -93
  339. package/tests/visual-test.html +0 -301
package/demo/sw.js DELETED
@@ -1,387 +0,0 @@
1
- /**
2
- * microUI Service Worker v2 - SOTA Caching & Performance
3
- *
4
- * Features:
5
- * - Content-hash based cache invalidation
6
- * - Stale-while-revalidate for optimal UX
7
- * - Precaching of critical assets
8
- * - Runtime caching with intelligent strategies
9
- * - Offline support
10
- * - Background sync ready
11
- */
12
-
13
- // Cache version - update this or use build hash
14
- const VERSION = '2.0.19';
15
- const CACHE_PREFIX = 'microui';
16
- const PRECACHE_NAME = `${CACHE_PREFIX}-precache-${VERSION}`;
17
- const RUNTIME_NAME = `${CACHE_PREFIX}-runtime-${VERSION}`;
18
-
19
- // Critical assets to precache (fetched on install)
20
- // App Shell Architecture: shell + all content fragments precached for instant load
21
- const PRECACHE_ASSETS = [
22
- '/',
23
- '/index.html',
24
- '/shell.html', // App Shell (minimal UI skeleton)
25
- // Content fragments (21 pages)
26
- '/content/home.html',
27
- '/content/installation.html',
28
- '/content/buttons.html',
29
- '/content/inputs.html',
30
- '/content/checkboxes.html',
31
- '/content/switches.html',
32
- '/content/radios.html',
33
- '/content/dropdowns.html',
34
- '/content/cards.html',
35
- '/content/layout.html',
36
- '/content/tabs.html',
37
- '/content/navbar.html',
38
- '/content/alerts.html',
39
- '/content/toasts.html',
40
- '/content/modals.html',
41
- '/content/progress.html',
42
- '/content/avatars.html',
43
- '/content/badges.html',
44
- '/content/chips.html',
45
- '/content/icons.html',
46
- '/content/enterprise.html',
47
- // Core assets
48
- '/dist/microui.css',
49
- '/dist/routes/shell.js',
50
- '/dist/routes/shell-critical.js',
51
- '/dist/routes/shell-deferred.js',
52
- '/dist/routes/home.js',
53
- '/favicon.png'
54
- ];
55
-
56
- // Cache strategies by asset type
57
- const CACHE_STRATEGIES = {
58
- // Immutable assets (hashed files) - cache forever
59
- immutable: /\.(woff2?|ttf|otf)$/,
60
- // Static assets - stale-while-revalidate
61
- static: /\.(js|css|png|jpg|jpeg|webp|svg|ico)$/,
62
- // HTML - network-first with cache fallback
63
- document: /\.html?$|\/$/,
64
- // API calls - network only (no cache)
65
- api: /\/api\//
66
- };
67
-
68
- // Maximum age for runtime cache entries (7 days)
69
- const MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
70
- // Maximum entries in runtime cache
71
- const MAX_ENTRIES = 100;
72
-
73
- // ============================================
74
- // LRU CACHE HELPER - Enforces maxEntries limit
75
- // ============================================
76
-
77
- /**
78
- * Cache with LRU eviction - ensures cache never exceeds maxEntries
79
- * This is called after every cache.put() to enforce limits automatically
80
- */
81
- async function cacheWithLRU(cacheName, request, response, maxEntries = MAX_ENTRIES) {
82
- const cache = await caches.open(cacheName);
83
- await cache.put(request, response);
84
-
85
- // Enforce maxEntries with LRU (oldest entries first)
86
- const keys = await cache.keys();
87
- if (keys.length > maxEntries) {
88
- const toDelete = keys.slice(0, keys.length - maxEntries);
89
- await Promise.all(toDelete.map(key => cache.delete(key)));
90
- console.log(`[SW] LRU cleanup: removed ${toDelete.length} old entries from ${cacheName}`);
91
- }
92
- }
93
-
94
- /**
95
- * Cleanup stale entries older than MAX_AGE_MS
96
- */
97
- async function cleanupStaleEntries(cacheName) {
98
- try {
99
- const cache = await caches.open(cacheName);
100
- const requests = await cache.keys();
101
- const now = Date.now();
102
- let removed = 0;
103
-
104
- for (const request of requests) {
105
- const response = await cache.match(request);
106
- const dateHeader = response?.headers.get('date');
107
- if (dateHeader) {
108
- const cacheTime = new Date(dateHeader).getTime();
109
- if (now - cacheTime > MAX_AGE_MS) {
110
- await cache.delete(request);
111
- removed++;
112
- }
113
- }
114
- }
115
-
116
- if (removed > 0) {
117
- console.log(`[SW] Stale cleanup: removed ${removed} expired entries from ${cacheName}`);
118
- }
119
- } catch (error) {
120
- console.warn('[SW] Stale cleanup failed:', error);
121
- }
122
- }
123
-
124
- // ============================================
125
- // INSTALL - Precache critical assets
126
- // ============================================
127
- self.addEventListener('install', (event) => {
128
- event.waitUntil(
129
- caches.open(PRECACHE_NAME)
130
- .then((cache) => {
131
- console.log('[SW] Precaching critical assets');
132
- return cache.addAll(PRECACHE_ASSETS);
133
- })
134
- .then(() => {
135
- console.log('[SW] Precache complete, activating immediately');
136
- return self.skipWaiting();
137
- })
138
- .catch((error) => {
139
- console.error('[SW] Precache failed:', error);
140
- })
141
- );
142
- });
143
-
144
- // ============================================
145
- // ACTIVATE - Cleanup old caches
146
- // ============================================
147
- self.addEventListener('activate', (event) => {
148
- event.waitUntil(
149
- caches.keys()
150
- .then((cacheNames) => {
151
- return Promise.all(
152
- cacheNames
153
- .filter((name) => {
154
- // Delete caches from this app but different version
155
- return name.startsWith(CACHE_PREFIX) &&
156
- name !== PRECACHE_NAME &&
157
- name !== RUNTIME_NAME;
158
- })
159
- .map((name) => {
160
- console.log('[SW] Deleting old cache:', name);
161
- return caches.delete(name);
162
- })
163
- );
164
- })
165
- .then(() => {
166
- // Cleanup stale entries in runtime cache
167
- return cleanupStaleEntries(RUNTIME_NAME);
168
- })
169
- .then(() => {
170
- console.log('[SW] Claiming all clients');
171
- return self.clients.claim();
172
- })
173
- );
174
- });
175
-
176
- // ============================================
177
- // FETCH - Intelligent routing
178
- // ============================================
179
- self.addEventListener('fetch', (event) => {
180
- const { request } = event;
181
- const url = new URL(request.url);
182
-
183
- // Skip non-GET requests
184
- if (request.method !== 'GET') return;
185
-
186
- // Skip cross-origin requests
187
- if (url.origin !== self.location.origin) return;
188
-
189
- // Skip chrome-extension and other protocols
190
- if (!url.protocol.startsWith('http')) return;
191
-
192
- // Route to appropriate strategy
193
- if (CACHE_STRATEGIES.api.test(url.pathname)) {
194
- // API: Network only
195
- return;
196
- }
197
-
198
- if (CACHE_STRATEGIES.immutable.test(url.pathname)) {
199
- event.respondWith(cacheFirst(request, RUNTIME_NAME, true));
200
- return;
201
- }
202
-
203
- if (CACHE_STRATEGIES.document.test(url.pathname) || url.pathname === '/') {
204
- event.respondWith(networkFirst(request, PRECACHE_NAME));
205
- return;
206
- }
207
-
208
- if (CACHE_STRATEGIES.static.test(url.pathname)) {
209
- event.respondWith(staleWhileRevalidate(request, RUNTIME_NAME));
210
- return;
211
- }
212
-
213
- // Default: stale-while-revalidate
214
- event.respondWith(staleWhileRevalidate(request, RUNTIME_NAME));
215
- });
216
-
217
- // ============================================
218
- // CACHE STRATEGIES
219
- // ============================================
220
-
221
- /**
222
- * Cache-first: Best for immutable assets
223
- * Returns cached response immediately, only fetches if not cached
224
- */
225
- async function cacheFirst(request, cacheName, immutable = false) {
226
- const cached = await caches.match(request);
227
- if (cached) {
228
- return cached;
229
- }
230
-
231
- try {
232
- const response = await fetch(request);
233
- if (response.ok) {
234
- // Use LRU caching to enforce limits
235
- await cacheWithLRU(cacheName, request, response.clone());
236
- }
237
- return response;
238
- } catch (error) {
239
- console.error('[SW] Cache-first fetch failed:', error);
240
- // Return offline fallback if available
241
- return caches.match('/');
242
- }
243
- }
244
-
245
- /**
246
- * Network-first: Best for HTML documents
247
- * Always tries network, falls back to cache
248
- */
249
- async function networkFirst(request, cacheName) {
250
- try {
251
- const response = await fetch(request);
252
- if (response.ok) {
253
- // Use LRU caching to enforce limits
254
- await cacheWithLRU(cacheName, request, response.clone());
255
- }
256
- return response;
257
- } catch (error) {
258
- console.log('[SW] Network failed, serving from cache:', request.url);
259
- const cached = await caches.match(request);
260
- if (cached) {
261
- return cached;
262
- }
263
- // Ultimate fallback
264
- return caches.match('/');
265
- }
266
- }
267
-
268
- /**
269
- * Stale-while-revalidate: Best for static assets
270
- * Returns cache immediately, updates cache in background
271
- */
272
- async function staleWhileRevalidate(request, cacheName) {
273
- const cache = await caches.open(cacheName);
274
- const cached = await cache.match(request);
275
-
276
- // Fetch in background regardless, with LRU enforcement
277
- const fetchPromise = fetch(request)
278
- .then(async (response) => {
279
- if (response.ok) {
280
- // Use LRU caching to enforce limits
281
- await cacheWithLRU(cacheName, request, response.clone());
282
- }
283
- return response;
284
- })
285
- .catch(() => null);
286
-
287
- // Return cached immediately if available
288
- if (cached) {
289
- return cached;
290
- }
291
-
292
- // Otherwise wait for network
293
- const response = await fetchPromise;
294
- if (response) {
295
- return response;
296
- }
297
-
298
- // Fallback
299
- return caches.match('/');
300
- }
301
-
302
- // ============================================
303
- // MESSAGE HANDLING - Cache control from app
304
- // ============================================
305
- self.addEventListener('message', (event) => {
306
- const { type, payload } = event.data || {};
307
-
308
- switch (type) {
309
- case 'SKIP_WAITING':
310
- self.skipWaiting();
311
- break;
312
-
313
- case 'CLEAR_CACHE':
314
- event.waitUntil(
315
- caches.keys().then((names) =>
316
- Promise.all(names.map((name) => caches.delete(name)))
317
- ).then(() => {
318
- event.ports[0]?.postMessage({ success: true });
319
- })
320
- );
321
- break;
322
-
323
- case 'CACHE_URLS':
324
- if (payload?.urls) {
325
- event.waitUntil(
326
- caches.open(RUNTIME_NAME).then((cache) =>
327
- cache.addAll(payload.urls)
328
- ).then(() => {
329
- event.ports[0]?.postMessage({ success: true });
330
- })
331
- );
332
- }
333
- break;
334
-
335
- case 'GET_CACHE_STATUS':
336
- event.waitUntil(
337
- getCacheStatus().then((status) => {
338
- event.ports[0]?.postMessage(status);
339
- })
340
- );
341
- break;
342
- }
343
- });
344
-
345
- /**
346
- * Get cache status for debugging
347
- */
348
- async function getCacheStatus() {
349
- const cacheNames = await caches.keys();
350
- const status = { version: VERSION, caches: {} };
351
-
352
- for (const name of cacheNames) {
353
- const cache = await caches.open(name);
354
- const keys = await cache.keys();
355
- status.caches[name] = keys.length;
356
- }
357
-
358
- return status;
359
- }
360
-
361
- // ============================================
362
- // PERIODIC CACHE CLEANUP
363
- // ============================================
364
- self.addEventListener('periodicsync', (event) => {
365
- if (event.tag === 'cache-cleanup') {
366
- event.waitUntil(cleanupOldCaches());
367
- }
368
- });
369
-
370
- async function cleanupOldCaches() {
371
- const cache = await caches.open(RUNTIME_NAME);
372
- const requests = await cache.keys();
373
- const now = Date.now();
374
-
375
- for (const request of requests) {
376
- const response = await cache.match(request);
377
- const dateHeader = response?.headers.get('date');
378
- if (dateHeader) {
379
- const cacheTime = new Date(dateHeader).getTime();
380
- if (now - cacheTime > MAX_AGE_MS) {
381
- await cache.delete(request);
382
- }
383
- }
384
- }
385
- }
386
-
387
- console.log(`[SW] microUI Service Worker v${VERSION} loaded`);
@@ -1,113 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * @fileoverview Lighthouse audit using puppeteer-core (no chrome-launcher)
4
- *
5
- * This script bypasses chrome-launcher's mktemp issue by:
6
- * 1. Launching Chrome ourselves with puppeteer-core
7
- * 2. Connecting Lighthouse to the running instance
8
- *
9
- * Requirements:
10
- * - Global Lighthouse: npm install -g lighthouse
11
- * - Chrome in ~/.cache/puppeteer
12
- * - Run with Node 20+: node lighthouse-audit.mjs
13
- */
14
-
15
- import { execSync } from 'child_process';
16
- import { existsSync, readdirSync, readFileSync, writeFileSync } from 'fs';
17
- import { join } from 'path';
18
- import { createRequire } from 'module';
19
-
20
- // Import Lighthouse from global installation
21
- const require = createRequire(import.meta.url);
22
- const globalNodeModules = execSync('npm root -g', { encoding: 'utf-8' }).trim();
23
- const lighthouse = (await import(`${globalNodeModules}/lighthouse/core/index.js`)).default;
24
-
25
- // Import puppeteer-core from project
26
- const puppeteer = (await import('puppeteer-core')).default;
27
-
28
- // Find Chrome in cache locations
29
- const findChrome = () => {
30
- const cachePaths = [
31
- join(process.env.HOME, '.cache', 'puppeteer'),
32
- '/tmp/puppeteer'
33
- ];
34
-
35
- for (const cachePath of cachePaths) {
36
- if (!existsSync(cachePath)) continue;
37
- const dirs = readdirSync(cachePath);
38
- for (const browserType of ['chrome-headless-shell', 'chrome']) {
39
- for (const dir of dirs) {
40
- if (dir.startsWith(browserType)) {
41
- const chromeDir = join(cachePath, dir);
42
- try {
43
- const versions = readdirSync(chromeDir).sort().reverse();
44
- for (const version of versions) {
45
- const armPath = join(chromeDir, version, `${browserType}-mac-arm64`, browserType);
46
- if (existsSync(armPath)) return armPath;
47
- }
48
- } catch (e) { /* skip */ }
49
- }
50
- }
51
- }
52
- }
53
- return null;
54
- };
55
-
56
- const chromePath = findChrome();
57
- if (!chromePath) {
58
- console.error('āŒ Chrome not found');
59
- process.exit(1);
60
- }
61
-
62
- console.log('šŸ” Chrome:', chromePath);
63
- console.log('šŸ“Š Lighthouse loaded from global installation');
64
-
65
- // Launch Chrome with puppeteer-core (bypasses chrome-launcher!)
66
- const browser = await puppeteer.launch({
67
- executablePath: chromePath,
68
- headless: true,
69
- args: [
70
- '--no-sandbox',
71
- '--disable-setuid-sandbox',
72
- '--disable-dev-shm-usage',
73
- '--remote-debugging-port=9222'
74
- ],
75
- userDataDir: `/tmp/lighthouse-${Date.now()}` // In /tmp, not /var/folders
76
- });
77
-
78
- console.log('šŸš€ Chrome launched on port 9222');
79
-
80
- // URLs to audit
81
- const urls = [
82
- { name: 'shell', url: 'http://localhost:5001/demo/shell.html' }
83
- ];
84
-
85
- for (const { name, url } of urls) {
86
- console.log(`\n${'='.repeat(60)}`);
87
- console.log(`šŸ“Š Auditing: ${name}`);
88
- console.log('='.repeat(60));
89
-
90
- try {
91
- const result = await lighthouse(url, {
92
- port: 9222,
93
- onlyCategories: ['accessibility', 'best-practices', 'seo', 'performance'],
94
- output: 'json'
95
- });
96
-
97
- // Save report
98
- writeFileSync(`/tmp/lighthouse-${name}.json`, JSON.stringify(result.lhr, null, 2));
99
-
100
- // Display scores
101
- console.log('\nšŸ“Š SCORES:');
102
- for (const [key, cat] of Object.entries(result.lhr.categories)) {
103
- const score = Math.round(cat.score * 100);
104
- const emoji = score >= 90 ? 'āœ…' : score >= 50 ? 'āš ļø' : 'āŒ';
105
- console.log(` ${emoji} ${cat.title}: ${score}/100`);
106
- }
107
- } catch (e) {
108
- console.error(`āŒ Failed: ${e.message}`);
109
- }
110
- }
111
-
112
- await browser.close();
113
- console.log('\nāœ“ Audit complete. Reports in /tmp/lighthouse-*.json');
@@ -1,105 +0,0 @@
1
- /**
2
- * @fileoverview MicroUI Component Analyzer
3
- *
4
- * Scans source code to generate custom-elements.json manifest.
5
- * Follows Custom Elements Manifest (CEM) schema.
6
- *
7
- * Usage: node scripts/analyze-components.js
8
- */
9
-
10
- import { readFileSync, writeFileSync, readdirSync, existsSync } from 'fs';
11
- import { join } from 'path';
12
-
13
- const SRC_DIR = './src/components';
14
- const OUT_FILE = './custom-elements.json';
15
-
16
- const manifest = {
17
- schemaVersion: "1.0.0",
18
- readme: "AGENTS.md",
19
- modules: []
20
- };
21
-
22
- console.log('šŸ” Analyzing components...');
23
-
24
- if (existsSync(SRC_DIR)) {
25
- const files = readdirSync(SRC_DIR).filter(f => f.endsWith('.js'));
26
-
27
- files.forEach(file => {
28
- const content = readFileSync(join(SRC_DIR, file), 'utf-8');
29
- const moduleDoc = {
30
- kind: "javascript-module",
31
- path: `src/components/${file}`,
32
- declarations: [],
33
- exports: []
34
- };
35
-
36
- // RegEx to find class definition
37
- const classMatch = content.match(/class\s+(\w+)\s+extends\s+MuElement/);
38
- if (classMatch) {
39
- const className = classMatch[1];
40
-
41
- // Find tag name
42
- const tagMatch = content.match(/define\(['"]([\w-]+)['"]\s*,\s*\w+\)/);
43
- const tagName = tagMatch ? tagMatch[1] : null;
44
-
45
- // Find observed attributes
46
- const obsAttrMatch = content.match(/static\s+observedAttributes\s*=\s*\[(.*?)\]/s);
47
- const attributes = [];
48
- if (obsAttrMatch) {
49
- const attrs = obsAttrMatch[1].split(',').map(s => s.trim().replace(/['"]/g, ''));
50
- attrs.forEach(attr => {
51
- if (attr) attributes.push({ name: attr, type: { text: "string" } });
52
- });
53
- }
54
-
55
- // Find base class for component specific baseClass
56
- const baseClassMatch = content.match(/static\s+baseClass\s*=\s*['"]([\w-]+)['"]/);
57
- const cssBaseClass = baseClassMatch ? baseClassMatch[1] : null;
58
-
59
- // Regex to find JSDoc before class
60
- const jsdocMatch = content.match(/\/\*\*\s*([\s\S]*?)\s*\*\/\s*export\s+class/);
61
- let description = `MicroUI component: ${tagName}`;
62
-
63
- if (jsdocMatch) {
64
- const jsdoc = jsdocMatch[1];
65
- // Extract description (text before @tags)
66
- const descMatch = jsdoc.match(/@fileoverview\s+([^\n]+)/); // Try fileoverview
67
- if (descMatch) {
68
- description = descMatch[1].trim();
69
- } else {
70
- // Fallback to first line of JSDoc inside
71
- const lines = jsdoc.split('\n').filter(l => !l.trim().startsWith('* @') && l.trim().length > 3);
72
- if (lines.length > 0) description = lines[0].replace(/\*\s*/, '').trim();
73
- }
74
- }
75
-
76
- const declaration = {
77
- kind: "class",
78
- name: className,
79
- tagName: tagName,
80
- superclass: { name: "MuElement" },
81
- attributes: attributes,
82
- description: description,
83
- members: [
84
- { kind: "field", name: "baseClass", privacy: "public", default: cssBaseClass }
85
- ]
86
- };
87
-
88
- moduleDoc.declarations.push(declaration);
89
-
90
- if (tagName) {
91
- moduleDoc.exports.push({
92
- kind: "custom-element-definition",
93
- name: tagName,
94
- declaration: { name: className, module: `src/components/${file}` }
95
- });
96
- }
97
- }
98
-
99
- manifest.modules.push(moduleDoc);
100
- console.log(` āœ… ${file}`);
101
- });
102
- }
103
-
104
- writeFileSync(OUT_FILE, JSON.stringify(manifest, null, 2));
105
- console.log(`\n✨ Manifest generated: ${OUT_FILE}`);