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
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}`);