zero-query 1.1.1 → 1.2.0
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/LICENSE +21 -21
- package/README.md +2 -0
- package/cli/args.js +33 -33
- package/cli/commands/build-api.js +443 -442
- package/cli/commands/build.js +254 -247
- package/cli/commands/bundle.js +1228 -1224
- package/cli/commands/create.js +137 -121
- package/cli/commands/dev/devtools/index.js +56 -56
- package/cli/commands/dev/devtools/js/components.js +49 -49
- package/cli/commands/dev/devtools/js/core.js +423 -423
- package/cli/commands/dev/devtools/js/elements.js +421 -421
- package/cli/commands/dev/devtools/js/network.js +166 -166
- package/cli/commands/dev/devtools/js/performance.js +73 -73
- package/cli/commands/dev/devtools/js/router.js +105 -105
- package/cli/commands/dev/devtools/js/source.js +132 -132
- package/cli/commands/dev/devtools/js/stats.js +35 -35
- package/cli/commands/dev/devtools/js/tabs.js +79 -79
- package/cli/commands/dev/devtools/panel.html +95 -95
- package/cli/commands/dev/devtools/styles.css +244 -244
- package/cli/commands/dev/index.js +107 -107
- package/cli/commands/dev/logger.js +75 -75
- package/cli/commands/dev/overlay.js +858 -858
- package/cli/commands/dev/server.js +220 -220
- package/cli/commands/dev/validator.js +94 -94
- package/cli/commands/dev/watcher.js +172 -172
- package/cli/help.js +114 -112
- package/cli/index.js +52 -52
- package/cli/scaffold/default/LICENSE +21 -21
- package/cli/scaffold/default/app/app.js +207 -207
- package/cli/scaffold/default/app/components/about.js +201 -201
- package/cli/scaffold/default/app/components/api-demo.js +143 -143
- package/cli/scaffold/default/app/components/contact-card.js +231 -231
- package/cli/scaffold/default/app/components/contacts/contacts.css +706 -706
- package/cli/scaffold/default/app/components/contacts/contacts.html +200 -200
- package/cli/scaffold/default/app/components/contacts/contacts.js +196 -196
- package/cli/scaffold/default/app/components/counter.js +127 -127
- package/cli/scaffold/default/app/components/home.js +249 -249
- package/cli/scaffold/default/app/components/not-found.js +16 -16
- package/cli/scaffold/default/app/components/playground/playground.css +115 -115
- package/cli/scaffold/default/app/components/playground/playground.html +161 -161
- package/cli/scaffold/default/app/components/playground/playground.js +116 -116
- package/cli/scaffold/default/app/components/todos.js +225 -225
- package/cli/scaffold/default/app/components/toolkit/toolkit.css +97 -97
- package/cli/scaffold/default/app/components/toolkit/toolkit.html +146 -146
- package/cli/scaffold/default/app/components/toolkit/toolkit.js +280 -280
- package/cli/scaffold/default/app/routes.js +15 -15
- package/cli/scaffold/default/app/store.js +101 -101
- package/cli/scaffold/default/global.css +552 -552
- package/cli/scaffold/default/index.html +99 -99
- package/cli/scaffold/minimal/app/app.js +85 -85
- package/cli/scaffold/minimal/app/components/about.js +68 -68
- package/cli/scaffold/minimal/app/components/counter.js +122 -122
- package/cli/scaffold/minimal/app/components/home.js +68 -68
- package/cli/scaffold/minimal/app/components/not-found.js +16 -16
- package/cli/scaffold/minimal/app/routes.js +9 -9
- package/cli/scaffold/minimal/app/store.js +36 -36
- package/cli/scaffold/minimal/global.css +300 -300
- package/cli/scaffold/minimal/index.html +44 -44
- package/cli/scaffold/ssr/app/app.js +41 -41
- package/cli/scaffold/ssr/app/components/about.js +55 -55
- package/cli/scaffold/ssr/app/components/blog/index.js +65 -65
- package/cli/scaffold/ssr/app/components/blog/post.js +86 -86
- package/cli/scaffold/ssr/app/components/home.js +37 -37
- package/cli/scaffold/ssr/app/components/not-found.js +15 -15
- package/cli/scaffold/ssr/app/routes.js +8 -8
- package/cli/scaffold/ssr/global.css +228 -228
- package/cli/scaffold/ssr/index.html +37 -37
- package/cli/scaffold/ssr/package.json +8 -8
- package/cli/scaffold/ssr/server/data/posts.js +144 -144
- package/cli/scaffold/ssr/server/index.js +213 -213
- package/cli/scaffold/webrtc/app/app.js +11 -0
- package/cli/scaffold/webrtc/app/components/video-room.js +295 -0
- package/cli/scaffold/webrtc/app/lib/room.js +252 -0
- package/cli/scaffold/webrtc/assets/.gitkeep +0 -0
- package/cli/scaffold/webrtc/global.css +250 -0
- package/cli/scaffold/webrtc/index.html +21 -0
- package/cli/utils.js +305 -287
- package/dist/API.md +661 -0
- package/dist/zquery.dist.zip +0 -0
- package/dist/zquery.js +10313 -6614
- package/dist/zquery.min.js +8 -631
- package/index.d.ts +570 -371
- package/index.js +311 -240
- package/package.json +76 -70
- package/src/component.js +1709 -1691
- package/src/core.js +921 -921
- package/src/diff.js +497 -497
- package/src/errors.js +209 -209
- package/src/expression.js +922 -922
- package/src/http.js +242 -242
- package/src/package.json +1 -1
- package/src/reactive.js +255 -255
- package/src/router.js +843 -843
- package/src/ssr.js +418 -418
- package/src/store.js +318 -318
- package/src/utils.js +515 -515
- package/src/webrtc/e2ee.js +351 -0
- package/src/webrtc/errors.js +116 -0
- package/src/webrtc/ice.js +301 -0
- package/src/webrtc/index.js +131 -0
- package/src/webrtc/joinToken.js +119 -0
- package/src/webrtc/observe.js +172 -0
- package/src/webrtc/peer.js +351 -0
- package/src/webrtc/reactive.js +268 -0
- package/src/webrtc/room.js +625 -0
- package/src/webrtc/sdp.js +302 -0
- package/src/webrtc/sfu/index.js +43 -0
- package/src/webrtc/sfu/livekit.js +131 -0
- package/src/webrtc/sfu/mediasoup.js +150 -0
- package/src/webrtc/signaling.js +373 -0
- package/src/webrtc/turn.js +237 -0
- package/tests/_helpers/webrtcFakes.js +289 -0
- package/tests/audit.test.js +4158 -4158
- package/tests/cli.test.js +1136 -1103
- package/tests/compare.test.js +497 -486
- package/tests/component.test.js +3969 -3938
- package/tests/core.test.js +1910 -1910
- package/tests/dev-server.test.js +489 -489
- package/tests/diff.test.js +1416 -1416
- package/tests/docs.test.js +1664 -1650
- package/tests/electron-features.test.js +864 -864
- package/tests/errors.test.js +619 -619
- package/tests/expression.test.js +1056 -1056
- package/tests/http.test.js +648 -648
- package/tests/reactive.test.js +819 -819
- package/tests/router.test.js +2327 -2327
- package/tests/ssr.test.js +870 -870
- package/tests/store.test.js +830 -830
- package/tests/test-minifier.js +153 -153
- package/tests/test-ssr.js +27 -27
- package/tests/utils.test.js +1377 -1377
- package/tests/webrtc/e2ee.test.js +283 -0
- package/tests/webrtc/ice.test.js +202 -0
- package/tests/webrtc/joinToken.test.js +89 -0
- package/tests/webrtc/observe.test.js +111 -0
- package/tests/webrtc/peer.test.js +373 -0
- package/tests/webrtc/reactive.test.js +235 -0
- package/tests/webrtc/room.test.js +406 -0
- package/tests/webrtc/sdp.test.js +151 -0
- package/tests/webrtc/sfu-livekit.test.js +119 -0
- package/tests/webrtc/sfu.test.js +160 -0
- package/tests/webrtc/signaling.test.js +251 -0
- package/tests/webrtc/turn.test.js +256 -0
- package/types/collection.d.ts +383 -383
- package/types/component.d.ts +186 -186
- package/types/errors.d.ts +135 -135
- package/types/http.d.ts +92 -92
- package/types/misc.d.ts +201 -201
- package/types/reactive.d.ts +98 -98
- package/types/router.d.ts +190 -190
- package/types/ssr.d.ts +102 -102
- package/types/store.d.ts +146 -146
- package/types/utils.d.ts +245 -245
- package/types/webrtc.d.ts +653 -0
|
@@ -1,201 +1,201 @@
|
|
|
1
|
-
// about.js - About page with theme switcher
|
|
2
|
-
//
|
|
3
|
-
// Features used:
|
|
4
|
-
// $.storage - localStorage wrapper (get / set)
|
|
5
|
-
// $.version - library version string
|
|
6
|
-
// $.unitTests - build-time test results object
|
|
7
|
-
// $.bus.emit - toast notifications
|
|
8
|
-
// data-theme attr - dark / light theming
|
|
9
|
-
|
|
10
|
-
$.component('about-page', {
|
|
11
|
-
styles: `
|
|
12
|
-
/* -- Hero -- */
|
|
13
|
-
.about-hero { text-align: center; padding: 2.5rem 1rem 1.5rem; }
|
|
14
|
-
.about-hero h1 { font-size: 2rem; font-weight: 700; letter-spacing: -0.03em; margin-bottom: 0.35rem; }
|
|
15
|
-
.about-hero .ver { display: inline-block; padding: 0.2rem 0.65rem; border-radius: 999px;
|
|
16
|
-
font-size: 0.78rem; font-weight: 600; color: var(--accent);
|
|
17
|
-
background: var(--accent-soft); border: 1px solid rgba(88,166,255,.15);
|
|
18
|
-
margin-bottom: 0.75rem; }
|
|
19
|
-
.about-hero p { color: var(--text-muted); font-size: 0.95rem; max-width: 520px; margin: 0 auto; }
|
|
20
|
-
|
|
21
|
-
/* -- Stats bar -- */
|
|
22
|
-
.about-stats { display: flex; justify-content: center; gap: 2rem; flex-wrap: wrap;
|
|
23
|
-
padding: 1.25rem 0; border-top: 1px solid var(--border);
|
|
24
|
-
border-bottom: 1px solid var(--border); margin: 1.25rem 0; }
|
|
25
|
-
.about-stat { text-align: center; }
|
|
26
|
-
.about-stat-val { font-size: 1.35rem; font-weight: 700; color: var(--accent);
|
|
27
|
-
font-variant-numeric: tabular-nums; }
|
|
28
|
-
.about-stat-lbl { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase;
|
|
29
|
-
letter-spacing: 0.04em; }
|
|
30
|
-
|
|
31
|
-
/* -- Theme switcher -- */
|
|
32
|
-
.theme-switch { display: inline-flex; border-radius: var(--radius); overflow: hidden;
|
|
33
|
-
border: 1px solid var(--border); background: var(--bg); }
|
|
34
|
-
.theme-btn { padding: 0.45rem 1rem; font-size: 0.82rem; font-weight: 500;
|
|
35
|
-
background: transparent; border: none; color: var(--text-muted);
|
|
36
|
-
cursor: pointer; transition: all .15s ease; font-family: inherit;
|
|
37
|
-
display: inline-flex; align-items: center; gap: 0.35rem; }
|
|
38
|
-
.theme-btn:hover { color: var(--text); background: var(--bg-hover); }
|
|
39
|
-
.theme-btn.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
|
|
40
|
-
.theme-btn + .theme-btn { border-left: 1px solid var(--border); }
|
|
41
|
-
|
|
42
|
-
/* -- Feature categories -- */
|
|
43
|
-
.feat-section { margin-bottom: 0.5rem; }
|
|
44
|
-
.feat-label { font-size: 0.72rem; font-weight: 600; text-transform: uppercase;
|
|
45
|
-
letter-spacing: 0.05em; color: var(--text-muted); margin-bottom: 0.4rem;
|
|
46
|
-
padding-left: 0.1rem; }
|
|
47
|
-
|
|
48
|
-
/* -- Test badge -- */
|
|
49
|
-
.test-badge { display: inline-flex; align-items: center; gap: 0.3rem;
|
|
50
|
-
padding: 0.2rem 0.55rem; border-radius: 999px;
|
|
51
|
-
font-size: 0.7rem; font-weight: 600; line-height: 1;
|
|
52
|
-
margin-top: 0.35rem; }
|
|
53
|
-
.test-badge.pass { background: rgba(63,185,80,.12); color: var(--success);
|
|
54
|
-
border: 1px solid rgba(63,185,80,.25); }
|
|
55
|
-
.test-badge.fail { background: rgba(248,81,73,.12); color: var(--danger);
|
|
56
|
-
border: 1px solid rgba(248,81,73,.25); }
|
|
57
|
-
.test-badge svg { width: 11px; height: 11px; }
|
|
58
|
-
|
|
59
|
-
@media (max-width: 768px) {
|
|
60
|
-
.about-hero { padding: 1.5rem 0.5rem 1rem; }
|
|
61
|
-
.about-hero h1 { font-size: 1.5rem; }
|
|
62
|
-
.about-stats { gap: 1rem; }
|
|
63
|
-
.about-stat-val { font-size: 1.1rem; }
|
|
64
|
-
.theme-btn { padding: 0.4rem 0.65rem; font-size: 0.78rem; }
|
|
65
|
-
}
|
|
66
|
-
@media (max-width: 480px) {
|
|
67
|
-
.about-hero h1 { font-size: 1.3rem; }
|
|
68
|
-
.about-stats { gap: 0.6rem 1rem; }
|
|
69
|
-
.about-stat-val { font-size: 1rem; }
|
|
70
|
-
}
|
|
71
|
-
`,
|
|
72
|
-
|
|
73
|
-
state: () => ({
|
|
74
|
-
theme: 'system',
|
|
75
|
-
}),
|
|
76
|
-
|
|
77
|
-
mounted() {
|
|
78
|
-
this.state.theme = $.storage.get('theme') || 'system';
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
setTheme(mode) {
|
|
82
|
-
this.state.theme = mode;
|
|
83
|
-
$.storage.set('theme', mode);
|
|
84
|
-
window.__applyTheme(mode);
|
|
85
|
-
const label = mode === 'system' ? 'system (auto)' : mode;
|
|
86
|
-
$.bus.emit('toast', { message: `Theme: ${label}`, type: 'info' });
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
render() {
|
|
90
|
-
const t = this.state.theme;
|
|
91
|
-
const feats = {
|
|
92
|
-
'Core & Components': [
|
|
93
|
-
['$.component()', 'Reactive components with state, lifecycle, and template rendering'],
|
|
94
|
-
['computed / watch', 'Derived state and reactive watchers on the counter page'],
|
|
95
|
-
['DOM Diffing', 'Efficient morph() engine patches only changed DOM nodes'],
|
|
96
|
-
['z-key', 'Keyed list reconciliation in z-for loops'],
|
|
97
|
-
['z-model / z-ref', 'Two-way data binding and DOM element references'],
|
|
98
|
-
['CSP-safe expressions', 'Template expressions without eval() or new Function()'],
|
|
99
|
-
],
|
|
100
|
-
'Directives': [
|
|
101
|
-
['z-if / z-for / z-show', 'Structural directives for conditional & list rendering'],
|
|
102
|
-
['z-bind / z-class / z-style', 'Dynamic attributes, classes, and inline styles'],
|
|
103
|
-
['z-debounce', 'Debounced model updates - z-model z-debounce="300"'],
|
|
104
|
-
['z-lowercase / z-uppercase', 'Auto-transform text input on contacts email'],
|
|
105
|
-
['z-html', 'Trusted HTML injection in the playground'],
|
|
106
|
-
['templateUrl / styleUrl', 'External templates and CSS with auto-scoping'],
|
|
107
|
-
],
|
|
108
|
-
'Events': [
|
|
109
|
-
['@click.stop / .prevent', 'Event modifiers for fine-grained control'],
|
|
110
|
-
['@click.self / .once', 'Self-only and one-shot handlers in modals'],
|
|
111
|
-
['@click.outside', 'Outside-click detection for dropdowns'],
|
|
112
|
-
['@keydown.escape', 'Key modifiers - Escape to close forms'],
|
|
113
|
-
],
|
|
114
|
-
'Reactive Primitives': [
|
|
115
|
-
['$.signal() / $.computed()', 'Fine-grained reactive primitives for derived state'],
|
|
116
|
-
['$.effect()', 'Side-effects that auto-track signal dependencies'],
|
|
117
|
-
],
|
|
118
|
-
'State & Routing': [
|
|
119
|
-
['$.router()', 'SPA routing with history mode and fallback pages'],
|
|
120
|
-
['$.store()', 'Centralized state with actions, getters, subscriptions'],
|
|
121
|
-
['store.use / store.snapshot', 'Action middleware, deep-cloning, and history'],
|
|
122
|
-
['$.bus', 'Event bus for cross-component communication'],
|
|
123
|
-
['$.storage', 'localStorage wrapper for persisting preferences'],
|
|
124
|
-
],
|
|
125
|
-
'HTTP & Utilities': [
|
|
126
|
-
['$.get() / $.http', 'HTTP client, CRUD, interceptors, and abort signals'],
|
|
127
|
-
['$.pipe / $.memoize / $.retry', 'Function composition, LRU caching, resilient async'],
|
|
128
|
-
['$.escapeHtml()', 'Safe rendering of user-generated content'],
|
|
129
|
-
['$.fn', 'Custom chainable collection methods via plugins'],
|
|
130
|
-
['fadeIn / fadeOut / slideToggle', 'Promise-based animations with chaining'],
|
|
131
|
-
['$.on()', 'Global delegated event listeners'],
|
|
132
|
-
],
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
return `
|
|
136
|
-
<div class="about-hero">
|
|
137
|
-
<span class="ver">v${$.version}</span>
|
|
138
|
-
<h1>zQuery</h1>
|
|
139
|
-
<p>A zero-dependency frontend micro-library - reactive components, routing, state management, and more in <strong>${$.libSize}</strong> minified.</p>
|
|
140
|
-
</div>
|
|
141
|
-
|
|
142
|
-
<div class="about-stats">
|
|
143
|
-
<div class="about-stat"><div class="about-stat-val">${$.libSize}</div><div class="about-stat-lbl">Minified</div></div>
|
|
144
|
-
<div class="about-stat"><div class="about-stat-val">0</div><div class="about-stat-lbl">Dependencies</div></div>
|
|
145
|
-
<div class="about-stat">
|
|
146
|
-
<div class="about-stat-val">${$.unitTests.total}</div>
|
|
147
|
-
<div class="about-stat-lbl">Tests</div>
|
|
148
|
-
<span class="test-badge ${$.unitTests.ok ? 'pass' : 'fail'}">${$.unitTests.ok
|
|
149
|
-
? '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg> passing'
|
|
150
|
-
: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg> ' + $.unitTests.failed + ' failing'}</span>
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
|
|
154
|
-
<div class="card">
|
|
155
|
-
<h3><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="var(--accent)" style="width:20px;height:20px;vertical-align:-4px;margin-right:0.25rem;"><path stroke-linecap="round" stroke-linejoin="round" d="M9.53 16.122a3 3 0 0 0-5.78 1.128 2.25 2.25 0 0 1-2.4 2.245 4.5 4.5 0 0 0 8.4-2.245c0-.399-.078-.78-.22-1.128Zm0 0a15.998 15.998 0 0 0 3.388-1.62m-5.043-.025a15.994 15.994 0 0 1 1.622-3.395m3.42 3.42a15.995 15.995 0 0 0 4.764-4.648l3.876-5.814a1.151 1.151 0 0 0-1.597-1.597L14.146 6.32a15.996 15.996 0 0 0-4.649 4.763m3.42 3.42a6.776 6.776 0 0 0-3.42-3.42"/></svg> Theme</h3>
|
|
156
|
-
<p>Choose your preferred appearance. <strong>System</strong> follows your OS setting automatically.</p>
|
|
157
|
-
<div class="theme-switch">
|
|
158
|
-
<button class="theme-btn ${t === 'system' ? 'active' : ''}" @click="setTheme('system')">
|
|
159
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width:14px;height:14px;"><path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z"/></svg>
|
|
160
|
-
System
|
|
161
|
-
</button>
|
|
162
|
-
<button class="theme-btn ${t === 'dark' ? 'active' : ''}" @click="setTheme('dark')">
|
|
163
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width:14px;height:14px;"><path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z"/></svg>
|
|
164
|
-
Dark
|
|
165
|
-
</button>
|
|
166
|
-
<button class="theme-btn ${t === 'light' ? 'active' : ''}" @click="setTheme('light')">
|
|
167
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width:14px;height:14px;"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"/></svg>
|
|
168
|
-
Light
|
|
169
|
-
</button>
|
|
170
|
-
</div>
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
<div class="card">
|
|
174
|
-
<h3><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="var(--accent)" style="width:20px;height:20px;vertical-align:-4px;margin-right:0.25rem;"><path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75a4.5 4.5 0 0 1-4.884 4.484c-1.076-.091-2.264.071-2.95.904l-7.152 8.684a2.548 2.548 0 1 1-3.586-3.586l8.684-7.152c.833-.686.995-1.874.904-2.95a4.5 4.5 0 0 1 6.336-4.486l-3.276 3.276a3.004 3.004 0 0 0 2.25 2.25l3.276-3.276c.256.565.398 1.192.398 1.852Z"/></svg> Features Used in This App</h3>
|
|
175
|
-
${Object.entries(feats).map(([cat, items]) => `
|
|
176
|
-
<div class="feat-section">
|
|
177
|
-
<div class="feat-label">${cat}</div>
|
|
178
|
-
<div class="feature-grid">
|
|
179
|
-
${items.map(([name, desc]) => `
|
|
180
|
-
<div class="feature-item">
|
|
181
|
-
<strong>${name}</strong>
|
|
182
|
-
<span>${desc}</span>
|
|
183
|
-
</div>
|
|
184
|
-
`).join('')}
|
|
185
|
-
</div>
|
|
186
|
-
</div>
|
|
187
|
-
`).join('')}
|
|
188
|
-
</div>
|
|
189
|
-
|
|
190
|
-
<div class="card card-muted">
|
|
191
|
-
<h3><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="var(--accent)" style="width:20px;height:20px;vertical-align:-4px;margin-right:0.25rem;"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"/></svg> Next Steps</h3>
|
|
192
|
-
<ul class="next-steps">
|
|
193
|
-
<li>Read the <a href="https://z-query.com/docs" target="_blank" rel="noopener">full documentation</a></li>
|
|
194
|
-
<li>Explore the <a href="https://github.com/tonywied17/zero-query" target="_blank" rel="noopener">source on GitHub</a></li>
|
|
195
|
-
<li>Run <code>npx zquery bundle</code> to build for production</li>
|
|
196
|
-
<li>Run <code>npx zquery dev</code> for live-reload development</li>
|
|
197
|
-
</ul>
|
|
198
|
-
</div>
|
|
199
|
-
`;
|
|
200
|
-
}
|
|
201
|
-
});
|
|
1
|
+
// about.js - About page with theme switcher
|
|
2
|
+
//
|
|
3
|
+
// Features used:
|
|
4
|
+
// $.storage - localStorage wrapper (get / set)
|
|
5
|
+
// $.version - library version string
|
|
6
|
+
// $.unitTests - build-time test results object
|
|
7
|
+
// $.bus.emit - toast notifications
|
|
8
|
+
// data-theme attr - dark / light theming
|
|
9
|
+
|
|
10
|
+
$.component('about-page', {
|
|
11
|
+
styles: `
|
|
12
|
+
/* -- Hero -- */
|
|
13
|
+
.about-hero { text-align: center; padding: 2.5rem 1rem 1.5rem; }
|
|
14
|
+
.about-hero h1 { font-size: 2rem; font-weight: 700; letter-spacing: -0.03em; margin-bottom: 0.35rem; }
|
|
15
|
+
.about-hero .ver { display: inline-block; padding: 0.2rem 0.65rem; border-radius: 999px;
|
|
16
|
+
font-size: 0.78rem; font-weight: 600; color: var(--accent);
|
|
17
|
+
background: var(--accent-soft); border: 1px solid rgba(88,166,255,.15);
|
|
18
|
+
margin-bottom: 0.75rem; }
|
|
19
|
+
.about-hero p { color: var(--text-muted); font-size: 0.95rem; max-width: 520px; margin: 0 auto; }
|
|
20
|
+
|
|
21
|
+
/* -- Stats bar -- */
|
|
22
|
+
.about-stats { display: flex; justify-content: center; gap: 2rem; flex-wrap: wrap;
|
|
23
|
+
padding: 1.25rem 0; border-top: 1px solid var(--border);
|
|
24
|
+
border-bottom: 1px solid var(--border); margin: 1.25rem 0; }
|
|
25
|
+
.about-stat { text-align: center; }
|
|
26
|
+
.about-stat-val { font-size: 1.35rem; font-weight: 700; color: var(--accent);
|
|
27
|
+
font-variant-numeric: tabular-nums; }
|
|
28
|
+
.about-stat-lbl { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase;
|
|
29
|
+
letter-spacing: 0.04em; }
|
|
30
|
+
|
|
31
|
+
/* -- Theme switcher -- */
|
|
32
|
+
.theme-switch { display: inline-flex; border-radius: var(--radius); overflow: hidden;
|
|
33
|
+
border: 1px solid var(--border); background: var(--bg); }
|
|
34
|
+
.theme-btn { padding: 0.45rem 1rem; font-size: 0.82rem; font-weight: 500;
|
|
35
|
+
background: transparent; border: none; color: var(--text-muted);
|
|
36
|
+
cursor: pointer; transition: all .15s ease; font-family: inherit;
|
|
37
|
+
display: inline-flex; align-items: center; gap: 0.35rem; }
|
|
38
|
+
.theme-btn:hover { color: var(--text); background: var(--bg-hover); }
|
|
39
|
+
.theme-btn.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
|
|
40
|
+
.theme-btn + .theme-btn { border-left: 1px solid var(--border); }
|
|
41
|
+
|
|
42
|
+
/* -- Feature categories -- */
|
|
43
|
+
.feat-section { margin-bottom: 0.5rem; }
|
|
44
|
+
.feat-label { font-size: 0.72rem; font-weight: 600; text-transform: uppercase;
|
|
45
|
+
letter-spacing: 0.05em; color: var(--text-muted); margin-bottom: 0.4rem;
|
|
46
|
+
padding-left: 0.1rem; }
|
|
47
|
+
|
|
48
|
+
/* -- Test badge -- */
|
|
49
|
+
.test-badge { display: inline-flex; align-items: center; gap: 0.3rem;
|
|
50
|
+
padding: 0.2rem 0.55rem; border-radius: 999px;
|
|
51
|
+
font-size: 0.7rem; font-weight: 600; line-height: 1;
|
|
52
|
+
margin-top: 0.35rem; }
|
|
53
|
+
.test-badge.pass { background: rgba(63,185,80,.12); color: var(--success);
|
|
54
|
+
border: 1px solid rgba(63,185,80,.25); }
|
|
55
|
+
.test-badge.fail { background: rgba(248,81,73,.12); color: var(--danger);
|
|
56
|
+
border: 1px solid rgba(248,81,73,.25); }
|
|
57
|
+
.test-badge svg { width: 11px; height: 11px; }
|
|
58
|
+
|
|
59
|
+
@media (max-width: 768px) {
|
|
60
|
+
.about-hero { padding: 1.5rem 0.5rem 1rem; }
|
|
61
|
+
.about-hero h1 { font-size: 1.5rem; }
|
|
62
|
+
.about-stats { gap: 1rem; }
|
|
63
|
+
.about-stat-val { font-size: 1.1rem; }
|
|
64
|
+
.theme-btn { padding: 0.4rem 0.65rem; font-size: 0.78rem; }
|
|
65
|
+
}
|
|
66
|
+
@media (max-width: 480px) {
|
|
67
|
+
.about-hero h1 { font-size: 1.3rem; }
|
|
68
|
+
.about-stats { gap: 0.6rem 1rem; }
|
|
69
|
+
.about-stat-val { font-size: 1rem; }
|
|
70
|
+
}
|
|
71
|
+
`,
|
|
72
|
+
|
|
73
|
+
state: () => ({
|
|
74
|
+
theme: 'system',
|
|
75
|
+
}),
|
|
76
|
+
|
|
77
|
+
mounted() {
|
|
78
|
+
this.state.theme = $.storage.get('theme') || 'system';
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
setTheme(mode) {
|
|
82
|
+
this.state.theme = mode;
|
|
83
|
+
$.storage.set('theme', mode);
|
|
84
|
+
window.__applyTheme(mode);
|
|
85
|
+
const label = mode === 'system' ? 'system (auto)' : mode;
|
|
86
|
+
$.bus.emit('toast', { message: `Theme: ${label}`, type: 'info' });
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
render() {
|
|
90
|
+
const t = this.state.theme;
|
|
91
|
+
const feats = {
|
|
92
|
+
'Core & Components': [
|
|
93
|
+
['$.component()', 'Reactive components with state, lifecycle, and template rendering'],
|
|
94
|
+
['computed / watch', 'Derived state and reactive watchers on the counter page'],
|
|
95
|
+
['DOM Diffing', 'Efficient morph() engine patches only changed DOM nodes'],
|
|
96
|
+
['z-key', 'Keyed list reconciliation in z-for loops'],
|
|
97
|
+
['z-model / z-ref', 'Two-way data binding and DOM element references'],
|
|
98
|
+
['CSP-safe expressions', 'Template expressions without eval() or new Function()'],
|
|
99
|
+
],
|
|
100
|
+
'Directives': [
|
|
101
|
+
['z-if / z-for / z-show', 'Structural directives for conditional & list rendering'],
|
|
102
|
+
['z-bind / z-class / z-style', 'Dynamic attributes, classes, and inline styles'],
|
|
103
|
+
['z-debounce', 'Debounced model updates - z-model z-debounce="300"'],
|
|
104
|
+
['z-lowercase / z-uppercase', 'Auto-transform text input on contacts email'],
|
|
105
|
+
['z-html', 'Trusted HTML injection in the playground'],
|
|
106
|
+
['templateUrl / styleUrl', 'External templates and CSS with auto-scoping'],
|
|
107
|
+
],
|
|
108
|
+
'Events': [
|
|
109
|
+
['@click.stop / .prevent', 'Event modifiers for fine-grained control'],
|
|
110
|
+
['@click.self / .once', 'Self-only and one-shot handlers in modals'],
|
|
111
|
+
['@click.outside', 'Outside-click detection for dropdowns'],
|
|
112
|
+
['@keydown.escape', 'Key modifiers - Escape to close forms'],
|
|
113
|
+
],
|
|
114
|
+
'Reactive Primitives': [
|
|
115
|
+
['$.signal() / $.computed()', 'Fine-grained reactive primitives for derived state'],
|
|
116
|
+
['$.effect()', 'Side-effects that auto-track signal dependencies'],
|
|
117
|
+
],
|
|
118
|
+
'State & Routing': [
|
|
119
|
+
['$.router()', 'SPA routing with history mode and fallback pages'],
|
|
120
|
+
['$.store()', 'Centralized state with actions, getters, subscriptions'],
|
|
121
|
+
['store.use / store.snapshot', 'Action middleware, deep-cloning, and history'],
|
|
122
|
+
['$.bus', 'Event bus for cross-component communication'],
|
|
123
|
+
['$.storage', 'localStorage wrapper for persisting preferences'],
|
|
124
|
+
],
|
|
125
|
+
'HTTP & Utilities': [
|
|
126
|
+
['$.get() / $.http', 'HTTP client, CRUD, interceptors, and abort signals'],
|
|
127
|
+
['$.pipe / $.memoize / $.retry', 'Function composition, LRU caching, resilient async'],
|
|
128
|
+
['$.escapeHtml()', 'Safe rendering of user-generated content'],
|
|
129
|
+
['$.fn', 'Custom chainable collection methods via plugins'],
|
|
130
|
+
['fadeIn / fadeOut / slideToggle', 'Promise-based animations with chaining'],
|
|
131
|
+
['$.on()', 'Global delegated event listeners'],
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
return `
|
|
136
|
+
<div class="about-hero">
|
|
137
|
+
<span class="ver">v${$.version}</span>
|
|
138
|
+
<h1>zQuery</h1>
|
|
139
|
+
<p>A zero-dependency frontend micro-library - reactive components, routing, state management, and more in <strong>${$.libSize}</strong> minified.</p>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<div class="about-stats">
|
|
143
|
+
<div class="about-stat"><div class="about-stat-val">${$.libSize}</div><div class="about-stat-lbl">Minified</div></div>
|
|
144
|
+
<div class="about-stat"><div class="about-stat-val">0</div><div class="about-stat-lbl">Dependencies</div></div>
|
|
145
|
+
<div class="about-stat">
|
|
146
|
+
<div class="about-stat-val">${$.unitTests.total}</div>
|
|
147
|
+
<div class="about-stat-lbl">Tests</div>
|
|
148
|
+
<span class="test-badge ${$.unitTests.ok ? 'pass' : 'fail'}">${$.unitTests.ok
|
|
149
|
+
? '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg> passing'
|
|
150
|
+
: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg> ' + $.unitTests.failed + ' failing'}</span>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<div class="card">
|
|
155
|
+
<h3><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="var(--accent)" style="width:20px;height:20px;vertical-align:-4px;margin-right:0.25rem;"><path stroke-linecap="round" stroke-linejoin="round" d="M9.53 16.122a3 3 0 0 0-5.78 1.128 2.25 2.25 0 0 1-2.4 2.245 4.5 4.5 0 0 0 8.4-2.245c0-.399-.078-.78-.22-1.128Zm0 0a15.998 15.998 0 0 0 3.388-1.62m-5.043-.025a15.994 15.994 0 0 1 1.622-3.395m3.42 3.42a15.995 15.995 0 0 0 4.764-4.648l3.876-5.814a1.151 1.151 0 0 0-1.597-1.597L14.146 6.32a15.996 15.996 0 0 0-4.649 4.763m3.42 3.42a6.776 6.776 0 0 0-3.42-3.42"/></svg> Theme</h3>
|
|
156
|
+
<p>Choose your preferred appearance. <strong>System</strong> follows your OS setting automatically.</p>
|
|
157
|
+
<div class="theme-switch">
|
|
158
|
+
<button class="theme-btn ${t === 'system' ? 'active' : ''}" @click="setTheme('system')">
|
|
159
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width:14px;height:14px;"><path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z"/></svg>
|
|
160
|
+
System
|
|
161
|
+
</button>
|
|
162
|
+
<button class="theme-btn ${t === 'dark' ? 'active' : ''}" @click="setTheme('dark')">
|
|
163
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width:14px;height:14px;"><path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z"/></svg>
|
|
164
|
+
Dark
|
|
165
|
+
</button>
|
|
166
|
+
<button class="theme-btn ${t === 'light' ? 'active' : ''}" @click="setTheme('light')">
|
|
167
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width:14px;height:14px;"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"/></svg>
|
|
168
|
+
Light
|
|
169
|
+
</button>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<div class="card">
|
|
174
|
+
<h3><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="var(--accent)" style="width:20px;height:20px;vertical-align:-4px;margin-right:0.25rem;"><path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75a4.5 4.5 0 0 1-4.884 4.484c-1.076-.091-2.264.071-2.95.904l-7.152 8.684a2.548 2.548 0 1 1-3.586-3.586l8.684-7.152c.833-.686.995-1.874.904-2.95a4.5 4.5 0 0 1 6.336-4.486l-3.276 3.276a3.004 3.004 0 0 0 2.25 2.25l3.276-3.276c.256.565.398 1.192.398 1.852Z"/></svg> Features Used in This App</h3>
|
|
175
|
+
${Object.entries(feats).map(([cat, items]) => `
|
|
176
|
+
<div class="feat-section">
|
|
177
|
+
<div class="feat-label">${cat}</div>
|
|
178
|
+
<div class="feature-grid">
|
|
179
|
+
${items.map(([name, desc]) => `
|
|
180
|
+
<div class="feature-item">
|
|
181
|
+
<strong>${name}</strong>
|
|
182
|
+
<span>${desc}</span>
|
|
183
|
+
</div>
|
|
184
|
+
`).join('')}
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
`).join('')}
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
<div class="card card-muted">
|
|
191
|
+
<h3><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="var(--accent)" style="width:20px;height:20px;vertical-align:-4px;margin-right:0.25rem;"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"/></svg> Next Steps</h3>
|
|
192
|
+
<ul class="next-steps">
|
|
193
|
+
<li>Read the <a href="https://z-query.com/docs" target="_blank" rel="noopener">full documentation</a></li>
|
|
194
|
+
<li>Explore the <a href="https://github.com/tonywied17/zero-query" target="_blank" rel="noopener">source on GitHub</a></li>
|
|
195
|
+
<li>Run <code>npx zquery bundle</code> to build for production</li>
|
|
196
|
+
<li>Run <code>npx zquery dev</code> for live-reload development</li>
|
|
197
|
+
</ul>
|
|
198
|
+
</div>
|
|
199
|
+
`;
|
|
200
|
+
}
|
|
201
|
+
});
|