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.
- package/AGENTS.md +71 -71
- package/CHANGELOG.md +1 -1
- package/README.md +14 -9
- package/dist/AGENTS.md +71 -71
- package/dist/README.md +14 -9
- package/dist/microui.css +1 -1
- package/dist/microui.esm.js.map +1 -1
- package/dist/microui.min.js.map +1 -1
- package/docs/getting-started.md +3 -3
- package/package.json +39 -11
- package/src/components/mu-schema-form.js +1 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -33
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
- package/.github/workflows/ci.yml +0 -42
- package/.github/workflows/deploy-pages.yml +0 -112
- package/CODE_OF_CONDUCT.md +0 -59
- package/CONTRIBUTING.md +0 -156
- package/SECURITY.md +0 -58
- package/app/.generated/routes/alerts.js +0 -8
- package/app/.generated/routes/avatars.js +0 -8
- package/app/.generated/routes/badges.js +0 -8
- package/app/.generated/routes/buttons.js +0 -10
- package/app/.generated/routes/cards.js +0 -10
- package/app/.generated/routes/checkboxes.js +0 -9
- package/app/.generated/routes/chips.js +0 -8
- package/app/.generated/routes/dropdowns.js +0 -9
- package/app/.generated/routes/home.js +0 -7
- package/app/.generated/routes/icons.js +0 -9
- package/app/.generated/routes/inputs.js +0 -10
- package/app/.generated/routes/installation.js +0 -7
- package/app/.generated/routes/layout.js +0 -9
- package/app/.generated/routes/modals.js +0 -9
- package/app/.generated/routes/navbar.js +0 -7
- package/app/.generated/routes/progress.js +0 -9
- package/app/.generated/routes/radios.js +0 -9
- package/app/.generated/routes/switches.js +0 -9
- package/app/.generated/routes/tabs.js +0 -8
- package/app/.generated/routes/toasts.js +0 -9
- package/app/index.html +0 -67
- package/app/pages/alerts.html +0 -23
- package/app/pages/avatars.html +0 -22
- package/app/pages/badges.html +0 -22
- package/app/pages/buttons.html +0 -71
- package/app/pages/cards.html +0 -54
- package/app/pages/checkboxes.html +0 -39
- package/app/pages/chips.html +0 -23
- package/app/pages/dropdowns.html +0 -41
- package/app/pages/home.html +0 -59
- package/app/pages/icons.html +0 -29
- package/app/pages/inputs.html +0 -66
- package/app/pages/installation.html +0 -34
- package/app/pages/layout.html +0 -30
- package/app/pages/modals.html +0 -21
- package/app/pages/navbar.html +0 -22
- package/app/pages/progress.html +0 -35
- package/app/pages/radios.html +0 -40
- package/app/pages/switches.html +0 -39
- package/app/pages/tabs.html +0 -30
- package/app/pages/toasts.html +0 -22
- package/app-dist/index.html +0 -67
- package/app-dist/pages/alerts.html +0 -23
- package/app-dist/pages/avatars.html +0 -22
- package/app-dist/pages/badges.html +0 -22
- package/app-dist/pages/buttons.html +0 -71
- package/app-dist/pages/cards.html +0 -54
- package/app-dist/pages/checkboxes.html +0 -39
- package/app-dist/pages/chips.html +0 -23
- package/app-dist/pages/dropdowns.html +0 -41
- package/app-dist/pages/home.html +0 -59
- package/app-dist/pages/icons.html +0 -29
- package/app-dist/pages/inputs.html +0 -66
- package/app-dist/pages/installation.html +0 -34
- package/app-dist/pages/layout.html +0 -30
- package/app-dist/pages/modals.html +0 -21
- package/app-dist/pages/navbar.html +0 -22
- package/app-dist/pages/progress.html +0 -35
- package/app-dist/pages/radios.html +0 -40
- package/app-dist/pages/switches.html +0 -39
- package/app-dist/pages/tabs.html +0 -30
- package/app-dist/pages/toasts.html +0 -22
- package/app-dist/pages.json +0 -217
- package/app-dist/routes/alerts.js +0 -5
- package/app-dist/routes/avatars.js +0 -1
- package/app-dist/routes/badges.js +0 -1
- package/app-dist/routes/buttons.js +0 -1
- package/app-dist/routes/cards.js +0 -1
- package/app-dist/routes/checkboxes.js +0 -9
- package/app-dist/routes/chips.js +0 -4
- package/app-dist/routes/chunk-019e5e2f.js +0 -5
- package/app-dist/routes/chunk-0m4j19yd.js +0 -2
- package/app-dist/routes/chunk-0tmmp5q0.js +0 -1
- package/app-dist/routes/chunk-10xn709r.js +0 -1
- package/app-dist/routes/chunk-15m2qcda.js +0 -2
- package/app-dist/routes/chunk-1bh8g23n.js +0 -1
- package/app-dist/routes/chunk-1vg0v937.js +0 -1
- package/app-dist/routes/chunk-1zvcgy3j.js +0 -1
- package/app-dist/routes/chunk-2afb0861.js +0 -1
- package/app-dist/routes/chunk-2c6ttpzt.js +0 -5
- package/app-dist/routes/chunk-3dy30fhs.js +0 -1
- package/app-dist/routes/chunk-426dnces.js +0 -13
- package/app-dist/routes/chunk-44kgxery.js +0 -1
- package/app-dist/routes/chunk-47fdnejd.js +0 -33
- package/app-dist/routes/chunk-49a6t2vq.js +0 -1
- package/app-dist/routes/chunk-4fe1rm5b.js +0 -1
- package/app-dist/routes/chunk-4ggmvkta.js +0 -33
- package/app-dist/routes/chunk-4vkz81q7.js +0 -33
- package/app-dist/routes/chunk-4w4tmj8f.js +0 -31
- package/app-dist/routes/chunk-532s62kr.js +0 -31
- package/app-dist/routes/chunk-5hm3bssy.js +0 -33
- package/app-dist/routes/chunk-5vrh24hc.js +0 -1
- package/app-dist/routes/chunk-61pcg25a.js +0 -1
- package/app-dist/routes/chunk-6nfhygvf.js +0 -1
- package/app-dist/routes/chunk-700e7je6.js +0 -33
- package/app-dist/routes/chunk-7fsn17kg.js +0 -1
- package/app-dist/routes/chunk-7k789b32.js +0 -1
- package/app-dist/routes/chunk-7r46q0ys.js +0 -36
- package/app-dist/routes/chunk-86fmc1fr.js +0 -5
- package/app-dist/routes/chunk-8qth37vw.js +0 -1
- package/app-dist/routes/chunk-924wv8n0.js +0 -1
- package/app-dist/routes/chunk-9mbhgxk9.js +0 -1
- package/app-dist/routes/chunk-a216hyd9.js +0 -1
- package/app-dist/routes/chunk-akzxykh9.js +0 -33
- package/app-dist/routes/chunk-b3dcvy8c.js +0 -1
- package/app-dist/routes/chunk-b74zahz5.js +0 -31
- package/app-dist/routes/chunk-bftj53p2.js +0 -5
- package/app-dist/routes/chunk-c01hnz3e.js +0 -1
- package/app-dist/routes/chunk-d8pvv5km.js +0 -1
- package/app-dist/routes/chunk-dev0aezr.js +0 -2
- package/app-dist/routes/chunk-dh6vnv0e.js +0 -1
- package/app-dist/routes/chunk-dn2cbpva.js +0 -36
- package/app-dist/routes/chunk-dvn0my90.js +0 -1
- package/app-dist/routes/chunk-dvq8mnve.js +0 -36
- package/app-dist/routes/chunk-e8c2gc4d.js +0 -5
- package/app-dist/routes/chunk-ejf9ak2x.js +0 -1
- package/app-dist/routes/chunk-f083m55s.js +0 -1
- package/app-dist/routes/chunk-fnrj28s1.js +0 -31
- package/app-dist/routes/chunk-fvg3yjdp.js +0 -31
- package/app-dist/routes/chunk-g7k381n1.js +0 -1
- package/app-dist/routes/chunk-h01kq2ae.js +0 -13
- package/app-dist/routes/chunk-h4dk761v.js +0 -5
- package/app-dist/routes/chunk-hmx91z2x.js +0 -5
- package/app-dist/routes/chunk-hxbg4m42.js +0 -36
- package/app-dist/routes/chunk-jbjnfp2b.js +0 -2
- package/app-dist/routes/chunk-jxtz5vv6.js +0 -36
- package/app-dist/routes/chunk-jxzcs0ey.js +0 -36
- package/app-dist/routes/chunk-kt7wwhcx.js +0 -1
- package/app-dist/routes/chunk-kzptszyc.js +0 -33
- package/app-dist/routes/chunk-mhgca4w4.js +0 -2
- package/app-dist/routes/chunk-mhswxa20.js +0 -1
- package/app-dist/routes/chunk-n8zfeex6.js +0 -1
- package/app-dist/routes/chunk-pee47b2r.js +0 -1
- package/app-dist/routes/chunk-pesmw829.js +0 -1
- package/app-dist/routes/chunk-pgc4c6f3.js +0 -36
- package/app-dist/routes/chunk-q8egegm1.js +0 -1
- package/app-dist/routes/chunk-q9mn2qyq.js +0 -36
- package/app-dist/routes/chunk-qh0rtaf3.js +0 -5
- package/app-dist/routes/chunk-qqhmk6ye.js +0 -2
- package/app-dist/routes/chunk-qrxygmf7.js +0 -33
- package/app-dist/routes/chunk-r46yzksx.js +0 -36
- package/app-dist/routes/chunk-rgpbw2w0.js +0 -5
- package/app-dist/routes/chunk-rnpzv3d8.js +0 -2
- package/app-dist/routes/chunk-s5v8cv05.js +0 -2
- package/app-dist/routes/chunk-sbwn5bpc.js +0 -1
- package/app-dist/routes/chunk-sqbg8jbt.js +0 -33
- package/app-dist/routes/chunk-sv8dqnf7.js +0 -1
- package/app-dist/routes/chunk-t67sw3za.js +0 -1
- package/app-dist/routes/chunk-tjdpqwdf.js +0 -31
- package/app-dist/routes/chunk-tq2mfghg.js +0 -1
- package/app-dist/routes/chunk-ttn10vt6.js +0 -1
- package/app-dist/routes/chunk-v2hzpjxr.js +0 -1
- package/app-dist/routes/chunk-wfjjkw9y.js +0 -1
- package/app-dist/routes/chunk-wt8cxzmf.js +0 -31
- package/app-dist/routes/chunk-x45d372k.js +0 -5
- package/app-dist/routes/chunk-y3wsazkt.js +0 -1
- package/app-dist/routes/chunk-y7pmgc7t.js +0 -33
- package/app-dist/routes/chunk-zefdt2q3.js +0 -31
- package/app-dist/routes/dropdowns.js +0 -6
- package/app-dist/routes/home.js +0 -1
- package/app-dist/routes/icons.js +0 -1
- package/app-dist/routes/inputs.js +0 -12
- package/app-dist/routes/installation.js +0 -1
- package/app-dist/routes/layout.js +0 -1
- package/app-dist/routes/modals.js +0 -7
- package/app-dist/routes/navbar.js +0 -1
- package/app-dist/routes/progress.js +0 -1
- package/app-dist/routes/radios.js +0 -6
- package/app-dist/routes/switches.js +0 -6
- package/app-dist/routes/tabs.js +0 -1
- package/app-dist/routes/toasts.js +0 -16
- package/assets/fonts/material-symbols-mini.woff2 +0 -0
- package/assets/fonts/material-symbols.woff2 +0 -0
- package/assets/fonts/roboto-400.woff2 +0 -0
- package/assets/fonts/roboto-500.woff2 +0 -0
- package/assets/fonts/roboto-700.woff2 +0 -0
- package/assets/logo-banner-400.jpg +0 -0
- package/assets/logo-banner-400.webp +0 -0
- package/assets/logo-banner-800.webp +0 -0
- package/assets/logo-banner.jpg +0 -0
- package/assets/logo-icon-64.jpg +0 -0
- package/assets/logo-icon-64.webp +0 -0
- package/assets/logo-icon.jpg +0 -0
- package/assets/logo-square.jpg +0 -0
- package/bun.lock +0 -312
- package/bunfig.toml +0 -4
- package/custom-elements.json +0 -1916
- package/demo/api/sample-data.json +0 -38
- package/demo/content/alerts.html +0 -115
- package/demo/content/avatars.html +0 -70
- package/demo/content/badges.html +0 -65
- package/demo/content/buttons.html +0 -188
- package/demo/content/callouts.html +0 -91
- package/demo/content/cards.html +0 -121
- package/demo/content/checkboxes.html +0 -178
- package/demo/content/chips.html +0 -67
- package/demo/content/codeblocks.html +0 -101
- package/demo/content/confirms.html +0 -115
- package/demo/content/datatables.html +0 -149
- package/demo/content/dividers.html +0 -119
- package/demo/content/dropdowns.html +0 -89
- package/demo/content/enterprise.html +0 -252
- package/demo/content/home.html +0 -149
- package/demo/content/icons.html +0 -89
- package/demo/content/inputs.html +0 -135
- package/demo/content/installation.html +0 -16
- package/demo/content/layout.html +0 -136
- package/demo/content/modals.html +0 -141
- package/demo/content/navbar.html +0 -70
- package/demo/content/progress.html +0 -119
- package/demo/content/radios.html +0 -88
- package/demo/content/skeletons.html +0 -109
- package/demo/content/spinners.html +0 -96
- package/demo/content/switches.html +0 -84
- package/demo/content/tables.html +0 -124
- package/demo/content/tabs.html +0 -85
- package/demo/content/toasts.html +0 -116
- package/demo/content/tooltips.html +0 -107
- package/demo/content/virtual-lists.html +0 -233
- package/demo/favicon.ico +0 -0
- package/demo/favicon.png +0 -0
- package/demo/full.html +0 -52
- package/demo/iife.html +0 -46
- package/demo/manifest.json +0 -34
- package/demo/pages/datatable-demo.html +0 -237
- package/demo/pages/prompt-ui-demo.html +0 -218
- package/demo/pages/responsive-demo.html +0 -122
- package/demo/pages/schema-form-demo.html +0 -270
- package/demo/robots.txt +0 -6
- package/demo/shell.html +0 -712
- package/demo/sw.js +0 -387
- package/lighthouse-audit.mjs +0 -113
- package/scripts/analyze-components.js +0 -105
- package/scripts/build-app.js +0 -193
- package/scripts/build-framework.js +0 -444
- package/scripts/build-utils.js +0 -101
- package/scripts/test-isolated.js +0 -151
- package/server.js +0 -256
- package/tests/agents/agent-integration.test.js +0 -76
- package/tests/benchmark.html +0 -296
- package/tests/build/scan-components.test.js +0 -173
- package/tests/components/all-components.test.js +0 -245
- package/tests/components/all-missing-components.test.js +0 -574
- package/tests/components/mu-alert.test.js +0 -113
- package/tests/components/mu-avatar.test.js +0 -148
- package/tests/components/mu-badge.test.js +0 -92
- package/tests/components/mu-button.test.js +0 -112
- package/tests/components/mu-card.test.js +0 -89
- package/tests/components/mu-checkbox.test.js +0 -158
- package/tests/components/mu-chip.test.js +0 -118
- package/tests/components/mu-container.test.js +0 -120
- package/tests/components/mu-divider.test.js +0 -98
- package/tests/components/mu-drawer-item.test.js +0 -199
- package/tests/components/mu-drawer.test.js +0 -96
- package/tests/components/mu-dropdown.test.js +0 -125
- package/tests/components/mu-form.test.js +0 -138
- package/tests/components/mu-grid.test.js +0 -135
- package/tests/components/mu-icon.test.js +0 -110
- package/tests/components/mu-input.test.js +0 -131
- package/tests/components/mu-lazy.test.js +0 -103
- package/tests/components/mu-modal.test.js +0 -275
- package/tests/components/mu-navbar.test.js +0 -101
- package/tests/components/mu-progress.test.js +0 -115
- package/tests/components/mu-radio.test.js +0 -114
- package/tests/components/mu-repeat.test.js +0 -106
- package/tests/components/mu-sidebar.test.js +0 -126
- package/tests/components/mu-skeleton.test.js +0 -162
- package/tests/components/mu-stack.test.js +0 -143
- package/tests/components/mu-switch.test.js +0 -292
- package/tests/components/mu-table.test.js +0 -124
- package/tests/components/mu-tabs.test.js +0 -104
- package/tests/components/mu-textarea.test.js +0 -115
- package/tests/components/mu-toast.test.js +0 -321
- package/tests/components/mu-tooltip.test.js +0 -133
- package/tests/components/mu-virtual-list.test.js +0 -109
- package/tests/core/MuElement.test.js +0 -120
- package/tests/core/agent-api.test.js +0 -125
- package/tests/core/all-core-modules.test.js +0 -442
- package/tests/core/bus.test.js +0 -364
- package/tests/core/component-schema.test.js +0 -160
- package/tests/core/feature-registry.test.js +0 -198
- package/tests/core/form-state.test.js +0 -167
- package/tests/core/http.test.js +0 -119
- package/tests/core/keyboard.test.js +0 -319
- package/tests/core/layers.test.js +0 -129
- package/tests/core/namespaced-stores.test.js +0 -114
- package/tests/core/render.test.js +0 -121
- package/tests/core/ripple.test.js +0 -131
- package/tests/core/router.test.js +0 -89
- package/tests/core/scheduler.test.js +0 -121
- package/tests/core/signals.test.js +0 -128
- package/tests/core/store.test.js +0 -171
- package/tests/core/transitions.test.js +0 -82
- package/tests/e2e/accessibility-harness.html +0 -58
- package/tests/e2e/accessibility.test.js +0 -401
- package/tests/e2e/agent-features.test.js +0 -372
- package/tests/e2e/card-spacing.test.js +0 -287
- package/tests/e2e/components.test.js +0 -439
- package/tests/e2e/demo-routes.test.js +0 -478
- package/tests/e2e/layout-css-fallback.test.js +0 -334
- package/tests/e2e/mu-alert.e2e.test.js +0 -111
- package/tests/e2e/mu-checkbox.test.js +0 -489
- package/tests/e2e/mu-chip.test.js +0 -347
- package/tests/e2e/mu-form.test.js +0 -499
- package/tests/e2e/mu-icon.test.js +0 -114
- package/tests/e2e/mu-radio.test.js +0 -113
- package/tests/e2e/mu-skeleton.test.js +0 -140
- package/tests/e2e/mu-switch.test.js +0 -415
- package/tests/e2e/mu-tabs.test.js +0 -494
- package/tests/e2e/mu-textarea.test.js +0 -242
- package/tests/e2e/mu-virtual-list.test.js +0 -427
- package/tests/e2e/perf-memory.test.js +0 -161
- package/tests/e2e/puppeteer-helper.js +0 -137
- package/tests/e2e/puppeteer.test.js +0 -226
- package/tests/e2e/pwa.test.js +0 -261
- package/tests/e2e/test-harness.html +0 -319
- package/tests/manual/test-components.html +0 -120
- package/tests/memory-test.html +0 -309
- package/tests/setup-dom.js +0 -93
- 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>
|