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/shell.html DELETED
@@ -1,712 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <meta name="description"
8
- content="microUI v0.1.0 - AI-First Web Components Library with 49 Material Design 3 components">
9
- <title>microUI v0.1.0 - Component Showcase</title>
10
-
11
- <!-- Security: Content Security Policy -->
12
- <meta http-equiv="Content-Security-Policy"
13
- content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; connect-src 'self'; ">
14
- <!-- Permissions Policy -->
15
- <meta http-equiv="Permissions-Policy" content="camera=(), microphone=(), geolocation=()">
16
-
17
- <!-- PWA -->
18
- <link rel="manifest" href="manifest.json">
19
- <meta name="theme-color" content="#6750A4">
20
- <meta name="apple-mobile-web-app-capable" content="yes">
21
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
22
- <meta name="apple-mobile-web-app-title" content="microUI">
23
-
24
- <link rel="icon" type="image/png" href="favicon.png">
25
- <link rel="apple-touch-icon" href="favicon.png">
26
- <link rel="canonical" href="https://microui.dev/demo/">
27
-
28
- <!-- Preload critical resources -->
29
- <link rel="preload" as="image" type="image/webp" href="../assets/logo-banner-400.webp"
30
- imagesrcset="../assets/logo-banner-400.webp 1x, ../assets/logo-banner-800.webp 2x" fetchpriority="high">
31
- <link rel="preload" as="style" href="../dist/microui.css?v=2.0.197">
32
- <!-- Self-hosted fonts: Preload Roboto only (icons now use inline SVG) -->
33
- <link rel="preload" href="../assets/fonts/roboto-400.woff2" as="font" type="font/woff2" crossorigin>
34
-
35
- <!-- SOTA 2026: Speculation Rules API for predictive prefetching -->
36
- <script type="speculationrules">
37
- {
38
- "prefetch": [
39
- {
40
- "urls": [
41
- "/dist/routes/home.js",
42
- "/dist/routes/buttons.js",
43
- "/dist/routes/inputs.js",
44
- "/dist/routes/cards.js"
45
- ],
46
- "eagerness": "moderate"
47
- }
48
- ]
49
- }
50
- </script>
51
-
52
- <style>
53
- /* Self-hosted Roboto (eliminates render-blocking Google Fonts request) */
54
- @font-face {
55
- font-family: 'Roboto';
56
- font-style: normal;
57
- font-weight: 400;
58
- font-display: swap;
59
- src: url('../assets/fonts/roboto-400.woff2') format('woff2');
60
- }
61
-
62
- @font-face {
63
- font-family: 'Roboto';
64
- font-style: normal;
65
- font-weight: 500;
66
- font-display: swap;
67
- src: url('../assets/fonts/roboto-500.woff2') format('woff2');
68
- }
69
-
70
- @font-face {
71
- font-family: 'Roboto';
72
- font-style: normal;
73
- font-weight: 700;
74
- font-display: swap;
75
- src: url('../assets/fonts/roboto-700.woff2') format('woff2');
76
- }
77
-
78
- /* Material Symbols font removed - icons use inline SVG now */
79
- </style>
80
- <!-- Async CSS loading: media=print prevents blocking, onload switches to all -->
81
- <link rel="stylesheet" href="../dist/microui.css?v=2.0.197" media="print" onload="this.media='all'">
82
- <noscript>
83
- <link rel="stylesheet" href="../dist/microui.css?v=2.0.197">
84
- </noscript>
85
- <style>
86
- /* Size-adjusted Arial fallback to match Roboto metrics (from Capsize) */
87
- @font-face {
88
- font-family: 'Roboto-fallback';
89
- src: local('Arial');
90
- size-adjust: 100.06%;
91
- ascent-override: 95.01%;
92
- descent-override: 25%;
93
- line-gap-override: 0%;
94
- }
95
-
96
- /* Critical CSS */
97
- :root {
98
- --md-sys-typescale-font: 'Roboto', 'Roboto-fallback', system-ui, -apple-system, sans-serif;
99
- --md-sys-color-background: #FFFBFE;
100
- --md-sys-color-on-background: #1D1B20;
101
- --md-sys-color-surface-container: #F3EDF7;
102
- --md-sys-color-surface-container-low: #F7F2FA;
103
- --md-sys-color-primary: #6750A4;
104
- --md-sys-color-primary-container: #EADDFF;
105
- --md-sys-color-on-primary-container: #21005D;
106
- --md-sys-color-outline-variant: #CAC4D0;
107
- --md-sys-shape-corner-small: 8px;
108
- --md-sys-shape-corner-large: 16px;
109
- }
110
-
111
- [data-theme="dark"] {
112
- --md-sys-color-background: #141218;
113
- --md-sys-color-on-background: #E6E0E9;
114
- --md-sys-color-surface-container: #211F26;
115
- --md-sys-color-surface-container-low: #1D1B20;
116
- --md-sys-color-primary: #D0BCFF;
117
- --md-sys-color-primary-container: #4F378B;
118
- --md-sys-color-on-primary-container: #EADDFF;
119
- --md-sys-color-outline-variant: #49454F;
120
- }
121
-
122
- * {
123
- box-sizing: border-box;
124
- margin: 0;
125
- padding: 0;
126
- }
127
-
128
- html {
129
- font-family: var(--md-sys-typescale-font);
130
- background: var(--md-sys-color-background);
131
- color: var(--md-sys-color-on-background);
132
- }
133
-
134
- body {
135
- min-height: 100vh;
136
- display: flex;
137
- flex-direction: column;
138
- }
139
-
140
- /* App Header */
141
- .app-header {
142
- position: sticky;
143
- top: 0;
144
- z-index: 100;
145
- display: flex;
146
- align-items: center;
147
- justify-content: space-between;
148
- padding: 0 16px;
149
- height: 64px;
150
- background: var(--md-sys-color-surface-container);
151
- border-bottom: 1px solid var(--md-sys-color-outline-variant);
152
- transition: box-shadow 0.2s;
153
- }
154
-
155
- .app-header.is-scrolled {
156
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
157
- }
158
-
159
- .app-logo {
160
- display: flex;
161
- align-items: center;
162
- gap: 12px;
163
- }
164
-
165
- .logo-text {
166
- font-size: 20px;
167
- font-weight: 500;
168
- }
169
-
170
- .menu-btn {
171
- display: none;
172
- align-items: center;
173
- justify-content: center;
174
- width: 48px;
175
- height: 48px;
176
- background: transparent;
177
- border: none;
178
- border-radius: 50%;
179
- cursor: pointer;
180
- color: var(--md-sys-color-on-surface);
181
- }
182
-
183
- @media (max-width: 599px) {
184
- .app-header {
185
- padding: 0 8px;
186
- }
187
-
188
- .menu-btn {
189
- display: flex;
190
- }
191
-
192
- .logo-text {
193
- display: none;
194
- }
195
- }
196
-
197
- /* Main content */
198
- .app-main {
199
- flex: 1;
200
- padding: 32px;
201
- max-width: 900px;
202
- min-height: calc(100vh - 64px);
203
- }
204
-
205
- .app-main:focus {
206
- outline: none;
207
- }
208
-
209
- @media (max-width: 599px) {
210
- .app-main {
211
- padding: 16px;
212
- padding-bottom: calc(var(--mu-bottom-nav-height, 80px) + 16px + env(safe-area-inset-bottom, 0));
213
- }
214
- }
215
-
216
- /* Footer */
217
- .app-footer {
218
- background: var(--md-sys-color-surface-container);
219
- padding: 24px;
220
- text-align: center;
221
- border-top: 1px solid var(--md-sys-color-outline-variant);
222
- font-size: 0.875rem;
223
- color: var(--md-sys-color-on-surface-variant);
224
- }
225
-
226
- /* Loading skeleton */
227
- .shell-loading {
228
- display: flex;
229
- flex-direction: column;
230
- gap: 16px;
231
- animation: pulse 1.5s infinite;
232
- }
233
-
234
- .skeleton-block {
235
- height: 24px;
236
- background: var(--md-sys-color-surface-container);
237
- border-radius: 4px;
238
- }
239
-
240
- .skeleton-block.title {
241
- height: 32px;
242
- width: 60%;
243
- }
244
-
245
- .skeleton-block.subtitle {
246
- height: 18px;
247
- width: 80%;
248
- }
249
-
250
- .skeleton-block.content {
251
- height: 200px;
252
- }
253
-
254
- @keyframes pulse {
255
-
256
- 0%,
257
- 100% {
258
- opacity: 1;
259
- }
260
-
261
- 50% {
262
- opacity: 0.5;
263
- }
264
- }
265
-
266
- /* CLS Prevention: Pre-define bottom-nav dimensions before element registers */
267
- mu-bottom-nav:not(:defined) {
268
- display: block;
269
- position: fixed;
270
- bottom: 0;
271
- left: 0;
272
- right: 0;
273
- height: var(--mu-bottom-nav-height, 80px);
274
- z-index: 1000;
275
- }
276
-
277
- /* CLS Prevention: Contain layout for main content */
278
- #content-area {
279
- contain: layout style;
280
- min-height: 500px;
281
- }
282
-
283
- /* SOTA 2026: content-visibility for lazy rendering of off-screen examples */
284
- /* Dramatically reduces initial rendering work - up to 7x boost */
285
- mu-example {
286
- content-visibility: auto;
287
- contain-intrinsic-size: auto 300px;
288
- }
289
-
290
- /* View Transitions API: Smooth page-to-page navigation */
291
- ::view-transition-old(root),
292
- ::view-transition-new(root) {
293
- animation-duration: 150ms;
294
- }
295
-
296
- @media (prefers-reduced-motion: reduce) {
297
-
298
- ::view-transition-old(root),
299
- ::view-transition-new(root) {
300
- animation: none;
301
- }
302
- }
303
- </style>
304
- </head>
305
-
306
- <body>
307
- <mu-toast-container></mu-toast-container>
308
-
309
- <!-- MD3 Responsive Layout (App Shell) -->
310
- <mu-layout>
311
- <!-- Header -->
312
- <header slot="header" class="app-header">
313
- <div style="display: flex; align-items: center; gap: 8px;">
314
- <button id="menu-toggle" class="menu-btn" aria-label="Toggle menu"
315
- onclick="document.querySelector('mu-drawer').toggle()">
316
- <mu-icon name="menu"></mu-icon>
317
- </button>
318
- <div class="app-logo">
319
- <picture>
320
- <source srcset="../assets/logo-icon-64.webp" type="image/webp">
321
- <img src="../assets/logo-icon-64.jpg" alt="microUI" width="32" height="32" decoding="async"
322
- style="border-radius: 6px;">
323
- </picture>
324
- <span class="logo-text">microUI v0.1.0</span>
325
- </div>
326
- </div>
327
- <div class="app-nav">
328
- <mu-theme-toggle></mu-theme-toggle>
329
- </div>
330
- </header>
331
-
332
- <!-- Drawer Navigation -->
333
- <mu-drawer slot="drawer" mode="auto" expand-on-hover>
334
- <div slot="header" style="padding: 16px; display: flex; align-items: center; gap: 12px;">
335
- <mu-icon name="widgets" style="color: var(--md-sys-color-primary);"></mu-icon>
336
- <span style="font-weight: 500;">Components</span>
337
- </div>
338
-
339
- <!-- Getting Started -->
340
- <mu-drawer-item icon="home" href="#home" data-page="home" active label="Overview"></mu-drawer-item>
341
- <mu-drawer-item icon="download" href="#installation" data-page="installation"
342
- label="Installation"></mu-drawer-item>
343
-
344
- <!-- Actions -->
345
- <mu-drawer-item icon="smart_button" href="#buttons" data-page="buttons" label="Buttons"></mu-drawer-item>
346
-
347
- <!-- Inputs -->
348
- <mu-drawer-item icon="text_fields" href="#inputs" data-page="inputs" label="Text Fields"></mu-drawer-item>
349
- <mu-drawer-item icon="check_box" href="#checkboxes" data-page="checkboxes"
350
- label="Checkboxes"></mu-drawer-item>
351
- <mu-drawer-item icon="toggle_on" href="#switches" data-page="switches" label="Switches"></mu-drawer-item>
352
- <mu-drawer-item icon="radio_button_checked" href="#radios" data-page="radios"
353
- label="Radio Buttons"></mu-drawer-item>
354
- <mu-drawer-item icon="arrow_drop_down_circle" href="#dropdowns"
355
- data-page="dropdowns">Dropdowns</mu-drawer-item>
356
-
357
- <!-- Layout -->
358
- <mu-drawer-item icon="view_carousel" href="#cards" data-page="cards" label="Cards"></mu-drawer-item>
359
- <mu-drawer-item icon="grid_view" href="#layout" data-page="layout" label="Stack & Grid"></mu-drawer-item>
360
- <mu-drawer-item icon="remove" href="#dividers" data-page="dividers" label="Divider"></mu-drawer-item>
361
-
362
- <!-- Navigation -->
363
- <mu-drawer-item icon="tab" href="#tabs" data-page="tabs" label="Tabs"></mu-drawer-item>
364
- <mu-drawer-item icon="menu" href="#navbar" data-page="navbar" label="Navbar"></mu-drawer-item>
365
-
366
- <!-- Feedback -->
367
- <mu-drawer-item icon="warning" href="#alerts" data-page="alerts" label="Alerts"></mu-drawer-item>
368
- <mu-drawer-item icon="info" href="#callouts" data-page="callouts" label="Callout"></mu-drawer-item>
369
- <mu-drawer-item icon="notifications" href="#toasts" data-page="toasts" label="Toasts"></mu-drawer-item>
370
- <mu-drawer-item icon="open_in_new" href="#modals" data-page="modals" label="Modals"></mu-drawer-item>
371
- <mu-drawer-item icon="hourglass_empty" href="#progress" data-page="progress"
372
- label="Progress"></mu-drawer-item>
373
- <mu-drawer-item icon="category" href="#skeletons" data-page="skeletons" label="Skeleton"></mu-drawer-item>
374
- <mu-drawer-item icon="widgets" href="#spinners" data-page="spinners" label="Spinner"></mu-drawer-item>
375
- <mu-drawer-item icon="check_circle" href="#confirms" data-page="confirms" label="Confirm"></mu-drawer-item>
376
-
377
- <!-- Display -->
378
- <mu-drawer-item icon="account_circle" href="#avatars" data-page="avatars" label="Avatars"></mu-drawer-item>
379
- <mu-drawer-item icon="fiber_manual_record" href="#badges" data-page="badges"
380
- label="Badges"></mu-drawer-item>
381
- <mu-drawer-item icon="label" href="#chips" data-page="chips" label="Chips"></mu-drawer-item>
382
- <mu-drawer-item icon="emoji_emotions" href="#icons" data-page="icons" label="Icons"></mu-drawer-item>
383
- <mu-drawer-item icon="notification_important" href="#tooltips" data-page="tooltips"
384
- label="Tooltip"></mu-drawer-item>
385
-
386
- <!-- Data -->
387
- <mu-drawer-item icon="grid_view" href="#tables" data-page="tables" label="Table"></mu-drawer-item>
388
- <mu-drawer-item icon="monitoring" href="#datatables" data-page="datatables"
389
- label="DataTable"></mu-drawer-item>
390
- <mu-drawer-item icon="settings" href="#codeblocks" data-page="codeblocks"
391
- label="Code Block"></mu-drawer-item>
392
- <mu-drawer-item icon="view_carousel" href="#virtual-lists" data-page="virtual-lists"
393
- label="Virtual List"></mu-drawer-item>
394
-
395
- <!-- Enterprise -->
396
- <mu-drawer-item icon="business" href="#enterprise" data-page="enterprise"
397
- label="Enterprise"></mu-drawer-item>
398
- </mu-drawer>
399
-
400
- <!-- Bottom Navigation (Mobile Only) -->
401
- <mu-bottom-nav slot="bottom" hide-on-desktop>
402
- <mu-nav-item icon="home" href="#home" active>Home</mu-nav-item>
403
- <mu-nav-item icon="smart_button" href="#buttons">Actions</mu-nav-item>
404
- <mu-nav-item icon="input" href="#inputs">Inputs</mu-nav-item>
405
- <mu-nav-item icon="category" href="#cards">Layout</mu-nav-item>
406
- </mu-bottom-nav>
407
-
408
- <!-- Main Content Area (dynamic) -->
409
- <!-- Skip link anchors for accessibility (Lighthouse requirement) -->
410
- <div id="home" tabindex="-1" aria-hidden="true"></div>
411
- <div id="installation" tabindex="-1" aria-hidden="true"></div>
412
- <div id="buttons" tabindex="-1" aria-hidden="true"></div>
413
- <div id="inputs" tabindex="-1" aria-hidden="true"></div>
414
- <div id="checkboxes" tabindex="-1" aria-hidden="true"></div>
415
- <div id="switches" tabindex="-1" aria-hidden="true"></div>
416
- <div id="radios" tabindex="-1" aria-hidden="true"></div>
417
- <div id="dropdowns" tabindex="-1" aria-hidden="true"></div>
418
- <div id="cards" tabindex="-1" aria-hidden="true"></div>
419
- <div id="layout" tabindex="-1" aria-hidden="true"></div>
420
- <div id="dividers" tabindex="-1" aria-hidden="true"></div>
421
- <div id="tabs" tabindex="-1" aria-hidden="true"></div>
422
- <div id="navbar" tabindex="-1" aria-hidden="true"></div>
423
- <div id="alerts" tabindex="-1" aria-hidden="true"></div>
424
- <div id="callouts" tabindex="-1" aria-hidden="true"></div>
425
- <div id="toasts" tabindex="-1" aria-hidden="true"></div>
426
- <div id="modals" tabindex="-1" aria-hidden="true"></div>
427
- <div id="progress" tabindex="-1" aria-hidden="true"></div>
428
- <div id="skeletons" tabindex="-1" aria-hidden="true"></div>
429
- <div id="spinners" tabindex="-1" aria-hidden="true"></div>
430
- <div id="confirms" tabindex="-1" aria-hidden="true"></div>
431
- <div id="avatars" tabindex="-1" aria-hidden="true"></div>
432
- <div id="badges" tabindex="-1" aria-hidden="true"></div>
433
- <div id="chips" tabindex="-1" aria-hidden="true"></div>
434
- <div id="icons" tabindex="-1" aria-hidden="true"></div>
435
- <div id="tooltips" tabindex="-1" aria-hidden="true"></div>
436
- <div id="tables" tabindex="-1" aria-hidden="true"></div>
437
- <div id="datatables" tabindex="-1" aria-hidden="true"></div>
438
- <div id="codeblocks" tabindex="-1" aria-hidden="true"></div>
439
- <div id="virtual-lists" tabindex="-1" aria-hidden="true"></div>
440
- <div id="enterprise" tabindex="-1" aria-hidden="true"></div>
441
- <main id="content-area" class="app-main">
442
- <!-- Loading skeleton shown while content loads -->
443
- <div class="shell-loading">
444
- <div class="skeleton-block title"></div>
445
- <div class="skeleton-block subtitle"></div>
446
- <div class="skeleton-block content"></div>
447
- </div>
448
- </main>
449
-
450
- <!-- Footer -->
451
- <footer slot="footer" class="app-footer">
452
- <p>microUI v0.1.0 • Apache-2.0 • Made with ❤️</p>
453
- </footer>
454
- </mu-layout>
455
-
456
- <script type="module">
457
- // =============================================
458
- // APP SHELL - Dynamic Content Loading
459
- // =============================================
460
- const perfStart = performance.now();
461
- const loadedRoutes = new Set();
462
- const loadedContent = new Map();
463
- const contentArea = document.getElementById('content-area');
464
-
465
- // Load JS route bundle
466
- async function loadRoute(name) {
467
- if (loadedRoutes.has(name)) return;
468
- loadedRoutes.add(name);
469
- const start = performance.now();
470
- await import('../dist/routes/' + name + '.js?v=2.0.197');
471
- console.log('[Shell] Route ' + name + '.js loaded in ' + (performance.now() - start).toFixed(0) + 'ms');
472
- }
473
-
474
- // Load HTML content fragment
475
- async function loadContent(pageId) {
476
- if (loadedContent.has(pageId)) {
477
- return loadedContent.get(pageId);
478
- }
479
-
480
- try {
481
- const response = await fetch('content/' + pageId + '.html');
482
- if (!response.ok) {
483
- // Fallback: try loading from index.html fragment
484
- console.log('[Shell] Content fragment not found, using inline');
485
- return null;
486
- }
487
- const html = await response.text();
488
- loadedContent.set(pageId, html);
489
- return html;
490
- } catch (e) {
491
- console.error('[Shell] Failed to load content:', e);
492
- return null;
493
- }
494
- }
495
-
496
- // Defer component loading
497
- const deferFn = window.requestIdleCallback || ((cb) => setTimeout(cb, 1));
498
- deferFn(() => loadRoute('shell-critical'), { timeout: 500 });
499
- deferFn(() => loadRoute('shell-deferred'), { timeout: 1000 });
500
-
501
- // Initial route
502
- const initialRoute = window.location.hash ? window.location.hash.slice(1) : 'home';
503
-
504
- // Show page with dynamic content loading
505
- // SOTA 2026: Use View Transitions API for smooth navigation
506
- async function showPage(pageId) {
507
- const updateDOM = async () => {
508
- // Load route JS
509
- await loadRoute(pageId);
510
-
511
- // Try to load content fragment
512
- const content = await loadContent(pageId);
513
-
514
- if (content) {
515
- contentArea.innerHTML = content;
516
- // Execute inline scripts (innerHTML doesn't run them automatically)
517
- contentArea.querySelectorAll('script').forEach(oldScript => {
518
- const newScript = document.createElement('script');
519
- newScript.textContent = oldScript.textContent;
520
- oldScript.parentNode.replaceChild(newScript, oldScript);
521
- });
522
- // Setup tabs after content injection
523
- setupContentTabs();
524
- } else {
525
- contentArea.innerHTML = `
526
- <div class="page active">
527
- <h1 class="page-title">${pageId.charAt(0).toUpperCase() + pageId.slice(1)}</h1>
528
- <p class="page-subtitle">Loading content...</p>
529
- </div>
530
- `;
531
- }
532
- };
533
-
534
- // Use View Transitions if available (progressive enhancement)
535
- if (document.startViewTransition) {
536
- await document.startViewTransition(updateDOM).finished;
537
- } else {
538
- await updateDOM();
539
- }
540
-
541
- // Update active states
542
- document.querySelectorAll('mu-drawer-item').forEach(item => {
543
- item.toggleAttribute('active', item.dataset.page === pageId);
544
- });
545
- document.querySelectorAll('mu-nav-item').forEach(item => {
546
- const href = item.getAttribute('href');
547
- item.toggleAttribute('active', href === '#' + pageId);
548
- });
549
-
550
- window.scrollTo(0, 0);
551
-
552
- // Interaction: Update title and manage focus for A11y
553
- document.title = `microUI v0.1.0 - ${pageId.charAt(0).toUpperCase() + pageId.slice(1)}`;
554
-
555
- // Move focus to main content (skip navigation)
556
- contentArea.setAttribute('tabindex', '-1');
557
- contentArea.focus({ preventScroll: true });
558
- }
559
-
560
- // Setup documentation tabs (Overview/API/Styling/Examples)
561
- function setupDocTabs(tabsId, contentIds) {
562
- const tabs = document.getElementById(tabsId);
563
- if (tabs) {
564
- tabs.addEventListener('mu-tab-change', (e) => {
565
- contentIds.forEach((id, i) => {
566
- const el = document.getElementById(id);
567
- if (el) {
568
- el.style.display = i === e.detail.index ? 'block' : 'none';
569
- }
570
- });
571
- });
572
- }
573
- }
574
-
575
- // Setup demo tabs (e.g., tabs within examples)
576
- function setupDemoTabs(tabsId, contentId, labels) {
577
- const tabs = document.getElementById(tabsId);
578
- const contentEl = document.getElementById(contentId);
579
- if (tabs && contentEl) {
580
- tabs.addEventListener('mu-tab-change', (e) => {
581
- contentEl.textContent = `Content for ${labels[e.detail.index]}`;
582
- });
583
- }
584
- }
585
-
586
- // Auto-setup tabs after content is loaded
587
- function setupContentTabs() {
588
- // Pattern: find all mu-tabs with id ending in '-doc-tabs'
589
- const docTabGroups = contentArea.querySelectorAll('mu-tabs[id$="-doc-tabs"]');
590
- docTabGroups.forEach(tabs => {
591
- const prefix = tabs.id.replace('-doc-tabs', '');
592
- const contentIds = [
593
- `${prefix}-overview`,
594
- `${prefix}-api`,
595
- `${prefix}-styling`,
596
- `${prefix}-examples`
597
- ];
598
- setupDocTabs(tabs.id, contentIds);
599
- });
600
-
601
- // Setup demo tabs (specific to tabs.html)
602
- setupDemoTabs('demo-tabs', 'tabs-content', ['Overview', 'Details', 'Settings']);
603
- }
604
-
605
- // showToast helper - uses Toast.show() directly
606
- window.showToast = async function (message, options = {}) {
607
- // Ensure toast component is loaded
608
- await loadRoute('toasts');
609
-
610
- // Use the Toast manager directly (more reliable than SignalBus emit)
611
- const position = options.position || 'bottom-center';
612
- let container = document.querySelector(`mu-toast-container[position="${position}"]`);
613
-
614
- if (!container) {
615
- container = document.querySelector('mu-toast-container');
616
- if (container && position !== 'bottom-center') {
617
- container.setAttribute('position', position);
618
- } else if (!container) {
619
- container = document.createElement('mu-toast-container');
620
- container.setAttribute('position', position);
621
- document.body.appendChild(container);
622
- }
623
- }
624
-
625
- const toast = document.createElement('mu-toast');
626
- toast.textContent = message;
627
-
628
- if (options.severity) {
629
- toast.setAttribute('severity', options.severity);
630
- }
631
- if (options.type) {
632
- toast.setAttribute('severity', options.type);
633
- }
634
- if (options.duration) {
635
- toast.setAttribute('duration', options.duration.toString());
636
- }
637
-
638
- container.appendChild(toast);
639
- return toast;
640
- };
641
-
642
- // Navigation event handlers
643
- document.querySelectorAll('mu-drawer-item').forEach(item => {
644
- item.addEventListener('mouseenter', () => {
645
- const pageId = item.dataset.page;
646
- if (pageId && !loadedRoutes.has(pageId)) {
647
- loadRoute(pageId); // Preload on hover
648
- }
649
- });
650
- item.addEventListener('click', async (e) => {
651
- e.preventDefault();
652
- const pageId = item.dataset.page;
653
- if (pageId) {
654
- window.location.hash = pageId;
655
- }
656
- });
657
- });
658
-
659
- // Hash change handler
660
- window.addEventListener('hashchange', () => {
661
- const pageId = window.location.hash.slice(1) || 'home';
662
- showPage(pageId);
663
- });
664
-
665
- // Header scroll elevation
666
- const appHeader = document.querySelector('.app-header');
667
- if (appHeader) {
668
- window.addEventListener('scroll', () => {
669
- appHeader.classList.toggle('is-scrolled', window.scrollY > 0);
670
- }, { passive: true });
671
- }
672
-
673
- // Initial page load
674
- showPage(initialRoute);
675
- console.log('[Shell] Initial load: ' + (performance.now() - perfStart).toFixed(0) + 'ms');
676
- </script>
677
-
678
- <!-- Service Worker Registration -->
679
- <script>
680
- window.microUICache = {
681
- clear: async () => {
682
- if (!navigator.serviceWorker?.controller) return false;
683
- return new Promise((resolve) => {
684
- const channel = new MessageChannel();
685
- channel.port1.onmessage = (e) => { resolve(e.data.success); location.reload(); };
686
- navigator.serviceWorker.controller.postMessage({ type: 'CLEAR_CACHE' }, [channel.port2]);
687
- });
688
- },
689
- status: async () => {
690
- if (!navigator.serviceWorker?.controller) return null;
691
- return new Promise((resolve) => {
692
- const channel = new MessageChannel();
693
- channel.port1.onmessage = (e) => resolve(e.data);
694
- navigator.serviceWorker.controller.postMessage({ type: 'GET_CACHE_STATUS' }, [channel.port2]);
695
- });
696
- }
697
- };
698
-
699
- if ('serviceWorker' in navigator) {
700
- window.addEventListener('load', async () => {
701
- try {
702
- const reg = await navigator.serviceWorker.register('sw.js');
703
- console.log('[SW] Registered:', reg.scope);
704
- } catch (e) {
705
- console.error('[SW] Registration failed:', e);
706
- }
707
- });
708
- }
709
- </script>
710
- </body>
711
-
712
- </html>