zero-query 0.9.9 → 1.0.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/README.md +33 -32
- package/cli/args.js +1 -1
- package/cli/commands/build.js +2 -2
- package/cli/commands/bundle.js +15 -15
- package/cli/commands/create.js +2 -2
- package/cli/commands/dev/devtools/index.js +1 -1
- package/cli/commands/dev/devtools/js/core.js +14 -14
- package/cli/commands/dev/devtools/js/elements.js +4 -4
- package/cli/commands/dev/devtools/js/stats.js +1 -1
- package/cli/commands/dev/devtools/styles.css +2 -2
- package/cli/commands/dev/index.js +2 -2
- package/cli/commands/dev/logger.js +1 -1
- package/cli/commands/dev/overlay.js +21 -14
- package/cli/commands/dev/server.js +5 -5
- package/cli/commands/dev/validator.js +7 -7
- package/cli/commands/dev/watcher.js +6 -6
- package/cli/help.js +3 -3
- package/cli/index.js +2 -2
- package/cli/scaffold/default/app/app.js +17 -18
- package/cli/scaffold/default/app/components/about.js +9 -9
- package/cli/scaffold/default/app/components/api-demo.js +6 -6
- package/cli/scaffold/default/app/components/contact-card.js +4 -4
- package/cli/scaffold/default/app/components/contacts/contacts.css +2 -2
- package/cli/scaffold/default/app/components/contacts/contacts.html +3 -3
- package/cli/scaffold/default/app/components/contacts/contacts.js +11 -11
- package/cli/scaffold/default/app/components/counter.js +8 -8
- package/cli/scaffold/default/app/components/home.js +13 -13
- package/cli/scaffold/default/app/components/not-found.js +1 -1
- package/cli/scaffold/default/app/components/playground/playground.css +1 -1
- package/cli/scaffold/default/app/components/playground/playground.html +11 -11
- package/cli/scaffold/default/app/components/playground/playground.js +11 -11
- package/cli/scaffold/default/app/components/todos.js +8 -8
- package/cli/scaffold/default/app/components/toolkit/toolkit.css +1 -1
- package/cli/scaffold/default/app/components/toolkit/toolkit.html +4 -4
- package/cli/scaffold/default/app/components/toolkit/toolkit.js +7 -7
- package/cli/scaffold/default/app/routes.js +1 -1
- package/cli/scaffold/default/app/store.js +1 -1
- package/cli/scaffold/default/global.css +2 -2
- package/cli/scaffold/default/index.html +2 -2
- package/cli/scaffold/minimal/app/app.js +6 -7
- package/cli/scaffold/minimal/app/components/about.js +5 -5
- package/cli/scaffold/minimal/app/components/counter.js +6 -6
- package/cli/scaffold/minimal/app/components/home.js +8 -8
- package/cli/scaffold/minimal/app/components/not-found.js +1 -1
- package/cli/scaffold/minimal/app/routes.js +1 -1
- package/cli/scaffold/minimal/app/store.js +1 -1
- package/cli/scaffold/minimal/global.css +2 -2
- package/cli/scaffold/minimal/index.html +1 -1
- package/cli/scaffold/ssr/app/app.js +1 -2
- package/cli/scaffold/ssr/app/components/about.js +5 -5
- package/cli/scaffold/ssr/app/components/home.js +2 -2
- package/cli/scaffold/ssr/app/components/not-found.js +1 -1
- package/cli/scaffold/ssr/app/routes.js +1 -1
- package/cli/scaffold/ssr/global.css +2 -2
- package/cli/scaffold/ssr/index.html +2 -2
- package/cli/scaffold/ssr/server/index.js +4 -4
- package/cli/utils.js +6 -6
- package/dist/zquery.dist.zip +0 -0
- package/dist/zquery.js +508 -227
- package/dist/zquery.min.js +2 -2
- package/index.d.ts +16 -13
- package/index.js +7 -5
- package/package.json +2 -2
- package/src/component.js +64 -63
- package/src/core.js +15 -15
- package/src/diff.js +38 -38
- package/src/errors.js +17 -17
- package/src/expression.js +15 -17
- package/src/http.js +4 -4
- package/src/reactive.js +75 -9
- package/src/router.js +104 -24
- package/src/ssr.js +28 -28
- package/src/store.js +103 -21
- package/src/utils.js +64 -12
- package/tests/audit.test.js +143 -15
- package/tests/cli.test.js +20 -20
- package/tests/component.test.js +121 -121
- package/tests/core.test.js +56 -56
- package/tests/diff.test.js +42 -42
- package/tests/errors.test.js +5 -5
- package/tests/expression.test.js +58 -53
- package/tests/http.test.js +20 -20
- package/tests/reactive.test.js +185 -24
- package/tests/router.test.js +501 -74
- package/tests/ssr.test.js +15 -13
- package/tests/store.test.js +264 -23
- package/tests/utils.test.js +163 -26
- package/types/collection.d.ts +2 -2
- package/types/component.d.ts +5 -5
- package/types/errors.d.ts +3 -3
- package/types/http.d.ts +3 -3
- package/types/misc.d.ts +9 -9
- package/types/reactive.d.ts +25 -3
- package/types/router.d.ts +10 -6
- package/types/ssr.d.ts +2 -2
- package/types/store.d.ts +40 -5
- package/types/utils.d.ts +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* playground.css
|
|
1
|
+
/* playground.css - scoped styles for the playground page component */
|
|
2
2
|
|
|
3
3
|
.pg-section { display: flex; align-items: center; gap: .5rem;
|
|
4
4
|
font-size: .72rem; font-weight: 600; text-transform: uppercase;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
playground.html
|
|
2
|
+
playground.html - external template for playground-page component
|
|
3
3
|
|
|
4
|
-
Interactive UI patterns
|
|
4
|
+
Interactive UI patterns - event modifiers, animations, reactive bindings,
|
|
5
5
|
and plugins. Uses {{expression}} syntax for data binding.
|
|
6
6
|
-->
|
|
7
7
|
<div class="page-header" z-cloak>
|
|
8
8
|
<h1>Playground</h1>
|
|
9
|
-
<p class="subtitle">Interactive UI patterns
|
|
9
|
+
<p class="subtitle">Interactive UI patterns - event modifiers, animations, reactive bindings, and plugins.</p>
|
|
10
10
|
</div>
|
|
11
11
|
|
|
12
12
|
<!-- ── Interaction Patterns ──────────────────────────── -->
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
<div class="card" style="position:relative;z-index:2;">
|
|
16
16
|
<h3>Dropdown → Modal Flow</h3>
|
|
17
|
-
<p>Select an action from the <code>@click.outside</code> dropdown
|
|
17
|
+
<p>Select an action from the <code>@click.outside</code> dropdown - it opens a confirmation modal. Dismiss via overlay (<code>@click.self</code>) or <kbd style="padding:.1rem .35rem;background:var(--bg-hover);border-radius:4px;font-size:.82rem;">Esc</kbd>.</p>
|
|
18
18
|
<div style="display:flex;align-items:center;gap:1rem;flex-wrap:wrap;">
|
|
19
19
|
<div class="pg-dropdown" @click.outside="closeDropdown">
|
|
20
20
|
<button class="btn btn-primary" @click="toggleDropdown">
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<button z-else class="btn btn-ghost" disabled>✓ Once fired</button>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
33
|
-
<!-- Modal
|
|
33
|
+
<!-- Modal - faded in via JS, dismissed via overlay @click.self or Escape -->
|
|
34
34
|
<div class="pg-modal-backdrop" z-if="modalOpen" style="display:none" @click.self="closeModal">
|
|
35
35
|
<div class="pg-modal" @keydown.escape="closeModal" tabindex="-1">
|
|
36
36
|
<h3>Confirm: <span z-text="dropdownSelected || 'Action'"></span></h3>
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
<span id="pg-acc-icon-a" class="pg-accordion-icon">▸</span>
|
|
58
58
|
</button>
|
|
59
59
|
<div id="pg-acc-a" style="display:none">
|
|
60
|
-
<div class="pg-accordion-body">A zero-dependency frontend library for reactive SPAs
|
|
60
|
+
<div class="pg-accordion-body">A zero-dependency frontend library for reactive SPAs - components, routing, stores, HTTP, and 200+ utilities in one ~28 KB file.</div>
|
|
61
61
|
</div>
|
|
62
62
|
</div>
|
|
63
63
|
<div class="pg-accordion-item">
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
<div class="card-grid">
|
|
88
88
|
<div class="card">
|
|
89
89
|
<h3>Dynamic Styles</h3>
|
|
90
|
-
<p>Object binding via <code>z-style</code>
|
|
90
|
+
<p>Object binding via <code>z-style</code> - inline styles update reactively.</p>
|
|
91
91
|
<div class="pg-style-preview" z-style="{ color: previewColor, fontSize: previewSize + 'px', borderRadius: previewRadius + 'px', borderColor: previewColor }">
|
|
92
92
|
Live Preview
|
|
93
93
|
</div>
|
|
@@ -100,14 +100,14 @@
|
|
|
100
100
|
|
|
101
101
|
<div class="card">
|
|
102
102
|
<h3>Rich Content</h3>
|
|
103
|
-
<p>Render trusted HTML with <code>z-html</code>
|
|
103
|
+
<p>Render trusted HTML with <code>z-html</code> - only use with sanitized content.</p>
|
|
104
104
|
<textarea z-model="richContent" class="input" rows="2" style="resize:vertical;"></textarea>
|
|
105
105
|
<div class="pg-rich-preview" style="margin-top:.5rem;" z-html="richContent"></div>
|
|
106
106
|
</div>
|
|
107
107
|
|
|
108
108
|
<div class="card">
|
|
109
109
|
<h3>Conditional Classes</h3>
|
|
110
|
-
<p>Switch a single class from a set using <code>z-class</code>
|
|
110
|
+
<p>Switch a single class from a set using <code>z-class</code> - the object syntax applies only the matching key.</p>
|
|
111
111
|
<div class="pg-variant-row">
|
|
112
112
|
<div class="pg-variant-box" z-class="{'info': variant === 'info', 'success': variant === 'success', 'warning': variant === 'warning', 'danger': variant === 'danger'}">
|
|
113
113
|
{{variant.charAt(0).toUpperCase() + variant.slice(1)}} Variant
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
|
|
129
129
|
<div class="card">
|
|
130
130
|
<h3>Key & System Modifiers</h3>
|
|
131
|
-
<p>Template-level keyboard filtering
|
|
131
|
+
<p>Template-level keyboard filtering - no manual <code>e.key</code> checks needed.</p>
|
|
132
132
|
<div style="display:flex;gap:.5rem;flex-wrap:wrap;align-items:center;">
|
|
133
133
|
<input type="text" class="input input-sm" placeholder="Press Enter…" @keyup.enter="logShortcut('Enter ↵')" style="flex:1;min-width:140px;" />
|
|
134
134
|
<button class="btn btn-sm btn-outline" @click.ctrl="logShortcut('Ctrl+Click')">Ctrl+Click</button>
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
<div class="pg-section">Plugin System</div>
|
|
145
145
|
|
|
146
146
|
<div class="card">
|
|
147
|
-
<h3><code>$.fn</code>
|
|
147
|
+
<h3><code>$.fn</code> - Extend the Collection</h3>
|
|
148
148
|
<p>Register custom chainable methods on every <code>$(...)</code> selection. Click the buttons to trigger each plugin.</p>
|
|
149
149
|
<div id="pg-plugin-box" class="pg-plugin-target">✦ Target Element</div>
|
|
150
150
|
<div class="pg-plugin-btns">
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
// playground.js
|
|
1
|
+
// playground.js - Interactive UI patterns
|
|
2
2
|
//
|
|
3
3
|
// Features used:
|
|
4
|
-
// @click.outside / .self / .once
|
|
5
|
-
// @keydown.escape / @keyup.enter
|
|
6
|
-
// fadeIn / fadeOut / slideToggle
|
|
7
|
-
// z-style
|
|
8
|
-
// z-html
|
|
9
|
-
// $.fn
|
|
10
|
-
// z-skip
|
|
11
|
-
// templateUrl / styleUrl
|
|
4
|
+
// @click.outside / .self / .once - event modifiers
|
|
5
|
+
// @keydown.escape / @keyup.enter - keyboard modifiers
|
|
6
|
+
// fadeIn / fadeOut / slideToggle - DOM animations
|
|
7
|
+
// z-style - reactive inline styles
|
|
8
|
+
// z-html - trusted HTML rendering
|
|
9
|
+
// $.fn - collection plugin system
|
|
10
|
+
// z-skip - morph opt-out
|
|
11
|
+
// templateUrl / styleUrl - external files
|
|
12
12
|
|
|
13
13
|
// ── $.fn Plugins ─────────────────────────────────────────────────
|
|
14
14
|
$.fn.highlight = function (color = 'var(--accent)') {
|
|
@@ -88,7 +88,7 @@ $.component('playground-page', {
|
|
|
88
88
|
$.bus.emit('toast', { message: `${item} confirmed!`, type: 'success' });
|
|
89
89
|
},
|
|
90
90
|
|
|
91
|
-
/* Accordion
|
|
91
|
+
/* Accordion - pure DOM, z-skip prevents morph interference */
|
|
92
92
|
toggleAccordion(id) {
|
|
93
93
|
$(this._el).find(`#pg-acc-${id}`).slideToggle(250);
|
|
94
94
|
$(this._el).find(`#pg-acc-icon-${id}`).toggleClass('open');
|
|
@@ -112,6 +112,6 @@ $.component('playground-page', {
|
|
|
112
112
|
/* @click.once */
|
|
113
113
|
onceAction() {
|
|
114
114
|
this.state.onceClicked = true;
|
|
115
|
-
$.bus.emit('toast', { message: 'Fired once
|
|
115
|
+
$.bus.emit('toast', { message: 'Fired once - handler auto-removed!', type: 'info' });
|
|
116
116
|
},
|
|
117
117
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// todos.js
|
|
1
|
+
// todos.js - Todo list with global store
|
|
2
2
|
//
|
|
3
3
|
// Features used:
|
|
4
|
-
// $.getStore / dispatch / subscribe
|
|
5
|
-
// z-model / z-ref
|
|
6
|
-
// z-for + z-key
|
|
7
|
-
// z-class / z-if / z-show
|
|
8
|
-
// @submit.prevent / @keydown.escape
|
|
9
|
-
// mounted / destroyed lifecycle
|
|
4
|
+
// $.getStore / dispatch / subscribe - centralized state management
|
|
5
|
+
// z-model / z-ref - form bindings
|
|
6
|
+
// z-for + z-key - keyed list rendering with diffing
|
|
7
|
+
// z-class / z-if / z-show - conditional rendering
|
|
8
|
+
// @submit.prevent / @keydown.escape - event modifiers
|
|
9
|
+
// mounted / destroyed lifecycle - setup & teardown
|
|
10
10
|
|
|
11
11
|
$.component('todos-page', {
|
|
12
12
|
styles: `
|
|
@@ -204,7 +204,7 @@ $.component('todos-page', {
|
|
|
204
204
|
|
|
205
205
|
<div z-if="filtered.length === 0" class="td-empty">
|
|
206
206
|
<div class="td-empty-icon">${this.state.total === 0 ? '📝' : '🔍'}</div>
|
|
207
|
-
<p>${this.state.total === 0 ? 'No todos yet
|
|
207
|
+
<p>${this.state.total === 0 ? 'No todos yet - type something above and hit Add!' : 'No matching todos for this filter.'}</p>
|
|
208
208
|
</div>
|
|
209
209
|
|
|
210
210
|
<ul z-else class="td-list">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
toolkit.html
|
|
2
|
+
toolkit.html - external template for toolkit-page component
|
|
3
3
|
|
|
4
4
|
HTTP client with interceptors, 30+ utility functions, and advanced
|
|
5
5
|
store patterns. Uses {{expression}} syntax and z-if / z-for / z-show.
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
<div z-else-if="activeTab === 'utils'">
|
|
66
66
|
<div class="card">
|
|
67
67
|
<h3>Utility Belt</h3>
|
|
68
|
-
<p>30+ built-in helpers
|
|
68
|
+
<p>30+ built-in helpers - select a category to run a live demo.</p>
|
|
69
69
|
|
|
70
70
|
<div class="tk-util-grid">
|
|
71
71
|
<div class="tk-util-card {{activeUtil === 'pipe' ? 'selected' : ''}}" @click="runUtil('pipe')">
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
<div z-else>
|
|
103
103
|
<div class="card" style="margin-bottom:.75rem;">
|
|
104
104
|
<h3>Store Inspector</h3>
|
|
105
|
-
<p>Live view into the reactive store
|
|
105
|
+
<p>Live view into the reactive store - middleware, snapshots, and action history.</p>
|
|
106
106
|
|
|
107
107
|
<div style="display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem;">
|
|
108
108
|
<div class="tk-stat">
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
|
|
135
135
|
<div class="card card-muted" z-show="storeLog.length > 0">
|
|
136
136
|
<h3>Middleware Log</h3>
|
|
137
|
-
<p style="color:var(--text-muted);font-size:.85rem;margin-bottom:.5rem;">Real-time log from <code>store.use()</code>
|
|
137
|
+
<p style="color:var(--text-muted);font-size:.85rem;margin-bottom:.5rem;">Real-time log from <code>store.use()</code> - interact with other pages to generate entries.</p>
|
|
138
138
|
<div class="tk-log">
|
|
139
139
|
<div z-for="entry in storeLog" z-key="{{entry.id}}" class="tk-log-entry">
|
|
140
140
|
<span style="color:var(--text-muted);font-size:.78rem;min-width:65px;">{{entry.time}}</span>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// toolkit.js
|
|
1
|
+
// toolkit.js - HTTP, utilities, and advanced store features
|
|
2
2
|
//
|
|
3
3
|
// Features used:
|
|
4
|
-
// $.http / $.post / $.put / $.delete
|
|
5
|
-
// $.pipe / $.memoize / $.retry
|
|
6
|
-
// $.groupBy / $.chunk / $.unique
|
|
7
|
-
// store.use / snapshot / history
|
|
8
|
-
// templateUrl / styleUrl
|
|
4
|
+
// $.http / $.post / $.put / $.delete - HTTP client + interceptors
|
|
5
|
+
// $.pipe / $.memoize / $.retry - functional utilities
|
|
6
|
+
// $.groupBy / $.chunk / $.unique - collection helpers
|
|
7
|
+
// store.use / snapshot / history - middleware & time-travel
|
|
8
|
+
// templateUrl / styleUrl - external template & styles
|
|
9
9
|
|
|
10
10
|
$.component('toolkit-page', {
|
|
11
11
|
templateUrl: 'toolkit.html',
|
|
@@ -32,7 +32,7 @@ $.component('toolkit-page', {
|
|
|
32
32
|
actionCount: 0,
|
|
33
33
|
}),
|
|
34
34
|
|
|
35
|
-
// init() lifecycle
|
|
35
|
+
// init() lifecycle - runs before the first render
|
|
36
36
|
init() {
|
|
37
37
|
this._prevBaseURL = $.http.getConfig().baseURL || '';
|
|
38
38
|
$.http.configure({ baseURL: 'https://jsonplaceholder.typicode.com' });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* global.css
|
|
1
|
+
/* global.css - responsive scaffold styles
|
|
2
2
|
*
|
|
3
3
|
* Uses CSS custom properties for easy theming. Feel free to modify.
|
|
4
4
|
* Dark theme by default, light theme via [data-theme="light"].
|
|
@@ -504,7 +504,7 @@ code { background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-s
|
|
|
504
504
|
@keyframes toast-out { from { opacity: 1; transform: translateY(0) scale(1); } to { opacity: 0; transform: translateY(-10px) scale(0.95); } }
|
|
505
505
|
|
|
506
506
|
/* -- Route Transition -- */
|
|
507
|
-
|
|
507
|
+
z-outlet { animation: fade-in 0.25s var(--ease-out); }
|
|
508
508
|
@keyframes fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
|
|
509
509
|
|
|
510
510
|
/* -- Responsive: Mobile -- */
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
<div class="overlay" id="overlay"></div>
|
|
87
87
|
|
|
88
88
|
<!-- @ Router Outlet @ -->
|
|
89
|
-
<
|
|
90
|
-
<!-- @
|
|
89
|
+
<z-outlet class="content"></z-outlet>
|
|
90
|
+
<!-- @ Auto-detected by $.router() @ -->
|
|
91
91
|
|
|
92
92
|
<!-- Toast container for notifications -->
|
|
93
93
|
<div class="toast-container" id="toasts"></div>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
// app.js
|
|
1
|
+
// app.js - Application entry point
|
|
2
2
|
//
|
|
3
3
|
// Bootstraps the app: imports components, sets up routing,
|
|
4
4
|
// and wires the responsive sidebar.
|
|
5
5
|
//
|
|
6
6
|
// Key APIs used:
|
|
7
|
-
// $.router
|
|
8
|
-
// $.ready
|
|
9
|
-
// $.on
|
|
10
|
-
// $.storage
|
|
7
|
+
// $.router - SPA navigation (history mode)
|
|
8
|
+
// $.ready - run after DOM is loaded
|
|
9
|
+
// $.on - global delegated event listeners
|
|
10
|
+
// $.storage - localStorage wrapper
|
|
11
11
|
|
|
12
12
|
import './store.js';
|
|
13
13
|
import './components/home.js';
|
|
@@ -20,7 +20,6 @@ import { routes } from './routes.js';
|
|
|
20
20
|
// Router
|
|
21
21
|
// ---------------------------------------------------------------------------
|
|
22
22
|
const router = $.router({
|
|
23
|
-
el: '#app',
|
|
24
23
|
routes,
|
|
25
24
|
fallback: 'not-found',
|
|
26
25
|
mode: 'history'
|
|
@@ -75,7 +74,7 @@ $.ready(() => {
|
|
|
75
74
|
const current = window.location.pathname;
|
|
76
75
|
$.all(`.nav-link[z-link="${current}"]`).addClass('active');
|
|
77
76
|
|
|
78
|
-
console.log('⚡ {{NAME}}
|
|
77
|
+
console.log('⚡ {{NAME}} - powered by zQuery v' + $.version);
|
|
79
78
|
});
|
|
80
79
|
|
|
81
80
|
// ---------------------------------------------------------------------------
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// about.js
|
|
1
|
+
// about.js - About page with theme switcher
|
|
2
2
|
//
|
|
3
3
|
// Features used:
|
|
4
|
-
// $.storage
|
|
5
|
-
// $.version
|
|
6
|
-
// data-theme
|
|
4
|
+
// $.storage - localStorage wrapper (get / set)
|
|
5
|
+
// $.version - library version string
|
|
6
|
+
// data-theme - dark / light theming
|
|
7
7
|
|
|
8
8
|
$.component('about-page', {
|
|
9
9
|
styles: `
|
|
@@ -40,7 +40,7 @@ $.component('about-page', {
|
|
|
40
40
|
return `
|
|
41
41
|
<div class="page-header">
|
|
42
42
|
<h1>About</h1>
|
|
43
|
-
<p class="subtitle">zQuery v${$.version}
|
|
43
|
+
<p class="subtitle">zQuery v${$.version} - zero-dependency frontend micro-library.</p>
|
|
44
44
|
</div>
|
|
45
45
|
|
|
46
46
|
<div class="card">
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// counter.js
|
|
1
|
+
// counter.js - Interactive counter
|
|
2
2
|
//
|
|
3
3
|
// Features used:
|
|
4
|
-
// $.getStore / store.subscribe
|
|
5
|
-
// @click / z-model + z-number
|
|
6
|
-
// z-if / z-for / z-key
|
|
4
|
+
// $.getStore / store.subscribe - shared state + live re-render
|
|
5
|
+
// @click / z-model + z-number - events + two-way binding
|
|
6
|
+
// z-if / z-for / z-key - conditional & keyed list rendering
|
|
7
7
|
|
|
8
8
|
$.component('counter-page', {
|
|
9
9
|
styles: `
|
|
@@ -62,7 +62,7 @@ $.component('counter-page', {
|
|
|
62
62
|
decrement() {
|
|
63
63
|
const store = $.getStore('main');
|
|
64
64
|
store.dispatch('decrement');
|
|
65
|
-
this._pushHistory('
|
|
65
|
+
this._pushHistory('-', store.state.step, store.state.count);
|
|
66
66
|
},
|
|
67
67
|
|
|
68
68
|
setStep(e) {
|
|
@@ -96,7 +96,7 @@ $.component('counter-page', {
|
|
|
96
96
|
</div>
|
|
97
97
|
|
|
98
98
|
<div class="ctr-actions">
|
|
99
|
-
<button class="btn btn-outline" @click="decrement"
|
|
99
|
+
<button class="btn btn-outline" @click="decrement">- Subtract</button>
|
|
100
100
|
<button class="btn btn-primary" @click="increment">+ Add</button>
|
|
101
101
|
</div>
|
|
102
102
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// home.js
|
|
1
|
+
// home.js - Landing page
|
|
2
2
|
//
|
|
3
3
|
// Features used:
|
|
4
|
-
// $.component
|
|
5
|
-
// $.getStore
|
|
6
|
-
// store.subscribe
|
|
7
|
-
// @click / z-model
|
|
4
|
+
// $.component - define a component
|
|
5
|
+
// $.getStore - read/dispatch global store
|
|
6
|
+
// store.subscribe - re-render on store changes
|
|
7
|
+
// @click / z-model - event binding + two-way input
|
|
8
8
|
|
|
9
9
|
$.component('home-page', {
|
|
10
10
|
state: () => ({
|
|
@@ -41,7 +41,7 @@ $.component('home-page', {
|
|
|
41
41
|
<div class="card">
|
|
42
42
|
<h3>Getting Started</h3>
|
|
43
43
|
<p>
|
|
44
|
-
This is the <strong>minimal</strong> scaffold
|
|
44
|
+
This is the <strong>minimal</strong> scaffold - three pages, a global store,
|
|
45
45
|
and the router. Edit the files in <code>app/</code> to start building.
|
|
46
46
|
</p>
|
|
47
47
|
<p>
|
|
@@ -52,9 +52,9 @@ $.component('home-page', {
|
|
|
52
52
|
|
|
53
53
|
<div class="card">
|
|
54
54
|
<h3>Global Store</h3>
|
|
55
|
-
<p>The counter from <a z-link="/counter">Counter</a> is backed by <code>$.store</code>
|
|
55
|
+
<p>The counter from <a z-link="/counter">Counter</a> is backed by <code>$.store</code> - its value persists across pages:</p>
|
|
56
56
|
<div style="display:flex;align-items:center;gap:.75rem;margin-top:.75rem;">
|
|
57
|
-
<button class="btn btn-outline btn-sm" @click="decrement"
|
|
57
|
+
<button class="btn btn-outline btn-sm" @click="decrement">-</button>
|
|
58
58
|
<span style="font-size:1.25rem;font-weight:700;color:var(--accent);min-width:2rem;text-align:center;">${count}</span>
|
|
59
59
|
<button class="btn btn-primary btn-sm" @click="increment">+</button>
|
|
60
60
|
<button class="btn btn-outline btn-sm" @click="reset" style="margin-left:.5rem;">Reset</button>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* global.css
|
|
1
|
+
/* global.css - minimal scaffold styles
|
|
2
2
|
*
|
|
3
3
|
* Dark theme by default, light theme via [data-theme="light"].
|
|
4
4
|
* Modify the CSS variables below to customise the look and feel.
|
|
@@ -259,7 +259,7 @@ code { background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-s
|
|
|
259
259
|
.muted { color: var(--text-muted); }
|
|
260
260
|
|
|
261
261
|
/* -- Route Transition -- */
|
|
262
|
-
|
|
262
|
+
z-outlet { animation: fade-in 0.25s var(--ease-out); }
|
|
263
263
|
@keyframes fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
|
|
264
264
|
|
|
265
265
|
/* -- Responsive: Mobile -- */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// app.js
|
|
1
|
+
// app.js - Client entry point
|
|
2
2
|
//
|
|
3
3
|
// Imports shared component definitions and registers them with zQuery.
|
|
4
4
|
// The SSR server imports the same definitions via createSSRApp().
|
|
@@ -15,7 +15,6 @@ $.component('not-found', notFound);
|
|
|
15
15
|
|
|
16
16
|
// Client-side router
|
|
17
17
|
const router = $.router({
|
|
18
|
-
el: '#app',
|
|
19
18
|
routes,
|
|
20
19
|
fallback: 'not-found',
|
|
21
20
|
mode: 'history'
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// about.js
|
|
1
|
+
// about.js - About page component
|
|
2
2
|
|
|
3
3
|
export const aboutPage = {
|
|
4
4
|
state: () => ({
|
|
5
5
|
features: [
|
|
6
|
-
'createSSRApp()
|
|
7
|
-
'renderToString()
|
|
8
|
-
'renderPage()
|
|
9
|
-
'renderBatch()
|
|
6
|
+
'createSSRApp() - isolated component registry for Node.js',
|
|
7
|
+
'renderToString() - render a component to an HTML string',
|
|
8
|
+
'renderPage() - full HTML document with meta tags',
|
|
9
|
+
'renderBatch() - render multiple components in one call',
|
|
10
10
|
'Hydration markers (data-zq-ssr) for client takeover',
|
|
11
11
|
'SEO: description, canonical URL, Open Graph tags',
|
|
12
12
|
]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// home.js
|
|
1
|
+
// home.js - Home page component
|
|
2
2
|
//
|
|
3
3
|
// Exports a plain definition object that works on both client and server.
|
|
4
4
|
// The client registers it with $.component(), the server with app.component().
|
|
@@ -9,7 +9,7 @@ export const homePage = {
|
|
|
9
9
|
timestamp: new Date().toLocaleTimeString(),
|
|
10
10
|
}),
|
|
11
11
|
|
|
12
|
-
// init() runs on both client and server
|
|
12
|
+
// init() runs on both client and server - no DOM required
|
|
13
13
|
init() {
|
|
14
14
|
const hour = new Date().getHours();
|
|
15
15
|
this.state.greeting =
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* global.css
|
|
1
|
+
/* global.css - SSR Scaffold Styles */
|
|
2
2
|
|
|
3
3
|
*, *::before, *::after {
|
|
4
4
|
box-sizing: border-box;
|
|
@@ -56,7 +56,7 @@ body {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/* -- Main content -- */
|
|
59
|
-
|
|
59
|
+
z-outlet {
|
|
60
60
|
max-width: 800px;
|
|
61
61
|
margin: 2rem auto;
|
|
62
62
|
padding: 0 1.5rem;
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
</nav>
|
|
22
22
|
|
|
23
|
-
<!-- Main content
|
|
24
|
-
<
|
|
23
|
+
<!-- Main content - SSR output is injected here by the server -->
|
|
24
|
+
<z-outlet z-cloak></z-outlet>
|
|
25
25
|
|
|
26
26
|
<footer class="footer">
|
|
27
27
|
<small>Built with zQuery · SSR Scaffold</small>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// server/index.js
|
|
1
|
+
// server/index.js - SSR HTTP server
|
|
2
2
|
//
|
|
3
3
|
// Renders routes to HTML with zQuery SSR and serves them over HTTP.
|
|
4
|
-
// Components are imported from app/components/
|
|
4
|
+
// Components are imported from app/components/ - the same definitions
|
|
5
5
|
// the client uses.
|
|
6
6
|
//
|
|
7
7
|
// Usage:
|
|
@@ -14,7 +14,7 @@ import { join, extname, resolve } from 'node:path';
|
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { createSSRApp } from 'zero-query/ssr';
|
|
16
16
|
|
|
17
|
-
// Shared component definitions
|
|
17
|
+
// Shared component definitions - same ones the client registers
|
|
18
18
|
import { homePage } from '../app/components/home.js';
|
|
19
19
|
import { aboutPage } from '../app/components/about.js';
|
|
20
20
|
import { notFound } from '../app/components/not-found.js';
|
|
@@ -62,7 +62,7 @@ ${routes.map(r =>
|
|
|
62
62
|
}</a>`).join('\n')}
|
|
63
63
|
</div>
|
|
64
64
|
</nav>
|
|
65
|
-
<
|
|
65
|
+
<z-outlet>${body}</z-outlet>
|
|
66
66
|
<footer class="footer"><small>Built with zQuery · SSR</small></footer>
|
|
67
67
|
</body>
|
|
68
68
|
</html>`;
|
package/cli/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* cli/utils.js
|
|
2
|
+
* cli/utils.js - shared utility functions
|
|
3
3
|
*
|
|
4
4
|
* Context-aware comment stripping, quick minification, size formatting,
|
|
5
5
|
* and recursive directory copying. These are consumed by both the
|
|
@@ -12,7 +12,7 @@ const fs = require('fs');
|
|
|
12
12
|
const path = require('path');
|
|
13
13
|
|
|
14
14
|
// ---------------------------------------------------------------------------
|
|
15
|
-
// _copyTemplateLiteral
|
|
15
|
+
// _copyTemplateLiteral - copy a template literal verbatim, tracking ${…}
|
|
16
16
|
// nesting so that `//` inside template text isn't mistaken for a comment.
|
|
17
17
|
// ---------------------------------------------------------------------------
|
|
18
18
|
|
|
@@ -49,7 +49,7 @@ function _copyTemplateLiteral(code, start) {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// ---------------------------------------------------------------------------
|
|
52
|
-
// stripComments
|
|
52
|
+
// stripComments - context-aware, skips strings / templates / regex
|
|
53
53
|
// ---------------------------------------------------------------------------
|
|
54
54
|
|
|
55
55
|
function stripComments(code) {
|
|
@@ -127,7 +127,7 @@ function stripComments(code) {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
// ---------------------------------------------------------------------------
|
|
130
|
-
// minify
|
|
130
|
+
// minify - single-pass minification
|
|
131
131
|
// Strips comments, collapses whitespace to the minimum required,
|
|
132
132
|
// and preserves string / template-literal / regex content verbatim.
|
|
133
133
|
// ---------------------------------------------------------------------------
|
|
@@ -251,7 +251,7 @@ function _isRegexCtx(out) {
|
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
// ---------------------------------------------------------------------------
|
|
254
|
-
// sizeKB
|
|
254
|
+
// sizeKB - human-readable file size
|
|
255
255
|
// ---------------------------------------------------------------------------
|
|
256
256
|
|
|
257
257
|
function sizeKB(buf) {
|
|
@@ -259,7 +259,7 @@ function sizeKB(buf) {
|
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
// ---------------------------------------------------------------------------
|
|
262
|
-
// copyDirSync
|
|
262
|
+
// copyDirSync - recursive directory copy
|
|
263
263
|
// ---------------------------------------------------------------------------
|
|
264
264
|
|
|
265
265
|
function copyDirSync(src, dest) {
|
package/dist/zquery.dist.zip
CHANGED
|
Binary file
|